Fix absolute address issue in rom

This commit is contained in:
Lucas Scharenbroich 2023-05-19 20:40:52 -05:00
parent 310c3487ca
commit 64f7106143
11 changed files with 1812 additions and 244 deletions

105
demos/smb/App.Msg.s Normal file
View File

@ -0,0 +1,105 @@
HexToChar dfb '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'
; Convert a byte (Acc) into a string and store at (Y)
ByteToString and #$00FF
sep #$20
pha
lsr
lsr
lsr
lsr
and #$0F
tax
ldal HexToChar,x
sta: $0000,y
pla
and #$0F
tax
ldal HexToChar,x
sta: $0001,y
rep #$20
rts
; Convert a word (Acc) into a hexadecimal string and store at (Y)
WordToString pha
bra Addr2ToString
; Pass in Acc = High, X = low
Addr3ToString phx
jsr ByteToString
iny
iny
lda 1,s
Addr2ToString xba
jsr ByteToString
iny
iny
pla
jsr ByteToString
rts
; A=Value
; X=Screen offset
DrawWord phx ; Save register value
phy
ldy #WordBuff+1
jsr WordToString
ply
plx
lda #WordBuff
jsr DrawString
rts
WordBuff str '0000'
Addr3Buff str '000000' ; str adds leading length byte

View File

