Hello again. I've been working away at my little scrolling engine. Right now I'm just trying to get scrolling to the right to work. My level map is 3 screens wide, 2 screens tall. Here's how it works so far:
1) The player presses the right directional button, starting a 16-pixel scroll
2) Halfway through the scroll (8 pixels/frames), I draw one column offscreen.
3) Next frame I draw another column. My "metacolumn" is done.
Note: Up to here, everything works perfectly all across the three level map pages (and it wraps around forever if you keep pressing right, with no errors). It seems there are no problems with these 3 steps.
4) Next frame, update the attribute data for the new column
This is where I've been having problems. My subroutine works for almost a full page of attribute updates, but on the last attribute column it starts glitching, changing the colors for a part of the screen that I don't think I wrote to.
I'm going to post the attributeupdate subroutine I've been fiddling with. Before that, a note on how I'm storing the levelmap data. I don't store it one screen at a time, but rather one whole 3-page-wide row at a time. Like this (each byte is a 16x16 metatile):
Code:
levelmap:
.db $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 ;top row, 3 pages wide
.db $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00
.db $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$02
.db $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 ;row 2
.db $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00
.db $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00
etc...
The levelmap attribute data is stored in a similar way:
Code:
levelmapattribute:
.db %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000 ;first 3-page wide "row" of attribute data
.db %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000
.db %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000
.db %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000 ;2nd attribute "row"
.db %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000
.db %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000
etc.....
Here's my subroutine:
Code:
UpdateRightColumnAtt:
;;;this algorithm finds which byte of the levelmapattribute corresponds to the top of our new column
LDA CurrentMapCol ;CurrentMapCol marks where in the levelmap data the top left corner of the visible screen is
CLC
ADC #$11 ;new column map x coord. CurrentMapCol is the top left corner of the visible screen
;the column we just drew offscreen is #$11 over from this
LSR A ;divide by 2 to get the right place in the levelmapattribute data
TAX
;;;this part will help us know whether to start at $2xC0, $2xC1, $2xC2 ... or $2xC7
LDA CurrentMapCol ;redundant. optimize later
CLC
ADC #$11 ;same story as above
AND #$0F ;wipe out the left side
LSR A ;divide by 2. Gives us a number #$00 through #$07.
;we will add this to #$C0 to get the low byte of the desired attribute table address
TAY
LoadAttribute2Loop2:
LDA $2002 ;let's pull this out of the loop dummy
LDA #$23
CMP DrawPointerHigh ;this was set in the preceding drawcolumn routines.
BCS vegetable ;if greater than, we are in the first nametable. Otherwise, second
LDA #$27
vegetable: ;they're good for you
STA $2006
TYA
CLC
ADC #$C0
STA $2006
LDA levelmapattribute, x ; load data from address (levelmapattribute + the value in x)
STA $2007 ; write to PPU. This will write byte 1 (then 2, 3 and 4)
TXA
CLC
ADC #$60 ;Map is three screens wide. If it were one screen wide, I'd add #$20.
TAX
LDA levelmapattribute, x
STA $2007 ;this will write byte 5 (then 6,7 and 8)
TXA
SEC
SBC #$48 ;put X where it needs to go for the next go-round
TAX
TYA
CLC
ADC #$08
TAY
CPY #$20 ;The highest value Y should ever have is #$1F
BCC LoadAttribute2Loop2
LDA CurrentMapCol ;update map position
CLC
ADC #$01
CMP MapWidth
BNE UpdateRightColumnAttEnd
LDA #$00
UpdateRightColumnAttEnd:
STA CurrentMapCol
rts
If it helps, it seems to mess up starting when CurrentMapCol has a value of #$0D.
Can somebody please help me? Also, should I be storing my data in "screens" rather than rows?