Log inRegister an accountBrowse CSDbHelp & documentationFacts & StatisticsThe forumsAvailable RSS-feeds on CSDbSupport CSDb Commodore 64 Scene Database
You are not logged in - nap
CSDb User Forums


Forums > CSDb Entries > Release id #150179 : Differential Scrolling
2016-08-28 23:19
Compyx

Registered: Jan 2005
Posts: 631
Release id #150179 : Differential Scrolling

Guess I'll start the discussion then,

I don't see any advantage of using this technique over traditional ways of scrolling, and I'll leave VSP out of the equation for now.

Seems to me that when using actual 'level' data using a tile based approach would be faster and a lot less memory hungry. Not to mention it would allow scrolling backwards, something this differential scrolling would have a hard time to do.

Also I don't get the 'full screen' update when scrolling left-to-right at one pixel at a time, seems incredibly wasteful.

Well, I said my piece, now for the actual coders ;)
 
... 19 posts hidden. Click here to view all posts....
 
2016-08-31 01:26
White Flame

Registered: Sep 2002
Posts: 136
Oh, I just remembered another time I used this technique: BASIC animations! :-D Move the cursor, PRINT the animation item which also prints enough spaces beside it to erase the prior frame (or leave smears to animatedly draw a border or smoke trails or whatever). It makes fluid-enough large PETSCII animations quite feasible when you're an 8 year old who doesn't know asm yet. :-)
2016-08-31 08:03
ChristopherJam

Registered: Aug 2004
Posts: 1378
Of course, now to combine this technique with the LDA# optimised speedcode from Faster charmap scrolling…
2016-08-31 21:46
Claus_2015

Registered: Oct 2012
Posts: 53
While this has surely been made before, there seem to be some possible applications:

1. 8 pixel/frame scrolling (or even 16 pixel), which is hardly possible using traditional screen copy

2. Anything that is not traditional horizontal/vertical scrolling, e.g. 3d tunnel stuff etc.

I also thought about something like this in the past, but quickly assumed that it would take too much memory. But when looking at the numbers, it is actually comparable to what you need for tile based maps.
2016-09-01 08:11
enthusi

Registered: May 2004
Posts: 675
It is not too uncommon to directly write map-data into screen for games. No copy to *-1 but a full offset store.
Sometimes even lda map,x sta screen,y
In particular for horizontal scrollers. You dont have any limitations in scrolling speed then.
2016-09-02 09:49
Fungus

Registered: Sep 2002
Posts: 616
We've discussed such things before too.

If you have a tile map and use character sets with even offsets you can use bitwise manipulations to speed up plotting and just plot the whole screen. The bigger the tiles the more you save. With splits you can have multiple tiles sets too and even do it dynamically as long as the region doesn't share tiles with another, that will require duplication.

I'd like to see an implementation of the delta scrolling for color memory however, just to get an idea of it.
2016-09-02 10:48
oziphantom

Registered: Oct 2014
Posts: 478
My Squid Jump basically does the delta for CRAM that way I can actually scroll fast enough. Their is a preview on here if you want to have a look.
2019-04-24 06:59
TBH

Registered: Mar 2010
Posts: 20
I've been working on a similar scroll routine and popped over to CSDB to see if anyone had already discussed the technique. Of course they had!

Anyway, here's my take on it, for a single direction horizontal scroller (R-Type, etc) that scrolls chars and colour data.

Each column (scrolling right to left) can be represented by the barest minimum of code where there is a difference from the column on its left:
1) One LDA# per unique character
2) One indexed STA$ per unique char
3) One indexed STA$ per unique colour

Where colours share the same lower 4 bits as a char, that LDA is shared (up to 16 char/colour can be mapped this way) to avoid frequent loads of colour values.

The writes are indexed. The absolute value is always the address of Column 0 ($0400, $0428, etc). the index register (assuming .X here) indicates the column to write. To run the screen shift, X is set to 0 and the correct place in the buffer is JSR'd.

So, during spare cycle time, the information for a column is streamed to a code generator. The generator emits the absolute fastest code to generate the column.

The code to draw the rightmost two columns would look something like this, assuming two 2x2 block tiles are vertically stacked at the top of the screen, with a clear blue sky char in the column immediately left:

...
lda #TopLeftBrickChar ;(lower 4 bits is 9 - brown)
sta CharRow0,X
sta ColorRow0,X
sta CharRow2,X
sta ColorRow2,X

lda #BottomLeftBrickChar ;(lower 4 bits is 9 - brown)
sta CharRow1,X
sta ColorRow1,X
sta CharRow3,X
sta ColorRow3,X

inx ; next column

lda #TopRightBrickChar ; No need to change colour
sta CharRow0,X
sta CharRow2,X

lda #BottomRightBrickChar ; No need to change colour
sta CharRow1,X
sta CharRow3,X

rts


The code is written to a circular buffer. The address of each column code (immediately proceeding the INX) is stored in LO/HI tables (pointer, circular buffer). If the end of the code buffer is encountered while writing code then a JMP StartOfBuffer is written and the code is written from the start of the buffer. This can also be precomputed and added in the data stream as a control code.