@ -22,11 +22,20 @@ MyUserId equ 0
ROMStk equ 2
ROMZeroPg equ 4
LastScroll equ 6
RenderCtr equ 8
TileX equ 10 ; GTE tile store coordinates that correspond to the PPUSCROLL edge
TileY equ 12
ROMScreenEdge equ 14
ROMScrollEdge equ 16
ROMScrollDelta equ 18
OldROMScrollEdge equ 20
CurrScrollEdge equ 22
Tmp0 equ 240
Tmp1 equ 242
Tmp2 equ 244
Tmp3 equ 246
Tmp4 equ 248
Tmp5 equ 250
phk
plb
@ -34,7 +43,12 @@ Tmp3 equ 246
_MTStartUp ; GTE requires the miscellaneous toolset to be running
stz LastScroll
stz RenderCtr
stz TileX
stz TileY
stz ROMScreenEdge
stz ROMScrollEdge
stz ROMScrollDelta
stz OldROMScrollEdge
; The next two direct pages will be used by GTE, so get another 2 pages beyond that for the ROM. We get
; 4K of DP/Stack space by default, so there is plenty to share
@ -79,6 +93,12 @@ Tmp3 equ 246
pea #drawOAMSprites
_GTESetAddress
; Install a custom callback to update the tile store as the screen scrolls
pea extBG0TileUpdate
pea #^UpdateFromPPU
pea #UpdateFromPPU
_GTESetAddress
; Get the address of a low-level routine that can be used to draw a tile directly to the graphics screen
pea rawDrawTile
_GTEGetAddress
@ -133,42 +153,6 @@ Tmp3 equ 246
cpx #512*16
bcc :tloop
; Put the tile set on the screen
* lda #0
* stz Tmp1
* :yloop stz Tmp0
* :xloop
* pha
* pei Tmp0
* pei Tmp1
* pha
* _GTESetTile
* pla
* inc
* inc Tmp0
* ldx Tmp0
* cpx #32
* bcc :xloop
* inc Tmp1
* ldx Tmp1
* cpx #20
* bcc :yloop
* ; Render and wait for the user to continue
* pea $0000
* _GTERender
* :wait1
* pha
* _GTEReadControl
* pla
* and #$007F
* cmp #' '
* bne :wait1
; Set an internal flag to tell the VBL interrupt handler that it is
; ok to start invoking the game logic. The ROM code has to be run
; at 60 Hz because it controls the audio. Bad audio is way worse
@ -184,38 +168,60 @@ EvtLoop
beq :spin
stz nmiCount
; lda ppustatus ; Set the bit that the VBL has started
; bit #$80
; beq :spin
; and #$FF7F
; sta ppustatus
; 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
;
; ScreenEdge_PageLoc = $071a
; ScreenEdge_X_Pos = $071c
;
; So we can keep our scrolling in sync with the game. In order to efficiently update the
; GTE tile store, we handle this in two stages
;
; 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
; jsr triggerNMI
; Get the current global coordinates
; lda RenderCtr
; bne :no_render
sei
lda ROMScrollEdge ; This is set in the VBL IRQ
sta CurrScrollEdge ; Freeze it, then we can let the IRQs continue
cli
; lda #5
; sta RenderCtr
lsr
lsr
lsr
sta ROMScreenEdge
jsr CopyNametable
; Calculate how many blocks have been scrolled into view
lda ppuscroll+1
and #$00FF
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
sta LastScroll
lda ppuscroll
and #$00FF
pha
pea $0000
_GTESetBG0Origin
pea $FFFF ; NES mode
_GTERender
:no_render
dec RenderCtr
pha
_GTEReadControl
pla
@ -226,7 +232,8 @@ EvtLoop
and #PAD_BUTTON_A+PAD_BUTTON_B ; bits 0x200 and 0x100
lsr
lsr
sta native_joy
sta native_joy ; Put inputs on both controllers
sta native_joy+1
lda 1,s
and #$00FF
cmp #'n'
@ -254,6 +261,7 @@ EvtLoop
lda #$0001
:nes_merge ora native_joy
sta native_joy
sta native_joy+1
:nes_done
pla
; bit #PAD_KEY_DOWN
@ -262,23 +270,51 @@ EvtLoop
and #$007F
cmp #'1' ; Copy nametable 1
cmp #'r' ; Refresh
bne :not_1
lda #$2000
jsr CopyStatus
lda ROMScreenEdge ; global tile index
and #$003F ; mod the mirrored nametable size
ldx #33
ldy #0
jsr CopyNametable
brl EvtLoop
:not_1
cmp #'2'
bne :not_2
lda #$2400
cmp #'1'
bne :not_v
lda ROMScreenEdge
clc
adc #33
and #$003F
ldx #1
ldy #33
jsr CopyNametable
:not_2
brl EvtLoop
cmp #'s' ; next step
bne :not_n
jsr triggerNMI
:not_n
:not_v
cmp #'t' ; test by placing markers on screen
bne :not_t
pea 0
pea #3
pea $0150
_GTESetTile
pea #31
pea #3
pea $0150
_GTESetTile
pea #32
pea #3
pea $0150
_GTESetTile
pea #39
pea #3
pea $0150
_GTESetTile
brl EvtLoop
:not_t
cmp #'q'
beq Exit
@ -298,46 +334,234 @@ Greyscale dw $0000,$5555,$AAAA,$FFFF
nmiCount dw 0
DPSave dw 0
; Copy the tile and attribute bytes into the GTE buffer
; Take a PPU address and convert it to a tile store coordinate
;
; A = Nametable address ($2000, $2400, $2800, or $2C00)
CopyNametable
lda ppuctrl
and #$0003 ; nametable select bits
xba
asl
asl
; Inputs
; A = PPU address
; X = Global Address in GTE bytes
; Outputs
; X = relative tile store column
; Y = relative tile store row
PPUAddrToTileStore
:PPUAddr equ Tmp0
:PPUTopLeft equ Tmp1
sta :PPUAddr
; Based on the global coordiate, figure out whhat the left column in the PPU RAM is
txa
lsr ; Convert from bytes to tiles
lsr
and #$003F ; Logically there are 64 tiles in the mirrored PPU RAM
sta :PPUTopLeft
; Now we have the PPU address of the column that corresponds to the left edge of the GTE
; playfield. Now, calculate the relative coordinates of the passed PPU address
; The y-coordinate is easy. Since the top-left address is always on the top row (row = 0),
; we just have to extract the row that the PPU address occupies.
lda :PPUAddr
and #$03E0 ; Take the middle 5 bits (ignore nametable)
lsr
lsr
lsr
lsr
lsr
tay ; Save the y-index here
; The GTE playfield is positioned with the third PPU row as it's origin and is 25 tiles high.
; If the PPU tile is in rows 0, 1, 27, 28 or 29 then we can ignore it
cpy #2
bcc :outOfRange
cpy #27
bcs :outOfRange
; Adjust the relative position down by 2
dey
dey
; The horizontal coordinate is a bit trickier. We need to add 32 to the horizontal
; coordinate in it's in the second nametable
lda :PPUAddr
and #$041F ; Project it to the top row
bit #$0400
beq *+5
ora #$0020 ; Add 32
and #$003F ; Clamp to range of 0 - 63
; If we're in the top two row, they don't scroll, so skip the displacement
cpy #2
bcc :noshift
; Now calculate the difference between the PPUTopLeft index and this value
cmp :PPUTopLeft
bcs :ahead ; If the provided address is > than the origin, just calc the difference
adc #64 ; Else distance is (a - 0) + (64 - b) = a + 64 - b
sec
:ahead sbc :PPUTopLeft
:noshift
; If this value is larger than the payfield + 1, then we have the carry set or clear
tax
cmp #33
rts
:outOfRange
sec
rts
; 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
rts
; Scan through the queue of tiles that need to be updated before applying the scroll change
DrainNTQueue
:GTELeftEdge equ Tmp3
:PPUAddr equ Tmp4
; Prep item -- get the logical block of the left edge of the scroll window
lda CurrScrollEdge ; Global position that the GTE playfield was set to
lsr
sta :GTELeftEdge
lda nt_queue_front
cmp nt_queue_end
beq :out
:loop
tax
phx ; Save the x register
lda nt_queue,x ; get the PPU address that was stored
sta :PPUAddr ; save for later if we draw this tile
ldx :GTELeftEdge ; get the global coordinate
jsr PPUAddrToTileStore ; convert the PPU address to realtive tile store coordinates
bcs :skip ; if it's offscreen, no reason to draw it
; Now we have the relative position from the left edge of the tile. Add the origin
; tile to it (uless we're in rows 0 or 1)
txa
cpy #2
bcc :toprow
clc
adc #2*32
sta Tmp0 ; base address offset into nametable memory
adc TileX
cmp #41
bcc *+5
sbc #41
:toprow
pha ; Tile Store horizontal tile coordinate
; ora #$2000
; clc
; adc #PPU_MEM
; clc
; adc #2*32
; sta Tmp0 ; base address
phy ; No translation needed for y
; NES RAM $6D = page, $86 = player_x_in_page can be used to get a global position in the level, then subtracting the
; player's x coordinate will give us the global coordinate of the left edge of the screen and allow us to map between
; the GTE tile buffer and the PPU nametables
ldx :PPUAddr
lda PPU_MEM,x
and #$00FF
ora #$0100
pha
_GTESetTile
lda ppuscroll+1
:skip
pla ; Pop the saved x-register into the accumulator
inc
inc
and #{2*1024}-1
cmp nt_queue_end
bne :loop
:out
sta nt_queue_front
rts
; Copy the necessary columns into the TileStore when setting a new scroll position
UpdateFromPPU
:StartXMod164 equ 36
phb
phd
; Snag the StartXmod164 value from the GTE direct page so we can calulate the tile origin
; ourselves
ldx :StartXMod164
phk
plb
lda DPSave
tcd
txa
lsr
lsr
lsr
and #$001F
sta Tmp1 ; starting offset
sta TileX ; Tile column of playfield origin
; Check the scroll delta, if it's negative or just large enough, do a whole copy of the current PPU
; memory into the TileStore
lda ROMScrollDelta
beq :queue
cmp #32
bcc :partial
jsr ClearNTQueue ; kill any pending updates
lda ROMScreenEdge ; global tile index
and #$003F ; mod the mirrored nametable size
ldx #33 ; do the full width
ldy #0
jsr CopyNametable
bra :done
; Calculate the difference between the old and new
:partial
jsr DrainNTQueue
lda #33
sec
sbc ROMScrollDelta
tay
ldx ROMScrollDelta
inx
inx
lda ROMScreenEdge
clc
adc #33
sec
sbc ROMScrollDelta
and #$003F
jsr CopyNametable
:done
pld
plb
rtl
; Just drain the queue of any on-screen changes and then exit
:queue
jsr DrainNTQueue
pld
plb
rtl
CopyStatus
; Copy the first two rows from $2400 because they don't scroll
ldy #0
:yloop
ldx #0
cpy #2
bcs :offset
tya
clc
adc #2
@ -346,19 +570,84 @@ CopyNametable
asl
asl
asl
sta Tmp2
lda #0
sta Tmp3
bra :xloop
stz Tmp3
:xloop
phx ; Save X and Y
phy
:offset
lda Tmp0 ; Get the base address for this line
ora Tmp1 ; Move over to the first horizontal tile
phx ; x = GTE tile index = PPU tile index
phy ; No vertical scroll, so screen_y = tile_y
ldx Tmp2 ; Nametable address
lda PPU_MEM+$2000,x
and #$00FF
ora #$0100
pha
; Advance to the next tile (no wrapping needed)
inx
stx Tmp2
_GTESetTile
ply
plx
inx
cpx #33
bcc :xloop
iny
cpy #2
bcc :yloop
rts
; Copy the tile and attribute bytes into the GTE buffer
;
; A = logical column in mirrored PPU memory (0 - 63)
; X = number of columns to copy
; Y = number of GTE tiles to offset
CopyNametable
; cmp #5
; bcc *+4
; brk $88
sta Tmp2
bit #$0020 ; Is it >32?
beq *+5
ora #$0400 ; Move to the next nametable
and #$041F ; Mask to the top of a valid column
clc ; Add in the offset since we only copy rows 2 - 27
adc #4*32
sta Tmp0 ; base address offset into nametable memory
stx Tmp4
tya
clc
adc TileX
cmp #41
bcc *+5
sbc #41
sta Tmp5
; NES RAM $6D = page, $86 = player_x_in_page can be used to get a global position in the level, then subtracting the
; player's x coordinate will give us the global coordinate of the left edge of the screen and allow us to map between
; the GTE tile buffer and the PPU nametables
; Skip the first two rows -- call CopyStatus to get those
ldy #2
:yloop
ldx #0
lda Tmp0 ; Get the base address for this row
sta Tmp2 ; coarse x-scroll
lda Tmp1
sta Tmp3 ; Keep a separate count for the GTE tile position
lda Tmp5
sta Tmp3 ; Keep a separate variable for the GTE tile position
:xloop
phx ; Save X and Y
phy
@ -401,7 +690,7 @@ CopyNametable
sta Tmp3
inx
cpx #33
cpx Tmp4
bcc :xloop
lda Tmp0
@ -766,12 +1055,25 @@ nmiTask
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
pld
plb
plp
:skip
rtl
mx %00
put App.Msg.s
put font.s
put palette.s
put ppu.s

View File

@ -1,3 +1,25 @@
; 8 * 8 * 2 (2 bits to codify color) = 128 bits = 16 bytes to codify a single tile
;
; Surprisingly, 2 bits of a pixel are not codified in the same byte. A tile is
; described using 16 bytes. And each row is encoded using 2 bytes that stand 8
; bytes apart from each other. To figure out the color index of the top-left pixel,
; we need to read the 7th bit of byte 0x0000 and the 7th bit of byte 0x0008, to get
; the next pixel in the same row we would need to read 6th bits in the same bytes, etc.
;
; Decode the first row which is the back of mario's head
;
; ADDR VAL BITS ADDR VAL BITS
;
; 0x00 $03 00000011 0x08 $00 00000000 00 00 00 00 00 00 01 01 0 0 0 0 0 0 1 1
; 0x01 $0F 00001111 0x09 $00 00000000 00 00 00 00 01 01 01 01 0 0 0 0 1 1 1 1
; 0x02 $1F 00011111 0x0A $00 00000000 00 00 00 01 01 01 01 01 0 0 0 1 1 1 1 1
; 0x03 $1F 00011111 0x0B $00 00000000 = 00 00 00 01 01 01 01 01 = 0 0 0 1 1 1 1 1
; 0x04 $1C 00011100 0x0C $1F 00011111 00 00 00 11 11 11 10 10 0 0 0 3 3 3 2 2
; 0x05 $24 00100100 0x0D $3F 00111111 00 00 11 10 10 11 10 10 0 0 3 2 2 3 2 2
; 0x06 $26 00100110 0x0E $3F 00111111 00 00 11 10 10 11 11 10 0 0 3 2 2 3 3 2
; 0x07 $66 01100110 0x0F $7F 11111111 10 11 11 10 10 11 11 10 2 3 3 2 2 3 3 2
; Begin Bank 0
db $03,$0f,$1f,$1f,$1c,$24,$26,$66,$00,$00,$00,$00,$1f,$3f,$3f,$7f
db $e0,$c0,$80,$fc,$80,$c0,$00,$20,$00,$20,$60,$00,$f0,$fc,$fe,$fe
db $60,$70,$18,$07,$0f,$1f,$3f,$7f,$7f,$7f,$1f,$07,$00,$1e,$3f,$7f
@ -254,6 +276,9 @@
db $00,$00,$00,$00,$00,$00,$00,$00,$66,$e6,$66,$66,$66,$67,$f3,$00
db $00,$00,$00,$00,$00,$00,$00,$00,$5e,$59,$59,$59,$5e,$d8,$98,$00
db $00,$00,$00,$00,$00,$7c,$38,$00,$00,$00,$00,$00,$00,$04,$08,$00
; Begin Bank 1
; Tiles 0 - 15
db $38,$4c,$c6,$c6,$c6,$64,$38,$00,$00,$00,$00,$00,$00,$00,$00,$00
db $18,$38,$18,$18,$18,$18,$7e,$00,$00,$00,$00,$00,$00,$00,$00,$00
db $7c,$c6,$0e,$3c,$78,$e0,$fe,$00,$00,$00,$00,$00,$00,$00,$00,$00
@ -270,6 +295,8 @@
db $f8,$cc,$c6,$c6,$c6,$cc,$f8,$00,$00,$00,$00,$00,$00,$00,$00,$00
db $fe,$c0,$c0,$fc,$c0,$c0,$fe,$00,$00,$00,$00,$00,$00,$00,$00,$00
db $fe,$c0,$c0,$fc,$c0,$c0,$c0,$00,$00,$00,$00,$00,$00,$00,$00,$00
; Tiles 16 - 31
db $3e,$60,$c0,$ce,$c6,$66,$3e,$00,$00,$00,$00,$00,$00,$00,$00,$00
db $c6,$c6,$c6,$fe,$c6,$c6,$c6,$00,$00,$00,$00,$00,$00,$00,$00,$00
db $7e,$18,$18,$18,$18,$18,$7e,$00,$00,$00,$00,$00,$00,$00,$00,$00
@ -286,6 +313,8 @@
db $7e,$18,$18,$18,$18,$18,$18,$00,$00,$00,$00,$00,$00,$00,$00,$00
db $c6,$c6,$c6,$c6,$c6,$c6,$7c,$00,$00,$00,$00,$00,$00,$00,$00,$00
db $c6,$c6,$c6,$ee,$7c,$38,$10,$00,$00,$00,$00,$00,$00,$00,$00,$00
; Tiles 32 - 47
db $c6,$c6,$d6,$fe,$fe,$ee,$c6,$00,$00,$00,$00,$00,$00,$00,$00,$00
db $c6,$ee,$7c,$38,$7c,$ee,$c6,$00,$00,$00,$00,$00,$00,$00,$00,$00
db $66,$66,$66,$3c,$18,$18,$18,$00,$00,$00,$00,$00,$00,$00,$00,$00
@ -302,6 +331,8 @@
db $80,$80,$80,$c1,$e3,$ff,$ff,$ff,$7f,$7f,$7f,$3e,$1c,$00,$00,$ff
db $38,$7c,$7c,$7c,$7c,$7c,$38,$00,$08,$04,$04,$04,$04,$04,$08,$00
db $03,$06,$0c,$0c,$08,$08,$04,$03,$03,$05,$0b,$0b,$0f,$0f,$07,$03
; Tiles 48 - 63
db $01,$02,$04,$08,$10,$20,$40,$80,$01,$03,$07,$0f,$1f,$3f,$7f,$ff
db $00,$00,$00,$00,$00,$07,$38,$c0,$00,$00,$00,$00,$00,$07,$3f,$ff
db $00,$00,$00,$00,$00,$e0,$1c,$03,$00,$00,$00,$00,$00,$e0,$fc,$ff
@ -318,6 +349,8 @@
db $c0,$20,$10,$10,$10,$10,$20,$c0,$c0,$e0,$f0,$f0,$f0,$f0,$e0,$c0
db $00,$00,$00,$00,$3f,$7f,$e0,$c0,$00,$00,$00,$00,$00,$00,$1c,$3e
db $88,$9c,$88,$80,$80,$80,$80,$80,$7f,$7f,$7f,$3e,$1c,$00,$00,$00
; Tiles 64 - 79
db $fe,$fe,$fe,$fe,$fe,$fe,$fe,$fe,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff
db $08,$14,$24,$c4,$03,$40,$a1,$26,$00,$08,$18,$38,$fc,$bf,$5e,$d9
db $ff,$ff,$ff,$ff,$7f,$7f,$7f,$7f,$81,$81,$81,$81,$81,$81,$81,$81
@ -334,6 +367,8 @@
db $ff,$ff,$ff,$ff,$ff,$ff,$7e,$3c,$80,$80,$80,$80,$80,$81,$42,$3c
db $ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$00,$00,$00,$00,$00,$00,$00
db $ff,$ff,$ff,$ff,$ff,$ff,$fe,$7c,$00,$00,$00,$00,$00,$01,$82,$7c
; Tiles 80 - 95
db $ff,$ff,$ff,$ff,$ff,$ff,$fe,$7c,$00,$00,$00,$00,$00,$01,$83,$ff
db $f8,$fc,$fe,$fe,$ff,$ff,$ff,$ff,$f8,$04,$02,$02,$01,$01,$01,$01
db $ff,$ff,$ff,$ff,$ff,$ff,$7e,$3c,$01,$01,$01,$01,$01,$81,$42,$3c
@ -350,6 +385,8 @@
db $11,$39,$11,$01,$01,$01,$01,$01,$fe,$fe,$fe,$7c,$38,$00,$00,$00
db $ef,$28,$28,$28,$28,$28,$ef,$00,$20,$e7,$e7,$e7,$e7,$e7,$ef,$00
db $fe,$82,$82,$82,$82,$82,$fe,$00,$02,$7e,$7e,$7e,$7e,$7e,$fe,$00
; Tiles 96 - 111
db $80,$80,$80,$98,$9c,$8c,$80,$7f,$7f,$7f,$7f,$67,$67,$7f,$7f,$7f
db $ff,$ff,$83,$f3,$f3,$f3,$f3,$f3,$ff,$80,$fc,$8c,$8c,$8c,$8c,$8c
db $ff,$ff,$f0,$f6,$f6,$f6,$f6,$f6,$ff,$00,$0f,$09,$09,$09,$09,$09
@ -366,6 +403,8 @@
db $ff,$80,$80,$c0,$ff,$ff,$fe,$fe,$ff,$7f,$7f,$3f,$00,$00,$01,$01
db $ff,$7f,$7f,$ff,$ff,$07,$03,$03,$ff,$80,$80,$00,$00,$f8,$fc,$fc
db $ff,$00,$00,$00,$00,$81,$c3,$ff,$ff,$ff,$ff,$ff,$ff,$7e,$3c,$00
; Tiles 112 - 127
db $f8,$fc,$fe,$fe,$e3,$c1,$81,$81,$f8,$04,$02,$02,$1d,$3f,$7f,$7f
db $83,$ff,$ff,$ff,$ff,$ff,$7f,$1f,$fc,$80,$80,$80,$80,$80,$60,$1f
db $fc,$fc,$fc,$fc,$fe,$fe,$ff,$ff,$03,$03,$03,$03,$01,$01,$00,$ff
@ -382,6 +421,8 @@
db $04,$9a,$fa,$fd,$fd,$fd,$fd,$fd,$00,$80,$80,$80,$80,$80,$80,$80
db $7e,$38,$21,$00,$01,$00,$01,$00,$21,$21,$01,$01,$01,$01,$01,$01
db $fa,$8a,$84,$80,$80,$80,$80,$80,$80,$80,$80,$80,$80,$80,$80,$80
; Tiles 128 - 143
db $02,$04,$00,$10,$00,$40,$80,$00,$01,$01,$06,$08,$18,$20,$20,$c0
db $0b,$0b,$3b,$0b,$fb,$0b,$0b,$0a,$04,$04,$c4,$f4,$f4,$04,$04,$05
db $90,$10,$1f,$10,$1f,$10,$10,$90,$70,$f0,$f0,$ff,$ff,$f0,$f0,$70
@ -398,6 +439,8 @@
db $ff,$ff,$ff,$ff,$ff,$00,$ff,$ff,$00,$00,$00,$00,$00,$ff,$00,$00
db $fc,$fc,$fe,$fe,$fe,$02,$fe,$fe,$07,$07,$03,$03,$03,$ff,$03,$03
db $ff,$80,$80,$80,$80,$80,$80,$80,$80,$ff,$ff,$ff,$ff,$ff,$ff,$ff
; Tiles 144 - 159
db $ff,$03,$03,$03,$03,$03,$03,$03,$03,$ff,$ff,$ff,$ff,$ff,$ff,$ff
db $02,$02,$02,$02,$02,$02,$04,$04,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff
db $80,$80,$aa,$d5,$aa,$ff,$ff,$ff,$ff,$ff,$d5,$aa,$d5,$80,$80,$ff
@ -414,6 +457,8 @@
db $e1,$f9,$fd,$ff,$fe,$fe,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff
db $f0,$10,$10,$10,$10,$10,$10,$ff,$00,$e0,$e0,$e0,$e0,$e0,$e0,$e0
db $1f,$10,$10,$10,$10,$10,$10,$ff,$00,$0f,$0f,$0f,$0f,$0f,$0f,$0f
; Tiles 160 - 175
db $92,$92,$92,$fe,$fe,$00,$00,$00,$48,$48,$6c,$00,$00,$00,$fe,$00
db $0a,$0a,$3a,$0a,$fb,$0b,$0b,$0b,$05,$05,$c5,$f5,$f4,$04,$04,$04
db $90,$90,$9f,$90,$9f,$90,$90,$90,$70,$70,$70,$7f,$7f,$70,$70,$70
@ -426,10 +471,12 @@
db $f8,$f8,$f8,$f8,$f8,$f0,$f0,$e0,$98,$98,$98,$98,$98,$30,$30,$60
db $f1,$11,$11,$1f,$10,$10,$10,$ff,$0f,$ef,$ef,$ef,$ef,$ef,$ef,$e0
db $1f,$10,$10,$f0,$10,$10,$10,$ff,$e0,$ef,$ef,$ef,$ef,$ef,$ef,$0f
db $7f,$bf,$df,$ef,$f0,$f0,$f0,$f0,$80,$40,$20,$10,$0f,$0f,$0f,$0f
; db $7f,$bf,$df,$ef,$f0,$f0,$f0,$f0,$80,$40,$20,$10,$0f,$0f,$0f,$0f
db $f0,$f0,$f0,$f0,$ff,$ff,$ff,$ff,$0f,$0f,$0f,$0f,$1f,$3f,$7f,$ff
db $ff,$ff,$ff,$ff,$0f,$0f,$0f,$0f,$01,$03,$07,$0f,$ff,$ff,$ff,$ff
db $0f,$0f,$0f,$0f,$f7,$fb,$fd,$fe,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff
; Tiles 176 - 191
db $00,$00,$00,$00,$00,$00,$18,$18,$00,$00,$00,$00,$00,$00,$00,$00
db $1f,$3f,$7f,$7f,$7f,$ff,$ff,$ff,$1f,$20,$40,$40,$40,$80,$82,$82
db $ff,$ff,$ff,$7f,$7f,$7f,$3f,$1e,$82,$80,$a0,$44,$43,$40,$21,$1e
@ -446,6 +493,8 @@
db $7f,$7f,$7f,$3f,$3f,$1f,$0f,$07,$40,$40,$40,$20,$30,$1c,$0f,$07
db $fe,$fe,$fe,$fc,$fc,$f8,$f0,$f0,$02,$02,$02,$04,$0c,$38,$f0,$f0
db $0f,$0f,$0f,$0f,$0f,$0f,$07,$0f,$08,$08,$08,$08,$08,$0c,$05,$0a
; Tiles 192 - 207
db $f0,$f0,$f0,$f0,$f0,$f0,$e0,$f0,$10,$50,$50,$50,$50,$30,$a0,$50
db $81,$c1,$a3,$a3,$9d,$81,$81,$81,$00,$41,$22,$22,$1c,$00,$00,$00
db $e3,$f7,$c1,$c1,$c1,$c1,$f7,$e3,$e3,$14,$3e,$3e,$3e,$3e,$14,$e3
@ -462,6 +511,8 @@
db $e9,$e9,$e9,$ef,$e2,$e3,$f0,$ff,$76,$76,$76,$70,$7d,$7c,$7f,$7f
db $96,$96,$96,$f6,$46,$c6,$0e,$fe,$6f,$6f,$6f,$0f,$bf,$3f,$ff,$ff
db $00,$00,$00,$00,$00,$00,$7e,$3c,$3c,$7e,$7e,$ff,$ff,$ff,$42,$00
; Tiles 208 - 223
db $3c,$42,$99,$a1,$a1,$99,$42,$3c,$00,$00,$00,$00,$00,$00,$00,$00
db $0f,$1f,$1f,$3f,$3f,$7f,$7f,$7f,$f0,$e0,$e0,$c0,$c0,$80,$80,$80
db $f0,$f8,$f8,$fc,$fc,$fe,$fe,$fe,$0f,$07,$07,$03,$03,$01,$01,$01
@ -478,6 +529,8 @@
db $ff,$ff,$ff,$ff,$fc,$fe,$fe,$7e,$ff,$03,$03,$03,$03,$03,$03,$ff
db $ff,$ff,$ff,$ff,$00,$00,$00,$00,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff
db $7f,$7f,$7f,$7f,$7f,$7f,$7f,$7f,$80,$80,$80,$80,$80,$80,$80,$80
; Tiles 224 - 239
db $ff,$ff,$ff,$ff,$ff,$ff,$ff,$fe,$01,$01,$01,$03,$07,$03,$01,$01
db $7e,$7e,$7f,$7f,$7f,$7f,$7f,$7f,$81,$81,$81,$81,$81,$81,$81,$81
db $3f,$3f,$3f,$3f,$00,$00,$00,$00,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff
@ -494,6 +547,8 @@
db $20,$a6,$54,$26,$20,$c6,$54,$26,$20,$e6,$54,$26,$21,$06,$54,$26
db $20,$85,$01,$44,$20,$86,$54,$48,$20,$9a,$01,$49,$20,$a5,$c9,$46
db $20,$ba,$c9,$4a,$20,$a6,$0a,$d0,$d1,$d8,$d8,$de,$d1,$d0,$da,$de
; Tiles 240 - 255
db $d1,$20,$c6,$0a,$d2,$d3,$db,$db,$db,$d9,$db,$dc,$db,$df,$20,$e6
db $0a,$d4,$d5,$d4,$d9,$db,$e2,$d4,$da,$db,$e0,$21,$06,$0a,$d6,$d7
db $d6,$d7,$e1,$26,$d6,$dd,$e1,$e1,$21,$26,$14,$d0,$e8,$d1,$d0,$d1
@ -510,3 +565,5 @@
db $0a,$16,$0e,$22,$8b,$0d,$02,$24,$19,$15,$0a,$22,$0e,$1b,$24,$10
db $0a,$16,$0e,$22,$ec,$04,$1d,$18,$19,$28,$22,$f6,$01,$00,$23,$c9
db $56,$55,$23,$e2,$04,$99,$aa,$aa,$aa,$23,$ea,$04,$99,$aa,$aa,$aa
db $7f,$bf,$df,$ef,$f0,$f0,$f0,$f0,$80,$40,$20,$10,$0f,$0f,$0f,$0f

668
demos/smb/font.s Normal file
View File

@ -0,0 +1,668 @@
****************************************
* FONT ENGINE (v3?) *
* *
* Dagen Brock <dagenbrock@gmail.com> *
* 2013-07-20 *
****************************************
* A= ptr to string preceded by length *
* X= screen location *
****************************************
; each char:
; draw char at loc
; update loc
; see if length hit - no? back to draw char
rel
mx %00
]F_Length ds 2 ;length of string (only one byte currently used)
]F_CharIdx ds 2 ;index of current character
]F_CurrentPos ds 2 ;current top left char position
]F_StrPtr equ $01 ;pointer to string (including length byte) / DP
]F_StrClr equ $03
DrawString
pha ; local variable space
pha
tsc
phd
tcd
; sta ]F_StrPtr ; (done in pha init above) store at dp 0 ($00) for indirect loads
stx ]F_CurrentPos
sty ]F_StrClr
stz ]F_CharIdx
lda (]F_StrPtr)
and #$00ff ;strip off first char (len is only one byte)
sta ]F_Length ;get our length byte
NextChar lda ]F_CharIdx
cmp ]F_Length
bne :notDone
ldy ]F_StrClr ;restore the color pattern
pld
pla
pla
rts ;DONE! Return to caller
:notDone inc ]F_CharIdx
ldy ]F_CharIdx
lda (]F_StrPtr),y ;get next char!
and #$00FF ;mask high byte
sec
sbc #' ' ;our table starts with space ' '
asl ;*2
tay
ldx ]F_CurrentPos
jsr :drawChar
inc ]F_CurrentPos ;compare to addition time (?)
inc ]F_CurrentPos
inc ]F_CurrentPos
inc ]F_CurrentPos ;update screen pos (2 words=8 pixels)
bra NextChar
;x = TopLeft screen pos
;y = char table offset
:drawChar lda FontTable,y ;get real address of char data
sec
sbc #FontData ;pivot offset - now a is offset of fontdata
tay ;so we'll index with that
lda FontData,y
and ]F_StrClr
stal $E12000,x
lda FontData+2,y
and ]F_StrClr
stal $E12000+2,x
lda FontData+4,y
and ]F_StrClr
stal $E12000+160,x
lda FontData+6,y
and ]F_StrClr
stal $E12000+160+2,x
lda FontData+8,y
and ]F_StrClr
stal {$E12000+160*2},x
lda FontData+10,y
and ]F_StrClr
stal {$E12000+160*2+2},x
lda FontData+12,y
and ]F_StrClr
stal {$E12000+160*3},x
lda FontData+14,y
and ]F_StrClr
stal {$E12000+160*3+2},x
lda FontData+16,y
and ]F_StrClr
stal {$E12000+160*4},x
lda FontData+18,y
and ]F_StrClr
stal {$E12000+160*4+2},x
lda FontData+20,y
and ]F_StrClr
stal {$E12000+160*5},x
lda FontData+22,y
and ]F_StrClr
stal {$E12000+160*5+2},x
rts
FontTable dw s_Space
dw s_Exclaim
dw s_Quote
dw s_Number
dw s_Dollar
dw s_Percent
dw s_Amper
dw s_Single
dw s_OpenParen
dw s_CloseParen
dw s_Asterix
dw s_Plus
dw s_Comma
dw s_Minus
dw s_Period
dw s_Slash
dw s_N0
dw s_N1
dw s_N2
dw s_N3
dw s_N4
dw s_N5
dw s_N6
dw s_N7
dw s_N8
dw s_N9
dw s_Colon
dw s_Semi
dw s_LAngle
dw s_Equal
dw s_RAngle
dw s_Question
dw s_At
dw s_A
dw s_B
dw s_C
dw s_D
dw s_E
dw s_F
dw s_G
dw s_H
dw s_I
dw s_J
dw s_K
dw s_L
dw s_M
dw s_N
dw s_O
dw s_P
dw s_Q
dw s_R
dw s_S
dw s_T
dw s_U
dw s_V
dw s_W
dw s_X
dw s_Y
dw s_Z
dw s_LBracket
dw s_BackSlash
dw s_RBracket
dw s_Carot
dw s_UnderLine
FontData = *
s_Space hex 00000000
hex 00000000
hex 00000000
hex 00000000
hex 00000000
hex 00000000
s_Exclaim hex 000FF000
hex 000FF000
hex 000FF000
hex 000FF000
hex 00000000
hex 000FF000
s_Quote hex 0FF00FF0
hex 00F000F0
hex 00000000
hex 00000000
hex 00000000
hex 00000000
s_Number hex 00000000
hex 00F00F00
hex 0FFFFFF0
hex 00F00F00
hex 0FFFFFF0
hex 00F00F00
s_Dollar hex 000F0F00
hex 00FFFFF0
hex 0F0F0F00
hex 00FFFF00
hex 000F0FF0
hex 0FFFFF00
s_Percent hex 0FF000F0
hex 00000F00
hex 0000F000
hex 000F0000
hex 00F00000
hex 0F000FF0
s_Amper hex 000FF000
hex 00F00F00
hex 0F00F000
hex 00F000F0
hex 0F0FFF00
hex 00F0F000
s_Single hex 000FF000
hex 0000F000
hex 00000000
hex 00000000
hex 00000000
hex 00000000
s_OpenParen hex 000FF000
hex 00FF0000
hex 0FF00000
hex 0FF00000
hex 00FF0000
hex 000FF000
s_CloseParen hex 000FF000
hex 0000FF00
hex 00000FF0
hex 00000FF0
hex 0000FF00
hex 000FF000
s_Asterix hex 00000000
hex 00F0F0F0
hex 000FFF00
hex 00FFFFF0
hex 000FFF00
hex 00F0F0F0
s_Plus hex 000F0000
hex 000F0000
hex 0FFFFF00
hex 000F0000
hex 000F0000
hex 00000000
s_Comma hex 00000000
hex 00000000
hex 00000000
hex 00000000
hex 0000FF00
hex 0000F000
s_Minus hex 00000000
hex 00000000
hex 0FFFFF00
hex 00000000
hex 00000000
hex 00000000
s_Period hex 00000000
hex 00000000
hex 00000000
hex 00000000
hex 0000FF00
hex 0000FF00
s_Slash hex 000000F0
hex 00000F00
hex 0000F000
hex 000F0000
hex 00F00000
hex 0F000000
s_N0 hex 00FFFF00
hex 0F000FF0
hex 0F00F0F0
hex 0F0F00F0
hex 0FF000F0
hex 00FFFF00
s_N1 hex 000F0000
hex 00FF0000
hex 000F0000
hex 000F0000
hex 000F0000
hex 00FFF000
s_N2 hex 00FFFF00
hex 0F0000F0
hex 00000F00
hex 000FF000
hex 00F00000
hex 0FFFFFF0
s_N3 hex 00FFFF00
hex 000000F0
hex 000FFF00
hex 000000F0
hex 000000F0
hex 00FFFF00
s_N4 hex 0000FF00
hex 000F0F00
hex 00F00F00
hex 0FFFFFF0
hex 00000F00
hex 00000F00
s_N5 hex 0FFFFFF0
hex 0F000000
hex 0FFFFF00
hex 000000F0
hex 0F0000F0
hex 00FFFF00
s_N6 hex 000FFF00
hex 00F00000
hex 0F000000
hex 0FFFFF00
hex 0F0000F0
hex 00FFFFF0
s_N7 hex 0FFFFFF0
hex 000000F0
hex 00000F00
hex 0000F000
hex 000F0000
hex 000F0000
s_N8 hex 00FFFF00
hex 0F0000F0
hex 00FFFF00
hex 0F0000F0
hex 0F0000F0
hex 00FFFF00
s_N9 hex 00FFFF00
hex 0F0000F0
hex 00FFFF00
hex 0000F000
hex 000F0000
hex 00F00000
s_Colon hex 000FF000
hex 000FF000
hex 00000000
hex 000FF000
hex 000FF000
hex 00000000
s_Semi hex 00000000
hex 000FF000
hex 000FF000
hex 00000000
hex 000FF000
hex 000F0000
s_LAngle hex 0000F000
hex 000F0000
hex 00F00000
hex 000F0000
hex 0000F000
hex 00000000
s_Equal hex 00000000
hex 00000000
hex 0FFFFF00
hex 00000000
hex 0FFFFF00
hex 00000000
s_RAngle hex 0000F000
hex 00000F00
hex 000000F0
hex 00000F00
hex 0000F000
hex 00000000
s_Question hex 00FFF000
hex 0F000F00
hex 00000F00
hex 000FF000
hex 00000000
hex 000FF000
s_At hex 00FFFF00
hex 0F0000F0
hex 0F00F0F0
hex 0FFFF0F0
hex 000000F0
hex 0FFFFF00
s_A hex 000FF000
hex 00F00F00
hex 0F0000F0
hex 0FFFFFF0
hex 0F0000F0
hex 0F0000F0
s_B hex 0FFFFF00
hex 0F0000F0
hex 0FFFFF00
hex 0F0000F0
hex 0F0000F0
hex 0FFFFF00
s_C hex 00FFFFF0
hex 0F000000
hex 0F000000
hex 0F000000
hex 0F000000
hex 00FFFFF0
s_D hex 0FFFFF00
hex 0F0000F0
hex 0F0000F0
hex 0F0000F0
hex 0F0000F0
hex 0FFFFF00
s_E hex 0FFFFFF0
hex 0F000000
hex 0FFFF000
hex 0F000000
hex 0F000000
hex 0FFFFFF0
s_F hex 0FFFFFF0
hex 0F000000
hex 0FFFF000
hex 0F000000
hex 0F000000
hex 0F000000
s_G hex 00FFFFF0
hex 0F000000
hex 0F000000
hex 0F00FFF0
hex 0F0000F0
hex 00FFFF00
s_H hex 0F0000F0
hex 0F0000F0
hex 0FFFFFF0
hex 0F0000F0
hex 0F0000F0
hex 0F0000F0
s_I hex 0FFFFF00
hex 000F0000
hex 000F0000
hex 000F0000
hex 000F0000
hex 0FFFFF00
s_J hex 000000F0
hex 000000F0
hex 000000F0
hex 0F0000F0
hex 0F0000F0
hex 00FFFF00
s_K hex 0F000F00
hex 0F00F000
hex 0FFF0000
hex 0F00F000
hex 0F000F00
hex 0F000F00
s_L hex 0F000000
hex 0F000000
hex 0F000000
hex 0F000000
hex 0F000000
hex 0FFFFFF0
s_M hex 0F0000F0
hex 0FF00FF0
hex 0F0FF0F0
hex 0F0000F0
hex 0F0000F0
hex 0F0000F0
s_N hex 0F0000F0
hex 0FF000F0
hex 0F0F00F0
hex 0F00F0F0
hex 0F000FF0
hex 0F0000F0
s_O hex 00FFFF00
hex 0F0000F0
hex 0F0000F0
hex 0F0000F0
hex 0F0000F0
hex 00FFFF00
s_P hex 0FFFFF00
hex 0F0000F0
hex 0FFFFF00
hex 0F000000
hex 0F000000
hex 0F000000
s_Q hex 00FFFF00
hex 0F0000F0
hex 0F0000F0
hex 0F00F0F0
hex 0F000FF0
hex 00FFFFF0
s_R hex 0FFFFF00
hex 0F0000F0
hex 0FFFFF00
hex 0F000F00
hex 0F0000F0
hex 0F0000F0
s_S hex 00FFFFF0
hex 0F000000
hex 00FFFF00
hex 000000F0
hex 000000F0
hex 0FFFFF00
s_T hex 0FFFFF00
hex 000F0000
hex 000F0000
hex 000F0000
hex 000F0000
hex 000F0000
s_U hex 0F0000F0
hex 0F0000F0
hex 0F0000F0
hex 0F0000F0
hex 0F0000F0
hex 00FFFF00
s_V hex 0F0000F0
hex 0F0000F0
hex 0F0000F0
hex 0F0000F0
hex 00F00F00
hex 000FF000
s_W hex 0F0000F0
hex 0F0000F0
hex 0F0000F0
hex 0F0FF0F0
hex 0FF00FF0
hex 0F0000F0
s_X hex 0F0000F0
hex 00F00F00
hex 000FF000
hex 000FF000
hex 00F00F00
hex 0F0000F0
s_Y hex F00000F0
hex 0F000F00
hex 00F0F000
hex 000F0000
hex 000F0000
hex 000F0000
s_Z hex 0FFFFFF0
hex 00000F00
hex 0000F000
hex 000F0000
hex 00F00000
hex 0FFFFFF0
s_LBracket hex 000FFF00
hex 000F0000
hex 000F0000
hex 000F0000
hex 000F0000
hex 000FFF00
s_BackSlash hex 0F000000
hex 00F00000
hex 000F0000
hex 0000F000
hex 00000F00
hex 000000F0
s_RBracket hex 00FFF000
hex 0000F000
hex 0000F000
hex 0000F000
hex 0000F000
hex 00FFF000
s_Carot hex 0000F000
hex 000F0F00
hex 00F000F0
hex 00000000
hex 00000000
hex 00000000
s_UnderLine hex 00000000
hex 00000000
hex 00000000
hex 00000000
hex 00000000
hex FFFFFFF0
s_Template hex 00000000
hex 00000000
hex 00000000
hex 00000000
hex 00000000
hex 00000000

