Fix rendering bug that cause flicker when two sprites shared a block row

This commit is contained in:
Lucas Scharenbroich 2023-06-07 23:42:48 -05:00
parent b45d2e27bf
commit ef581ab97b
4 changed files with 156 additions and 33 deletions

View File

@ -184,26 +184,26 @@ FTblTmp equ 228
;AreaNumber = $0760
;OffScr_WorldNumber = $0766
;OffScr_AreaNumber = $0767
; OffScr_LevelNumber = $0763
;OffScr_LevelNumber = $0763
EvtLoop
:spin lda nmiCount
beq :spin
stz nmiCount
sep #$20
lda #1
stal ROMBase+$075f
stal ROMBase+$0766
; sep #$20
; lda #1
; stal ROMBase+$075f
; stal ROMBase+$0766
lda #1
stal ROMBase+$0763
stal ROMBase+$075c
; lda #2
; stal ROMBase+$0763
; stal ROMBase+$075c
lda #2
stal ROMBase+$0767
stal ROMBase+$0760
rep #$30
; lda #$2
; stal ROMBase+$0767
; stal ROMBase+$0760
; rep #$30
; The GTE playfield is 41 tiles wide, but the NES is 32 tiles wide. Fortunately, the game
; keeps track of the global coordinates of each level at

View File

@ -730,7 +730,7 @@ buildShadowBitmap
ldy OAM_COPY,x
iny ; This is the y-coordinate of the top of the sprite
ldx y2idx,y ; Get the index into the shadowBitmap array for this y coordinate
ldx y2idx,y ; Get the index into the shadowBitmap array for this y coordinate (y -> blk_y)
lda y2low,y ; Get the bit pattern for the first byte
ora shadowBitmap,x
sta shadowBitmap,x
@ -750,6 +750,34 @@ buildShadowBitmap
rep #$30
rts
; Set the SCB values equal to the bitmap to visually debug
ldx #0
ldy #0
:vloop
lda #8
sta Tmp6
lda shadowBitmap+2,y
:iloop
asl
pha
lda #0
bcc :zero
inc
:zero stal $E19D00,x
pla
inx
dec Tmp6
bne :iloop
iny
cpy #25
bcc :vloop
rep #$30
rts
y2idx const32 $00
const32 $04
const32 $08
@ -777,14 +805,48 @@ mul8 db $00,$08,$10,$18,$20,$28,$30,$38
db $C0,$C8,$D0,$D8,$E0,$E8,$F0,$F8
; Given a bit pattern, create a LUT that count to the first set bit (MSB -> LSB), e.g. $0F = 4, $3F = 2
offset db 0,7,6,6,5,5,5,5,4,4,4,4,4,4,4,4,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3 ; 0, 1, 2, 4, 8, 16
db 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2 ; 32
offset
db 8,7,6,6,5,5,5,5,4,4,4,4,4,4,4,4,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3
db 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2
db 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
db 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
invOffset
db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
db 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
db 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
db 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2
db 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,6,6,7,8
; Mask off all of the high 1 bits, keep all of the low bits after the first zero, e.g.
; offsetMask($E3) = offsetMask(11100011) = $1F. %11100011 & $1F = $03
offsetMask
db $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
db $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
db $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
db $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
db $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
db $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
db $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
db $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF ; 127 (everything here has a 0 in the high bit)
db $7F,$7F,$7F,$7F,$7F,$7F,$7F,$7F,$7F,$7F,$7F,$7F,$7F,$7F,$7F,$7F ; $80 - $8F
db $7F,$7F,$7F,$7F,$7F,$7F,$7F,$7F,$7F,$7F,$7F,$7F,$7F,$7F,$7F,$7F ; $90 - $9F
db $7F,$7F,$7F,$7F,$7F,$7F,$7F,$7F,$7F,$7F,$7F,$7F,$7F,$7F,$7F,$7F ; $A0 - $AF
db $7F,$7F,$7F,$7F,$7F,$7F,$7F,$7F,$7F,$7F,$7F,$7F,$7F,$7F,$7F,$7F ; $B0 - $BF
db $3F,$3F,$3F,$3F,$3F,$3F,$3F,$3F,$3F,$3F,$3F,$3F,$3F,$3F,$3F,$3F ; $C0 - $CF
db $3F,$3F,$3F,$3F,$3F,$3F,$3F,$3F,$3F,$3F,$3F,$3F,$3F,$3F,$3F,$3F ; $D0 - $DF
db $1F,$1F,$1F,$1F,$1F,$1F,$1F,$1F,$1F,$1F,$1F,$1F,$1F,$1F,$1F,$1F ; $E0 - $EF
db $0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F,$07,$07,$07,$07,$03,$03,$01,$00 ; $F0 - $FF
; Scan the bitmap list and call BltRange on the ranges
mx %00
@ -880,8 +942,9 @@ exposeShadowList
; This routine needs to adjust the y-coordinates based of the offset of the GTE playfield within
; the PPU RAM
shadowBitmapToList
:top equ Tmp0
:bottom equ Tmp2
:top equ Tmp0
:bottom equ Tmp2
:bitfield equ Tmp4
sep #$30
@ -894,9 +957,9 @@ shadowBitmapToList
ldy shadowBitmap,x
beq :zero_next
lda mul8-y_offset_rows,x ; This is the scanline we're on (offset by the starting byte)
lda {mul8-y_offset_rows},x ; This is the scanline we're on (offset by the starting byte)
clc
adc offset,y ; This is the first line defined by the bit pattern
adc offset,y ; This is the first line defined by the bit pattern
sta :top
bra :one_next
@ -908,13 +971,19 @@ shadowBitmapToList
:one_loop
lda shadowBitmap,x ; if the next byte is all sprite, just continue
eor #$FF
cmp #$FF
beq :one_next
tay ; Use the inverted bitfield in order to re-use the same lookup table
lda mul8-y_offset_rows,x
; The byte has to look like 1...10...0*. The first step is to mask off the high bits and store the result
; back into the shadowBitmap
tay
and offsetMask,y
sta shadowBitmap,x
lda {mul8-y_offset_rows},x
clc
adc offset,y
adc invOffset,y
ldy shadowListCount
sta shadowListBot,y
@ -922,7 +991,11 @@ shadowBitmapToList
sta shadowListTop,y
iny
sty shadowListCount
bra :zero_next
; Loop back to check if there is more sprite data on this byte
bra :zero_loop
:one_next
inx
@ -1015,7 +1088,7 @@ drawOAMSprites
cli
jsr buildShadowBitmap ; Run though and quickly create a bitmap of lines with sprites
jsr shadowBitmapToList ; Can the bitmap and create (top, bottom) pairs of ranges
jsr shadowBitmapToList ; Scan the bitmap and create (top, bottom) pairs of ranges
jsr drawShadowList ; Draw the background lines that have sprite on them
jsr drawSprites ; Draw the sprites on top of the lines they occupy

