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
rts
ClearWord lda #EmptyBuff
jsr DrawString
rts
EmptyBuff str ' '
WordBuff str '0000'
Addr3Buff str '000000' ; str adds leading length byte

View File

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

View File

@ -16,8 +16,9 @@ UP_ARROW equ $0B
DOWN_ARROW equ $0A
; Nametable queue
NT_QUEUE_SIZE equ $1000
NT_QUEUE_MOD equ {{2*NT_QUEUE_SIZE}-1}
NT_QUEUE_LEN equ $1000
NT_QUEUE_SIZE equ {2*NT_QUEUE_LEN}
NT_QUEUE_MOD equ {NT_QUEUE_SIZE-1}
mx %00
@ -33,6 +34,7 @@ ROMScrollEdge equ 16
ROMScrollDelta equ 18
OldROMScrollEdge equ 20
CurrScrollEdge equ 22
CurrNTQueueEnd equ 40
Tmp0 equ 240
Tmp1 equ 242
@ -162,9 +164,6 @@ EvtLoop
beq :spin
stz nmiCount
; lda #$0400
; stal ROMBase+$75F
; 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
;
@ -177,53 +176,35 @@ EvtLoop
; 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
; Get the current global coordinates
lda singleStepMode
bne :skip_render
jsr RenderFrame
:skip_render
sei
lda ROMScrollEdge ; This is set in the VBL IRQ
sta CurrScrollEdge ; Freeze it, then we can let the IRQs continue
cli
lda lastKey
lsr
lsr
lsr
sta ROMScreenEdge
bit #PAD_KEY_DOWN
beq EvtLoop
; 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
; 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
bne :not_1
jsr CopyStatus
@ -262,9 +243,60 @@ Greyscale dw $0000,$5555,$AAAA,$FFFF
dw $0000,$5555,$AAAA,$FFFF
dw $0000,$5555,$AAAA,$FFFF
lastKey dw 0
singleStepMode dw 0
nmiCount 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
;
; Inputs
@ -350,14 +382,19 @@ PPUAddrToTileStore
; If there is some other reason to draw the full screen, this will empty the queue
ClearNTQueue
stz nt_queue_front
stz nt_queue_end
; stz nt_queue_front
; stz nt_queue_end
lda CurrNTQueueEnd
sta nt_queue_front
rts
; Scan through the queue of tiles that need to be updated before applying the scroll change
DrainNTQueue
:GTELeftEdge equ Tmp3
:PPUAddr equ Tmp4
:Count equ Tmp5
stz :Count
; Prep item -- get the logical block of the left edge of the scroll window
@ -366,7 +403,7 @@ DrainNTQueue
sta :GTELeftEdge
lda nt_queue_front
cmp nt_queue_end
cmp CurrNTQueueEnd
beq :out
:loop
@ -393,7 +430,6 @@ DrainNTQueue
sbc #41
:toprow
pha ; Tile Store horizontal tile coordinate
phy ; No translation needed for y
ldx :PPUAddr
@ -402,17 +438,24 @@ DrainNTQueue
ora #$0100
pha
_GTESetTile
inc :Count
:skip
pla ; Pop the saved x-register into the accumulator
inc
inc
and #NT_QUEUE_MOD
cmp nt_queue_end
cmp CurrNTQueueEnd
bne :loop
:out
sta nt_queue_front
; lda :Count
; ldx #8*160
; ldy #$FFFF
; jsr DrawWord
rts
; Copy the necessary columns into the TileStore when setting a new scroll position
@ -437,6 +480,75 @@ UpdateFromPPU
lsr
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
; memory into the TileStore
@ -646,7 +758,19 @@ triggerNMI
stal ppustatus
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
; Expose joypad bits from GTE to the ROM: A-B-Select-Start-Up-Down-Left-Right
@ -985,18 +1109,11 @@ nmiTask
tcd
jsr readInput
ldal singleStepMode
bne :no_nmi
jsr triggerNMI
; 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
:no_nmi
pld
plb
@ -1009,6 +1126,7 @@ readInput
pha
_GTEReadControl
pla
stal lastKey ; Cache for other code
; 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
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
vram_buff dw 0 ; latched data when reading VRAM ($0000 - $3EFF)
@ -70,6 +71,7 @@ cond_s sta ]4
PPUCTRL_WRITE ENT
php
phb
phk
plb
@ -185,6 +187,10 @@ PPUADDR_WRITE ENT
eor #$01
sta w_bit
lda ppuaddr+1 ; Stay within the mirrored memory space
and #$3F
sta ppuaddr+1
pla
plx
plb
@ -210,6 +216,7 @@ PPUDATA_READ ENT
clc
adc ppuincr
and #$3FFF
sta ppuaddr
sep #$20 ; back to 8-bit acc for the read itself
@ -236,6 +243,11 @@ PPUDATA_READ ENT
pla
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_end dw 0
nt_queue ds 2*{NT_QUEUE_SIZE}
@ -250,6 +262,36 @@ PPUDATA_WRITE ENT
rep #$10
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
beq :nochange
@ -259,6 +301,7 @@ PPUDATA_WRITE ENT
txa
clc
adc ppuincr
and #$3FFF
sta ppuaddr
; 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
bcs :nocache
cpx #$2000
cpx #$2000 ; Change to $2080 to ignore score field updates
bcc :nocache
phy
@ -298,6 +341,7 @@ PPUDATA_WRITE ENT
txa
clc
adc ppuincr
and #$3FFF
sta ppuaddr
:done
@ -318,6 +362,7 @@ setborder
stal $E0C034
plp
rts
; 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
@ -538,7 +583,11 @@ PPUDMA_WRITE ENT
plp
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
; 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
lda PPU_OAM,x ; Y-coordinate
cmp #200+y_offset-9
cmp #y_height+y_offset-9
bcs :skip
cmp #16
cmp #y_offset
bcc :skip
lda PPU_OAM+1,x ; $FC is an empty tile, don't draw it
@ -731,16 +780,16 @@ drawShadowList
lda shadowListBot,x
and #$00FF
tay
cpy #201
bcc *+4
brk $cc
; cpy #201
; bcc *+4
; brk $cc
lda shadowListTop,x
and #$00FF
tax
cpx #200
bcc *+4
brk $dd
; cpx #200
; bcc *+4
; brk $dd
lda #0 ; Invoke the BltRange function
jsl LngJmp
@ -804,7 +853,7 @@ exposeShadowList
:exit
ldx :last ; Expose the final part
ldy #200
ldy #y_height
lda #0
jsl LngJmp
rts
@ -817,7 +866,7 @@ shadowBitmapToList
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
sta shadowListCount ; zero out the shadow list count
@ -826,7 +875,7 @@ shadowBitmapToList
ldy shadowBitmap,x
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
adc offset,y ; This is the first line defined by the bit pattern
sta :top
@ -834,7 +883,7 @@ shadowBitmapToList
:zero_next
inx
cpx #28 ; End at byte 27
cpx #y_height_rows+y_offset_rows+1 ; End at byte 27
bcc :zero_loop
bra :exit ; ended while not tracking a sprite, so exit the function
@ -844,7 +893,7 @@ shadowBitmapToList
beq :one_next
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
adc offset,y
@ -858,7 +907,7 @@ shadowBitmapToList
:one_next
inx
cpx #28
cpx #y_height_rows+y_offset_rows+1
bcc :one_loop
; If we end while tracking a sprite, add to the list as the last item
@ -866,7 +915,7 @@ shadowBitmapToList
ldx shadowListCount
lda :top
sta shadowListTop,x
lda #200
lda #y_height
sta shadowListBot,x
inx
stx shadowListCount

View File

@ -44,7 +44,7 @@ JOYPAD_PORT1 = $4016
JOYPAD_PORT2 = $4017
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
ObjectOffset = $08

16447
demos/smb/rom2.s Normal file

File diff suppressed because it is too large Load Diff