View File

@ -168,6 +168,7 @@ PPUADDR_WRITE ENT
plp
rtl
; 2007 - PPUDATA (Read/Write)
;
; If reading from the $0000 - $3EFF range, the value from vram_buff is returned and the actual data is loaded
@ -212,6 +213,10 @@ PPUDATA_READ ENT
pla
rtl
nt_queue_front dw 0
nt_queue_end dw 0
nt_queue ds 2*{1024}
PPUDATA_WRITE ENT
php
phb
@ -230,16 +235,43 @@ PPUDATA_WRITE ENT
adc ppuincr
sta ppuaddr
; Anything between $2000 and $3000, we need to add to the queue. We can't reject updates here because we may not
; actually update the GTE tile store for several game frames and the position of the tile within the tile store
; may change if the screen is scrolling
cpx #$3000
bcs :nocache
cpx #$2000
bcc :nocache
phy
lda nt_queue_end
tay
inc
inc
and #{2*1024}-1
cmp nt_queue_front
beq :full
sta nt_queue_end
txa
sta nt_queue,y
:full
ply
:nocache
cpx #$3F00
bcs :extra
:done
sep #$30
plx
pla
plb
plp
rtl
; 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
@ -526,7 +558,7 @@ drawOAMSprites
bra :noflip
:hflip
lda PPU_OAM,x ; Loda the tile index into the high byte (x256)
lda PPU_OAM,x ; Load the tile index into the high byte (x256)
and #$FF00
lsr ; multiple by 128
adc #64 ; horizontal flip

