mirror of
https://github.com/lscharen/iigs-game-engine.git
synced 2025-02-16 10:32:20 +00:00
Fresh rom2 that does not have the RenderArea bug
This commit is contained in:
parent
6c5bf4e494
commit
aa684ef58c
@ -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
|
||||
|
||||
|
@ -12,7 +12,7 @@
|
||||
|
||||
; Segment #2 -- ROM
|
||||
|
||||
ASM rom.s
|
||||
ASM rom2.s
|
||||
KND #$1100
|
||||
SNA SMBROM
|
||||
|
||||
|
246
demos/smb/Main.s
246
demos/smb/Main.s
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
16447
demos/smb/rom2.s
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user