In my ongoing game project, I am struggling with the scrolling routines. I use the tilemap as a window into a much larger game world. Right now I have a coding solution that is short and clean but comes with the cost of having to update the whole visible part of the tilemap at certain times. To be able to do this as fast as possible at vertical blank, I have a tile buffer prepared, so all I have to do is to copy 672 bytes from the buffer to VRAM. But the routine is not fast enough. It takes about 24 scanlines which of course causes a tearing of the upper part of the screen. If the screen is updated 60 times/second, the display is about 250 scanlines (I think there are a few more than those actually seen) and the emulator runs at 8 MHZ - there should be 8 000 000 / 250 / 60 cycles = 533 cycles for every scanline. That is not very much (but a lot more than on a C64 - I know : )).
I am thinking of different solutions:
1) I can rewrite the scrolling routines but I would be happy not to. They get complicated and messy real quick.
2) I can update the first rows of the tilemap directly when the tile buffer is prepared. At that point the screen updating has passed the upper part of the screen. And then I update the rest at vblank. Not a completely satisfying solution...
3) Or is there some other clever solution? How many cycles do I really have between vblank and the moment where ther topleft pixel of the screen is updated?
Below is the code for updating the tilemap:
;update topleftmost 21x16 tiles of 32x32 tilemap
lda #<_tilebuffer ;set tilebuffer pointer
sta ZP0
lda #>_tilebuffer
sta ZP1
lda #<L0_MAP_ADDR ;set tilemap pointer
sta VERA_ADDR_L
lda #>L0_MAP_ADDR
sta VERA_ADDR_M
lda #$10
sta VERA_ADDR_H
ldy #16 ;16 rows
-- ldx #21 ;21 columns of 2 bytes each
- lda (ZP0) ;copy tile from buffer to tilemap
sta VERA_DATA0 ;write first byte of column
inc ZP0
bne +
inc ZP1
+ lda (ZP0)
sta VERA_DATA0 ;write second byte of column
inc ZP0
bne +
inc ZP1
+ dex
bne -
clc ;add (32-21)*2 = 22 bytes to get addr for next tilemap row
lda #22
adc VERA_ADDR_L
sta VERA_ADDR_L
lda VERA_ADDR_M
adc #0
sta VERA_ADDR_M
dey
bne --
Question
Johan Kårlin
In my ongoing game project, I am struggling with the scrolling routines. I use the tilemap as a window into a much larger game world. Right now I have a coding solution that is short and clean but comes with the cost of having to update the whole visible part of the tilemap at certain times. To be able to do this as fast as possible at vertical blank, I have a tile buffer prepared, so all I have to do is to copy 672 bytes from the buffer to VRAM. But the routine is not fast enough. It takes about 24 scanlines which of course causes a tearing of the upper part of the screen. If the screen is updated 60 times/second, the display is about 250 scanlines (I think there are a few more than those actually seen) and the emulator runs at 8 MHZ - there should be 8 000 000 / 250 / 60 cycles = 533 cycles for every scanline. That is not very much (but a lot more than on a C64 - I know : )).
I am thinking of different solutions:
1) I can rewrite the scrolling routines but I would be happy not to. They get complicated and messy real quick.
2) I can update the first rows of the tilemap directly when the tile buffer is prepared. At that point the screen updating has passed the upper part of the screen. And then I update the rest at vblank. Not a completely satisfying solution...
3) Or is there some other clever solution? How many cycles do I really have between vblank and the moment where ther topleft pixel of the screen is updated?
Below is the code for updating the tilemap:
;update topleftmost 21x16 tiles of 32x32 tilemap
lda #<_tilebuffer ;set tilebuffer pointer
sta ZP0
lda #>_tilebuffer
sta ZP1
lda #<L0_MAP_ADDR ;set tilemap pointer
sta VERA_ADDR_L
lda #>L0_MAP_ADDR
sta VERA_ADDR_M
lda #$10
sta VERA_ADDR_H
ldy #16 ;16 rows
-- ldx #21 ;21 columns of 2 bytes each
- lda (ZP0) ;copy tile from buffer to tilemap
sta VERA_DATA0 ;write first byte of column
inc ZP0
bne +
inc ZP1
+ lda (ZP0)
sta VERA_DATA0 ;write second byte of column
inc ZP0
bne +
inc ZP1
+ dex
bne -
clc ;add (32-21)*2 = 22 bytes to get addr for next tilemap row
lda #22
adc VERA_ADDR_L
sta VERA_ADDR_L
lda VERA_ADDR_M
adc #0
sta VERA_ADDR_M
dey
bne --
Link to comment
Share on other sites
24 answers to this question
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.