View File

@ -30,19 +30,20 @@ PPU_SCROLL_REG = $2005
PPU_ADDRESS = $2006
PPU_DATA = $2007
SND_REGISTER = $4000
SND_SQUARE1_REG = $4000
SND_SQUARE2_REG = $4004
SND_TRIANGLE_REG = $4008
SND_NOISE_REG = $400c
SND_DELTA_REG = $4010
SND_MASTERCTRL_REG = $4015
SND_REGISTER = $4000 ; Only accessed via abs,x addressing
SND_SQUARE1_REG = $4000 ; Only accessed via abs addressing; sta, sty and stx
SND_SQUARE2_REG = $4004 ; Only accessed via abs addressing; sta, sty and stx
SND_TRIANGLE_REG = $4008 ; Only accessed via abs addressing; sta
SND_NOISE_REG = $400c ; Only accessed via abs addressing; sta, sty and stx
SND_DELTA_REG = $4010 ; Only accessed via abs addressing; sta, sty
SND_MASTERCTRL_REG = $4015 ; Only accessed via abs addressing; sta, stx
SPR_DMA = $4014
JOYPAD_PORT = $4016
JOYPAD_PORT1 = $4016
JOYPAD_PORT2 = $4017
GTE_TMP = $10 ; No zero page references in the assembly to this location
; GAME SPECIFIC DEFINES
ObjectOffset = $08
@ -271,13 +272,13 @@ Misc_SprDataOffset = $06f3
SprDataOffset_Ctrl = $03ee
Player_State = $1d
Enemy_State = $1e
Enemy_State = $1e ; (11) Lots of ,y indexing on this variable
Fireball_State = $24
Block_State = $26
Misc_State = $2a
Misc_State = $2a ; (4) Lots of ,y indexing on this variable
Player_MovingDir = $45
Enemy_MovingDir = $46
Enemy_MovingDir = $46 ; (1)
SprObject_X_Speed = $57
Player_X_Speed = $57
@ -292,41 +293,41 @@ JumpspringForce = $06db
SprObject_PageLoc = $6d
Player_PageLoc = $6d
Enemy_PageLoc = $6e
Enemy_PageLoc = $6e ; (6)
Fireball_PageLoc = $74
Block_PageLoc = $76
Misc_PageLoc = $7a
Block_PageLoc = $76 ; (1)
Misc_PageLoc = $7a ; (2)
Bubble_PageLoc = $83
SprObject_X_Position = $86
Player_X_Position = $86
Enemy_X_Position = $87
Enemy_X_Position = $87 ; Fix ,y indexing (7)
Fireball_X_Position = $8d
Block_X_Position = $8f
Misc_X_Position = $93
Block_X_Position = $8f ; (1)
Misc_X_Position = $93 ; (2)
Bubble_X_Position = $9c
SprObject_Y_Speed = $9f
Player_Y_Speed = $9f
Enemy_Y_Speed = $a0
Enemy_Y_Speed = $a0 ; (4)
Fireball_Y_Speed = $a6
Block_Y_Speed = $a8
Misc_Y_Speed = $ac
Misc_Y_Speed = $ac ; (1)
SprObject_Y_HighPos = $b5
Player_Y_HighPos = $b5
Enemy_Y_HighPos = $b6
Enemy_Y_HighPos = $b6 ; (1)
Fireball_Y_HighPos = $bc
Block_Y_HighPos = $be
Misc_Y_HighPos = $c2
Misc_Y_HighPos = $c2 ; (1)
Bubble_Y_HighPos = $cb
SprObject_Y_Position = $ce
Player_Y_Position = $ce
Enemy_Y_Position = $cf
Enemy_Y_Position = $cf ; (11)
Fireball_Y_Position = $d5
Block_Y_Position = $d7
Misc_Y_Position = $db
Block_Y_Position = $d7 ; (1)
Misc_Y_Position = $db ; (2)
Bubble_Y_Position = $e4
SprObject_Rel_XPos = $03ad
@ -374,8 +375,8 @@ Misc_BoundBoxCtrl = $04a2
EnemyFrenzyBuffer = $06cb
EnemyFrenzyQueue = $06cd
Enemy_Flag = $0f
Enemy_ID = $16
Enemy_Flag = $0f ; (4)
Enemy_ID = $16 ; (7)
PlayerGfxOffset = $06d5
Player_XSpeedAbsolute = $0700
@ -682,7 +683,11 @@ PPUDATA_WRITE EXT
PPUDMA_WRITE EXT
ROMBase ENT
ds $8000-14-50-14
ds $7800-14-50-14
; 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
mx %11
@ -3708,12 +3713,23 @@ NoKillE dex ;do this until all
FrenzyIDData
db FlyCheepCheepFrenzy, BBill_CCheep_Frenzy,
AreaFrenzy ldx $00 ;use area object identifier bit as offset
lda FrenzyIDData-8,x ;note that it starts at 8, thus weird address here
ldy #$05
FreCompLoop dey ;check regular slots of enemy object buffer
;AreaFrenzy ldx $00 ;use area object identifier bit as offset
; lda FrenzyIDData-8,x ;note that it starts at 8, thus weird address here
; ldy #$05
;FreCompLoop dey ;check regular slots of enemy object buffer
; bmi ExitAFrenzy ;if all slots checked and enemy object not found, branch to store
; cmp Enemy_ID,y ;check for enemy object in buffer versus frenzy object
; bne FreCompLoop
; lda #$00 ;if enemy object already present, nullify queue and leave
;ExitAFrenzy sta EnemyFrenzyQueue ;store enemy into frenzy queue
; rts
AreaFrenzy ldy $00 ;use area object identifier bit as offset
lda FrenzyIDData-8,y ;note that it starts at 8, thus weird address here
ldx #$05
FreCompLoop dex ;check regular slots of enemy object buffer
bmi ExitAFrenzy ;if all slots checked and enemy object not found, branch to store
cmp Enemy_ID,y ;check for enemy object in buffer versus frenzy object
cmp Enemy_ID,x ;check for enemy object in buffer versus frenzy object
bne FreCompLoop
lda #$00 ;if enemy object already present, nullify queue and leave
ExitAFrenzy sta EnemyFrenzyQueue ;store enemy into frenzy queue
@ -6783,12 +6799,30 @@ Setup_Vine
sta Enemy_ID,x ;store in buffer
lda #$01
sta Enemy_Flag,x ;set flag for enemy object buffer
lda Block_PageLoc,y
sta Enemy_PageLoc,x ;copy page location from previous object
lda Block_X_Position,y
sta Enemy_X_Position,x ;copy horizontal coordinate from previous object
lda Block_Y_Position,y
; lda Block_PageLoc,y ; FIXME
; sta Enemy_PageLoc,x ;copy page location from previous object
; lda Block_X_Position,y ; FIXME
; sta Enemy_X_Position,x ;copy horizontal coordinate from previous object
; lda Block_Y_Position,y ; FIXME
; sta Enemy_Y_Position,x ;copy vertical coordinate from previous object
stx GTE_TMP
tyx
lda Block_PageLoc,x ; FIXME
pha
lda Block_X_Position,x ; FIXME
pha
lda Block_Y_Position,x ; FIXME
ldx GTE_TMP
sta Enemy_Y_Position,x ;copy vertical coordinate from previous object
pla
sta Enemy_X_Position,x ;copy horizontal coordinate from previous object
pla
sta Enemy_PageLoc,x ;copy page location from previous object
ldy VineFlagOffset ;load vine flag/offset to next available vine slot
bne NextVO ;if set at all, don't bother to store vertical
sta VineStart_Y_Position ;otherwise store vertical coordinate here
@ -6981,7 +7015,12 @@ SpawnHammerObj
lda PseudoRandomBitReg+1
and #%00001000 ;get d3 from same part of LSFR
SetMOfs tay ;use either d3 or d2-d0 for offset here
lda Misc_State,y ;if any values loaded in
; lda Misc_State,y ;if any values loaded in
tyx
lda Misc_State,x
; x is set immediately on both paths
bne NoHammer ;$2a-$32 where offset is then leave with carry clear
ldx HammerEnemyOfsData,y ;get offset of enemy slot to check using Y as offset
lda Enemy_Flag,x ;check enemy buffer flag at offset
@ -6990,7 +7029,13 @@ SetMOfs tay ;use either d3 or d
txa
sta HammerEnemyOffset,y ;save here
lda #$90
sta Misc_State,y ;save hammer's state here
; sta Misc_State,y ;save hammer's state here
phx
tyx
sta Misc_State,x
plx
lda #$07
sta Misc_BoundBoxCtrl,y ;set something else entirely, here
sec ;return with carry set
@ -7030,23 +7075,47 @@ ProcHammerObj
jmp RunAllH ;branch to essential subroutines
SetHSpd lda #$fe
sta Misc_Y_Speed,x ;set hammer's vertical speed
lda Enemy_State,y ;get enemy object state
; No need to preserve x here because it's loaded afterward
tyx
; lda Enemy_State,y ;get enemy object state
lda Enemy_State,x
and #%11110111 ;mask out d3
sta Enemy_State,y ;store new state
; sta Enemy_State,y ;store new state
sta Enemy_State,x
ldx Enemy_MovingDir,y ;get enemy's moving direction
dex ;decrement to use as offset
lda HammerXSpdData,x ;get proper speed to use based on moving direction
ldx ObjectOffset ;reobtain hammer's buffer offset
sta Misc_X_Speed,x ;set hammer's horizontal speed
SetHPos dec Misc_State,x ;decrement hammer's state
lda Enemy_X_Position,y ;get enemy's horizontal position
stx GTE_TMP
; lda Enemy_X_Position,y ;get enemy's horizontal position
tyx
lda Enemy_X_Position,x
ldx GTE_TMP
clc
adc #$02 ;set position 2 pixels to the right
sta Misc_X_Position,x ;store as hammer's horizontal position
lda Enemy_PageLoc,y ;get enemy's page location
; lda Enemy_PageLoc,y ;get enemy's page location
tyx
lda Enemy_PageLoc,x
ldx GTE_TMP
adc #$00 ;add carry
sta Misc_PageLoc,x ;store as hammer's page location
lda Enemy_Y_Position,y ;get enemy's vertical position
; lda Enemy_Y_Position,y ;get enemy's vertical position
tyx
lda Enemy_Y_Position,x
ldx GTE_TMP
sec
sbc #$0a ;move position 10 pixels upward
sta Misc_Y_Position,x ;store as hammer's vertical position
@ -7066,50 +7135,98 @@ RunHSubs jsr GetMiscOffscreenBits ;get offscreen info
CoinBlock
jsr FindEmptyMiscSlot ;set offset for empty or last misc object buffer slot
; lda Block_PageLoc,x ;get page location of block object
; sta Misc_PageLoc,y ;store as page location of misc object
; lda Block_X_Position,x ;get horizontal coordinate of block object
; ora #$05 ;add 5 pixels
; sta Misc_X_Position,y ;store as horizontal coordinate of misc object
; lda Block_Y_Position,x ;get vertical coordinate of block object
; sbc #$10 ;subtract 16 pixels
; sta Misc_Y_Position,y ;store as vertical coordinate of misc object
stx GTE_TMP
lda Block_PageLoc,x ;get page location of block object
sta Misc_PageLoc,y ;store as page location of misc object
tyx
sta Misc_PageLoc,x ;store as page location of misc object
ldx GTE_TMP
lda Block_X_Position,x ;get horizontal coordinate of block object
ora #$05 ;add 5 pixels
sta Misc_X_Position,y ;store as horizontal coordinate of misc object
tyx
sta Misc_X_Position,x ;store as horizontal coordinate of misc object
ldx GTE_TMP
lda Block_Y_Position,x ;get vertical coordinate of block object
sbc #$10 ;subtract 16 pixels
sta Misc_Y_Position,y ;store as vertical coordinate of misc object
tyx
sta Misc_Y_Position,x ;store as vertical coordinate of misc object
ldx GTE_TMP
jmp JCoinC ;jump to rest of code as applies to this misc object
SetupJumpCoin
jsr FindEmptyMiscSlot ;set offset for empty or last misc object buffer slot
lda Block_PageLoc2,x ;get page location saved earlier
sta Misc_PageLoc,y ;and save as page location for misc object
; sta Misc_PageLoc,y ;and save as page location for misc object
phx
tyx
sta Misc_PageLoc,x
lda $06 ;get low byte of block buffer offset
asl
asl ;multiply by 16 to use lower nybble
asl
asl
ora #$05 ;add five pixels
sta Misc_X_Position,y ;save as horizontal coordinate for misc object
; sta Misc_X_Position,y ;save as horizontal coordinate for misc object
sta Misc_X_Position,X
lda $02 ;get vertical high nybble offset from earlier
adc #$20 ;add 32 pixels for the status bar
sta Misc_Y_Position,y ;store as vertical coordinate
; sta Misc_Y_Position,y ;store as vertical coordinate
sta Misc_Y_Position,x
plx
JCoinC lda #$fb
sta Misc_Y_Speed,y ;set vertical speed
; sta Misc_Y_Speed,y ;set vertical speed
phx
tyx
sta Misc_Y_Speed,x
lda #$01
sta Misc_Y_HighPos,y ;set vertical high byte
sta Misc_State,y ;set state for misc object
; sta Misc_Y_HighPos,y ;set vertical high byte
; sta Misc_State,y ;set state for misc object
sta Misc_Y_HighPos,x
sta Misc_State,x
plx
sta Square2SoundQueue ;load coin grab sound
stx ObjectOffset ;store current control bit as misc object offset
jsr GiveOneCoin ;update coin tally on the screen and coin amount variable
inc CoinTallyFor1Ups ;increment coin tally used to activate 1-up block flag
rts
FindEmptyMiscSlot
ldy #$08 ;start at end of misc objects buffer
FMiscLoop lda Misc_State,y ;get misc object state
; ldy #$08 ;start at end of misc objects buffer
;FMiscLoop lda Misc_State,y ;get misc object state
; beq UseMiscS ;branch if none found to use current offset
; dey ;decrement offset
; cpy #$05 ;do this for three slots
; bne FMiscLoop ;do this until all slots are checked
; ldy #$08 ;if no empty slots found, use last slot
;UseMiscS sty JumpCoinMiscOffset ;store offset of misc object buffer here (residual)
phx
ldx #$08 ;start at end of misc objects buffer
FMiscLoop lda Misc_State,x ;get misc object state
beq UseMiscS ;branch if none found to use current offset
dey ;decrement offset
cpy #$05 ;do this for three slots
dex ;decrement offset
cpx #$05 ;do this for three slots
bne FMiscLoop ;do this until all slots are checked
ldy #$08 ;if no empty slots found, use last slot
UseMiscS sty JumpCoinMiscOffset ;store offset of misc object buffer here (residual)
ldx #$08 ;if no empty slots found, use last slot
UseMiscS stx JumpCoinMiscOffset ;store offset of misc object buffer here (residual)
txy
plx
rts
;-------------------------------------------------------------------------------------
@ -7130,7 +7247,7 @@ MiscLoop stx ObjectOffset ;store misc object
;$02 - used to set maximum speed
ProcJumpCoin
ldy Misc_State,x ;check misc object state
ldy Misc_State,x
dey ;decrement to see if it's set to 1
beq JCoinRun ;if so, branch to handle jumping coin
inc Misc_State,x ;otherwise increment state to either start off or as timer
@ -7880,9 +7997,17 @@ ChkAreaTsk lda AreaParserTaskNum ;check number of ta
ChkBowserF pla ;get data from stack
and #%00001111 ;mask out high nybble
tay
lda Enemy_Flag,y ;use as pointer and load same place with different offset
bne ExitELCore
; lda Enemy_Flag,y ;use as pointer and load same place with different offset
; bne ExitELCore
stx GTE_TMP
tyx
lda Enemy_Flag,x
bne ExitELCore2
ldx GTE_TMP
sta Enemy_Flag,x ;if second enemy flag not set, also clear first one
ExitELCore2 ldx GTE_TMP
ExitELCore rts
;--------------------------------
@ -8384,7 +8509,13 @@ LakituAndSpinyHandler
lda #$80 ;set timer
sta FrenzyEnemyTimer
ldy #$04 ;start with the last enemy slot
ChkLak lda Enemy_ID,y ;check all enemy slots to see
ChkLak
; lda Enemy_ID,y ;check all enemy slots to see
phx
tyx
lda Enemy_ID,x
plx
cmp #Lakitu ;if lakitu is on one of them
beq CreateSpiny ;if so, branch out of this loop
dey ;otherwise check another slot
@ -8415,15 +8546,31 @@ CreateSpiny
lda Player_Y_Position ;if player above a certain point, branch to leave
cmp #$2c
bcc ExLSHand
lda Enemy_State,y ;if lakitu is not in normal state, branch to leave
; lda Enemy_State,y ;if lakitu is not in normal state, branch to leave
stx GTE_TMP
tyx
lda Enemy_State,x
ldx GTE_TMP
bne ExLSHand
lda Enemy_PageLoc,y ;store horizontal coordinates (high and low) of lakitu
; lda Enemy_PageLoc,y ;store horizontal coordinates (high and low) of lakitu
tyx
lda Enemy_PageLoc,x
ldx GTE_TMP
sta Enemy_PageLoc,x ;into the coordinates of the spiny we're going to create
lda Enemy_X_Position,y
; lda Enemy_X_Position,y
tyx
lda Enemy_X_Position,x
ldx GTE_TMP
sta Enemy_X_Position,x
lda #$01 ;put spiny within vertical screen unit
sta Enemy_Y_HighPos,x
lda Enemy_Y_Position,y ;put spiny eight pixels above where lakitu is
; lda Enemy_Y_Position,y ;put spiny eight pixels above where lakitu is
tyx
lda Enemy_Y_Position,x
ldx GTE_TMP
sec
sbc #$08
sta Enemy_Y_Position,x
@ -8628,23 +8775,64 @@ InitBowser
;--------------------------------
DuplicateEnemyObj
ldy #$ff ;start at beginning of enemy slots
FSLoop iny ;increment one slot
lda Enemy_Flag,y ;check enemy buffer flag for empty slot
bne FSLoop ;if set, branch and keep checking
sty DuplicateObj_Offset ;otherwise set offset here
; ldy #$ff ;start at beginning of enemy slots
;:FSLoop iny ;increment one slot
; lda Enemy_Flag,y ;check enemy buffer flag for empty slot
; bne :FSLoop ;if set, branch and keep checking
; sty DuplicateObj_Offset ;otherwise set offset here
; txa ;transfer original enemy buffer offset
; ora #%10000000 ;store with d7 set as flag in new enemy
; sta Enemy_Flag,y ;slot as well as enemy offset
; lda Enemy_PageLoc,x
; sta Enemy_PageLoc,y ;copy page location and horizontal coordinates
; lda Enemy_X_Position,x ;from original enemy to new enemy
; sta Enemy_X_Position,y
; lda #$01
; sta Enemy_Flag,x ;set flag as normal for original enemy
; sta Enemy_Y_HighPos,y ;set high vertical byte for new enemy
; lda Enemy_Y_Position,x
; sta Enemy_Y_Position,y ;copy vertical coordinate from original to new
stx GTE_TMP
ldx #$ff ;start at beginning of enemy slots
:FSLoop inx ;increment one slot
lda Enemy_Flag,x ;check enemy buffer flag for empty slot
bne :FSLoop ;if set, branch and keep checking
stx DuplicateObj_Offset ;otherwise set offset here
ldx GTE_TMP
txa ;transfer original enemy buffer offset
ora #%10000000 ;store with d7 set as flag in new enemy
sta Enemy_Flag,y ;slot as well as enemy offset
; sta Enemy_Flag,y ;slot as well as enemy offset
pha
lda Enemy_PageLoc,x
sta Enemy_PageLoc,y ;copy page location and horizontal coordinates
; sta Enemy_PageLoc,y ;copy page location and horizontal coordinates
pha
lda Enemy_X_Position,x ;from original enemy to new enemy
sta Enemy_X_Position,y
; sta Enemy_X_Position,y
pha
lda #$01
sta Enemy_Flag,x ;set flag as normal for original enemy
sta Enemy_Y_HighPos,y ;set high vertical byte for new enemy
; sta Enemy_Y_HighPos,y ;set high vertical byte for new enemy
lda Enemy_Y_Position,x
sta Enemy_Y_Position,y ;copy vertical coordinate from original to new
; sta Enemy_Y_Position,y ;copy vertical coordinate from original to new
tyx
sta Enemy_Y_Position,x
lda #$01
sta Enemy_Y_HighPos,x
pla
sta Enemy_X_Position,x
pla
sta Enemy_PageLoc,x
pla
sta Enemy_Flag,x
ldx GTE_TMP
FlmEx rts ;and then leave
;--------------------------------
@ -8663,7 +8851,13 @@ InitBowserFlame
ora #Sfx_BowserFlame ;load bowser's flame sound into queue
sta NoiseSoundQueue
ldy BowserFront_Offset ;get bowser's buffer offset
lda Enemy_ID,y ;check for bowser
; lda Enemy_ID,y ;check for bowser
phx
tyx
lda Enemy_ID,x
plx
cmp #Bowser
beq SpawnFromMouth ;branch if found
jsr SetFlameTimer ;get timer data based on flame counter
@ -8692,13 +8886,27 @@ PutAtRightExtent
jmp FinishFlame ;skip this part to finish setting values
SpawnFromMouth
lda Enemy_X_Position,y ;get bowser's horizontal position
; lda Enemy_X_Position,y ;get bowser's horizontal position
stx GTE_TMP
tyx
lda Enemy_X_Position,x
ldx GTE_TMP
sec
sbc #$0e ;subtract 14 pixels
sta Enemy_X_Position,x ;save as flame's horizontal position
lda Enemy_PageLoc,y
; lda Enemy_PageLoc,y
tyx
lda Enemy_PageLoc,x
ldx GTE_TMP
sta Enemy_PageLoc,x ;copy page location from bowser to flame
lda Enemy_Y_Position,y
; lda Enemy_Y_Position,y
tyx
lda Enemy_Y_Position,x
ldx GTE_TMP
clc ;add 8 pixels to bowser's vertical position
adc #$08
sta Enemy_Y_Position,x ;save as flame's vertical position
@ -8741,25 +8949,40 @@ InitFireworks
lda #$20 ;otherwise reset timer
sta FrenzyEnemyTimer
dec FireworksCounter ;decrement for each explosion
ldy #$06 ;start at last slot
StarFChk dey
lda Enemy_ID,y ;check for presence of star flag object
; ldy #$06 ;start at last slot
;:StarFChk dey
; lda Enemy_ID,y ;check for presence of star flag object
stx GTE_TMP
ldx #$06 ;start at last slot
:StarFChk dex
lda Enemy_ID,x ;check for presence of star flag object
cmp #StarFlagObject ;if there isn't a star flag object,
bne StarFChk ;routine goes into infinite loop = crash
lda Enemy_X_Position,y
bne :StarFChk ;routine goes into infinite loop = crash
; lda Enemy_X_Position,y
lda Enemy_X_Position,x
sec ;get horizontal coordinate of star flag object, then
sbc #$30 ;subtract 48 pixels from it and save to
pha ;the stack
lda Enemy_PageLoc,y
; lda Enemy_PageLoc,y
lda Enemy_PageLoc,x
sbc #$00 ;subtract the carry from the page location
sta $00 ;of the star flag object
lda FireworksCounter ;get fireworks counter
clc
adc Enemy_State,y ;add state of star flag object (possibly not necessary)
; adc Enemy_State,y ;add state of star flag object (possibly not necessary)
adc Enemy_State,x
ldx GTE_TMP
tay ;use as offset
pla ;get saved horizontal coordinate of star flag - 48 pixels
clc
adc FireworksXPosData,y ;add number based on offset of fireworks counter
sta Enemy_X_Position,x ;store as the fireworks object horizontal coordinate
lda $00
adc #$00 ;add carry and store as page location for
@ -8832,18 +9055,35 @@ AddFBit ora BitMFilter ;add bit to already
jmp CheckpointEnemyID ;process our new enemy object
DoBulletBills
ldy #$ff ;start at beginning of enemy slots
BB_SLoop iny ;move onto the next slot
cpy #$05 ;branch to play sound if we've done all slots
; ldy #$ff ;start at beginning of enemy slots
;BB_SLoop iny ;move onto the next slot
; cpy #$05 ;branch to play sound if we've done all slots
; bcs FireBulletBill
; lda Enemy_Flag,y ;if enemy buffer flag not set,
; beq BB_SLoop ;loop back and check another slot
; lda Enemy_ID,y
; cmp #BulletBill_FrenzyVar ;check enemy identifier for
; bne BB_SLoop ;bullet bill object (frenzy variant)
stx GTE_TMP
ldx #$ff ;start at beginning of enemy slots
:BB_SLoop inx ;move onto the next slot
cpx #$05 ;branch to play sound if we've done all slots
bcs FireBulletBill
lda Enemy_Flag,y ;if enemy buffer flag not set,
beq BB_SLoop ;loop back and check another slot
lda Enemy_ID,y
lda Enemy_Flag,x ;if enemy buffer flag not set,
beq :BB_SLoop ;loop back and check another slot
lda Enemy_ID,x
cmp #BulletBill_FrenzyVar ;check enemy identifier for
bne BB_SLoop ;bullet bill object (frenzy variant)
bne :BB_SLoop ;bullet bill object (frenzy variant)
txy
stx GTE_TMP
ExF17 rts ;if found, leave
FireBulletBill
txy
stx GTE_TMP
lda Square2SoundQueue
ora #Sfx_Blast ;play fireworks/gunfire sound
sta Square2SoundQueue
@ -8954,14 +9194,23 @@ NoFrenzyCode
;--------------------------------
EndFrenzy
ldy #$05 ;start at last slot
LakituChk lda Enemy_ID,y ;check enemy identifiers
phx
; ldy #$05 ;start at last slot
;:LakituChk lda Enemy_ID,y ;check enemy identifiers
ldx #$05
:LakituChk lda Enemy_ID,x ;check enemy identifiers
cmp #Lakitu ;for lakitu
bne NextFSlot
bne :NextFSlot
lda #$01 ;if found, set state
sta Enemy_State,y
NextFSlot dey ;move onto the next slot
bpl LakituChk ;do this until all slots are checked
; sta Enemy_State,y
;:NextFSlot dey ;move onto the next slot
sta Enemy_State,x
:NextFSlot dex ;move onto the next slot
bpl :LakituChk ;do this until all slots are checked
txy
plx
lda #$00
sta EnemyFrenzyBuffer ;empty enemy frenzy buffer
sta Enemy_Flag,x ;disable enemy buffer flag for this object
@ -10083,11 +10332,20 @@ ChkLS lda Enemy_State,x ;if lakitu's enemy
bne SetLSpd ;load horizontal speed and do unconditional branch
Fr12S lda #Spiny
sta EnemyFrenzyBuffer ;set spiny identifier in frenzy buffer
ldy #$02
LdLDa lda LakituDiffAdj,y ;load values
sta $0001,y ;store in zero page
dey
bpl LdLDa ;do this until all values are stired
; ldy #$02
;:LdLDa lda LakituDiffAdj,y ;load values
; sta $0001,y ;store in zero page
; dey
; bpl :LdLDa ;do this until all values are stired
phx
ldx #$02
:LdLDa lda LakituDiffAdj,x ;load values
sta $01,x ;store in zero page
dex
bpl :LdLDa ;do this until all values are stired
plx
jsr PlayerLakituDiff ;execute sub to set speed and create spinys
SetLSpd sta LakituMoveSpeed,x ;set movement speed returned from sub
ldy #$01 ;set moving direction to right by default
@ -10157,7 +10415,13 @@ ChkSpinyO lda Enemy_ID,x ;check for spiny ob
ChkEmySpd lda Enemy_Y_Speed,x ;check vertical speed
bne SubDifAdj ;branch if nonzero
ldy #$00 ;otherwise reinit offset
SubDifAdj lda $0001,y ;get one of three saved values from earlier
SubDifAdj
; lda $0001,y ;get one of three saved values from earlier
phx
tyx
lda $01,x
plx
ldy $00 ;get saved horizontal difference
SPixelLak sec ;subtract one for each pixel of horizontal difference
sbc #$01 ;from one of three saved values
@ -10376,15 +10640,36 @@ CopyFToR tya ;move bowser's rear
clc
adc Enemy_X_Position,x ;add to bowser's front object horizontal coordinate
ldy DuplicateObj_Offset ;get bowser's rear object offset
sta Enemy_X_Position,y ;store A as bowser's rear horizontal coordinate
stx GTE_TMP
; sta Enemy_X_Position,y ;store A as bowser's rear horizontal coordinate
tyx
sta Enemy_X_Position,x ;store A as bowser's rear horizontal coordinate
ldx GTE_TMP
lda Enemy_Y_Position,x
clc ;add eight pixels to bowser's front object
adc #$08 ;vertical coordinate and store as vertical coordinate
sta Enemy_Y_Position,y ;for bowser's rear
; sta Enemy_Y_Position,y ;for bowser's rear
tyx
sta Enemy_Y_Position,x
ldx GTE_TMP
lda Enemy_State,x
sta Enemy_State,y ;copy enemy state directly from front to rear
; sta Enemy_State,y ;copy enemy state directly from front to rear
tyx
sta Enemy_State,x
ldx GTE_TMP
lda Enemy_MovingDir,x
sta Enemy_MovingDir,y ;copy moving direction also
; sta Enemy_MovingDir,y ;copy moving direction also
tyx
sta Enemy_MovingDir,x
ldx GTE_TMP
lda ObjectOffset ;save enemy object offset of front to stack
pha
ldx DuplicateObj_Offset ;put enemy object offset of rear as current
@ -10800,13 +11085,23 @@ MakePlatformFall
jmp InitPlatformFall ;make platforms fall
ChkOtherForFall
cmp Enemy_Y_Position,y ;check if other platform is above a certain point
; cmp Enemy_Y_Position,y ;check if other platform is above a certain point
phx
tyx
cmp Enemy_Y_Position,x
plx
bcc ChkToMoveBalPlat ;if not, branch elsewhere
cpx $00 ;if collision flag is set to same value as
beq MakePlatformFall ;enemy state, branch to make platforms fall
clc
adc #$02 ;otherwise add 2 pixels to vertical position
sta Enemy_Y_Position,y ;of other platform and branch elsewhere
; sta Enemy_Y_Position,y ;of other platform and branch elsewhere
phx
tyx
sta Enemy_Y_Position,x
plx
jmp StopPlatforms ;jump to stop movement and do not return
ChkToMoveBalPlat
@ -10840,8 +11135,15 @@ DoOtherPlatform
sec
sbc Enemy_Y_Position,x ;get difference of old vs. new coordinate
clc
adc Enemy_Y_Position,y ;add difference to vertical coordinate of other
sta Enemy_Y_Position,y ;platform to move it in the opposite direction
; adc Enemy_Y_Position,y ;add difference to vertical coordinate of other
; sta Enemy_Y_Position,y ;platform to move it in the opposite direction
phx
tyx
adc Enemy_Y_Position,x
sta Enemy_Y_Position,x
plx
lda PlatformCollisionFlag,x ;if no collision, skip this part here
bmi DrawEraseRope
tax ;put offset which collision occurred here
@ -10849,13 +11151,23 @@ DoOtherPlatform
DrawEraseRope
ldy ObjectOffset ;get enemy object offset
lda Enemy_Y_Speed,y ;check to see if current platform is
; lda Enemy_Y_Speed,y ;check to see if current platform is
phx
tyx
lda Enemy_Y_Speed,x
plx
ora Enemy_Y_MoveForce,y ;moving at all
beq ExitRp ;if not, skip all of this and branch to leave
ldx VRAM_Buffer1_Offset ;get vram buffer offset
cpx #$20 ;if offset beyond a certain point, go ahead
bcs ExitRp ;and skip this, branch to leave
lda Enemy_Y_Speed,y
; lda Enemy_Y_Speed,y
phx
tyx
lda Enemy_Y_Speed,x
plx
pha ;save two copies of vertical speed to stack
pha
jsr SetupPlatformRope ;do a sub to figure out where to put new bg tiles
@ -10865,8 +11177,12 @@ DrawEraseRope
sta VRAM_Buffer1+1,x
lda #$02 ;set length for 2 bytes
sta VRAM_Buffer1+2,x
lda Enemy_Y_Speed,y ;if platform moving upwards, branch
bmi EraseR1 ;to do something else
; lda Enemy_Y_Speed,y
phx
tyx
lda Enemy_Y_Speed,x
plx
bmi EraseR1 ;to do something else
lda #$a2
sta VRAM_Buffer1+3,x ;otherwise put tile numbers for left
lda #$a3 ;and right sides of rope in vram buffer
@ -10877,7 +11193,12 @@ EraseR1 lda #$24 ;put blank tiles in
sta VRAM_Buffer1+4,x
OtherRope
lda Enemy_State,y ;get offset of other platform from state
phx
; lda Enemy_State,y ;get offset of other platform from state
tyx
lda Enemy_State,x
plx
tay ;use as Y here
pla ;pull second copy of vertical speed from stack
eor #$ff ;invert bits to reverse speed
@ -10909,7 +11230,12 @@ ExitRp ldx ObjectOffset ;get enemy object b
SetupPlatformRope
pha ;save second/third copy to stack
lda Enemy_X_Position,y ;get horizontal coordinate
; lda Enemy_X_Position,y ;get horizontal coordinate
phx
tyx
lda Enemy_X_Position,x
plx
clc
adc #$08 ;add eight pixels
ldx SecondaryHardMode ;if secondary hard mode flag set,
@ -10917,7 +11243,12 @@ SetupPlatformRope
clc
adc #$10 ;otherwise add sixteen more pixels
GetLRp pha ;save modified horizontal coordinate to stack
lda Enemy_PageLoc,y
; lda Enemy_PageLoc,y
phx
tyx
lda Enemy_PageLoc,x
plx
adc #$00 ;add carry to page location
sta $02 ;and save here
pla ;pull modified horizontal coordinate
@ -10953,7 +11284,12 @@ GetHRp txa ;move vertical coor
clc
adc $00 ;add to horizontal part saved here
sta $00 ;save as name table low byte
lda Enemy_Y_Position,y
; lda Enemy_Y_Position,y
phx
tyx
lda Enemy_Y_Position,x
plx
cmp #$e8 ;if vertical position not below the
bcc ExPRp ;bottom of the screen, we're done, branch to leave
lda $00
@ -10976,7 +11312,12 @@ InitPlatformFall
StopPlatforms
jsr InitVStf ;initialize vertical speed and low byte
sta Enemy_Y_Speed,y ;for both platforms and leave
; sta Enemy_Y_Speed,y ;for both platforms and leave
phx
tyx
sta Enemy_Y_Speed,x
plx
sta Enemy_Y_MoveForce,y
rts
@ -11696,7 +12037,13 @@ ECLoop stx $01 ;save enemy object
ldy $01 ;use second enemy offset for Y
bcc NoEnemyCollision ;if carry clear, no collision, branch ahead of this
lda Enemy_State,x
ora Enemy_State,y ;check both enemy states for d7 set
; ora Enemy_State,y ;check both enemy states for d7 set
phx
tyx
ora Enemy_State,x
plx
and #%10000000
bne YesEC ;branch if at least one of them is set
lda Enemy_CollisionBits,y ;load first enemy's collision-related bits
@ -11725,7 +12072,12 @@ ExitECRoutine
rts ;leave
ProcEnemyCollisions
lda Enemy_State,y ;check both enemy states for d5 set
; lda Enemy_State,y ;check both enemy states for d5 set
stx GTE_TMP
tyx
lda Enemy_State,x
ldx GTE_TMP
ora Enemy_State,x
and #%00100000 ;if d5 is set in either state, or both, branch
bne ExitProcessEColl ;to leave and do nothing else at this point
@ -11735,7 +12087,12 @@ ProcEnemyCollisions
lda Enemy_ID,x ;check second enemy identifier for hammer bro
cmp #HammerBro ;if hammer bro found in alt state, branch to leave
beq ExitProcessEColl
lda Enemy_State,y ;check first enemy state for d7 set
; lda Enemy_State,y ;check first enemy state for d7 set
tyx
lda Enemy_State,x
ldx GTE_TMP
asl
bcc ShellCollisions ;branch if d7 is clear
lda #$06
@ -11760,10 +12117,20 @@ ExitProcessEColl
rts ;leave!!!
ProcSecondEnemyColl
lda Enemy_State,y ;if first enemy state < $06, branch elsewhere
stx GTE_TMP
; lda Enemy_State,y ;if first enemy state < $06, branch elsewhere
tyx
lda Enemy_State,x
ldx GTE_TMP
cmp #$06
bcc MoveEOfs
lda Enemy_ID,y ;check first enemy identifier for hammer bro
; lda Enemy_ID,y ;check first enemy identifier for hammer bro
tyx
lda Enemy_ID,x
ldx GTE_TMP
cmp #HammerBro ;if hammer bro found in alt state, branch to leave
beq ExitProcessEColl
jsr ShellOrBlockDefeat ;otherwise, kill first enemy
@ -16450,7 +16817,7 @@ BrickShatterEnvData
;-------------------------------------------------------------------------------------
;INTERRUPT VECTORS
; ds 34
dw NonMaskableInterrupt
dw Start
dw $fff0 ;unused

