diff --git a/demos/smb/Main.s b/demos/smb/Main.s index 7c14493..b58c9da 100644 --- a/demos/smb/Main.s +++ b/demos/smb/Main.s @@ -36,6 +36,7 @@ OldROMScrollEdge equ 20 CurrScrollEdge equ 22 CurrNTQueueEnd equ 40 BGToggle equ 44 +LastEnable equ 46 Tmp0 equ 240 Tmp1 equ 242 @@ -43,6 +44,7 @@ Tmp2 equ 244 Tmp3 equ 246 Tmp4 equ 248 Tmp5 equ 250 +Tmp6 equ 252 FTblPtr equ 224 FTblTmp equ 228 @@ -63,8 +65,12 @@ FTblTmp equ 228 lda #1 sta BGToggle + lda #$0008 + sta LastEnable + ; 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 + tdc sta DPSave clc @@ -74,6 +80,8 @@ FTblTmp equ 228 adc #$1FF ; Stack starts at the top of the page sta ROMStk +; brl :debug + lda #ENGINE_MODE_USER_TOOL ; Engine in Fast Mode as a User Tool jsr GTEStartUp ; Load and install the GTE User Tool @@ -95,6 +103,12 @@ FTblTmp equ 228 pea #UpdateFromPPU _GTESetAddress +; Install a custom tile blitter to merge PPU attributes with the extracted tile data + pea userTileCallback + pea #^NESTileBlitter + pea #NESTileBlitter + _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 @@ -114,13 +128,17 @@ FTblTmp equ 228 ; pea #144 _GTESetScreenMode + ldx #AreaPalette + lda #TmpPalette + jsr NESColorToIIgs + pea $0000 - pea #^Greyscale - pea #Greyscale + pea #^TmpPalette + pea #TmpPalette _GTESetPalette ; Convert the CHR ROM from the cart into GTE tiles - +:debug ldx #0 ldy #0 :tloop @@ -128,14 +146,14 @@ FTblTmp equ 228 phy lda #TileBuff - jsr ConvertROMTile + jsr ConvertROMTile2 lda 1,s - pha + pha ; start inc - pha - pea #^TileBuff + pha ; finish + pea #^TileBuff ; pointer pea #TileBuff _GTELoadTileSet @@ -220,7 +238,7 @@ EvtLoop stz singleStepMode :not_g - cmp #'r' ; Refresh + cmp #'r' ; Refresh bne :not_1 jsr CopyStatus @@ -258,11 +276,37 @@ Greyscale dw $0000,$5555,$AAAA,$FFFF dw $0000,$5555,$AAAA,$FFFF dw $0000,$5555,$AAAA,$FFFF +TmpPalette ds 32 + lastKey dw 0 singleStepMode dw 0 nmiCount dw 0 DPSave dw 0 +; Convert NES palette entries to IIgs +; X = NES palette (16 color indices) +; A = 32 byte array to write results +NESColorToIIgs + sta Tmp0 + stz Tmp1 + +:loop lda: 0,x + asl + tay + lda nesPalette,y + ldy Tmp1 + sta (Tmp0),y + + inx + inx + + iny + iny + sty Tmp1 + cpy #32 + bcc :loop + rts + ; Helper to perform the essential functions of rendering a frame RenderFrame @@ -309,8 +353,12 @@ RenderFrame lda ppumask and #$0008 ; Isolate background enable/disable bit + cmp LastEnable + beq :bghop + sta LastEnable pha _GTEEnableBackground +:bghop pea $FFFF ; NES mode _GTERender @@ -402,8 +450,6 @@ 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 lda CurrNTQueueEnd sta nt_queue_front rts @@ -433,10 +479,24 @@ DrainNTQueue lda nt_queue,x ; get the PPU address that was stored sta :PPUAddr ; save for later if we draw this tile + lda :PPUAddr 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 + jsr PPUAddrToTileStore ; convert the PPU address to relative tile store coordinates + bcc :set_tile ; if it's onscreen, draw it +:skip + pla ; Pop the saved x-register into the accumulator + inc + inc + and #NT_QUEUE_MOD + cmp CurrNTQueueEnd + bne :loop + +:out + sta nt_queue_front + rts + +:set_tile ; 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) @@ -455,27 +515,93 @@ DrainNTQueue ldx :PPUAddr lda PPU_MEM,x and #$00FF - ora #$0100 + ora #$0100+TILE_USER_BIT pha + jsr GetPaletteSelect + ora 1,s ; Merge bits 9 and 10 into the Tile ID that's on the stack + sta 1,s + _GTESetTile inc :Count + brl :skip -:skip - pla ; Pop the saved x-register into the accumulator - inc - inc - and #NT_QUEUE_MOD - cmp CurrNTQueueEnd - bne :loop -:out - sta nt_queue_front +; Do the calculation to get the palette select bits from the attribute byte that corresponds to the +; PPU address in the x-registers +GetPaletteSelect -; lda :Count -; ldx #8*160 -; ldy #$FFFF -; jsr DrawWord +; Get the palette select bits. We need to calculate both the address of the attribute value and +; which bits to isolate from the byte and then merge into the TileId. The most straighforward way +; is to identify the quadrant right away and have alternate code paths + txa + and #$2C00 + ora #$03C0 + sta Tmp6 ; Base attribute table address + +; Not calculate the byte within the attribute table + + txa + and #$001F ; 32 byte rows, divide by 4 + lsr + lsr + ora Tmp6 + sta Tmp6 + + txa + and #$0380 ; Isolate the top 3 bits + lsr + lsr + lsr + lsr + ora Tmp6 + tay + + lda PPU_MEM,y ; This is the attribute byte + and #$00FF + pha ; Which we save for a minute + +; Now figure out the quadrant that this address is in for the attribute byte value + + txa + bit #%01000010 + beq :top_left + bit #%01000000 + beq :top_right + bit #%00000010 + beq :bot_left + +:bot_right + pla + and #$00C0 + asl + asl + asl + bra :set_palette + +:bot_left + pla + and #$0030 + xba + lsr + lsr + lsr + bra :set_palette + +:top_right + pla + and #$000C + xba + lsr + bra :set_palette + +:top_left + pla + and #$0003 + xba + asl + +:set_palette rts ; Copy the necessary columns into the TileStore when setting a new scroll position @@ -645,8 +771,11 @@ CopyStatus ldx Tmp2 ; Nametable address lda PPU_MEM+$2000,x and #$00FF - ora #$0100 + ora #$0100+TILE_USER_BIT pha + jsr GetPaletteSelect + ora 1,s ; Merge bits 9 and 10 into the Tile ID that's on the stack + sta 1,s ; Advance to the next tile (no wrapping needed) @@ -721,8 +850,11 @@ CopyNametable ldx Tmp2 ; Nametable address lda PPU_MEM+$2000,x and #$00FF - ora #$0100 + ora #$0100+TILE_USER_BIT ; USe top 256 tiles and set as a user-defined tile pha + jsr GetPaletteSelect + ora 1,s ; Merge bits 9 and 10 into the Tile ID that's on the stack + sta 1,s ; Advance to the next tile (handle nametable wrapping) @@ -802,132 +934,132 @@ native_joy ENT ; ; This keeps the tile in 2-bit mode in a format that makes it easy to look up pixel data ; based on a dynamic palette selection +; +; Tiles are stored in a pre-shifted, 16-bit format (2 bits per pixel): 0000000w wxxyyzz0 +; When rendered, the 2-bit palette selection is passed in bits 9 and 10 and ORed with +; the palette data to create a single word of 00000ppw wxxyyzz0. This value is used +; to index directly into a 2048-byte swizzel table that will load the appropriate +; pixel data for the word. There are 2 swizzle tables, one for tiles and one for sprites +; that take care of mapping the 25 possible on-screen colors to a 16-color palette. +ConvertROMTile2 +:DPtr equ Tmp1 +:MPtr equ Tmp2 + jsr ROMTileToLookup + +; Now we have 32 bytes (4 x 8) with each byte being a 4-bit value that holds two pairs of bits +; from the PPU pattern table. We use these 4-bit values as lookup indices into tables +; that decode the values differently depending on the use case. + + sta :DPtr + clc + adc #32 ; Move to the mask + sta :MPtr + + lda #0 ; Zero out high byte + sep #$30 ; 8-bit mode + ldy #0 + +:loop + lda (:DPtr),y ; Load the index for the initial high nibble + tax + lda MLUT4,x ; Look up the mask value for this byte. This table decodes the 4 bits into an 8-bit mask + sta (:MPtr),y + + lda DLUT2,x ; Look up the two, 2-bit pixel values for this quad of bits. This remains a 4-bit value + asl + asl + asl + asl + sta Tmp3 + + iny + lda (:DPtr),y + tax + lda DLUT2,x ; Look up the two, 2-bit pixel values for next quad of bits + ora Tmp3 ; Move it int othe top nibble since it will decode to the top-byte on the SHR screen + + dey + sta (:DPtr),y ; Put in low byte + iny + lda #0 + sta (:DPtr),y ; Zero high byte + + lda MLUT4,x + sta (:MPtr),y + + iny + cpy #32 + bcc :loop + + +; Reverse and shift the data + + rep #$30 + ldy #8 + ldx :DPtr + +:rloop + lda: 0,x ; Load the word: xx00 + jsr reverse2 ; Reverse the bottom byte in chunks of 2 bits + asl ; Shift by 1 for indexing + sta: 66,x + asl: 0,x ; Shift the original word, too + + lda: 2,x + jsr reverse2 + asl + sta: 64,x + asl: 2,x + + inx + inx + inx + inx + dey + bne :rloop + rts ; X = address in the rom file ; A = address to write ConvertROMTile -DPtr equ Tmp1 -MPtr equ Tmp2 +:DPtr equ Tmp1 +:MPtr equ Tmp2 - sta DPtr + jsr ROMTileToLookup + + sta :DPtr clc adc #32 ; Move to the mask - sta MPtr - lda #0 ; Clear A and B + sta :MPtr - sep #$20 ; 8-bit mode + sep #$30 ; 8-bit mode ldy #0 :loop - lda CHR_ROM,x ; Load the high bits - rol - rol - rol - rol - and #$06 - sta Tmp0 - - lda CHR_ROM+8,x - and #$C0 - lsr - lsr - lsr - ora Tmp0 ; Combine the two and create a lookup value - - phx + lda (:DPtr),y ; Load the index for this tile byte tax - lda DLUT,x ; Look up the two, 4-bit pixel values for this quad of bits - sta (DPtr),y - lda MLUT,x - sta (MPtr),y + lda DLUT4,x ; Look up the two, 4-bit pixel values for this quad of bits + sta (:DPtr),y + lda MLUT4,x ; Look up the mask value for this byte + sta (:MPtr),y iny - plx - -; Repeat for bits 4 & 5 - - ldal CHR_ROM,x ; Load the high bits - and #$30 - lsr - lsr - lsr - sta Tmp0 - - ldal CHR_ROM+8,x - and #$30 - lsr - ora Tmp0 ; Combine the two and create a lookup value - - phx - tax - lda DLUT,x - sta (DPtr),y - lda MLUT,x - sta (MPtr),y - iny - plx - -; Repeat for bits 2 & 3 - - ldal CHR_ROM,x ; Load the high bits - and #$0C - lsr - sta Tmp0 - - ldal CHR_ROM+8,x - and #$0C - asl - ora Tmp0 ; Combine the two and create a lookup value - - phx - tax - lda DLUT,x - sta (DPtr),y - lda MLUT,x - sta (MPtr),y - iny - plx - -; Repeat for bits 0 & 1 - - ldal CHR_ROM,x ; Load the high bits - and #$03 - asl - sta Tmp0 - - ldal CHR_ROM+8,x - and #$03 - asl - asl - asl - ora Tmp0 ; Combine the two and create a lookup value - - phx - tax - lda DLUT,x - sta (DPtr),y - lda MLUT,x - sta (MPtr),y - iny - plx - - inx cpy #32 - bcs :done - brl :loop -:done - rep #$20 + bcc :loop -; Flip the tile before returning +; Switch back to 16-bit mode and flip the tile data before returning + + rep #$20 ldy #16 - ldx DPtr + ldx :DPtr + :rloop lda: 0,x - jsr reverse + jsr reverse4 sta: 66,x lda: 2,x - jsr reverse + jsr reverse4 sta: 64,x inx inx @@ -937,7 +1069,176 @@ MPtr equ Tmp2 bne :rloop rts -reverse +; Build a table of index values for the ROM tile data. The different routines +; can mix and match the lookup table information as they see fit +; +; X = address in the rom file +; A = address to write +; +; For each byte of pattern table memory, we create two bytes in the DPtr with +; a lookup value for the pixels corresponding to bits in that location +; +; Example: +; Tile 0: $03,$0F,$1F,$1F,$1C,$24,$26,$66, $00,$00,$00,$00,$1F,$3F,$3F,$7F +; +; 0,1 2,3 4,5 6,7 +; +; $03 | 00000011 | 00000000 | $00 -> 0000 0000 0000 0011 -> 00 00 05 00 +; $0F | 00001111 | 00000000 | $00 -> 0000 0000 0011 0011 -> 00 00 55 00 +; $1F | 00011111 | 00000000 | $00 -> 0000 0001 0011 0011 -> 01 00 55 00 +; $1F | 00011111 | 00000000 | $00 -> 0000 0001 0011 0011 -> 01 00 55 00 +; $1C | 00011100 | 00011111 | $1F -> 0000 0101 1111 1100 -> 03 00 FA 00 +; $24 | 00100100 | 00111111 | $3F -> 0000 1110 1101 1100 -> 0E 00 BA 00 +; $26 | 00100110 | 00111111 | $3F -> 0000 1110 1101 1110 -> 0E 00 BE 00 +; $66 | 01100110 | 01111111 | $7F -> 0101 1110 1101 1110 -> 3E 00 BE 00 +; +; +; e.g. Plane 0 = 0101 0001 (LSB) +; Plane 1 = 1001 0001 (MSB) +; +; For speed, use a table and convert one pair at a time +; +; Pair 1 = 1001 -> 1001 +; Pair 2 = 0101 -> 0011 +; Pair 3 = 0000 -> 0000 +; Pair 4 = 0101 -> 0011 +; +; Lookup[0] = 10 01 00 11 +; Lookup[1] = 00 00 00 11 +; +; Tile Data = 63 00 03 00 +; Pixel Data = 12 03 00 03 + mx %00 +ROMTileToLookup +:DPtr equ Tmp1 + pha + phx + + sta :DPtr + lda #0 ; Clear A and B + + sep #$20 ; 8-bit mode + ldy #0 + +:loop + +; Top two bits from each byte defines the two left-most pixels + + lda CHR_ROM,x ; Load the low bits + and #$C0 + lsr + lsr + sta Tmp0 + + lda CHR_ROM+8,x ; Load the high bits + and #$C0 + ora Tmp0 + lsr + lsr + lsr + lsr + sta (:DPtr),y ; First byte + iny + +; Repeat for bits 4 & 5 + + lda CHR_ROM,x + and #$30 + lsr + lsr + sta Tmp0 + + lda CHR_ROM+8,x + and #$30 + ora Tmp0 + lsr + lsr + sta (:DPtr),y + iny + +; Repeat for bits 2 & 3 + + lda CHR_ROM,x + and #$0C + lsr + lsr + sta Tmp0 + + lda CHR_ROM+8,x + and #$0C + ora Tmp0 ; Combine the two and create a lookup value + sta (:DPtr),y + iny + +; Repeat for bits 0 & 1 + + lda CHR_ROM,x ; Load the high bits + and #$03 + sta Tmp0 + + lda CHR_ROM+8,x + and #$03 + asl + asl + ora Tmp0 ; Combine the two and create a lookup value + sta (:DPtr),y + iny + + inx + cpy #32 + bcc :loop + + rep #$20 + plx + pla + rts + +; Reverse the 2-bit fields in a byte + mx %00 +reverse2 + php + sta Tmp0 + stz Tmp1 + + sep #$20 + + and #$C0 + lsr + lsr + lsr + lsr + lsr + lsr + tsb Tmp1 + + lda Tmp0 + and #$30 + lsr + lsr + tsb Tmp1 + + lda Tmp0 + and #$0C + asl + asl + tsb Tmp1 + + lda Tmp0 + and #$03 + asl + asl + asl + asl + asl + asl + ora Tmp1 + + plp + rts + +; Reverse the nibbles in a word + mx %00 +reverse4 xba sta Tmp0 and #$0F0F @@ -955,11 +1256,17 @@ reverse ora Tmp1 rts +; Look up the 2-bit indexes for the data words +DLUT2 db $00,$01,$04,$05 ; CHR_ROM[0] = xy, CHR_ROM[8] = 00 -> 0x0y + db $02,$03,$06,$07 ; CHR_ROM[0] = xy, CHR_ROM[8] = 01 -> 0x1y + db $08,$09,$0C,$0D ; CHR_ROM[0] = xy, CHR_ROM[8] = 10 -> + db $0A,$0B,$0E,$0F ; CHR_ROM[0] = xy, CHR_ROM[8] = 11 -DLUT dw $00,$01,$10,$11 ; CHR_ROM[0] = xx, CHR_ROM[8] = 00 - dw $02,$03,$12,$13 ; CHR_ROM[0] = xx, CHR_ROM[8] = 01 - dw $20,$21,$30,$31 ; CHR_ROM[0] = xx, CHR_ROM[8] = 10 - dw $22,$23,$32,$33 ; CHR_ROM[0] = xx, CHR_ROM[8] = 11 +; Look up the 4-bit indexes for the data words +DLUT4 db $00,$01,$10,$11 ; CHR_ROM[0] = xx, CHR_ROM[8] = 00 + db $02,$03,$12,$13 ; CHR_ROM[0] = xx, CHR_ROM[8] = 01 + db $20,$21,$30,$31 ; CHR_ROM[0] = xx, CHR_ROM[8] = 10 + db $22,$23,$32,$33 ; CHR_ROM[0] = xx, CHR_ROM[8] = 11 ;MLUT dw $FF,$F0,$0F,$00 ; dw $F0,$F0,$00,$00 @@ -967,10 +1274,10 @@ DLUT dw $00,$01,$10,$11 ; CHR_ROM[0] = xx, CHR_ROM[8] = 00 ; dw $00,$00,$00,$00 ; Inverted mask for using eor/and/eor rendering -MLUT dw $00,$0F,$F0,$FF - dw $0F,$0F,$FF,$FF - dw $F0,$FF,$F0,$FF - dw $FF,$FF,$FF,$FF +MLUT4 db $00,$0F,$F0,$FF + db $0F,$0F,$FF,$FF + db $F0,$FF,$F0,$FF + db $FF,$FF,$FF,$FF ; Extracted tiles TileBuff ds 128 @@ -1132,7 +1439,13 @@ nmiTask ldal singleStepMode bne :no_nmi +; lda #1 +; jsr setborder + jsr triggerNMI + +; lda #0 +; jsr setborder :no_nmi pld @@ -1199,7 +1512,13 @@ readInput ds \,$00 ; pad to the next page boundary PPU_MEM -CHR_ROM put chr2.s ; 8K of CHR-ROM at PPU memory $0000 - $2000 -PPU_NT ds $2000 ; Nametable memory from $2000 - $3000, $3F00 - $3F14 is palette RAM -PPU_OAM ds 256 ; 256 bytes of separate OAM RAM - +CHR_ROM put chr2.s ; 8K of CHR-ROM at PPU memory $0000 - $2000 +PPU_NT ds $2000 ; Nametable memory from $2000 - $3000, $3F00 - $3F14 is palette RAM +PPU_OAM ds 256 ; 256 bytes of separate OAM RAM + +; Palettes of NES color indexes +;AreaPalette dw $0F, $00, $29, $1A, $09, $36, $1C, $30, $21, $16, $27, $18, $17, $3C, $1D, $37 +AreaPalette dw $22, $00, $29, $1A, $0F, $36, $17, $30, $21, $16, $27, $18, $1A, $00, $00, $37 + +; Palette remapping + put pal_w11.s \ No newline at end of file diff --git a/demos/smb/mkswizzetbl.sh b/demos/smb/mkswizzetbl.sh new file mode 100644 index 0000000..e5df867 --- /dev/null +++ b/demos/smb/mkswizzetbl.sh @@ -0,0 +1,19 @@ +# World 1-1, Underground +#node swizzle.js W11_T0 2 3 4 +#node swizzle.js W11_T1 13 6 0 +#node swizzle.js W11_T2 7 8 6 +#node swizzle.js W11_T3 1 12 6 +#node swizzle.js W11_S0 15 10 11 +#node swizzle.js W11_S1 6 5 12 +#node swizzle.js W11_S2 9 7 10 +#node swizzle.js W11_S3 14 13 6 + +# World 1-1, Aboveground +node swizzle.js W11_T0 2 3 4 +node swizzle.js W11_T1 5 6 4 +node swizzle.js W11_T2 7 8 4 +node swizzle.js W11_T3 1 6 4 +node swizzle.js W11_S0 15 10 11 +node swizzle.js W11_S1 12 7 10 +node swizzle.js W11_S2 9 7 10 +node swizzle.js W11_S3 4 5 6 \ No newline at end of file diff --git a/demos/smb/package.json b/demos/smb/package.json index a9cd71b..491597b 100644 --- a/demos/smb/package.json +++ b/demos/smb/package.json @@ -13,10 +13,12 @@ "scripts": { "test": "npm run build && npm run build:image && npm run gsport", "gsport": "%npm_package_config_gsport%", + "build:rom": "%npm_package_config_merlin32% -V %npm_package_config_macros% RomOnly.s", "build:sys16": "%npm_package_config_merlin32% -V %npm_package_config_macros% App.s", "build": "npm run build:tool && npm run build:sys16", "build:tool": "%npm_package_config_merlin32% -V %npm_package_config_macros% ../../src/Master.s", "build:image": "build-image.bat %npm_package_config_cadius%", + "build:swizzle": "", "debug": "\"%npm_package_config_crossrunner%\" SuperMarioGS -Source SuperMarioGS_S02__Output.txt -Source SuperMarioGS_S03__Output.txt -Debug -CompatibilityLayer" }, diff --git a/demos/smb/pal_w11.s b/demos/smb/pal_w11.s new file mode 100644 index 0000000..18f0891 --- /dev/null +++ b/demos/smb/pal_w11.s @@ -0,0 +1,136 @@ +W11_T0 + dw $0000,$0200,$0300,$0400,$2000,$2200,$2300,$2400,$3000,$3200,$3300,$3400,$4000,$4200,$4300,$4400 + dw $0002,$0202,$0302,$0402,$2002,$2202,$2302,$2402,$3002,$3202,$3302,$3402,$4002,$4202,$4302,$4402 + dw $0003,$0203,$0303,$0403,$2003,$2203,$2303,$2403,$3003,$3203,$3303,$3403,$4003,$4203,$4303,$4403 + dw $0004,$0204,$0304,$0404,$2004,$2204,$2304,$2404,$3004,$3204,$3304,$3404,$4004,$4204,$4304,$4404 + dw $0020,$0220,$0320,$0420,$2020,$2220,$2320,$2420,$3020,$3220,$3320,$3420,$4020,$4220,$4320,$4420 + dw $0022,$0222,$0322,$0422,$2022,$2222,$2322,$2422,$3022,$3222,$3322,$3422,$4022,$4222,$4322,$4422 + dw $0023,$0223,$0323,$0423,$2023,$2223,$2323,$2423,$3023,$3223,$3323,$3423,$4023,$4223,$4323,$4423 + dw $0024,$0224,$0324,$0424,$2024,$2224,$2324,$2424,$3024,$3224,$3324,$3424,$4024,$4224,$4324,$4424 + dw $0030,$0230,$0330,$0430,$2030,$2230,$2330,$2430,$3030,$3230,$3330,$3430,$4030,$4230,$4330,$4430 + dw $0032,$0232,$0332,$0432,$2032,$2232,$2332,$2432,$3032,$3232,$3332,$3432,$4032,$4232,$4332,$4432 + dw $0033,$0233,$0333,$0433,$2033,$2233,$2333,$2433,$3033,$3233,$3333,$3433,$4033,$4233,$4333,$4433 + dw $0034,$0234,$0334,$0434,$2034,$2234,$2334,$2434,$3034,$3234,$3334,$3434,$4034,$4234,$4334,$4434 + dw $0040,$0240,$0340,$0440,$2040,$2240,$2340,$2440,$3040,$3240,$3340,$3440,$4040,$4240,$4340,$4440 + dw $0042,$0242,$0342,$0442,$2042,$2242,$2342,$2442,$3042,$3242,$3342,$3442,$4042,$4242,$4342,$4442 + dw $0043,$0243,$0343,$0443,$2043,$2243,$2343,$2443,$3043,$3243,$3343,$3443,$4043,$4243,$4343,$4443 + dw $0044,$0244,$0344,$0444,$2044,$2244,$2344,$2444,$3044,$3244,$3344,$3444,$4044,$4244,$4344,$4444 +W11_T1 + dw $0000,$0500,$0600,$0400,$5000,$5500,$5600,$5400,$6000,$6500,$6600,$6400,$4000,$4500,$4600,$4400 + dw $0005,$0505,$0605,$0405,$5005,$5505,$5605,$5405,$6005,$6505,$6605,$6405,$4005,$4505,$4605,$4405 + dw $0006,$0506,$0606,$0406,$5006,$5506,$5606,$5406,$6006,$6506,$6606,$6406,$4006,$4506,$4606,$4406 + dw $0004,$0504,$0604,$0404,$5004,$5504,$5604,$5404,$6004,$6504,$6604,$6404,$4004,$4504,$4604,$4404 + dw $0050,$0550,$0650,$0450,$5050,$5550,$5650,$5450,$6050,$6550,$6650,$6450,$4050,$4550,$4650,$4450 + dw $0055,$0555,$0655,$0455,$5055,$5555,$5655,$5455,$6055,$6555,$6655,$6455,$4055,$4555,$4655,$4455 + dw $0056,$0556,$0656,$0456,$5056,$5556,$5656,$5456,$6056,$6556,$6656,$6456,$4056,$4556,$4656,$4456 + dw $0054,$0554,$0654,$0454,$5054,$5554,$5654,$5454,$6054,$6554,$6654,$6454,$4054,$4554,$4654,$4454 + dw $0060,$0560,$0660,$0460,$5060,$5560,$5660,$5460,$6060,$6560,$6660,$6460,$4060,$4560,$4660,$4460 + dw $0065,$0565,$0665,$0465,$5065,$5565,$5665,$5465,$6065,$6565,$6665,$6465,$4065,$4565,$4665,$4465 + dw $0066,$0566,$0666,$0466,$5066,$5566,$5666,$5466,$6066,$6566,$6666,$6466,$4066,$4566,$4666,$4466 + dw $0064,$0564,$0664,$0464,$5064,$5564,$5664,$5464,$6064,$6564,$6664,$6464,$4064,$4564,$4664,$4464 + dw $0040,$0540,$0640,$0440,$5040,$5540,$5640,$5440,$6040,$6540,$6640,$6440,$4040,$4540,$4640,$4440 + dw $0045,$0545,$0645,$0445,$5045,$5545,$5645,$5445,$6045,$6545,$6645,$6445,$4045,$4545,$4645,$4445 + dw $0046,$0546,$0646,$0446,$5046,$5546,$5646,$5446,$6046,$6546,$6646,$6446,$4046,$4546,$4646,$4446 + dw $0044,$0544,$0644,$0444,$5044,$5544,$5644,$5444,$6044,$6544,$6644,$6444,$4044,$4544,$4644,$4444 +W11_T2 + dw $0000,$0700,$0800,$0400,$7000,$7700,$7800,$7400,$8000,$8700,$8800,$8400,$4000,$4700,$4800,$4400 + dw $0007,$0707,$0807,$0407,$7007,$7707,$7807,$7407,$8007,$8707,$8807,$8407,$4007,$4707,$4807,$4407 + dw $0008,$0708,$0808,$0408,$7008,$7708,$7808,$7408,$8008,$8708,$8808,$8408,$4008,$4708,$4808,$4408 + dw $0004,$0704,$0804,$0404,$7004,$7704,$7804,$7404,$8004,$8704,$8804,$8404,$4004,$4704,$4804,$4404 + dw $0070,$0770,$0870,$0470,$7070,$7770,$7870,$7470,$8070,$8770,$8870,$8470,$4070,$4770,$4870,$4470 + dw $0077,$0777,$0877,$0477,$7077,$7777,$7877,$7477,$8077,$8777,$8877,$8477,$4077,$4777,$4877,$4477 + dw $0078,$0778,$0878,$0478,$7078,$7778,$7878,$7478,$8078,$8778,$8878,$8478,$4078,$4778,$4878,$4478 + dw $0074,$0774,$0874,$0474,$7074,$7774,$7874,$7474,$8074,$8774,$8874,$8474,$4074,$4774,$4874,$4474 + dw $0080,$0780,$0880,$0480,$7080,$7780,$7880,$7480,$8080,$8780,$8880,$8480,$4080,$4780,$4880,$4480 + dw $0087,$0787,$0887,$0487,$7087,$7787,$7887,$7487,$8087,$8787,$8887,$8487,$4087,$4787,$4887,$4487 + dw $0088,$0788,$0888,$0488,$7088,$7788,$7888,$7488,$8088,$8788,$8888,$8488,$4088,$4788,$4888,$4488 + dw $0084,$0784,$0884,$0484,$7084,$7784,$7884,$7484,$8084,$8784,$8884,$8484,$4084,$4784,$4884,$4484 + dw $0040,$0740,$0840,$0440,$7040,$7740,$7840,$7440,$8040,$8740,$8840,$8440,$4040,$4740,$4840,$4440 + dw $0047,$0747,$0847,$0447,$7047,$7747,$7847,$7447,$8047,$8747,$8847,$8447,$4047,$4747,$4847,$4447 + dw $0048,$0748,$0848,$0448,$7048,$7748,$7848,$7448,$8048,$8748,$8848,$8448,$4048,$4748,$4848,$4448 + dw $0044,$0744,$0844,$0444,$7044,$7744,$7844,$7444,$8044,$8744,$8844,$8444,$4044,$4744,$4844,$4444 +W11_T3 + dw $0000,$0100,$0600,$0400,$1000,$1100,$1600,$1400,$6000,$6100,$6600,$6400,$4000,$4100,$4600,$4400 + dw $0001,$0101,$0601,$0401,$1001,$1101,$1601,$1401,$6001,$6101,$6601,$6401,$4001,$4101,$4601,$4401 + dw $0006,$0106,$0606,$0406,$1006,$1106,$1606,$1406,$6006,$6106,$6606,$6406,$4006,$4106,$4606,$4406 + dw $0004,$0104,$0604,$0404,$1004,$1104,$1604,$1404,$6004,$6104,$6604,$6404,$4004,$4104,$4604,$4404 + dw $0010,$0110,$0610,$0410,$1010,$1110,$1610,$1410,$6010,$6110,$6610,$6410,$4010,$4110,$4610,$4410 + dw $0011,$0111,$0611,$0411,$1011,$1111,$1611,$1411,$6011,$6111,$6611,$6411,$4011,$4111,$4611,$4411 + dw $0016,$0116,$0616,$0416,$1016,$1116,$1616,$1416,$6016,$6116,$6616,$6416,$4016,$4116,$4616,$4416 + dw $0014,$0114,$0614,$0414,$1014,$1114,$1614,$1414,$6014,$6114,$6614,$6414,$4014,$4114,$4614,$4414 + dw $0060,$0160,$0660,$0460,$1060,$1160,$1660,$1460,$6060,$6160,$6660,$6460,$4060,$4160,$4660,$4460 + dw $0061,$0161,$0661,$0461,$1061,$1161,$1661,$1461,$6061,$6161,$6661,$6461,$4061,$4161,$4661,$4461 + dw $0066,$0166,$0666,$0466,$1066,$1166,$1666,$1466,$6066,$6166,$6666,$6466,$4066,$4166,$4666,$4466 + dw $0064,$0164,$0664,$0464,$1064,$1164,$1664,$1464,$6064,$6164,$6664,$6464,$4064,$4164,$4664,$4464 + dw $0040,$0140,$0640,$0440,$1040,$1140,$1640,$1440,$6040,$6140,$6640,$6440,$4040,$4140,$4640,$4440 + dw $0041,$0141,$0641,$0441,$1041,$1141,$1641,$1441,$6041,$6141,$6641,$6441,$4041,$4141,$4641,$4441 + dw $0046,$0146,$0646,$0446,$1046,$1146,$1646,$1446,$6046,$6146,$6646,$6446,$4046,$4146,$4646,$4446 + dw $0044,$0144,$0644,$0444,$1044,$1144,$1644,$1444,$6044,$6144,$6644,$6444,$4044,$4144,$4644,$4444 +W11_S0 + dw $0000,$0f00,$0a00,$0b00,$f000,$ff00,$fa00,$fb00,$a000,$af00,$aa00,$ab00,$b000,$bf00,$ba00,$bb00 + dw $000f,$0f0f,$0a0f,$0b0f,$f00f,$ff0f,$fa0f,$fb0f,$a00f,$af0f,$aa0f,$ab0f,$b00f,$bf0f,$ba0f,$bb0f + dw $000a,$0f0a,$0a0a,$0b0a,$f00a,$ff0a,$fa0a,$fb0a,$a00a,$af0a,$aa0a,$ab0a,$b00a,$bf0a,$ba0a,$bb0a + dw $000b,$0f0b,$0a0b,$0b0b,$f00b,$ff0b,$fa0b,$fb0b,$a00b,$af0b,$aa0b,$ab0b,$b00b,$bf0b,$ba0b,$bb0b + dw $00f0,$0ff0,$0af0,$0bf0,$f0f0,$fff0,$faf0,$fbf0,$a0f0,$aff0,$aaf0,$abf0,$b0f0,$bff0,$baf0,$bbf0 + dw $00ff,$0fff,$0aff,$0bff,$f0ff,$ffff,$faff,$fbff,$a0ff,$afff,$aaff,$abff,$b0ff,$bfff,$baff,$bbff + dw $00fa,$0ffa,$0afa,$0bfa,$f0fa,$fffa,$fafa,$fbfa,$a0fa,$affa,$aafa,$abfa,$b0fa,$bffa,$bafa,$bbfa + dw $00fb,$0ffb,$0afb,$0bfb,$f0fb,$fffb,$fafb,$fbfb,$a0fb,$affb,$aafb,$abfb,$b0fb,$bffb,$bafb,$bbfb + dw $00a0,$0fa0,$0aa0,$0ba0,$f0a0,$ffa0,$faa0,$fba0,$a0a0,$afa0,$aaa0,$aba0,$b0a0,$bfa0,$baa0,$bba0 + dw $00af,$0faf,$0aaf,$0baf,$f0af,$ffaf,$faaf,$fbaf,$a0af,$afaf,$aaaf,$abaf,$b0af,$bfaf,$baaf,$bbaf + dw $00aa,$0faa,$0aaa,$0baa,$f0aa,$ffaa,$faaa,$fbaa,$a0aa,$afaa,$aaaa,$abaa,$b0aa,$bfaa,$baaa,$bbaa + dw $00ab,$0fab,$0aab,$0bab,$f0ab,$ffab,$faab,$fbab,$a0ab,$afab,$aaab,$abab,$b0ab,$bfab,$baab,$bbab + dw $00b0,$0fb0,$0ab0,$0bb0,$f0b0,$ffb0,$fab0,$fbb0,$a0b0,$afb0,$aab0,$abb0,$b0b0,$bfb0,$bab0,$bbb0 + dw $00bf,$0fbf,$0abf,$0bbf,$f0bf,$ffbf,$fabf,$fbbf,$a0bf,$afbf,$aabf,$abbf,$b0bf,$bfbf,$babf,$bbbf + dw $00ba,$0fba,$0aba,$0bba,$f0ba,$ffba,$faba,$fbba,$a0ba,$afba,$aaba,$abba,$b0ba,$bfba,$baba,$bbba + dw $00bb,$0fbb,$0abb,$0bbb,$f0bb,$ffbb,$fabb,$fbbb,$a0bb,$afbb,$aabb,$abbb,$b0bb,$bfbb,$babb,$bbbb +W11_S1 + dw $0000,$0c00,$0700,$0a00,$c000,$cc00,$c700,$ca00,$7000,$7c00,$7700,$7a00,$a000,$ac00,$a700,$aa00 + dw $000c,$0c0c,$070c,$0a0c,$c00c,$cc0c,$c70c,$ca0c,$700c,$7c0c,$770c,$7a0c,$a00c,$ac0c,$a70c,$aa0c + dw $0007,$0c07,$0707,$0a07,$c007,$cc07,$c707,$ca07,$7007,$7c07,$7707,$7a07,$a007,$ac07,$a707,$aa07 + dw $000a,$0c0a,$070a,$0a0a,$c00a,$cc0a,$c70a,$ca0a,$700a,$7c0a,$770a,$7a0a,$a00a,$ac0a,$a70a,$aa0a + dw $00c0,$0cc0,$07c0,$0ac0,$c0c0,$ccc0,$c7c0,$cac0,$70c0,$7cc0,$77c0,$7ac0,$a0c0,$acc0,$a7c0,$aac0 + dw $00cc,$0ccc,$07cc,$0acc,$c0cc,$cccc,$c7cc,$cacc,$70cc,$7ccc,$77cc,$7acc,$a0cc,$accc,$a7cc,$aacc + dw $00c7,$0cc7,$07c7,$0ac7,$c0c7,$ccc7,$c7c7,$cac7,$70c7,$7cc7,$77c7,$7ac7,$a0c7,$acc7,$a7c7,$aac7 + dw $00ca,$0cca,$07ca,$0aca,$c0ca,$ccca,$c7ca,$caca,$70ca,$7cca,$77ca,$7aca,$a0ca,$acca,$a7ca,$aaca + dw $0070,$0c70,$0770,$0a70,$c070,$cc70,$c770,$ca70,$7070,$7c70,$7770,$7a70,$a070,$ac70,$a770,$aa70 + dw $007c,$0c7c,$077c,$0a7c,$c07c,$cc7c,$c77c,$ca7c,$707c,$7c7c,$777c,$7a7c,$a07c,$ac7c,$a77c,$aa7c + dw $0077,$0c77,$0777,$0a77,$c077,$cc77,$c777,$ca77,$7077,$7c77,$7777,$7a77,$a077,$ac77,$a777,$aa77 + dw $007a,$0c7a,$077a,$0a7a,$c07a,$cc7a,$c77a,$ca7a,$707a,$7c7a,$777a,$7a7a,$a07a,$ac7a,$a77a,$aa7a + dw $00a0,$0ca0,$07a0,$0aa0,$c0a0,$cca0,$c7a0,$caa0,$70a0,$7ca0,$77a0,$7aa0,$a0a0,$aca0,$a7a0,$aaa0 + dw $00ac,$0cac,$07ac,$0aac,$c0ac,$ccac,$c7ac,$caac,$70ac,$7cac,$77ac,$7aac,$a0ac,$acac,$a7ac,$aaac + dw $00a7,$0ca7,$07a7,$0aa7,$c0a7,$cca7,$c7a7,$caa7,$70a7,$7ca7,$77a7,$7aa7,$a0a7,$aca7,$a7a7,$aaa7 + dw $00aa,$0caa,$07aa,$0aaa,$c0aa,$ccaa,$c7aa,$caaa,$70aa,$7caa,$77aa,$7aaa,$a0aa,$acaa,$a7aa,$aaaa +W11_S2 + dw $0000,$0900,$0700,$0a00,$9000,$9900,$9700,$9a00,$7000,$7900,$7700,$7a00,$a000,$a900,$a700,$aa00 + dw $0009,$0909,$0709,$0a09,$9009,$9909,$9709,$9a09,$7009,$7909,$7709,$7a09,$a009,$a909,$a709,$aa09 + dw $0007,$0907,$0707,$0a07,$9007,$9907,$9707,$9a07,$7007,$7907,$7707,$7a07,$a007,$a907,$a707,$aa07 + dw $000a,$090a,$070a,$0a0a,$900a,$990a,$970a,$9a0a,$700a,$790a,$770a,$7a0a,$a00a,$a90a,$a70a,$aa0a + dw $0090,$0990,$0790,$0a90,$9090,$9990,$9790,$9a90,$7090,$7990,$7790,$7a90,$a090,$a990,$a790,$aa90 + dw $0099,$0999,$0799,$0a99,$9099,$9999,$9799,$9a99,$7099,$7999,$7799,$7a99,$a099,$a999,$a799,$aa99 + dw $0097,$0997,$0797,$0a97,$9097,$9997,$9797,$9a97,$7097,$7997,$7797,$7a97,$a097,$a997,$a797,$aa97 + dw $009a,$099a,$079a,$0a9a,$909a,$999a,$979a,$9a9a,$709a,$799a,$779a,$7a9a,$a09a,$a99a,$a79a,$aa9a + dw $0070,$0970,$0770,$0a70,$9070,$9970,$9770,$9a70,$7070,$7970,$7770,$7a70,$a070,$a970,$a770,$aa70 + dw $0079,$0979,$0779,$0a79,$9079,$9979,$9779,$9a79,$7079,$7979,$7779,$7a79,$a079,$a979,$a779,$aa79 + dw $0077,$0977,$0777,$0a77,$9077,$9977,$9777,$9a77,$7077,$7977,$7777,$7a77,$a077,$a977,$a777,$aa77 + dw $007a,$097a,$077a,$0a7a,$907a,$997a,$977a,$9a7a,$707a,$797a,$777a,$7a7a,$a07a,$a97a,$a77a,$aa7a + dw $00a0,$09a0,$07a0,$0aa0,$90a0,$99a0,$97a0,$9aa0,$70a0,$79a0,$77a0,$7aa0,$a0a0,$a9a0,$a7a0,$aaa0 + dw $00a9,$09a9,$07a9,$0aa9,$90a9,$99a9,$97a9,$9aa9,$70a9,$79a9,$77a9,$7aa9,$a0a9,$a9a9,$a7a9,$aaa9 + dw $00a7,$09a7,$07a7,$0aa7,$90a7,$99a7,$97a7,$9aa7,$70a7,$79a7,$77a7,$7aa7,$a0a7,$a9a7,$a7a7,$aaa7 + dw $00aa,$09aa,$07aa,$0aaa,$90aa,$99aa,$97aa,$9aaa,$70aa,$79aa,$77aa,$7aaa,$a0aa,$a9aa,$a7aa,$aaaa +W11_S3 + dw $0000,$0400,$0500,$0600,$4000,$4400,$4500,$4600,$5000,$5400,$5500,$5600,$6000,$6400,$6500,$6600 + dw $0004,$0404,$0504,$0604,$4004,$4404,$4504,$4604,$5004,$5404,$5504,$5604,$6004,$6404,$6504,$6604 + dw $0005,$0405,$0505,$0605,$4005,$4405,$4505,$4605,$5005,$5405,$5505,$5605,$6005,$6405,$6505,$6605 + dw $0006,$0406,$0506,$0606,$4006,$4406,$4506,$4606,$5006,$5406,$5506,$5606,$6006,$6406,$6506,$6606 + dw $0040,$0440,$0540,$0640,$4040,$4440,$4540,$4640,$5040,$5440,$5540,$5640,$6040,$6440,$6540,$6640 + dw $0044,$0444,$0544,$0644,$4044,$4444,$4544,$4644,$5044,$5444,$5544,$5644,$6044,$6444,$6544,$6644 + dw $0045,$0445,$0545,$0645,$4045,$4445,$4545,$4645,$5045,$5445,$5545,$5645,$6045,$6445,$6545,$6645 + dw $0046,$0446,$0546,$0646,$4046,$4446,$4546,$4646,$5046,$5446,$5546,$5646,$6046,$6446,$6546,$6646 + dw $0050,$0450,$0550,$0650,$4050,$4450,$4550,$4650,$5050,$5450,$5550,$5650,$6050,$6450,$6550,$6650 + dw $0054,$0454,$0554,$0654,$4054,$4454,$4554,$4654,$5054,$5454,$5554,$5654,$6054,$6454,$6554,$6654 + dw $0055,$0455,$0555,$0655,$4055,$4455,$4555,$4655,$5055,$5455,$5555,$5655,$6055,$6455,$6555,$6655 + dw $0056,$0456,$0556,$0656,$4056,$4456,$4556,$4656,$5056,$5456,$5556,$5656,$6056,$6456,$6556,$6656 + dw $0060,$0460,$0560,$0660,$4060,$4460,$4560,$4660,$5060,$5460,$5560,$5660,$6060,$6460,$6560,$6660 + dw $0064,$0464,$0564,$0664,$4064,$4464,$4564,$4664,$5064,$5464,$5564,$5664,$6064,$6464,$6564,$6664 + dw $0065,$0465,$0565,$0665,$4065,$4465,$4565,$4665,$5065,$5465,$5565,$5665,$6065,$6465,$6565,$6665 + dw $0066,$0466,$0566,$0666,$4066,$4466,$4566,$4666,$5066,$5466,$5566,$5666,$6066,$6466,$6566,$6666 diff --git a/demos/smb/palette.s b/demos/smb/palette.s index f83afc2..e6c785f 100644 --- a/demos/smb/palette.s +++ b/demos/smb/palette.s @@ -67,3 +67,55 @@ nesPalette dw $0EEE dw $0111 dw $0111 + +; Swizzle tables based on AreaType +; +; IIgs palette index 0 is always the background color: 'BBB' +; IIgs palette index 0 is always the color cycling color 'RRR' +; +; The rest are remapped. +; +; Underground: +; +; T0: $0F $29 $1A $09 +; T1: --- $3C $1C $0F +; T2: --- $30 $21 $1C +; T3: --- RRR $17 $1C +; S0: --- $16 $27 $18 --> $37 $27 $16 +; S1: --- $1C $36 $17 +; S2: --- $16 $30 $27 +; S3: --- $1D $3C $1C --> $0F RR $29 $1A $09 $36 $1C $30 $21 $16 $27 $18 $17 $3C $1D $37 : 0 free colors +; --> $00 $01 $02 $03 $04 $05 $06 $07 $08 $09 $0A $0B $0C $0D $0E $0F +; +; Mapped palettes +; +; T0: 0 2 3 4 +; T1: 0 D 6 0 +; T2: 0 7 8 6 +; T3: 0 1 C 6 +; S0: 0 F A B +; S1: 0 6 5 C +; S2: 0 9 7 A +; S3: 0 E D 6 +; +; Above Ground +; +; T0: $22 $29 $1A $0F +; T1: --- $36 $17 $0F +; T2: --- $30 $21 $0F +; T3: --- RRR $17 $0F +; S0: --- $16 $27 $18 --> $37 $27 $16 +; S1: --- $1A $30 $17 +; S2: --- $16 $30 $27 +; S3: --- $0F $36 $17 --> $22 RR $29 $1A $0F $36 $17 $30 $21 $16 $27 $18 $1A --- --- $16 : 2 free colors +; --> $00 $01 $02 $03 $04 $05 $06 $07 $08 $09 $0A $0B $0C $0D $0E $0F +; Mapped palettes +; +; T0: 0 2 3 4 +; T1: 0 5 6 4 +; T2: 0 7 8 4 +; T3: 0 1 6 4 +; S0: 0 F A B +; S1: 0 C 7 A +; S2: 0 9 7 A +; S3: 0 4 5 6 \ No newline at end of file diff --git a/demos/smb/ppu.s b/demos/smb/ppu.s index a190c4b..1a3337b 100644 --- a/demos/smb/ppu.s +++ b/demos/smb/ppu.s @@ -259,42 +259,15 @@ PPUDATA_WRITE ENT plb pha phx + phy 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 + ldy PPU_MEM,x ; Save in case we need to compare later sta PPU_MEM,x rep #$30 @@ -307,13 +280,50 @@ PPUDATA_WRITE ENT ; 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 +; +; There is one special case. We want the nt_queue to only be a queue of tiles to possibly redraw. If the PPU +; data that is updated is in the attribute table area, then we do some extra work to decide which of the 16 +; tiles *actually* need to be redrawn cpx #$3000 bcs :nocache cpx #$2000 ; Change to $2080 to ignore score field updates bcc :nocache - phy + txa + and #$03C0 + cmp #$03C0 + beq :attrtbl + + jsr :enqueue ; Add the address in the X register to the queue + +:nocache + cpx #$3F00 + bcc :done + brl :extra + +; bcs :extra +; bra :done + +:nochange + rep #$30 + txa + clc + adc ppuincr + and #$3FFF + sta ppuaddr + +:done + sep #$30 + ply + plx + pla + plb + plp + rtl + + mx %00 +:enqueue lda nt_queue_end tay inc @@ -327,37 +337,98 @@ PPUDATA_WRITE ENT sta nt_queue,y :full - lda #1 - jsr setborder - ply +; lda #1 +; jsr setborder + rts -:nocache - cpx #$3F00 - bcs :extra - bra :done +:attrtbl + txa ; Calculate the base address in the nametable from the attribute address + and #$2C00 + pha + txa + and #$0007 + asl + asl + ora 1,s + sta 1,s + txa + and #$0038 + asl + asl + asl + asl + ora 1,s + sta 1,s -:nochange - rep #$30 + tya + eor PPU_MEM,x ; Identify bit that have changed + and #$00FF + bit #$00C0 + beq :skip_bot_right + + pha + lda 3,s + clc + adc #64+2 ; offset 2 rows an 2 columns + tax + jsr :enqueue_blk + pla +:skip_bot_right + + bit #$0030 + beq :skip_bot_left + + pha + lda 3,s + clc + adc #64 ; offset 2 rows + tax + jsr :enqueue_blk + pla +:skip_bot_left + + bit #$000C + beq :skip_top_right + + pha + lda 3,s + tax + inx + inx + tax + jsr :enqueue_blk + pla +:skip_top_right + + bit #$0003 + beq :skip_top_left + + lda 1,s + tax + jsr :enqueue_blk +:skip_top_left + + pla ; pop the base address off + brl :done + +; Pass in PPU address in X register +:enqueue_blk + jsr :enqueue + inx + jsr :enqueue txa clc - adc ppuincr - and #$3FFF - sta ppuaddr - -:done - sep #$30 - plx - pla - plb - plp - rtl - + adc #32 + tax + jsr :enqueue + dex + jmp :enqueue setborder php sep #$20 eorl $E0C034 - and #$F0 + and #$0F eorl $E0C034 stal $E0C034 plp @@ -365,45 +436,13 @@ setborder ; Do some extra work to keep palette data in sync ; -; Based on the palette data that SMB uses, we map the NES palette entries as +; Based on the palette data that SMB uses, we remap the NES palette entries +; based on the AreaType, so most of the PPU writes are ignored. However, +; we do update some specific palette entries ; -; NES Description IIgs Palette -; ---------------------------------------- -; BG0 Background color 0 -; BG0,1 Light Green 1 -; BG0,2 Dark Green 2 -; BG0,3 Black 3 -; BG1,1 Peach 4 -; BG1,2 Brown 5 -; BG1,3 Black 3 -; BG2,1 White 6 -; BG2,2 Light Blue 7 -; BG2,3 Black 3 -; BG3,1 Cycle 8 ; Coins / Blocks -; BG3,2 Brown 5 -; BG3,3 Black 3 -; SP0 0 -; SP0,1 Red 9 -; SP0,2 Orange 10 -; SP0,3 Olive 11 -; SP1,1 Dark Green 2 -; SP1,2 White 6 -; SP1,3 Orange 10 -; SP2,1 Red 9 -; SP2,2 White 6 -; SP2,3 Orange 10 -; SP3,1 Black 3 -; SP3,2 Peach 4 -; SP3,3 Brown 5 -; -; There are 4 color to spare in case we need to add more entries. This mapping table is important because -; we have to have a custom tile rendering function and custom sprite rendering function that will dynamically -; map the 2-bit tile data into the proper palette range. This will likely be implemented with an 8-bit -; swizzle table. Possible optimization later on is to pre-swizzle certain tiles assuming that the palette -; assignments never change. -; -; BG Palette 2 can probably be ignored because it's just for the top of the screen and we can use a separate -; SCB palette for that line +; BG0,0 maps to IIgs Palette index 0 (Background color) +; BG3,1 maps to IIgs Palette index 1 (Color cycle for blocks) +; SP0,1 maps to IIgs Palette index 15 (Player primary color; changes with fire flower) mx %00 :extra txa @@ -427,92 +466,29 @@ ppu_3F00 ldx #0 brl extra_out -; Background Palette 0 -ppu_3F01 - lda PPU_MEM+$3F01 - ldx #2 - brl extra_out - -ppu_3F02 - lda PPU_MEM+$3F02 - ldx #4 - brl extra_out - -ppu_3F03 - lda PPU_MEM+$3F03 - ldx #6 - brl extra_out - ; Shadow for background color ppu_3F10 lda PPU_MEM+$3F10 ldx #0 brl extra_out -; Sprite Palette 0 + +; Tile palette 3, color 1 +ppu_3F0D + lda PPU_MEM+$3F0D + ldx #2 + brl extra_out + +; Sprite Palette 0, color 1 ppu_3F11 lda PPU_MEM+$3F11 - ldx #8 - brl extra_out - -ppu_3F12 - lda PPU_MEM+$3F12 - ldx #10 - brl extra_out - -ppu_3F13 - lda PPU_MEM+$3F13 - ldx #12 - brl extra_out - -; Sprite Palette 1 -ppu_3F15 - lda PPU_MEM+$3F15 - ldx #14 - brl extra_out - -ppu_3F16 - lda PPU_MEM+$3F16 - ldx #16 - brl extra_out - -ppu_3F17 - lda PPU_MEM+$3F17 - ldx #18 - brl extra_out - -; Sprite Palette 2 -ppu_3F19 - lda PPU_MEM+$3F19 - ldx #20 - brl extra_out - -ppu_3F1A - lda PPU_MEM+$3F1A - ldx #22 - brl extra_out - -ppu_3F1B - lda PPU_MEM+$3F1B - ldx #24 - brl extra_out - -; Sprite Palette 3 -ppu_3F1D - lda PPU_MEM+$3F1D - ldx #26 - brl extra_out - -ppu_3F1E - lda PPU_MEM+$3F1E - ldx #28 - brl extra_out - -ppu_3F1F - lda PPU_MEM+$3F1F ldx #30 brl extra_out +ppu_3F01 +ppu_3F02 +ppu_3F03 + ppu_3F04 ppu_3F05 ppu_3F06 @@ -524,29 +500,42 @@ ppu_3F0A ppu_3F0B ppu_3F0C -ppu_3F0D + ppu_3F0E ppu_3F0F +ppu_3F12 +ppu_3F13 + ppu_3F14 +ppu_3F15 +ppu_3F16 +ppu_3F17 + ppu_3F18 +ppu_3F19 +ppu_3F1A +ppu_3F1B + ppu_3F1C +ppu_3F1D +ppu_3F1E +ppu_3F1F brl no_pal ; Exit code to set a IIgs palette entry from the PPU memory ; ; A = NES palette value ; X = IIgs Palette index extra_out - phy and #$00FF asl tay lda nesPalette,y - ply stal $E19E00,x no_pal sep #$30 + ply plx pla plb @@ -1072,6 +1061,8 @@ oam_loop tax :noflip +; sta swizzle ; store a pointer to the swizzle table to use + pla asl and #$0146 ; Set the vflip bit, priority, and palette select bits @@ -1091,3 +1082,45 @@ drawTilePatch rep #$30 rts +; Custom tile blitter +; +; D = GTE blitter direct page space +; X = offset to the tile record +; + mx %00 + +; Temporary tile space on the direct page +tmp_tile_data equ 80 + +;USER_TILE_RECORD equ 178 +USER_TILE_ID equ 178 ; copy of the tile id in the tile store +;USER_TILE_CODE_PTR equ 180 ; pointer to the code bank in which to patch +USER_TILE_ADDR equ 184 ; address in the tile data bank (set on entry) +USER_FREE_SPACE equ 186 ; a few bytes of scratch space + +LDA_IND_LONG_IDX equ $B7 + +; Assume that when the tile is updated, it includes a full 10-bit value with the +; palette bits included with the lookup bits +NESTileBlitter + lda USER_TILE_ID + and #$0600 ; Select the tile palette from the tile id + clc + adc #W11_T0 + sta USER_FREE_SPACE + lda #^W11_T0 + sta USER_FREE_SPACE+2 + + ldx USER_TILE_ADDR ; Get the address of the tile (base only) +]line equ 0 + lup 8 + ldy: {]line*4},x + db LDA_IND_LONG_IDX,USER_FREE_SPACE + sta tmp_tile_data+{]line*4} + ldy: {]line*4}+2,x + db LDA_IND_LONG_IDX,USER_FREE_SPACE + sta tmp_tile_data+{]line*4}+2 +]line equ ]line+1 + --^ + lda #1 ; Request tmp_tile_data be copies to tile store + rtl \ No newline at end of file diff --git a/demos/smb/swizzle.js b/demos/smb/swizzle.js new file mode 100644 index 0000000..7388d49 --- /dev/null +++ b/demos/smb/swizzle.js @@ -0,0 +1,54 @@ +// Generate seizzle tables +// +// Maps an 8-bit value of wwxxyyzz to a lookup table that takes each 2-bit +// value to a 16-bit pixel index. Zero always maps to zero. The input +// is three 4-bit values that define the targets for 1, 2, and 3. + +// Run as: node swizzle.js label val1 val2 val3 +if (process.argv.length !== 6) { + console.log(process.argv); + process.exit(1); +} + +const output = process.stdout; + +const values = [ + 0, + Number(process.argv[3]), + Number(process.argv[4]), + Number(process.argv[5]), +]; + +output.write(process.argv[2] + '\n'); +for (let w = 0; w < 4; w++) { + for (let x = 0; x < 4; x++) { + output.write(' dw '); + const row = []; + for (let y = 0; y < 4; y++) { + for (let z = 0; z < 4; z++) { + // Because the NES PPU bits define the pixel order from high bit to low bit, but the + // 65816 is little endian, we need to swap the byte order in the mapping + /* + const target = + (values[w] * 4096) + + (values[x] * 256) + + (values[y] * 16) + + values[z]; + */ + const target = + (values[w] * 16) + + (values[x] * 1) + + (values[y] * 4096) + + (values[z] * 256); + + row.push(target); + } + } + // Output the values + output.write(row.map(s => '$' + s.toString(16).padStart(4, '0')).join(',')); + + // Line break + output.write('\n'); + } +} +