To scroll, load the index register (.X) with 0, and JSR to the address of the column that is currently leftmost (ie pointer in the address table). This will shift the screen as fast as technically possible.

Next, update the address pointer and add another column-worth of code to the code buffer (this operation can be spread across hardware-scroll frames). When the new column code is appended, the existing RTS is replaced with INX.

The number of columns in the code buffer can be more than 40, of course. It depends on how much space is available.

If changes are to be made to specific locations on the video or colour matrix, such as changing a char, then use an indexed source (such as the screen matrix itself):

lda CharRow0 + 1,X
sta CharRow0,X


The size of the code buffer can be programmatically determined by a simple parse of the map data.

The data for the column needs to convey information to the code generator such as the char/colour and the leftmost column's row addresses (use an index and lookup table, or a bitfield). This information can be assembled from tile data or some other compression technique. It's all deterministic, so there is a lot of leeway for storage, as well as deferring the actually code construction across several screen frames that have cycles to spare.

The screen shift's cycle usage is dependent on the complexity of the screen data, so there will be constraints on level design. But that's always been the case.
2019-04-24 10:02
ChristopherJam

Registered: Aug 2004
Posts: 1378
Very nice, TBH. Related ideas were also discussed at Faster charmap scrolling, albeit just for colour ram updates.

Are you currently leaning toward generating the speedcode directly from a traditional tilemap, or are you using some other kind of compressed hints?
2019-04-24 11:37
Oswald

Registered: Apr 2002
Posts: 5017
this could be extended to - not to reload A if the same value has to be writen to other rows aswell - which I prefer, it could restrict the gfx having the color info aswell in lower nibble? not being able to reuse chars with different colors. maybe its not an issue.
2019-04-24 15:49
TBH

Registered: Mar 2010
Posts: 20
@ ChristopherJam, regarding speedcode:

I think it's best the routine not care how the map is stored. It should only require (repeatedly) a column of chars and colours. I'm leaning toward a hybrid solution though, which analyses the game map during initialisation.

For example, at the start of a game level it would request each of the columns from the tile routine and use that data to generate and store hints for each of those columns. During the actual game the hints would be accessed so each tile column could be quickly sorted into to a "one-to-many" relationship between the loads and stores.

Alternatively, if there was enough spare RAM, the raw column data for loads (values) and stores (row indices) could be used: TopLeftBrickChar, 0, 2, BottomLeftBrickChar, 1, 3 ... and so on.
This is where a compressed bitfield would be useful: TopLeftBrickChar, %10100000, BottomLeftBrickChar, %01010000 ... and so on.

@ Oswald, regarding colour info:

The char/colour alignment allows up to 16 chars per colour - which although restrictive, is also optional.

The code generator would still have the option of emitting a separate unshared LDA operation for the colour value. I see such an optimised arrangement of char definitions done per-level, so the char definitions would quite likely be rearranged differently for each level of a game.

However, such optimisation may negatively impact other char-based optimisations - such as collision range tests (eg where platform chars are from 10 to 50, wall chars are from 51 to 80, etc).

I think some precalculation would have to be used, mostly an analyse of the map data to produce intermediate values useful for the code generation stage.

I've some spare time tomorrow, so will try to cobble my code together with some real world map data, and post the results.
Previous - 1 | 2 | 3 - Next
RefreshSubscribe to this thread:

You need to be logged in to post in the forum.

Search the forum:
Search   for   in  
All times are CET.
Search CSDb
Advanced
Users Online
megasoftargentina
iceout/Avatar/HF
AüMTRöN
Martin Piper
Codetapper
Guests online: 129
Top Demos
1 Next Level  (9.8)
2 Mojo  (9.7)
3 Coma Light 13  (9.7)
4 Edge of Disgrace  (9.6)
5 Comaland 100%  (9.6)
6 No Bounds  (9.6)
7 Uncensored  (9.6)
8 The Ghost  (9.6)
9 Wonderland XIV  (9.6)
10 Bromance  (9.6)
Top onefile Demos
1 It's More Fun to Com..  (9.8)
2 Party Elk 2  (9.7)
3 Cubic Dream  (9.6)
4 Copper Booze  (9.5)
5 Rainbow Connection  (9.5)
6 TRSAC, Gabber & Pebe..  (9.5)
7 Onscreen 5k  (9.5)
8 Wafer Demo  (9.5)
9 Dawnfall V1.1  (9.5)
10 Quadrants  (9.5)
Top Groups
1 Oxyron  (9.3)
2 Nostalgia  (9.3)
3 Booze Design  (9.3)
4 Censor Design  (9.3)
5 Crest  (9.3)
Top Logo Graphicians
1 Sander  (10)
2 Facet  (9.7)
3 Mermaid  (9.4)
4 Pal  (9.4)
5 Shine  (9.3)

Home - Disclaimer
Copyright © No Name 2001-2024
Page generated in: 0.044 sec.