View File

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

View File

@ -195,6 +195,7 @@ tileStore equ $0003
vblCallback equ $0004 ; User routine to be called by VBL interrupt. Set to $000000 to disconnect
extSpriteRenderer equ $0005
rawDrawTile equ $0006
extBG0TileUpdate equ $0007
; CopyPicToBG1 flags
COPY_PIC_NORMAL equ $0000 ; Copy into BG1 buffer in "normal mode" treating the buffer as a 164x208 pixmap with stride of 256
@ -310,6 +311,7 @@ StartXMod164Tbl EXT
LastOffsetTbl EXT
BG1StartXMod164Tbl EXT
ExtSpriteRenderer EXT
ExtUpdateBG0Tiles EXT
; Tool error codes
NO_TIMERS_AVAILABLE equ 10

View File

@ -153,10 +153,24 @@ _DoOverlay
:disp jsl $000000
rts
; Special NES renderer that externalizes the sprite rendreing in order to exceed the internal limit of 16 sprites
; Special NES renderer that externalizes the sprite rendering in order to exceed the internal limit of 16 sprites
_RenderNES
jsr _ApplyBG0YPos
jsr _ApplyBG0XPosPre
; Callback to update the tilestore with any new tiles
lda ExtUpdateBG0Tiles
ora ExtUpdateBG0Tiles+2
beq :no_tile
lda ExtUpdateBG0Tiles
stal :patch0+1
lda ExtUpdateBG0Tiles+1
stal :patch0+2
:patch0 jsl $000000
:no_tile
jsr _ApplyTiles ; This function actually draws the new tiles into the code field
; jsr _ApplyBG0XPos ; Patch the code field instructions with exit BRA opcode

