Fix tile rendering

This is not quite correct yet.  IT appears that two rows or columns are
drawn on the edges when only a single solumn or row is necessary.  Also,
this code is based on the old GTE codebase, so the initial rectangle for
rendering tiles is width+1, height+1. This can be improved.
This commit is contained in:
Lucas Scharenbroich 2021-08-10 07:59:14 -05:00
parent b9fced46cd
commit e3cb742626
8 changed files with 435 additions and 344 deletions

View File

@ -3,11 +3,11 @@ MoveLeft
adc StartX ; Increment the virtual X-position
jsr SetBG0XPos
lda StartX
lsr
jsr SetBG1XPos
; lda StartX
; lsr
; jsr SetBG1XPos
jsr DoFrame
jsr Render
rts
MoveRight
@ -19,11 +19,11 @@ MoveRight
lda #0
jsr SetBG0XPos
lda StartX
lsr
jsr SetBG1XPos
; lda StartX
; lsr
; jsr SetBG1XPos
jsr DoFrame
jsr Render
pla
rts
@ -46,7 +46,7 @@ MoveUp
; lsr
; jsr SetBG1YPos
jsr DoFrame
jsr Render
rts
MoveDown
@ -58,11 +58,11 @@ MoveDown
lda #0
jsr SetBG0YPos
lda StartY
lsr
jsr SetBG1YPos
; lda StartY
; lsr
; jsr SetBG1YPos
jsr DoFrame
jsr Render
pla
rts
@ -108,7 +108,7 @@ Demo
; jsr MoveLeft
jsr UpdateBG1Rotation
; jsr DoColorCycle
jsr DoFrame
jsr Render
inc frameCount
@ -190,7 +190,7 @@ AngleUp
sbc #64
sta angle
jsr _ApplyAngle
jsr DoFrame
jsr Render
rts
AngleDown
@ -201,7 +201,7 @@ AngleDown
adc #64
sta angle
jsr _ApplyAngle
jsr DoFrame
jsr Render
rts
angle dw 0
@ -289,3 +289,8 @@ _DoTimers

View File

@ -118,15 +118,9 @@ NO_MUSIC equ 1 ; turn music + tool loading
jsr BlitInit ; Initialize the memory
jsr GrafInit ; Initialize the graphics screen
ldx #0 ; Gameboy Advance size
ldx #0 ;
jsr SetScreenMode
lda #0 ; Set the virtual Y-position
jsr SetBG0YPos
lda #0 ; Set the virtual X-position
jsr SetBG0XPos
jsr _InitBG1 ; Initialize the second background
lda #0
@ -141,9 +135,9 @@ NO_MUSIC equ 1 ; turn music + tool loading
sta BankLoad ; Store "Bank Pointer"
jsr MovePlayerToOrigin ; Put the player at the beginning of the map
lda #$FFFF ; Force a redraw of all the tiles
jsr _UpdateBG0TileMap
lda #DIRTY_BIT_BG0_REFRESH ; Redraw all of the tiles on the next Render
tsb DirtyBits
; jsr DoTiles
; jsr DoLoadBG1
@ -173,7 +167,7 @@ EvtLoop
:3 cmp #'f' ; render a 'f'rame
bne :4
jsr DoFrame
jsr Render
bra EvtLoop
:4 cmp #'h' ; Show the 'h'eads up display
@ -272,6 +266,7 @@ Fatal brk $00
MovePlayerToOrigin
lda #0 ; Set the player's position
jsr SetBG0XPos
lda TileMapHeight
asl
asl
@ -279,6 +274,7 @@ MovePlayerToOrigin
sec
sbc ScreenHeight
jsr SetBG0YPos
rts
ClearBankLoad
@ -415,13 +411,6 @@ DoTiles
pla
rts
; Set up the code field and render it
DoFrame
lda #$FFFF
sta DirtyBits
jsr Render ; Render the play field
rts
; Load a binary file in the BG1 buffer
DoLoadBG1
lda BankLoad
@ -924,9 +913,13 @@ BlitInit
stz ScreenTileHeight
stz ScreenTileWidth
stz StartX
stz OldStartX
stz StartXMod164
stz StartY
stz OldStartY
stz StartYMod208
stz EngineMode
stz DirtyBits
stz LastPatchOffset
@ -1272,6 +1265,7 @@ qtRec adrl $0000
put Actions.s
put font.s
put Render.s
put Overlay.s
put blitter/Blitter.s
put blitter/Horz.s
put blitter/PEISlammer.s
@ -1291,17 +1285,6 @@ qtRec adrl $0000

View File

