Fresh rom2 that does not have the RenderArea bug

This commit is contained in:
Lucas Scharenbroich 2023-05-24 14:31:49 -05:00
parent 6c5bf4e494
commit aa684ef58c
6 changed files with 16703 additions and 84 deletions

View File

@ -52,6 +52,11 @@ DrawWord phx ; Save register value
jsr DrawString jsr DrawString
rts rts
ClearWord lda #EmptyBuff
jsr DrawString
rts
EmptyBuff str ' '
WordBuff str '0000' WordBuff str '0000'
Addr3Buff str '000000' ; str adds leading length byte Addr3Buff str '000000' ; str adds leading length byte

View File

@ -12,7 +12,7 @@
; Segment #2 -- ROM ; Segment #2 -- ROM
ASM rom.s ASM rom2.s
KND #$1100 KND #$1100
SNA SMBROM SNA SMBROM

View File

@ -16,8 +16,9 @@ UP_ARROW equ $0B
DOWN_ARROW equ $0A DOWN_ARROW equ $0A
; Nametable queue ; Nametable queue
NT_QUEUE_SIZE equ $1000 NT_QUEUE_LEN equ $1000
NT_QUEUE_MOD equ {{2*NT_QUEUE_SIZE}-1} NT_QUEUE_SIZE equ {2*NT_QUEUE_LEN}
NT_QUEUE_MOD equ {NT_QUEUE_SIZE-1}
mx %00 mx %00
@ -33,6 +34,7 @@ ROMScrollEdge equ 16
ROMScrollDelta equ 18 ROMScrollDelta equ 18
OldROMScrollEdge equ 20 OldROMScrollEdge equ 20
CurrScrollEdge equ 22 CurrScrollEdge equ 22
CurrNTQueueEnd equ 40
Tmp0 equ 240 Tmp0 equ 240
Tmp1 equ 242 Tmp1 equ 242
@ -162,9 +164,6 @@ EvtLoop
beq :spin beq :spin
stz nmiCount stz nmiCount
; lda #$0400
; stal ROMBase+$75F
; The GTE playfield is 41 tiles wide, but the NES is 32 tiles wide. Fortunately, the game ; 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 ; keeps track of the global coordinates of each level at
; ;
@ -177,53 +176,35 @@ EvtLoop
; 1. When new column(s) are exposed, set the tiles directly from the PPU nametable memory ; 1. When new column(s) are exposed, set the tiles directly from the PPU nametable memory
; 2. When the PPU nametable memory is updated in an area that is already on-screen, set the tile ; 2. When the PPU nametable memory is updated in an area that is already on-screen, set the tile
; Get the current global coordinates lda singleStepMode
bne :skip_render
jsr RenderFrame
:skip_render
sei lda lastKey
lda ROMScrollEdge ; This is set in the VBL IRQ
sta CurrScrollEdge ; Freeze it, then we can let the IRQs continue
cli
lsr bit #PAD_KEY_DOWN
lsr beq EvtLoop
lsr
sta ROMScreenEdge
; Calculate how many blocks have been scrolled into view
lda CurrScrollEdge
sec
sbc OldROMScrollEdge
sta Tmp1 ; This is the raw number of pixels moved
lda OldROMScrollEdge ; This is the number of partial pixels the old scroll position occupied
and #7
sta Tmp0
lda #7
sec
sbc Tmp0 ; This account for situations where going from 8 -> 9 reveals a new column
clc
adc Tmp1
lsr
lsr
lsr
sta ROMScrollDelta ; This many columns have been revealed
lda CurrScrollEdge
sta OldROMScrollEdge ; Stash a copy for the next round through
lsr
pha
pea $0000
_GTESetBG0Origin
pea $FFFF ; NES mode
_GTERender
pha
_GTEReadControl
pla
and #$007F and #$007F
; Put the game in single-step mode
cmp #'s'
bne :not_s
lda #1 ; Stop the VBL interrupt from running the game logic
sta singleStepMode
jsr triggerNMI
jsr RenderFrame
brl EvtLoop
:not_s
cmp #'g' ; Re-enable VBL-drive game logic
bne :not_g
stz singleStepMode
:not_g
cmp #'r' ; Refresh cmp #'r' ; Refresh
bne :not_1 bne :not_1
jsr CopyStatus jsr CopyStatus
@ -262,9 +243,60 @@ Greyscale dw $0000,$5555,$AAAA,$FFFF
dw $0000,$5555,$AAAA,$FFFF dw $0000,$5555,$AAAA,$FFFF
dw $0000,$5555,$AAAA,$FFFF dw $0000,$5555,$AAAA,$FFFF
lastKey dw 0
singleStepMode dw 0
nmiCount dw 0 nmiCount dw 0
DPSave dw 0 DPSave dw 0
; Helper to perform the essential functions of rendering a frame
RenderFrame
; Get the current global coordinates
sei
lda nt_queue_end
sta CurrNTQueueEnd
lda ROMScrollEdge ; This is set in the VBL IRQ
sta CurrScrollEdge ; Freeze it, then we can let the IRQs continue
cli
lsr
lsr
lsr
sta ROMScreenEdge
; Calculate how many blocks have been scrolled into view
lda CurrScrollEdge
sec
sbc OldROMScrollEdge
sta Tmp1 ; This is the raw number of pixels moved
lda OldROMScrollEdge ; This is the number of partial pixels the old scroll position occupied
and #7
sta Tmp0
lda #7
sec
sbc Tmp0 ; This account for situations where going from 8 -> 9 reveals a new column
clc
adc Tmp1
lsr
lsr
lsr
sta ROMScrollDelta ; This many columns have been revealed
lda CurrScrollEdge
sta OldROMScrollEdge ; Stash a copy for the next round through
lsr
pha
pea $0000
_GTESetBG0Origin
pea $FFFF ; NES mode
_GTERender
rts
; Take a PPU address and convert it to a tile store coordinate ; Take a PPU address and convert it to a tile store coordinate
; ;
; Inputs ; Inputs
@ -350,14 +382,19 @@ PPUAddrToTileStore
; If there is some other reason to draw the full screen, this will empty the queue ; If there is some other reason to draw the full screen, this will empty the queue
ClearNTQueue ClearNTQueue
stz nt_queue_front ; stz nt_queue_front
stz nt_queue_end ; stz nt_queue_end
lda CurrNTQueueEnd
sta nt_queue_front
rts rts
; Scan through the queue of tiles that need to be updated before applying the scroll change ; Scan through the queue of tiles that need to be updated before applying the scroll change
DrainNTQueue DrainNTQueue
:GTELeftEdge equ Tmp3 :GTELeftEdge equ Tmp3
:PPUAddr equ Tmp4 :PPUAddr equ Tmp4
:Count equ Tmp5
stz :Count
; Prep item -- get the logical block of the left edge of the scroll window ; Prep item -- get the logical block of the left edge of the scroll window
@ -366,7 +403,7 @@ DrainNTQueue
sta :GTELeftEdge sta :GTELeftEdge
lda nt_queue_front lda nt_queue_front
cmp nt_queue_end cmp CurrNTQueueEnd
beq :out beq :out
:loop :loop
@ -393,7 +430,6 @@ DrainNTQueue
sbc #41 sbc #41
:toprow :toprow
pha ; Tile Store horizontal tile coordinate pha ; Tile Store horizontal tile coordinate
phy ; No translation needed for y phy ; No translation needed for y
ldx :PPUAddr ldx :PPUAddr
@ -402,17 +438,24 @@ DrainNTQueue
ora #$0100 ora #$0100
pha pha
_GTESetTile _GTESetTile
inc :Count
:skip :skip
pla ; Pop the saved x-register into the accumulator pla ; Pop the saved x-register into the accumulator
inc inc
inc inc
and #NT_QUEUE_MOD and #NT_QUEUE_MOD
cmp nt_queue_end cmp CurrNTQueueEnd
bne :loop bne :loop
:out :out
sta nt_queue_front sta nt_queue_front
; lda :Count
; ldx #8*160
; ldy #$FFFF
; jsr DrawWord
rts rts
; Copy the necessary columns into the TileStore when setting a new scroll position ; Copy the necessary columns into the TileStore when setting a new scroll position
@ -437,6 +480,75 @@ UpdateFromPPU
lsr lsr
sta TileX ; Tile column of playfield origin sta TileX ; Tile column of playfield origin
; Debug the PPU writes
* ldy #0
* ldx #0
* lda #0
* :log_loop
* phy
* pha
* cpy ppu_write_log_len
* bcc :write_val
* pha
* tax
* ldy #$FFFF
* jsr ClearWord
* pla
* clc
* adc #160-16
* tax
* jsr ClearWord
* bra :next
* :write_val
* pha
* phy
* tax
* lda ppu_write_log,y
* ldy #$FFFF
* jsr DrawWord
* ply
* pla
* clc
* adc #160-16
* tax
* lda ppu_write_log+50,y
* ldy #$FFFF
* jsr DrawWord
* :next pla
* ply
* iny
* iny
* clc
* adc #8*160
* cpy #50
* bcc :log_loop
* stz ppu_write_log_len
; Show the queue depth
; lda CurrNTQueueEnd
; sec
; sbc nt_queue_front
; bpl *+5
; adc #NT_QUEUE_SIZE
; lsr ; Number of items in the queue
; ldx #0
; ldy #$FFFF
; jsr DrawWord
; Check the scroll delta, if it's negative or just large enough, do a whole copy of the current PPU ; Check the scroll delta, if it's negative or just large enough, do a whole copy of the current PPU
; memory into the TileStore ; memory into the TileStore
@ -646,7 +758,19 @@ triggerNMI
stal ppustatus stal ppustatus
ldx #NonMaskableInterrupt ldx #NonMaskableInterrupt
jmp romxfer jsr romxfer
; Immediately after the NMI returns, freeze some of the global state variables so we can sync up with this frame when
; we render the next frame. Since we're in an interrupt handler here, sno change of the variables changing under
; our nose
sep #$20
ldal ROMBase+$071a
xba
ldal ROMBase+$071c
rep #$20
sta ROMScrollEdge
:skip rts :skip rts
; Expose joypad bits from GTE to the ROM: A-B-Select-Start-Up-Down-Left-Right ; Expose joypad bits from GTE to the ROM: A-B-Select-Start-Up-Down-Left-Right
@ -985,18 +1109,11 @@ nmiTask
tcd tcd
jsr readInput jsr readInput
ldal singleStepMode
bne :no_nmi
jsr triggerNMI jsr triggerNMI
:no_nmi
; Immediately after the NMI returns, freeze some of the global state variables so we can sync up with this frame when
; we render the next frame. Since we're in an interrupt handler here, sno change of the variables changing under
; our nose
sep #$20
ldal ROMBase+$071a
xba
ldal ROMBase+$071c
rep #$20
sta ROMScrollEdge
pld pld
plb plb
@ -1009,6 +1126,7 @@ readInput
pha pha
_GTEReadControl _GTEReadControl
pla pla
stal lastKey ; Cache for other code
; Map the GTE field to the NES controller format: A-B-Select-Start-Up-Down-Left-Right ; Map the GTE field to the NES controller format: A-B-Select-Start-Up-Down-Left-Right