View File

@ -597,7 +597,9 @@ _TSSetBG1Origin
_TSGetTileAt
:y equ FirstParam
:x equ FirstParam+2
:output equ FirstParam+4
:output_id equ FirstParam+4
:output_x equ FirstParam+6
:output_y equ FirstParam+8
_TSEntry
@ -609,16 +611,23 @@ _TSGetTileAt
jsr _GetTileAt
bcc :ok
lda #0
sta :output_x,s
sta :output_y,s
bra :out
:ok
txa
sta :output_x,s
tya
sta :output_y,s
; Load the tile at that tile store location
:ok
jsr _GetTileStoreOffset0 ; Get the address of the X,Y tile position
tax
lda TileStore+TS_TILE_ID,x
:out
sta :output,s
sta :output_id,s
_TSExit #0;#4
@ -990,7 +999,16 @@ _TSSetAddress
sta ExtSpriteRenderer+2
bra :out
:next_4
:next_4 cmp #extBG0TileUpdate
bne :next_5
lda :ptr,s
sta ExtUpdateBG0Tiles
lda :ptr+2,s
sta ExtUpdateBG0Tiles+2
bra :out
:next_5
:out
_TSExit #0;#6

View File

@ -562,6 +562,8 @@ BG1YCache ENT
ExtSpriteRenderer ENT
dw 0,0
ExtUpdateBG0Tiles ENT
dw 0,0
; Scaling tables for the BG1 rotation tables.
ScalingTables ENT