
Since this is my first time doing diagonal scrolling it's hard to tell if my implementation is wrong, or if the logic I'm trying to implement in the first place is wrong (so any implementation of that logic would be flawed) so I figured getting more eyes on my code would help.
I have a ColumnUpdateBuffer that gets DMA'd to ColumnUpdateAddress vertically, a full 32 tiles tall. I also have a RowUpdateBuffer that similarly gets DMA'd to RowUpdateAddress horizontally and it's always 64 tiles wide for simplicity, and I only write to the portion of it that will be visible. My level buffer is in LevelBuf and it is 256 wide * 32 tall * 2 bytes per metatile, arranged in a series of columns from left to right.
When the scrolling has changed: (simplified)
If the X scroll value passes a tile boundary:
- If scrolling left, select a column 2 tiles left from the new scroll position
- If scrolling right, select a column 34 tiles right from the new scroll position
- (Selected column number will be called SelectedColumn)
- Set ColumnUpdateAddress to tilemap base address + SelectedColumn AND 31, use second screen if needed
- Prepare a pointer to start reading from level data (Level column is SelectedColumn / 2)
- -----
- Y = Y scroll position counted in metatiles
- X = Y, restricted to fit ColumnUpdateBuffer
- ColumnUpdateBuffer[X++] = Tile numbers[Level pointer[Y++]]
- Repeat the previous step 15 more times, wrapping X around in the buffer.
- If scrolling up, select a row 1 tiles up from the new scroll position
- If scrolling down, select a row 29 tiles down from the new scroll position
- (Selected row number will be called SelectedRow)
- Set RowUpdateAddress to tilemap base address + SelectedRow * 32
- Prepare a pointer to start reading from level data (Level column is X scroll position in metatiles, minus 1)
- -----
- Y = SelectedRow / 2
- X = X scroll position in metatiles * 2, minus 1, constrained to the buffer size
- RowUpdateBuffer[X++] = Tile numbers[Level pointer[Y]]
- Move Level pointer ahead one column
- Repeat previous two steps 20 times (probably more than needed. I was trying to make it slightly wider than the screen, hence starting a bit to the left of it)
scrolling.s
renderlevel.s