View File

@ -682,14 +682,16 @@ PPUDATA_READ EXT
PPUDATA_WRITE EXT
PPUDMA_WRITE EXT
APU_PUSLE1_REG1_WRITE EXT
APU_PUSLE1_REG2_WRITE EXT
APU_PUSLE1_REG3_WRITE EXT
APU_PUSLE1_REG4_WRITE EXT
ROMBase ENT
ds $7A00
; Macro to replace sta abs,y instructions that access zero page space with direct page
; instruction to actually get the correct data on the direct page _and_ bank memory.
; That way any lda 00,x or lda 0000,y will
; Hooks to call back to the GTE harness for PPU memory-mapped accesses
; Define a helper for the ROM InitializeMemory routine to properly deal with the
; direct page and stack being in a different bank
mx %11
GteInitMem
php
@ -703,6 +705,53 @@ GteLoop
plp
rts
; Hooks to call back to the GTE harness for APU register access
APU_IND_X_REG3_W
; x is 0, 4 or 8 -- dispatch to the correct underlying routine
jmp (:reg_tbl,x)
:reg_tbl dw APU_PULSE1_REG3_W,APU_PULSE1_REG3_W
dw APU_PULSE2_REG3_W,APU_PULSE2_REG3_W,
dw APU_TRIANGLE_REG3_W,APU_TRIANGLE_REG3_W
APU_IND_X_REG4_W
jmp (:reg_tbl,x)
:reg_tbl dw APU_PULSE1_REG4_W,APU_PULSE1_REG4_W
dw APU_PULSE2_REG4_W,APU_PULSE2_REG4_W,
dw APU_TRIANGLE_REG4_W,APU_TRIANGLE_REG4_W
APU_PULSE1_REG1_W
; jsl APU_PULSE1_REG1_WRITE
rts
APU_PULSE1_REG1_WX
; jsl APU_PULSE1_REG1_WRITE
rts
APU_PULSE1_REG2_W
; jsl APU_PULSE1_REG2_WRITE
rts
APU_PULSE1_REG2_WY
; jsl APU_PULSE1_REG2_WRITE
rts
APU_PULSE1_REG3_W
; jsl APU_PULSE1_REG3_WRITE
rts
APU_PULSE1_REG4_W
; jsl APU_PULSE1_REG4_WRITE
rts
APU_PULSE2_REG3_W
; jsl APU_PUSLE2_REG3_WRITE
rts
APU_PULSE2_REG4_W
; jsl APU_PULSE2_REG4_WRITE
rts
APU_TRIANGLE_REG3_W
; jsl APU_TRIANGLE_REG3_WRITE
rts
APU_TRIANGLE_REG4_W
; jsl APU_TRIANGLE_REG4_WRITE
rts
; Hooks to call back to the GTE harness for PPU memory-mapped accesses
mx %11
PPU_CTRL_W
jsl PPUCTRL_WRITE
@ -4466,7 +4515,7 @@ AreaDataOfsLoopback
LoadAreaPointer
jsr FindAreaPointer ;find it and store it here
sta AreaPointer
GetAreaType and #%01100000 ;mask out all but d6 and d5
GetAreaType and #%01100000 ;mask out all but d6 and d5
asl
rol
rol
@ -4516,7 +4565,7 @@ GetAreaDataAddrs
bcc StoreFore
sta BackgroundColorCtrl ;if 4 or greater, save value here as bg color control
lda #$00
StoreFore sta ForegroundScenery ;if less, save value here as foreground scenery
StoreFore sta ForegroundScenery ;if less, save value here as foreground scenery
pla ;pull byte from stack and push it back
pha
and #%00111000 ;save player entrance control bits
@ -4554,7 +4603,7 @@ StoreFore sta ForegroundScenery ;if less, save value here as foreground scen
bne StoreStyle ;and nullify other value
sta CloudTypeOverride ;otherwise store value in other place
lda #$00
StoreStyle sta AreaStyle
StoreStyle sta AreaStyle
lda AreaDataLow ;increment area data address by 2 bytes
clc
adc #$02

View File

@ -189,6 +189,7 @@ vblCallback equ $0004
extSpriteRenderer equ $0005
rawDrawTile equ $0006
extBG0TileUpdate equ $0007
userTileCallback equ $0008
; CopyPicToBG1 flags
COPY_PIC_NORMAL equ $0000 ; Copy into BG1 buffer in "normal mode"