View File

@ -27,7 +27,8 @@ rep8 mac
mx %11 mx %11
dw $a5a5 ; marker to find in memory dw $a5a5 ; marker to find in memory
ppuaddr ds 2 ; 16-bit ppu address ppuaddr ENT
ds 2 ; 16-bit ppu address
w_bit dw 1 ; currently writing to high or low to the address latch w_bit dw 1 ; currently writing to high or low to the address latch
vram_buff dw 0 ; latched data when reading VRAM ($0000 - $3EFF) vram_buff dw 0 ; latched data when reading VRAM ($0000 - $3EFF)
@ -70,6 +71,7 @@ cond_s sta ]4
PPUCTRL_WRITE ENT PPUCTRL_WRITE ENT
php php
phb phb
phk phk
plb plb
@ -185,6 +187,10 @@ PPUADDR_WRITE ENT
eor #$01 eor #$01
sta w_bit sta w_bit
lda ppuaddr+1 ; Stay within the mirrored memory space
and #$3F
sta ppuaddr+1
pla pla
plx plx
plb plb
@ -210,6 +216,7 @@ PPUDATA_READ ENT
clc clc
adc ppuincr adc ppuincr
and #$3FFF
sta ppuaddr sta ppuaddr
sep #$20 ; back to 8-bit acc for the read itself sep #$20 ; back to 8-bit acc for the read itself
@ -236,6 +243,11 @@ PPUDATA_READ ENT
pla pla
rtl rtl
ppu_write_log_len dw 0
ppu_write_log ds 100 ; record the first 50 PPU write addresses in each frame
nt_queue_front dw 0 nt_queue_front dw 0
nt_queue_end dw 0 nt_queue_end dw 0
nt_queue ds 2*{NT_QUEUE_SIZE} nt_queue ds 2*{NT_QUEUE_SIZE}
@ -250,6 +262,36 @@ PPUDATA_WRITE ENT
rep #$10 rep #$10
ldx ppuaddr ldx ppuaddr
* cpx #$3F00 ; Just log nametable access, not palette info
* bcs :nolog
* phy
* pha
* ldy ppu_write_log_len
* cpy #50
* bcs :log_full
* rep #$20
* txa
* sta ppu_write_log,y
* lda 1,s
* and #$00FF
* sta ppu_write_log+50,y
* iny
* iny
* sty ppu_write_log_len
* sep #$20
* :log_full
* pla
* ply
* :nolog
; cmp #$47
; bne :nobrk
; cpx #$2308
; bne :nobrk
; brk $FD
;:nobrk
cmp PPU_MEM,x cmp PPU_MEM,x
beq :nochange beq :nochange
@ -259,6 +301,7 @@ PPUDATA_WRITE ENT
txa txa
clc clc
adc ppuincr adc ppuincr
and #$3FFF
sta ppuaddr sta ppuaddr
; Anything between $2000 and $3000, we need to add to the queue. We can't reject updates here because we may not ; Anything between $2000 and $3000, we need to add to the queue. We can't reject updates here because we may not
@ -267,7 +310,7 @@ PPUDATA_WRITE ENT
cpx #$3000 cpx #$3000
bcs :nocache bcs :nocache
cpx #$2000 cpx #$2000 ; Change to $2080 to ignore score field updates
bcc :nocache bcc :nocache
phy phy
@ -298,6 +341,7 @@ PPUDATA_WRITE ENT
txa txa
clc clc
adc ppuincr adc ppuincr
and #$3FFF
sta ppuaddr sta ppuaddr
:done :done
@ -318,6 +362,7 @@ setborder
stal $E0C034 stal $E0C034
plp plp
rts rts
; Do some extra work to keep palette data in sync ; Do some extra work to keep palette data in sync
; ;
; Based on the palette data that SMB uses, we map the NES palette entries as ; Based on the palette data that SMB uses, we map the NES palette entries as
@ -538,7 +583,11 @@ PPUDMA_WRITE ENT
plp plp
rtl rtl
y_offset equ 16 y_offset_rows equ 2
y_height_rows equ 25
y_offset equ {y_offset_rows*8}
y_height equ {y_height_rows*8}
x_offset equ 16 x_offset equ 16
; Scan the OAM memory and copy the values of the sprites that need to be drawn. There are two reasons to do this ; Scan the OAM memory and copy the values of the sprites that need to be drawn. There are two reasons to do this
@ -560,9 +609,9 @@ scanOAMSprites
:loop :loop
lda PPU_OAM,x ; Y-coordinate lda PPU_OAM,x ; Y-coordinate
cmp #200+y_offset-9 cmp #y_height+y_offset-9
bcs :skip bcs :skip
cmp #16 cmp #y_offset
bcc :skip bcc :skip
lda PPU_OAM+1,x ; $FC is an empty tile, don't draw it lda PPU_OAM+1,x ; $FC is an empty tile, don't draw it
@ -731,16 +780,16 @@ drawShadowList
lda shadowListBot,x lda shadowListBot,x
and #$00FF and #$00FF
tay tay
cpy #201 ; cpy #201
bcc *+4 ; bcc *+4
brk $cc ; brk $cc
lda shadowListTop,x lda shadowListTop,x
and #$00FF and #$00FF
tax tax
cpx #200 ; cpx #200
bcc *+4 ; bcc *+4
brk $dd ; brk $dd
lda #0 ; Invoke the BltRange function lda #0 ; Invoke the BltRange function
jsl LngJmp jsl LngJmp
@ -804,7 +853,7 @@ exposeShadowList
:exit :exit
ldx :last ; Expose the final part ldx :last ; Expose the final part
ldy #200 ldy #y_height
lda #0 lda #0
jsl LngJmp jsl LngJmp
rts rts
@ -817,7 +866,7 @@ shadowBitmapToList
sep #$30 sep #$30
ldx #2 ; Start at he third row (y_offset = 16) walk the bitmap for 25 bytes (200 lines of height) ldx #y_offset_rows ; Start at he third row (y_offset = 16) walk the bitmap for 25 bytes (200 lines of height)
lda #0 lda #0
sta shadowListCount ; zero out the shadow list count sta shadowListCount ; zero out the shadow list count
@ -826,7 +875,7 @@ shadowBitmapToList
ldy shadowBitmap,x ldy shadowBitmap,x
beq :zero_next beq :zero_next
lda mul8-2,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 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 sta :top
@ -834,7 +883,7 @@ shadowBitmapToList
:zero_next :zero_next
inx inx
cpx #28 ; End at byte 27 cpx #y_height_rows+y_offset_rows+1 ; End at byte 27
bcc :zero_loop bcc :zero_loop
bra :exit ; ended while not tracking a sprite, so exit the function bra :exit ; ended while not tracking a sprite, so exit the function
@ -844,7 +893,7 @@ shadowBitmapToList
beq :one_next beq :one_next
tay ; Use the inverted bitfield in order to re-use the same lookup table tay ; Use the inverted bitfield in order to re-use the same lookup table
lda mul8-2,x lda mul8-y_offset_rows,x
clc clc
adc offset,y adc offset,y
@ -858,7 +907,7 @@ shadowBitmapToList
:one_next :one_next
inx inx
cpx #28 cpx #y_height_rows+y_offset_rows+1
bcc :one_loop bcc :one_loop
; If we end while tracking a sprite, add to the list as the last item ; If we end while tracking a sprite, add to the list as the last item
@ -866,7 +915,7 @@ shadowBitmapToList
ldx shadowListCount ldx shadowListCount
lda :top lda :top
sta shadowListTop,x sta shadowListTop,x
lda #200 lda #y_height
sta shadowListBot,x sta shadowListBot,x
inx inx
stx shadowListCount stx shadowListCount

View File

@ -44,7 +44,7 @@ JOYPAD_PORT1 = $4016
JOYPAD_PORT2 = $4017 JOYPAD_PORT2 = $4017
GTE_TMP = $10 ; No zero page references in the assembly to this location GTE_TMP = $10 ; No zero page references in the assembly to this location
;GTE_TMP = $7000 ; No zero page references in the assembly to this location
; GAME SPECIFIC DEFINES ; GAME SPECIFIC DEFINES
ObjectOffset = $08 ObjectOffset = $08

16447
demos/smb/rom2.s Normal file

File diff suppressed because it is too large Load Diff