@ -43,11 +43,12 @@ Addr2ToString xba
; A=Value
; X=Screen offset
DrawWord phx ; Save register value
phy
ldy #WordBuff+1
jsr WordToString
ply
plx
lda #WordBuff
ldy #$7777
jsr DrawString
rts
@ -145,6 +146,8 @@ Addr3Buff str '000000' ; str adds leading length byte

View File

@ -93,6 +93,12 @@ Render
; ldy #8
; jsr _PEISlam
; ldx #0 ; Blit the full virtual buffer to the screen
; ldy #16
; jsr _BltRange
; jsr Overlay
ldx #0 ; Blit the full virtual buffer to the screen
ldy ScreenHeight
jsr _BltRange
@ -101,6 +107,12 @@ Render
ldx ScreenHeight
jsr _RestoreBG0Opcodes
lda StartY
sta OldStartY
lda StartX
sta OldStartX
stz DirtyBits
rts
@ -112,3 +124,10 @@ Render

View File

@ -10,6 +10,17 @@
; in actual games since the primary background is often large empty areas, or runs
; of repeating tiles.
; Debug locations
LastTop ds 2
LastBottom ds 2
LastLeft ds 2
LastRight ds 2
; The ranges are [:Left, :Right] and [:Top, :Bottom], so :Right can be, at most, 40
; if we are drawing all 41 tiles (Index 0 through 40). The :Bottom value can be
; at most 25.
MAX_TILE_X equ 40
MAX_TILE_Y equ 25
; _UpdateBG0TileMap
;
@ -38,35 +49,24 @@ _UpdateBG0TileMap
:BlkX equ tmp12
:BlkY equ tmp13
:Refresh equ tmp14
cmp #$FFFF
lda #0
rol
sta :Refresh ; 1 if A = $FFFF, 0 otherwise
lda StartY ; calculate the tile index of the current location
and #$FFF8
lsr
lsr
lsr
sta BG0TileOriginY
lda OldStartY
and #$FFF8
lsr
lsr
lsr
sta OldBG0TileOriginY
lda StartX
and #$FFFC
lsr
lsr
sta BG0TileOriginX
lda OldStartX
and #$FFFC
lsr
lsr
sta OldBG0TileOriginX
@ -94,22 +94,18 @@ _UpdateBG0TileMap
stz :Left ; prepare to do the entire screen
lda ScreenTileWidth ; and then whack off the parts
sta :Right ; that are not needed
lda StartX
and #$0003 ; If not tile-aligned, then we need to draw one extra column
beq *+2
inc :Right
stz :Top
lda ScreenTileHeight
sta :Bottom
and #$0007
beq *+2
inc :Bottom
stz :Top ; since the ranges are inclusive, we are
lda ScreenTileHeight ; always going to be drawing width+1 tiles
sta :Bottom ; which takes care of edge tiles.
; If we are supposed to refresh the whole field, just do that and return
lda :Refresh
lda #DIRTY_BIT_BG0_REFRESH
bit DirtyBits
beq :NoRefresh
jmp :DrawRectBG0 ; Let the DrawRectBG0 RTS take care of the return for us
trb DirtyBits ; Clear the dirty bit
:FullScreen jmp :DrawRectBG0 ; Let the DrawRectBG0 RTS take care of the return for us
:NoRefresh
lda BG0TileOriginY
@ -121,14 +117,18 @@ _UpdateBG0TileMap
bpl :DoBottom ; if we scrolled up, fill in the bottom row(s)
eor #$FFFF ; if we scrolled down, Y_new < Y_old and we need
sta :Bottom ; to fill in the top row(s) from 0 to Y_new - Y_old - 1
cmp :Bottom ; to fill in the top row(s) from 0 to Y_new - Y_old - 1
bcs :FullScreen ; If the displacement was very large, just fill in the whole screen
sta :Bottom
bra :DoYUpdate
:DoBottom
eor #$FFFF ; same explanation as above, except we are filling in from
inc a ; Bottom - (Y_new - Y_old) to Bottom
inc ; Bottom - (Y_new - Y_old) to Bottom
clc
adc ScreenTileHeight
bmi :FullScreen
sta :Top
:DoYUpdate
@ -155,14 +155,14 @@ _UpdateBG0TileMap
lda :Top
beq :drewTop
dec a ; already did Y to HEIGHT, so only need to draw from
dec ; already did Y to HEIGHT, so only need to draw from
sta :Bottom ; 0 to (Y-1) for any horizontal updates
stz :Top
bra :NoYUpdate
:drewTop
lda :Bottom ; opposite, did 0 to Y
inc a ; so do Y+1 to HEIGHT
inc ; so do Y+1 to HEIGHT
sta :Top
lda ScreenTileHeight
sta :Bottom
@ -197,6 +197,8 @@ _UpdateBG0TileMap
; Handle the two sides in an analagous way as the vertical code
eor #$FFFF
cmp :Right
bcs :FullScreen
sta :Right
bra :DoXUpdate
@ -205,6 +207,7 @@ _UpdateBG0TileMap
inc
clc
adc ScreenTileWidth
bmi :FullScreen
sta :Left
:DoXUpdate
@ -213,25 +216,32 @@ _UpdateBG0TileMap
:NoXUpdate
rts
;:Debug
; lda :Top ; Debugging
; sta LastTop
; lda :Bottom
; sta LastBottom
; lda :Left
; sta LastLeft
; lda :Right
; sta LastRight
; rts
; This is a private subroutine that draws in tiles into the code fields using the
; data from the tilemap and the local :Top, :Left, :Bottom and :Right parameters.
;
; The ranges are [:Left, :Right) and [:Top, :Bottom), so :Right can be, at most, 41
; if we are drawing all 41 tiles (Index 0 through 40). The :Bottom value can be
; at most 26.
MAX_TILE_X equ 40
MAX_TILE_Y equ 25
:DrawRectBG0
lda :Bottom
sec
sbc :Top
sta :Height ; Maximum value of 25
inc
sta :Height ; Maximum value of 26 (top = 0, bottom = 25)
lda :Right
sec
sbc :Left
sta :Width ; Maximum value of 40
inc
sta :Width ; Maximum value of 41 (left = 0, right = 40)
; Compute the offset into the tile array of the top-left corner
@ -252,6 +262,7 @@ MAX_TILE_Y equ 25
asl ; Double for word sizes
sta :Offset ; Stash the pointer offset in Y
; Draw the tiles
lda TileMapWidth
sec
sbc :Width
@ -269,6 +280,9 @@ MAX_TILE_Y equ 25
lsr ; Could optimize because the Tile code shifts back....
clc
adc :Top
cmp #MAX_TILE_Y+1 ; Top can be less than or equal to 25
bcc *+5
sbc #MAX_TILE_Y+1
sta :BlkY ; This is the Y-block we start drawing from
lda StartXMod164 ; Dx the same thing for X, except only need to clamp by 4
@ -277,9 +291,11 @@ MAX_TILE_Y equ 25
lsr
clc
adc :Left
cmp #MAX_TILE_X+1 ; Left can be less than or equal to 40
bcc *+5
sbc #MAX_TILE_X+1
sta :BlkX
; Call the copy tile routine to blit the tile data into the playfield
;
; A = Tile ID (0 - 1023)
@ -302,7 +318,7 @@ MAX_TILE_Y equ 25
lda :BlkX
inc
cmp #MAX_TILE_X+1 ; If we go past the physical block index, wrap around
cmp #MAX_TILE_X+1 ; If we go past the maximum block index, wrap around
bcc *+5
lda #0
sta :BlkX
@ -321,7 +337,7 @@ MAX_TILE_Y equ 25
lda 1,s ; Reset the width
sta :Width
lda :BlkY ; The y lookup has a double0length array, may not need the bounds check
lda :BlkY ; The y lookup has a double-length array, may not need the bounds check
inc
cmp #MAX_TILE_Y+1
bcc *+5
@ -336,7 +352,6 @@ MAX_TILE_Y equ 25
rts
; Quick multiplication of the accumulator and x-register
; A = A * X
:MulAX
@ -388,6 +403,60 @@ MAX_TILE_Y equ 25

View File

@ -79,3 +79,6 @@ DIRTY_BIT_BG0_X equ $0001
DIRTY_BIT_BG0_Y equ $0002
DIRTY_BIT_BG1_X equ $0004
DIRTY_BIT_BG1_Y equ $0008
DIRTY_BIT_BG0_REFRESH equ $0010
DIRTY_BIT_BG1_REFRESH equ $0020

View File

@ -42,6 +42,7 @@ CopyTile
asl ; asl will clear the carry bit
tax
lda Col2CodeOffset,x
clc
adc BTableLow,y
tay
@ -239,3 +240,9 @@ CopyTile

View File

@ -37,6 +37,7 @@ DrawString
NextChar lda ]F_CharIdx
cmp ]F_Length
bne :notDone
ldy ]F_StrClr ;restore the color pattern
pld
pla
pla
@ -662,5 +663,6 @@ s_Template hex 00000000