diff --git a/demos/smb/Main.s b/demos/smb/Main.s index 1a72772..a9495b9 100644 --- a/demos/smb/Main.s +++ b/demos/smb/Main.s @@ -184,26 +184,26 @@ FTblTmp equ 228 ;AreaNumber = $0760 ;OffScr_WorldNumber = $0766 ;OffScr_AreaNumber = $0767 -; OffScr_LevelNumber = $0763 +;OffScr_LevelNumber = $0763 EvtLoop :spin lda nmiCount beq :spin stz nmiCount - sep #$20 - lda #1 - stal ROMBase+$075f - stal ROMBase+$0766 +; sep #$20 +; lda #1 +; stal ROMBase+$075f +; stal ROMBase+$0766 - lda #1 - stal ROMBase+$0763 - stal ROMBase+$075c +; lda #2 +; stal ROMBase+$0763 +; stal ROMBase+$075c - lda #2 - stal ROMBase+$0767 - stal ROMBase+$0760 - rep #$30 +; lda #$2 +; stal ROMBase+$0767 +; stal ROMBase+$0760 +; rep #$30 ; The GTE playfield is 41 tiles wide, but the NES is 32 tiles wide. Fortunately, the game ; keeps track of the global coordinates of each level at diff --git a/demos/smb/ppu.s b/demos/smb/ppu.s index 725817a..d79cea0 100644 --- a/demos/smb/ppu.s +++ b/demos/smb/ppu.s @@ -730,7 +730,7 @@ buildShadowBitmap ldy OAM_COPY,x iny ; This is the y-coordinate of the top of the sprite - ldx y2idx,y ; Get the index into the shadowBitmap array for this y coordinate + ldx y2idx,y ; Get the index into the shadowBitmap array for this y coordinate (y -> blk_y) lda y2low,y ; Get the bit pattern for the first byte ora shadowBitmap,x sta shadowBitmap,x @@ -750,6 +750,34 @@ buildShadowBitmap rep #$30 rts +; Set the SCB values equal to the bitmap to visually debug + ldx #0 + ldy #0 +:vloop + lda #8 + sta Tmp6 + lda shadowBitmap+2,y +:iloop + asl + pha + + lda #0 + bcc :zero + inc +:zero stal $E19D00,x + pla + + inx + dec Tmp6 + bne :iloop + + iny + cpy #25 + bcc :vloop + + rep #$30 + rts + y2idx const32 $00 const32 $04 const32 $08 @@ -777,14 +805,48 @@ mul8 db $00,$08,$10,$18,$20,$28,$30,$38 db $C0,$C8,$D0,$D8,$E0,$E8,$F0,$F8 ; Given a bit pattern, create a LUT that count to the first set bit (MSB -> LSB), e.g. $0F = 4, $3F = 2 -offset db 0,7,6,6,5,5,5,5,4,4,4,4,4,4,4,4,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3 ; 0, 1, 2, 4, 8, 16 - db 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2 ; 32 +offset + db 8,7,6,6,5,5,5,5,4,4,4,4,4,4,4,4,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3 + db 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2 db 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 db 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +invOffset + db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + db 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 + db 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 + db 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2 + db 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,6,6,7,8 + +; Mask off all of the high 1 bits, keep all of the low bits after the first zero, e.g. +; offsetMask($E3) = offsetMask(11100011) = $1F. %11100011 & $1F = $03 +offsetMask + db $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF + db $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF + db $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF + db $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF + db $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF + db $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF + db $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF + db $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF ; 127 (everything here has a 0 in the high bit) + + db $7F,$7F,$7F,$7F,$7F,$7F,$7F,$7F,$7F,$7F,$7F,$7F,$7F,$7F,$7F,$7F ; $80 - $8F + db $7F,$7F,$7F,$7F,$7F,$7F,$7F,$7F,$7F,$7F,$7F,$7F,$7F,$7F,$7F,$7F ; $90 - $9F + db $7F,$7F,$7F,$7F,$7F,$7F,$7F,$7F,$7F,$7F,$7F,$7F,$7F,$7F,$7F,$7F ; $A0 - $AF + db $7F,$7F,$7F,$7F,$7F,$7F,$7F,$7F,$7F,$7F,$7F,$7F,$7F,$7F,$7F,$7F ; $B0 - $BF + + db $3F,$3F,$3F,$3F,$3F,$3F,$3F,$3F,$3F,$3F,$3F,$3F,$3F,$3F,$3F,$3F ; $C0 - $CF + db $3F,$3F,$3F,$3F,$3F,$3F,$3F,$3F,$3F,$3F,$3F,$3F,$3F,$3F,$3F,$3F ; $D0 - $DF + + db $1F,$1F,$1F,$1F,$1F,$1F,$1F,$1F,$1F,$1F,$1F,$1F,$1F,$1F,$1F,$1F ; $E0 - $EF + db $0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F,$07,$07,$07,$07,$03,$03,$01,$00 ; $F0 - $FF + ; Scan the bitmap list and call BltRange on the ranges mx %00 @@ -880,8 +942,9 @@ exposeShadowList ; This routine needs to adjust the y-coordinates based of the offset of the GTE playfield within ; the PPU RAM shadowBitmapToList -:top equ Tmp0 -:bottom equ Tmp2 +:top equ Tmp0 +:bottom equ Tmp2 +:bitfield equ Tmp4 sep #$30 @@ -894,9 +957,9 @@ shadowBitmapToList ldy shadowBitmap,x beq :zero_next - lda mul8-y_offset_rows,x ; This is the scanline we're on (offset by the starting byte) + lda {mul8-y_offset_rows},x ; This is the scanline we're on (offset by the starting byte) clc - adc offset,y ; This is the first line defined by the bit pattern + adc offset,y ; This is the first line defined by the bit pattern sta :top bra :one_next @@ -908,13 +971,19 @@ shadowBitmapToList :one_loop lda shadowBitmap,x ; if the next byte is all sprite, just continue - eor #$FF + cmp #$FF beq :one_next - tay ; Use the inverted bitfield in order to re-use the same lookup table - lda mul8-y_offset_rows,x +; The byte has to look like 1...10...0*. The first step is to mask off the high bits and store the result +; back into the shadowBitmap + + tay + and offsetMask,y + sta shadowBitmap,x + + lda {mul8-y_offset_rows},x clc - adc offset,y + adc invOffset,y ldy shadowListCount sta shadowListBot,y @@ -922,7 +991,11 @@ shadowBitmapToList sta shadowListTop,y iny sty shadowListCount - bra :zero_next + +; Loop back to check if there is more sprite data on this byte + + bra :zero_loop + :one_next inx @@ -1015,7 +1088,7 @@ drawOAMSprites cli jsr buildShadowBitmap ; Run though and quickly create a bitmap of lines with sprites - jsr shadowBitmapToList ; Can the bitmap and create (top, bottom) pairs of ranges + jsr shadowBitmapToList ; Scan the bitmap and create (top, bottom) pairs of ranges jsr drawShadowList ; Draw the background lines that have sprite on them jsr drawSprites ; Draw the sprites on top of the lines they occupy diff --git a/demos/smb/rom2.s b/demos/smb/rom2.s index fa41e4c..06685e6 100644 --- a/demos/smb/rom2.s +++ b/demos/smb/rom2.s @@ -682,14 +682,16 @@ PPUDATA_READ EXT PPUDATA_WRITE EXT PPUDMA_WRITE EXT +APU_PUSLE1_REG1_WRITE EXT +APU_PUSLE1_REG2_WRITE EXT +APU_PUSLE1_REG3_WRITE EXT +APU_PUSLE1_REG4_WRITE EXT + ROMBase ENT ds $7A00 -; Macro to replace sta abs,y instructions that access zero page space with direct page -; instruction to actually get the correct data on the direct page _and_ bank memory. -; That way any lda 00,x or lda 0000,y will - -; Hooks to call back to the GTE harness for PPU memory-mapped accesses +; Define a helper for the ROM InitializeMemory routine to properly deal with the +; direct page and stack being in a different bank mx %11 GteInitMem php @@ -703,6 +705,53 @@ GteLoop plp rts +; Hooks to call back to the GTE harness for APU register access +APU_IND_X_REG3_W +; x is 0, 4 or 8 -- dispatch to the correct underlying routine + jmp (:reg_tbl,x) +:reg_tbl dw APU_PULSE1_REG3_W,APU_PULSE1_REG3_W + dw APU_PULSE2_REG3_W,APU_PULSE2_REG3_W, + dw APU_TRIANGLE_REG3_W,APU_TRIANGLE_REG3_W + +APU_IND_X_REG4_W + jmp (:reg_tbl,x) +:reg_tbl dw APU_PULSE1_REG4_W,APU_PULSE1_REG4_W + dw APU_PULSE2_REG4_W,APU_PULSE2_REG4_W, + dw APU_TRIANGLE_REG4_W,APU_TRIANGLE_REG4_W + +APU_PULSE1_REG1_W +; jsl APU_PULSE1_REG1_WRITE + rts +APU_PULSE1_REG1_WX +; jsl APU_PULSE1_REG1_WRITE + rts +APU_PULSE1_REG2_W +; jsl APU_PULSE1_REG2_WRITE + rts +APU_PULSE1_REG2_WY +; jsl APU_PULSE1_REG2_WRITE + rts +APU_PULSE1_REG3_W +; jsl APU_PULSE1_REG3_WRITE + rts +APU_PULSE1_REG4_W +; jsl APU_PULSE1_REG4_WRITE + rts + +APU_PULSE2_REG3_W +; jsl APU_PUSLE2_REG3_WRITE + rts +APU_PULSE2_REG4_W +; jsl APU_PULSE2_REG4_WRITE + rts + +APU_TRIANGLE_REG3_W +; jsl APU_TRIANGLE_REG3_WRITE + rts +APU_TRIANGLE_REG4_W +; jsl APU_TRIANGLE_REG4_WRITE + rts +; Hooks to call back to the GTE harness for PPU memory-mapped accesses mx %11 PPU_CTRL_W jsl PPUCTRL_WRITE @@ -4466,7 +4515,7 @@ AreaDataOfsLoopback LoadAreaPointer jsr FindAreaPointer ;find it and store it here sta AreaPointer -GetAreaType and #%01100000 ;mask out all but d6 and d5 +GetAreaType and #%01100000 ;mask out all but d6 and d5 asl rol rol @@ -4516,7 +4565,7 @@ GetAreaDataAddrs bcc StoreFore sta BackgroundColorCtrl ;if 4 or greater, save value here as bg color control lda #$00 -StoreFore sta ForegroundScenery ;if less, save value here as foreground scenery +StoreFore sta ForegroundScenery ;if less, save value here as foreground scenery pla ;pull byte from stack and push it back pha and #%00111000 ;save player entrance control bits @@ -4554,7 +4603,7 @@ StoreFore sta ForegroundScenery ;if less, save value here as foreground scen bne StoreStyle ;and nullify other value sta CloudTypeOverride ;otherwise store value in other place lda #$00 -StoreStyle sta AreaStyle +StoreStyle sta AreaStyle lda AreaDataLow ;increment area data address by 2 bytes clc adc #$02 diff --git a/macros/GTE.Macs.s b/macros/GTE.Macs.s index 4ebdddc..4c7a967 100644 --- a/macros/GTE.Macs.s +++ b/macros/GTE.Macs.s @@ -189,6 +189,7 @@ vblCallback equ $0004 extSpriteRenderer equ $0005 rawDrawTile equ $0006 extBG0TileUpdate equ $0007 +userTileCallback equ $0008 ; CopyPicToBG1 flags COPY_PIC_NORMAL equ $0000 ; Copy into BG1 buffer in "normal mode"