├── src ├── qol.asm ├── spc │ ├── TRI6_SR2.ASM │ ├── TRI6_SR3.ASM │ ├── TRI6_SR4.ASM │ ├── TRI6_SR1.ASM │ ├── spc.bin │ ├── TRI6.ASM │ ├── spc_v0_first_half.bin │ ├── pl1a-0.asm │ ├── pl1a-2.asm │ ├── pl1a-1.asm │ ├── pl1a-3.asm │ ├── TRI6_SL1.ASM │ ├── pl1-0.asm │ ├── pl1-1.asm │ ├── pl1-2.asm │ ├── pl1-3.asm │ ├── pl1.asm │ ├── pl1a.asm │ ├── TRI6_SL2.ASM │ ├── pl2.asm │ ├── PL2-1.ASM │ ├── PL2-2.ASM │ ├── PL2-3.ASM │ ├── pl2-0.asm │ ├── TRI6_SL3.ASM │ ├── pl3-0.asm │ ├── pl3-1.asm │ ├── pl3-2.asm │ ├── pl3-3.asm │ ├── pl3.asm │ └── TRI5.ASM ├── options.bin ├── wram_routines.bin ├── wram_routines_v0.bin ├── 2a03_emulator_first_8000.asm ├── windows.asm ├── hiromheader.asm ├── input.asm ├── macros.inc ├── main.asm ├── resetvector.asm ├── konamicode.asm ├── 2a03_conversion.asm ├── wram_routines_v0.asm ├── 2a03_variables.inc ├── scrolling-mmc3.asm ├── intro_screen.asm ├── scrolling.asm ├── palette_lookup.asm ├── palette_updates.asm ├── wram_routines.asm ├── hirom.cfg ├── vars.inc ├── hdma_scroll_lookups.asm ├── bank-snes.asm ├── sprites.asm ├── options_macro_defs.asm ├── 2a03_conversion_v0.asm ├── hardware-status-switches.asm ├── options_screen.asm ├── tiles.asm └── dpcm_audio.asm ├── resources ├── asar.exe ├── boxart-lifeforce.pdn └── boxart-lifeforce.png ├── README.md └── utilities ├── parseNesFileToBanks.go └── generate_options_asm.go /src/qol.asm: -------------------------------------------------------------------------------- 1 | ; QOL_SETTINGS = $081D 2 | ; HOVER_TICK = $081F 3 | -------------------------------------------------------------------------------- /src/spc/TRI6_SR2.ASM: -------------------------------------------------------------------------------- 1 | db $a3, $04, $73, $fb, $8c, $04, $73, $fb, $8c 2 | -------------------------------------------------------------------------------- /src/spc/TRI6_SR3.ASM: -------------------------------------------------------------------------------- 1 | db $a3, $07, $f8, $07, $f8, $07, $f8, $07, $f8 2 | -------------------------------------------------------------------------------- /src/spc/TRI6_SR4.ASM: -------------------------------------------------------------------------------- 1 | db $a3, $78, $78, $78, $78, $78, $78, $78, $78 2 | -------------------------------------------------------------------------------- /src/spc/TRI6_SR1.ASM: -------------------------------------------------------------------------------- 1 | 2 | db $a3, $02, $46, $75, $31, $fd, $b9, $8a, $ce 3 | -------------------------------------------------------------------------------- /src/options.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rumbleminze/lifeforce-snes/HEAD/src/options.bin -------------------------------------------------------------------------------- /src/spc/spc.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rumbleminze/lifeforce-snes/HEAD/src/spc/spc.bin -------------------------------------------------------------------------------- /resources/asar.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rumbleminze/lifeforce-snes/HEAD/resources/asar.exe -------------------------------------------------------------------------------- /src/wram_routines.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rumbleminze/lifeforce-snes/HEAD/src/wram_routines.bin -------------------------------------------------------------------------------- /src/wram_routines_v0.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rumbleminze/lifeforce-snes/HEAD/src/wram_routines_v0.bin -------------------------------------------------------------------------------- /src/spc/TRI6.ASM: -------------------------------------------------------------------------------- 1 | db $a2, $01, $23, $45, $67, $76, $54, $32, $10 2 | db $a3, $fe, $dc, $ba, $98, $89, $ab, $cd, $ef -------------------------------------------------------------------------------- /resources/boxart-lifeforce.pdn: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rumbleminze/lifeforce-snes/HEAD/resources/boxart-lifeforce.pdn -------------------------------------------------------------------------------- /resources/boxart-lifeforce.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rumbleminze/lifeforce-snes/HEAD/resources/boxart-lifeforce.png -------------------------------------------------------------------------------- /src/spc/spc_v0_first_half.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rumbleminze/lifeforce-snes/HEAD/src/spc/spc_v0_first_half.bin -------------------------------------------------------------------------------- /src/2a03_emulator_first_8000.asm: -------------------------------------------------------------------------------- 1 | .segment "EMU_2A03_B1" 2 | sound_emulator_first_2FBB: 3 | .incbin "spc/spc_v0_first_half.bin" 4 | 5 | -------------------------------------------------------------------------------- /src/spc/pl1a-0.asm: -------------------------------------------------------------------------------- 1 | 2 | ; Old 3 | ;.db $B3,$44,$BB,$BB,$BB,$BB,$BB,$BB,$BB 4 | 5 | ; New 6 | ; [b3] 54abbbbbbbbbbbbb 7 | db $b3, $54, $ab, $bb, $bb, $bb, $bb, $bb, $bb -------------------------------------------------------------------------------- /src/spc/pl1a-2.asm: -------------------------------------------------------------------------------- 1 | 2 | ; Old 3 | ;.db $B3,$44,$44,$44,$44,$BB,$BB,$BB,$BB 4 | 5 | ; New 6 | ; [b3] 54444444abbbbbbb 7 | db $b3, $54, $44, $44, $44, $ab, $bb, $bb, $bb -------------------------------------------------------------------------------- /src/spc/pl1a-1.asm: -------------------------------------------------------------------------------- 1 | 2 | ; Old 3 | ;.db $B3,$44,$44,$BB,$BB,$BB,$BB,$BB,$BB 4 | 5 | ; New 6 | ; [b3] 5444abbbbbbbbbbb 7 | db $b3, $54, $44, $ab, $bb, $bb, $bb, $bb, $bb 8 | -------------------------------------------------------------------------------- /src/spc/pl1a-3.asm: -------------------------------------------------------------------------------- 1 | 2 | ; Old 3 | ;.db $B3,$BB,$BB,$BB,$BB,$BB,$BB,$44,$44 4 | 5 | ; New 6 | ; [b3] abbbbbbbbbbb5444 7 | db $b3, $ab, $bb, $bb, $bb, $bb, $bb, $54, $44 8 | -------------------------------------------------------------------------------- /src/spc/TRI6_SL1.ASM: -------------------------------------------------------------------------------- 1 | db $a2, $00, $11, $22, $33, $44, $55, $66, $77 2 | db $a2, $77, $66, $55, $44, $33, $22, $11, $00 3 | db $a2, $ff, $ee, $dd, $cc, $bb, $aa, $99, $88 4 | db $a3, $88, $99, $aa, $bb, $cc, $dd, $ee, $ff 5 | -------------------------------------------------------------------------------- /src/spc/pl1-0.asm: -------------------------------------------------------------------------------- 1 | 2 | ; Old 3 | ;.db $B0,$44,$44,$BB,$BB,$BB,$BB,$BB,$BB 4 | ;.db $B3,$BB,$BB,$BB,$BB,$BB,$BB,$BB,$BB 5 | 6 | ; New 7 | ; [b0] 5444abbbbbbbbbbb 8 | ; [b3] bbbbbbbbbbbbbbbb 9 | db $b0, $54, $44, $ab, $bb, $bb, $bb, $bb, $bb 10 | db $b3, $bb, $bb, $bb, $bb, $bb, $bb, $bb, $bb -------------------------------------------------------------------------------- /src/spc/pl1-1.asm: -------------------------------------------------------------------------------- 1 | 2 | ; Old 3 | ;.db $B0,$44,$44,$44,$44,$BB,$BB,$BB,$BB 4 | ;.db $B3,$BB,$BB,$BB,$BB,$BB,$BB,$BB,$BB 5 | 6 | ; New 7 | ; [b0] 54444444abbbbbbb 8 | ; [b3] bbbbbbbbbbbbbbbb 9 | db $b0, $54, $44, $44, $44, $ab, $bb, $bb, $bb 10 | db $b3, $bb, $bb, $bb, $bb, $bb, $bb, $bb, $bb -------------------------------------------------------------------------------- /src/spc/pl1-2.asm: -------------------------------------------------------------------------------- 1 | 2 | ; Old 3 | ;.db $B0,$44,$44,$44,$44,$44,$44,$44,$44 4 | ;.db $B3,$BB,$BB,$BB,$BB,$BB,$BB,$BB,$BB 5 | 6 | ; New 7 | ; [b0] 5444444444444444 8 | ; [b3] abbbbbbbbbbbbbbb 9 | db $b0, $54, $44, $44, $44, $44, $44, $44, $44 10 | db $b3, $ab, $bb, $bb, $bb, $bb, $bb, $bb, $bb -------------------------------------------------------------------------------- /src/spc/pl1-3.asm: -------------------------------------------------------------------------------- 1 | 2 | ; Old 3 | ;.db $B0,$44,$44,$44,$44,$44,$44,$44,$44 4 | ;.db $B3,$44,$44,$44,$44,$BB,$BB,$BB,$BB 5 | 6 | ; New 7 | ; [b0] 5444444444444444 8 | ; [b3] 44444444abbbbbbb 9 | db $b0, $54, $44, $44, $44, $44, $44, $44, $44 10 | db $b3, $44, $44, $44, $44, $ab, $bb, $bb, $bb -------------------------------------------------------------------------------- /src/spc/pl1.asm: -------------------------------------------------------------------------------- 1 | 2 | ; Old 3 | ;.db $B0,$44,$44,$44,$44,$44,$44,$44,$44 4 | ;.db $B3,$BB,$BB,$BB,$BB,$BB,$BB,$BB,$BB 5 | 6 | ; New 7 | ; [b0] 5444444444444444 8 | ; [b3] abbbbbbbbbbbbbbb 9 | db $b0, $54, $44, $44, $44, $44, $44, $44, $44 10 | db $b3, $ab, $bb, $bb, $bb, $bb, $bb, $bb, $bb -------------------------------------------------------------------------------- /src/spc/pl1a.asm: -------------------------------------------------------------------------------- 1 | 2 | ; Old 3 | ;.db $B0,$44,$44,$44,$44,$44,$44,$44,$44 4 | ;.db $B3,$BB,$BB,$BB,$BB,$BB,$BB,$BB,$BB 5 | 6 | ; New 7 | ; [b0] 5444444444444444 8 | ; [b3] abbbbbbbbbbbbbbb 9 | db $b0, $54, $44, $44, $44, $44, $44, $44, $44 10 | db $b3, $ab, $bb, $bb, $bb, $bb, $bb, $bb, $bb -------------------------------------------------------------------------------- /src/spc/TRI6_SL2.ASM: -------------------------------------------------------------------------------- 1 | db $a2, $00, $00, $11, $11, $22, $22, $33, $33 2 | db $a2, $44, $44, $55, $55, $66, $66, $77, $77 3 | db $a2, $77, $77, $66, $66, $55, $55, $44, $44 4 | db $a2, $33, $33, $22, $22, $11, $11, $00, $00 5 | db $a2, $ff, $ff, $ee, $ee, $dd, $dd, $cc, $cc 6 | db $a2, $bb, $bb, $aa, $aa, $99, $99, $88, $88 7 | db $a2, $88, $88, $99, $99, $aa, $aa, $bb, $bb 8 | db $a3, $cc, $cc, $dd, $dd, $ee, $ee, $ff, $ff -------------------------------------------------------------------------------- /src/spc/pl2.asm: -------------------------------------------------------------------------------- 1 | 2 | ; Old 3 | ;.db $B0,$44,$44,$44,$44,$44,$44,$44,$44 4 | ;.db $B0,$44,$44,$44,$44,$44,$44,$44,$44 5 | ;.db $B0,$BB,$BB,$BB,$BB,$BB,$BB,$BB,$BB 6 | ;.db $B3,$BB,$BB,$BB,$BB,$BB,$BB,$BB,$BB 7 | 8 | ; New 9 | ; [b0] 5444444444444444 10 | ; [b0] 4444444444444444 11 | ; [b0] abbbbbbbbbbbbbbb 12 | ; [b3] bbbbbbbbbbbbbbbb 13 | db $b0, $54, $44, $44, $44, $44, $44, $44, $44 14 | db $b0, $44, $44, $44, $44, $44, $44, $44, $44 15 | db $b0, $ab, $bb, $bb, $bb, $bb, $bb, $bb, $bb 16 | db $b3, $bb, $bb, $bb, $bb, $bb, $bb, $bb, $bb -------------------------------------------------------------------------------- /src/spc/PL2-1.ASM: -------------------------------------------------------------------------------- 1 | 2 | ; Old 3 | ;.db $B0,$44,$44,$44,$44,$44,$44,$44,$44 4 | ;.db $B0,$BB,$BB,$BB,$BB,$BB,$BB,$BB,$BB 5 | ;.db $B0,$BB,$BB,$BB,$BB,$BB,$BB,$BB,$BB 6 | ;.db $B3,$BB,$BB,$BB,$BB,$BB,$BB,$BB,$BB 7 | 8 | ; New 9 | ; [b0] 5444444444444444 10 | ; [b0] abbbbbbbbbbbbbbb 11 | ; [b0] bbbbbbbbbbbbbbbb 12 | ; [b3] bbbbbbbbbbbbbbbb 13 | db $b0, $54, $44, $44, $44, $44, $44, $44, $44 14 | db $b0, $ab, $bb, $bb, $bb, $bb, $bb, $bb, $bb 15 | db $b0, $bb, $bb, $bb, $bb, $bb, $bb, $bb, $bb 16 | db $b3, $bb, $bb, $bb, $bb, $bb, $bb, $bb, $bb 17 | -------------------------------------------------------------------------------- /src/spc/PL2-2.ASM: -------------------------------------------------------------------------------- 1 | 2 | ; Old 3 | ;.db $B0,$44,$44,$44,$44,$44,$44,$44,$44 4 | ;.db $B0,$44,$44,$44,$44,$44,$44,$44,$44 5 | ;.db $B0,$BB,$BB,$BB,$BB,$BB,$BB,$BB,$BB 6 | ;.db $B3,$BB,$BB,$BB,$BB,$BB,$BB,$BB,$BB 7 | 8 | ; New 9 | ; [b0] 5444444444444444 10 | ; [b0] 4444444444444444 11 | ; [b0] abbbbbbbbbbbbbbb 12 | ; [b3] bbbbbbbbbbbbbbbb 13 | db $b0, $54, $44, $44, $44, $44, $44, $44, $44 14 | db $b0, $44, $44, $44, $44, $44, $44, $44, $44 15 | db $b0, $ab, $bb, $bb, $bb, $bb, $bb, $bb, $bb 16 | db $b3, $bb, $bb, $bb, $bb, $bb, $bb, $bb, $bb 17 | -------------------------------------------------------------------------------- /src/spc/PL2-3.ASM: -------------------------------------------------------------------------------- 1 | 2 | ; Old 3 | ;.db $B0,$44,$44,$44,$44,$44,$44,$44,$44 4 | ;.db $B0,$44,$44,$44,$44,$44,$44,$44,$44 5 | ;.db $B0,$44,$44,$44,$44,$44,$44,$44,$44 6 | ;.db $B3,$BB,$BB,$BB,$BB,$BB,$BB,$BB,$BB 7 | 8 | ; New 9 | ; [b0] 5444444444444444 10 | ; [b0] 4444444444444444 11 | ; [b0] 4444444444444444 12 | ; [b3] abbbbbbbbbbbbbbb 13 | db $b0, $54, $44, $44, $44, $44, $44, $44, $44 14 | db $b0, $44, $44, $44, $44, $44, $44, $44, $44 15 | db $b0, $44, $44, $44, $44, $44, $44, $44, $44 16 | db $b3, $ab, $bb, $bb, $bb, $bb, $bb, $bb, $bb 17 | -------------------------------------------------------------------------------- /src/spc/pl2-0.asm: -------------------------------------------------------------------------------- 1 | 2 | ; Old 3 | ;.db $B0,$44,$44,$44,$44,$BB,$BB,$BB,$BB 4 | ;.db $B0,$BB,$BB,$BB,$BB,$BB,$BB,$BB,$BB 5 | ;.db $B0,$BB,$BB,$BB,$BB,$BB,$BB,$BB,$BB 6 | ;.db $B3,$BB,$BB,$BB,$BB,$BB,$BB,$BB,$BB 7 | 8 | ; New 9 | ; [b0] 54444444abbbbbbb 10 | ; [b0] bbbbbbbbbbbbbbbb 11 | ; [b0] bbbbbbbbbbbbbbbb 12 | ; [b3] bbbbbbbbbbbbbbbb 13 | db $b0, $54, $44, $44, $44, $ab, $bb, $bb, $bb 14 | db $b0, $bb, $bb, $bb, $bb, $bb, $bb, $bb, $bb 15 | db $b0, $bb, $bb, $bb, $bb, $bb, $bb, $bb, $bb 16 | db $b3, $bb, $bb, $bb, $bb, $bb, $bb, $bb, $bb 17 | -------------------------------------------------------------------------------- /src/windows.asm: -------------------------------------------------------------------------------- 1 | ; sets up a black window on the left column of the screen 2 | setup_hide_left_8_pixel_window: 3 | LDA #$01 4 | STA TMW 5 | 6 | ; Window 1 Left 7 | LDA #$00 8 | STA WH0 9 | 10 | LDA #$10 11 | STA WH1 12 | 13 | LDA #%10101010 14 | STA WBGLOG 15 | 16 | LDA #%00001010 17 | STA WOBJLOG 18 | 19 | LDA #$02 20 | STA W12SEL 21 | STA WOBJSEL 22 | 23 | jslb disable_hide_left_8_pixel_window, $a0 24 | rts 25 | 26 | enable_hide_left_8_pixel_window: 27 | LDA #%00000010 28 | STA W12SEL 29 | 30 | RTL 31 | 32 | disable_hide_left_8_pixel_window: 33 | LDA #$00 34 | STA W12SEL 35 | RTL -------------------------------------------------------------------------------- /src/spc/TRI6_SL3.ASM: -------------------------------------------------------------------------------- 1 | db $a2, $00, $00, $00, $00, $11, $11, $11, $11 2 | db $a2, $22, $22, $22, $22, $33, $33, $33, $33 3 | db $a2, $44, $44, $44, $44, $55, $55, $55, $55 4 | db $a2, $66, $66, $66, $66, $77, $77, $77, $77 5 | db $a2, $77, $77, $77, $77, $66, $66, $66, $66 6 | db $a2, $55, $55, $55, $55, $44, $44, $44, $44 7 | db $a2, $33, $33, $33, $33, $22, $22, $22, $22 8 | db $a2, $11, $11, $11, $11, $00, $00, $00, $00 9 | db $a2, $ff, $ff, $ff, $ff, $ee, $ee, $ee, $ee 10 | db $a2, $dd, $dd, $dd, $dd, $cc, $cc, $cc, $cc 11 | db $a2, $bb, $bb, $bb, $bb, $aa, $aa, $aa, $aa 12 | db $a2, $99, $99, $99, $99, $88, $88, $88, $88 13 | db $a2, $88, $88, $88, $88, $99, $99, $99, $99 14 | db $a2, $aa, $aa, $aa, $aa, $bb, $bb, $bb, $bb 15 | db $a2, $cc, $cc, $cc, $cc, $dd, $dd, $dd, $dd 16 | db $a3, $ee, $ee, $ee, $ee, $ff, $ff, $ff, $ff -------------------------------------------------------------------------------- /src/hiromheader.asm: -------------------------------------------------------------------------------- 1 | .segment "HEADER" 2 | ; 012345678901234567890 3 | .byte "LIFE FORCE SNES REV A" ; ROM name, must be 21 chars 4 | 5 | 6 | .segment "ROMSPEC" 7 | .byte $31 ; Map Mode: 3.58MHz HiROM 8 | .byte $01 ; Cartridge Type: ROM+SRAM only 9 | .byte $0C ; ROM Size 10 | .byte $00 ; RAM size 11 | .byte $01 ; Destination Code: USA 12 | .byte $01 ; Fixed value 13 | .byte $00 ; Mask ROM Version 14 | .word $0000 ; Complement Check 15 | .word $0000 ; Check Sum 16 | 17 | .segment "VECTOR" 18 | ; native mode vectors 19 | .word 0, 0 20 | .addr _rti ; COP 21 | .addr _rti ; BRK 22 | .addr _rti ; ABORT 23 | .addr nmi ; NMI 24 | .addr start ; RST 25 | .addr _rti ; IRQ 26 | 27 | ; emulation mode vectors - largely unused, since we run in native mode 28 | .word 0, 0 29 | .addr 0 30 | .addr 0 31 | .addr 0 32 | .addr 0 33 | .addr start ; RST 34 | .addr 0 -------------------------------------------------------------------------------- /src/input.asm: -------------------------------------------------------------------------------- 1 | augment_input: 2 | 3 | ; origingal code 4 | LDX $FB 5 | INX 6 | STX JOYSER0 7 | DEX 8 | STX JOYSER0 9 | LDX #$08 10 | : LDA JOYSER0 11 | LSR 12 | ROL $F5 13 | LSR 14 | ROL $00 15 | LDA JOYSER1 16 | LSR 17 | ROL $F6 18 | LSR 19 | ROL $01 20 | DEX 21 | BNE :- 22 | 23 | ; example from Double Dragon 24 | ; we also ready the next bit, which is the SNES "A" button 25 | ; and if it's on, treat it as if they've hit both Y and B 26 | ; lda JOYSER0 27 | ; AND #$01 28 | ; BEQ :+ 29 | ; LDA $00 30 | ; ORA #$C0 31 | ; STA $00 32 | 33 | ; X 34 | ; lda JOYSER0 35 | ; lda JOYSER0 36 | ; AND #$01 37 | ; BEQ :+ 38 | 39 | 40 | ; this checks for the komani code by looking at where the game stores input. 41 | ; : jsr check_for_code_input_from_ram_values 42 | 43 | RTL -------------------------------------------------------------------------------- /src/macros.inc: -------------------------------------------------------------------------------- 1 | .macro setA8 2 | sep #$20 3 | .endmacro 4 | 5 | .macro setA16 6 | rep #$20 7 | .endmacro 8 | 9 | .macro setAXY8 10 | sep #$30 11 | .endmacro 12 | 13 | .macro setAXY16 14 | rep #$30 15 | .endmacro 16 | 17 | .macro setXY8 18 | sep #$10 19 | .endmacro 20 | 21 | .macro setXY16 22 | rep #$10 23 | .endmacro 24 | 25 | .macro nops num 26 | 27 | .if num > 0 28 | NOP 29 | nops num -1 30 | .endif 31 | 32 | .endmacro 33 | 34 | .macro brks num 35 | 36 | .if num > 0 37 | BRK 38 | brks num -1 39 | .endif 40 | 41 | .endmacro 42 | 43 | ; jslb and jmlb are used to ensure our jsl and jml stay in the fastrom (a0-af) banks 44 | .macro jslb label, bank 45 | .byte $22, label, bank 46 | .endmacro 47 | 48 | .macro jmlb label, bank 49 | .byte $5C, label, bank 50 | .endmacro 51 | 52 | .macro repeat value, count 53 | 54 | .if count > 0 55 | .byte value 56 | repeat value, (count-1) 57 | .endif 58 | 59 | .endmacro -------------------------------------------------------------------------------- /src/spc/pl3-0.asm: -------------------------------------------------------------------------------- 1 | 2 | ; Old 3 | ;.db $B0,$44,$44,$44,$44,$44,$44,$44,$44 4 | ;.db $B0,$BB,$BB,$BB,$BB,$BB,$BB,$BB,$BB 5 | ;.db $B0,$BB,$BB,$BB,$BB,$BB,$BB,$BB,$BB 6 | ;.db $B0,$BB,$BB,$BB,$BB,$BB,$BB,$BB,$BB 7 | ;.db $B0,$BB,$BB,$BB,$BB,$BB,$BB,$BB,$BB 8 | ;.db $B0,$BB,$BB,$BB,$BB,$BB,$BB,$BB,$BB 9 | ;.db $B0,$BB,$BB,$BB,$BB,$BB,$BB,$BB,$BB 10 | ;.db $B3,$BB,$BB,$BB,$BB,$BB,$BB,$BB,$BB 11 | 12 | ; New 13 | ; [b0] 5444444444444444 14 | ; [b0] abbbbbbbbbbbbbbb 15 | ; [b0] bbbbbbbbbbbbbbbb 16 | ; [b0] bbbbbbbbbbbbbbbb 17 | ; [b0] bbbbbbbbbbbbbbbb 18 | ; [b0] bbbbbbbbbbbbbbbb 19 | ; [b0] bbbbbbbbbbbbbbbb 20 | ; [b3] bbbbbbbbbbbbbbbb 21 | db $b0, $54, $44, $44, $44, $44, $44, $44, $44 22 | db $b0, $ab, $bb, $bb, $bb, $bb, $bb, $bb, $bb 23 | db $b0, $bb, $bb, $bb, $bb, $bb, $bb, $bb, $bb 24 | db $b0, $bb, $bb, $bb, $bb, $bb, $bb, $bb, $bb 25 | db $b0, $bb, $bb, $bb, $bb, $bb, $bb, $bb, $bb 26 | db $b0, $bb, $bb, $bb, $bb, $bb, $bb, $bb, $bb 27 | db $b0, $bb, $bb, $bb, $bb, $bb, $bb, $bb, $bb 28 | db $b3, $bb, $bb, $bb, $bb, $bb, $bb, $bb, $bb 29 | -------------------------------------------------------------------------------- /src/spc/pl3-1.asm: -------------------------------------------------------------------------------- 1 | 2 | ; Old 3 | ;.db $B0,$44,$44,$44,$44,$44,$44,$44,$44 4 | ;.db $B0,$44,$44,$44,$44,$44,$44,$44,$44 5 | ;.db $B0,$BB,$BB,$BB,$BB,$BB,$BB,$BB,$BB 6 | ;.db $B0,$BB,$BB,$BB,$BB,$BB,$BB,$BB,$BB 7 | ;.db $B0,$BB,$BB,$BB,$BB,$BB,$BB,$BB,$BB 8 | ;.db $B0,$BB,$BB,$BB,$BB,$BB,$BB,$BB,$BB 9 | ;.db $B0,$BB,$BB,$BB,$BB,$BB,$BB,$BB,$BB 10 | ;.db $B3,$BB,$BB,$BB,$BB,$BB,$BB,$BB,$BB 11 | 12 | ; New 13 | ; [b0] 5444444444444444 14 | ; [b0] 4444444444444444 15 | ; [b0] abbbbbbbbbbbbbbb 16 | ; [b0] bbbbbbbbbbbbbbbb 17 | ; [b0] bbbbbbbbbbbbbbbb 18 | ; [b0] bbbbbbbbbbbbbbbb 19 | ; [b0] bbbbbbbbbbbbbbbb 20 | ; [b3] bbbbbbbbbbbbbbbb 21 | db $b0, $54, $44, $44, $44, $44, $44, $44, $44 22 | db $b0, $44, $44, $44, $44, $44, $44, $44, $44 23 | db $b0, $ab, $bb, $bb, $bb, $bb, $bb, $bb, $bb 24 | db $b0, $bb, $bb, $bb, $bb, $bb, $bb, $bb, $bb 25 | db $b0, $bb, $bb, $bb, $bb, $bb, $bb, $bb, $bb 26 | db $b0, $bb, $bb, $bb, $bb, $bb, $bb, $bb, $bb 27 | db $b0, $bb, $bb, $bb, $bb, $bb, $bb, $bb, $bb 28 | db $b3, $bb, $bb, $bb, $bb, $bb, $bb, $bb, $bb 29 | -------------------------------------------------------------------------------- /src/spc/pl3-2.asm: -------------------------------------------------------------------------------- 1 | 2 | ; Old 3 | ;.db $B0,$44,$44,$44,$44,$44,$44,$44,$44 4 | ;.db $B0,$44,$44,$44,$44,$44,$44,$44,$44 5 | ;.db $B0,$44,$44,$44,$44,$44,$44,$44,$44 6 | ;.db $B0,$44,$44,$44,$44,$44,$44,$44,$44 7 | ;.db $B0,$BB,$BB,$BB,$BB,$BB,$BB,$BB,$BB 8 | ;.db $B0,$BB,$BB,$BB,$BB,$BB,$BB,$BB,$BB 9 | ;.db $B0,$BB,$BB,$BB,$BB,$BB,$BB,$BB,$BB 10 | ;.db $B3,$BB,$BB,$BB,$BB,$BB,$BB,$BB,$BB 11 | 12 | ; New 13 | ; [b0] 5444444444444444 14 | ; [b0] 4444444444444444 15 | ; [b0] 4444444444444444 16 | ; [b0] 4444444444444444 17 | ; [b0] abbbbbbbbbbbbbbb 18 | ; [b0] bbbbbbbbbbbbbbbb 19 | ; [b0] bbbbbbbbbbbbbbbb 20 | ; [b3] bbbbbbbbbbbbbbbb 21 | db $b0, $54, $44, $44, $44, $44, $44, $44, $44 22 | db $b0, $44, $44, $44, $44, $44, $44, $44, $44 23 | db $b0, $44, $44, $44, $44, $44, $44, $44, $44 24 | db $b0, $44, $44, $44, $44, $44, $44, $44, $44 25 | db $b0, $ab, $bb, $bb, $bb, $bb, $bb, $bb, $bb 26 | db $b0, $bb, $bb, $bb, $bb, $bb, $bb, $bb, $bb 27 | db $b0, $bb, $bb, $bb, $bb, $bb, $bb, $bb, $bb 28 | db $b3, $bb, $bb, $bb, $bb, $bb, $bb, $bb, $bb 29 | -------------------------------------------------------------------------------- /src/spc/pl3-3.asm: -------------------------------------------------------------------------------- 1 | 2 | ; Old 3 | ;.db $B0,$44,$44,$44,$44,$44,$44,$44,$44 4 | ;.db $B0,$44,$44,$44,$44,$44,$44,$44,$44 5 | ;.db $B0,$44,$44,$44,$44,$44,$44,$44,$44 6 | ;.db $B0,$44,$44,$44,$44,$44,$44,$44,$44 7 | ;.db $B0,$44,$44,$44,$44,$44,$44,$44,$44 8 | ;.db $B0,$44,$44,$44,$44,$44,$44,$44,$44 9 | ;.db $B0,$BB,$BB,$BB,$BB,$BB,$BB,$BB,$BB 10 | ;.db $B3,$BB,$BB,$BB,$BB,$BB,$BB,$BB,$BB 11 | 12 | ; New 13 | ; [b0] 5444444444444444 14 | ; [b0] 4444444444444444 15 | ; [b0] 4444444444444444 16 | ; [b0] 4444444444444444 17 | ; [b0] 4444444444444444 18 | ; [b0] 4444444444444444 19 | ; [b0] abbbbbbbbbbbbbbb 20 | ; [b3] bbbbbbbbbbbbbbbb 21 | db $b0, $54, $44, $44, $44, $44, $44, $44, $44 22 | db $b0, $44, $44, $44, $44, $44, $44, $44, $44 23 | db $b0, $44, $44, $44, $44, $44, $44, $44, $44 24 | db $b0, $44, $44, $44, $44, $44, $44, $44, $44 25 | db $b0, $44, $44, $44, $44, $44, $44, $44, $44 26 | db $b0, $44, $44, $44, $44, $44, $44, $44, $44 27 | db $b0, $ab, $bb, $bb, $bb, $bb, $bb, $bb, $bb 28 | db $b3, $bb, $bb, $bb, $bb, $bb, $bb, $bb, $bb 29 | -------------------------------------------------------------------------------- /src/spc/pl3.asm: -------------------------------------------------------------------------------- 1 | 2 | ; Old 3 | ;.db $B0,$44,$44,$44,$44,$44,$44,$44,$44 4 | ;.db $B0,$44,$44,$44,$44,$44,$44,$44,$44 5 | ;.db $B0,$44,$44,$44,$44,$44,$44,$44,$44 6 | ;.db $B0,$44,$44,$44,$44,$44,$44,$44,$44 7 | ;.db $B0,$BB,$BB,$BB,$BB,$BB,$BB,$BB,$BB 8 | ;.db $B0,$BB,$BB,$BB,$BB,$BB,$BB,$BB,$BB 9 | ;.db $B0,$BB,$BB,$BB,$BB,$BB,$BB,$BB,$BB 10 | ;.db $B3,$BB,$BB,$BB,$BB,$BB,$BB,$BB,$BB 11 | 12 | ; New 13 | ; [b0] 5444444444444444 14 | ; [b0] 4444444444444444 15 | ; [b0] 4444444444444444 16 | ; [b0] 4444444444444444 17 | ; [b0] abbbbbbbbbbbbbbb 18 | ; [b0] bbbbbbbbbbbbbbbb 19 | ; [b0] bbbbbbbbbbbbbbbb 20 | ; [b3] bbbbbbbbbbbbbbbb 21 | db $b0, $54, $44, $44, $44, $44, $44, $44, $44 22 | db $b0, $44, $44, $44, $44, $44, $44, $44, $44 23 | db $b0, $44, $44, $44, $44, $44, $44, $44, $44 24 | db $b0, $44, $44, $44, $44, $44, $44, $44, $44 25 | db $b0, $ab, $bb, $bb, $bb, $bb, $bb, $bb, $bb 26 | db $b0, $bb, $bb, $bb, $bb, $bb, $bb, $bb, $bb 27 | db $b0, $bb, $bb, $bb, $bb, $bb, $bb, $bb, $bb 28 | db $b3, $bb, $bb, $bb, $bb, $bb, $bb, $bb, $bb 29 | -------------------------------------------------------------------------------- /src/main.asm: -------------------------------------------------------------------------------- 1 | .p816 2 | .smart 3 | 4 | 5 | .include "macros.inc" 6 | .include "registers.inc" 7 | .include "vars.inc" 8 | .include "2a03_variables.inc" 9 | 10 | .if OLD_2A03 = 0 11 | .include "wram_routines.asm" 12 | .else 13 | .include "wram_routines_v0.asm" 14 | .endif 15 | 16 | .include "hiromheader.asm" 17 | 18 | .segment "CODE" 19 | .include "resetvector.asm" 20 | 21 | .segment "EMPTY_SPACE" 22 | 23 | .include "bank-snes.asm" 24 | ; these would need to be created from the original ROM using 25 | ; the /utilities/parseNesFileToBanks.go file 26 | .include "bank0.asm" 27 | .include "bank1.asm" 28 | .include "bank2.asm" 29 | .include "bank3.asm" 30 | .include "bank4.asm" 31 | .include "bank5.asm" 32 | .include "bank6.asm" 33 | 34 | ; These are optional if the game uses CH ROM 35 | ; .include "chrom-tiles-0.asm" 36 | ; .include "chrom-tiles-1.asm" 37 | ; .include "chrom-tiles-2.asm" 38 | ; .include "chrom-tiles-3.asm" 39 | ; .include "chrom-tiles-4.asm" 40 | ; .include "chrom-tiles-5.asm" 41 | ; .include "chrom-tiles-6.asm" 42 | ; .include "chrom-tiles-7.asm" 43 | ; these are tiles I use for intro/menu screens 44 | .include "chrom-basic-intro-tiles.asm" 45 | 46 | .include "msu.asm" 47 | ; .include "chrom-tiles-msu-intro.asm" 48 | ; .include "msu_video_player.asm" 49 | .include "intro_screen.asm" 50 | 51 | .if OLD_2A03 = 0 52 | .include "dpcm_audio.asm" 53 | .else 54 | .include "2a03_emulator_first_8000.asm" 55 | .endif -------------------------------------------------------------------------------- /src/spc/TRI5.ASM: -------------------------------------------------------------------------------- 1 | 2 | ; Old 3 | ;db $92,$00,$10,$21,$32,$43,$54,$65,$76 4 | ;db $A2,$43,$44,$54,$55,$65,$66,$76,$77 5 | ;db $B2,$34,$33,$33,$33,$23,$22,$22,$22 6 | ;db $A2,$34,$33,$23,$22,$12,$11,$01,$00 7 | ;db $92,$F0,$EF,$DE,$CD,$BC,$AB,$9A,$89 8 | ;db $A2,$BC,$BB,$AB,$AA,$9A,$99,$89,$88 9 | ;db $B2,$CB,$CC,$CC,$CC,$DC,$DD,$DD,$DD 10 | ;db $A3,$CB,$CC,$DC,$DD,$ED,$EE,$FE,$FF 11 | 12 | ; New 2 13 | db $a2, $00, $00, $11, $11, $22, $22, $33, $33 14 | db $a2, $44, $44, $55, $55, $66, $66, $77, $77 15 | db $a2, $77, $77, $66, $66, $55, $55, $44, $44 16 | db $a2, $33, $33, $22, $22, $11, $11, $00, $00 17 | db $a2, $ff, $ff, $ee, $ee, $dd, $dd, $cc, $cc 18 | db $a2, $bb, $bb, $aa, $aa, $99, $99, $88, $88 19 | db $a2, $88, $88, $99, $99, $aa, $aa, $bb, $bb 20 | db $a3, $cc, $cc, $dd, $dd, $ee, $ee, $ff, $ff 21 | 22 | ; Old 23 | ; [92] 0001122334455667 24 | ; [a2] 3444455556666777 25 | ; [b2] 4333333332222222 26 | ; [a2] 4333322221111000 27 | ; [92] 0ffeeddccbbaa998 28 | ; [a2] cbbbbaaaa9999888 29 | ; [b2] bccccccccddddddd 30 | ; [a3] bccccddddeeeefff 31 | 32 | ; New 33 | ; [92] 0001122334455667 34 | ; [a2] 3444455556666777 35 | ; [a2] 7777666655554444 36 | ; [a2] 4333322221111000 37 | ; [92] 0ffeeddccbbaa998 38 | ; [a2] cbbbbaaaa9999888 39 | ; [a2] 88889999aaaabbbb 40 | ; [93] 8899aabbccddeeff 41 | 42 | ; New 2 43 | ; [a2] 0000111122223333 44 | ; [a2] 4444555566667777 45 | ; [a2] 7777666655554444 46 | ; [a2] 3333222211110000 47 | ; [a2] ffffeeeeddddcccc 48 | ; [a2] bbbbaaaa99998888 49 | ; [a2] 88889999aaaabbbb 50 | ; [a3] ccccddddeeeeffff 51 | -------------------------------------------------------------------------------- /src/resetvector.asm: -------------------------------------------------------------------------------- 1 | start: 2 | SEI 3 | CLC 4 | XCE 5 | 6 | setXY16 7 | LDX #$01FF 8 | TXS 9 | LDA #$A0 10 | PHA 11 | PLB 12 | JSL $A08000 13 | 14 | nmi: 15 | ; PHP 16 | PHA 17 | PHX 18 | PHY 19 | setAXY8 20 | ; sometimes the NES doesn't RTI, so we're going to set defaults for when it does that here 21 | ; jslb set_scrolling_hdma_defaults, $a0 22 | jslb store_current_hdma_values, $a0 23 | jslb dma_oam_table_long, $a0 24 | jslb check_for_palette_updates, $a0 25 | jslb check_and_copy_attribute_buffer_l, $a0 26 | ; jump to NES NMI 27 | CLC 28 | LDA ACTIVE_NES_BANK 29 | INC 30 | ADC #$A0 31 | STA BANK_SWITCH_DB 32 | PHA 33 | PLB 34 | 35 | ; LifeForce NMI is at E76B 36 | LDA #$E7 37 | STA BANK_SWITCH_HB 38 | LDA #$6B 39 | STA BANK_SWITCH_LB 40 | PLY 41 | PLX 42 | PLA 43 | JML [BANK_SWITCH_LB] 44 | 45 | return_from_nes_nmi: 46 | PHP 47 | PHA 48 | PHX 49 | PHY 50 | 51 | LDA NMITIMEN_STATE 52 | AND #$7F 53 | STA NMITIMEN 54 | 55 | jslb SnesUpdateAudio, $a0 56 | 57 | ; handle sprite traslation last, since if that bleeds out of vblank it's ok 58 | jslb snes_nmi, $a0 59 | 60 | jslb msu_nmi_check, $b2 61 | jslb translate_8_by_16_sprites, $a0 62 | 63 | LDA RDNMI 64 | LDA NMITIMEN_STATE 65 | STA NMITIMEN 66 | 67 | PLY 68 | PLX 69 | PLA 70 | PLP 71 | RTI 72 | 73 | ; this is used by the MSU video player, ignore it if you don't use it. 74 | _rti: 75 | JML $C7FF14 76 | LDA $01B0 77 | BEQ :+ 78 | LDA $E6 79 | BEQ :+ 80 | JSR $D000 81 | : LDA #$A1 82 | PHA 83 | PLB 84 | JMP start 85 | 86 | rti -------------------------------------------------------------------------------- /src/konamicode.asm: -------------------------------------------------------------------------------- 1 | 2 | ; This is a file that can be included to implement the Konami Code in the port 3 | ; where in the code the user correctly is 4 | CODE_INDEX = $0820 5 | JOYPAD1 = $0822 6 | JOYTRIGGER1 = $0824 7 | JOYHELD1 = $0826 8 | buttons = $0828 9 | KONAMI_CODE_ENABLED = $082A 10 | 11 | UP_BUTTON = $08 12 | DOWN_BUTTON = $04 13 | LEFT_BUTTON = $02 14 | RIGHT_BUTTON = $01 15 | 16 | A_BUTTON = $80 17 | B_BUTTON = $40 18 | START_BUTTON = $10 19 | SELECT_BUTTON = $20 20 | 21 | code_values: 22 | .byte UP_BUTTON, UP_BUTTON, DOWN_BUTTON, DOWN_BUTTON 23 | .byte LEFT_BUTTON, RIGHT_BUTTON, LEFT_BUTTON, RIGHT_BUTTON 24 | .byte B_BUTTON, A_BUTTON 25 | .byte $FF 26 | 27 | 28 | check_for_code_input: 29 | PHA 30 | readjoy: 31 | lda #$01 32 | STA JOYSER0 33 | STA buttons 34 | LSR A 35 | sta JOYSER0 36 | loop: 37 | lda JOYSER0 38 | lsr a 39 | rol buttons 40 | bcc loop 41 | 42 | lda buttons 43 | ldy JOYPAD1 44 | sta JOYPAD1 45 | tya 46 | eor JOYPAD1 47 | and JOYPAD1 48 | sta JOYTRIGGER1 49 | beq :++ 50 | 51 | tya 52 | and JOYPAD1 53 | sta JOYHELD1 54 | 55 | lda CODE_INDEX 56 | tay 57 | 58 | lda code_values, y 59 | cmp JOYTRIGGER1 60 | beq :+ 61 | stz CODE_INDEX 62 | bra :++ 63 | ; correct input 64 | : INY 65 | INC CODE_INDEX 66 | LDA code_values, y 67 | CMP #$FF 68 | BNE :+ 69 | jsr code_effect 70 | 71 | : 72 | PLA 73 | rts 74 | 75 | code_effect: 76 | LDA RDNMI 77 | : LDA RDNMI 78 | BEQ :- 79 | 80 | AND #$80 81 | STZ CGADD 82 | LDA #$00 83 | STA CGDATA 84 | STA CGDATA 85 | 86 | LDA #$D6 87 | STA CGDATA 88 | LDA #$10 89 | STA CGDATA 90 | 91 | INC KONAMI_CODE_ENABLED 92 | rts -------------------------------------------------------------------------------- /src/2a03_conversion.asm: -------------------------------------------------------------------------------- 1 | totals_audio: 2 | 3 | SoundEmulateLengthCounters: 4 | setAXY8 5 | lda SNDCHANSW4015 6 | ora #$04 7 | tay 8 | 9 | bit #$01 10 | beq sq1 11 | 12 | lda SNDSQR1CTRL4000 13 | and #$20 14 | bne :++ 15 | ldx APUSq0Length 16 | bne :+ 17 | tya 18 | and #$fe 19 | tay 20 | bra sq1 21 | : 22 | dex 23 | stx APUSq0Length 24 | : 25 | tya 26 | 27 | sq1: 28 | bit #$02 29 | beq noise 30 | 31 | lda SNDSQR2CTRL4004 32 | and #$20 33 | bne :++ 34 | ldx APUSq1Length 35 | bne :+ 36 | tya 37 | and #$fd 38 | tay 39 | bra sq1 40 | : 41 | dex 42 | stx APUSq1Length 43 | : 44 | tya 45 | 46 | noise: 47 | bit #$08 48 | beq tri 49 | 50 | lda SNDNOISESHM400C 51 | and #$20 52 | bne :++ 53 | ldx APUNoiLength 54 | bne :+ 55 | tya 56 | and #$f7 57 | tay 58 | bra sq1 59 | : 60 | dex 61 | stx APUNoiLength 62 | : 63 | tya 64 | 65 | tri: 66 | ldx SNDTRIACTRL4008 67 | bpl :++ 68 | 69 | ldx APUTriLength 70 | bne :+ 71 | and #$fb 72 | bra end 73 | : 74 | dex 75 | stx APUTriLength 76 | : 77 | end: 78 | sta SNDCHANSW4015 79 | rts 80 | 81 | SnesUpdateAudio: 82 | PHX 83 | PHY 84 | PHA 85 | PHP 86 | setAXY8 87 | 88 | ; This isn't great but fixes some SFX 89 | ; but makes the triangle channel never stop 90 | ; LDA $A08 91 | ; ORA #$80 92 | ; STA $A08 93 | 94 | JSR SoundEmulateLengthCounters 95 | 96 | LDA SNDCHANSW4015 97 | BNE :++ 98 | ; Silence everything 99 | LDX #$00 100 | : 101 | STZ SOUND_EMULATOR_BUFFER_START, x 102 | INX 103 | CPX #$17 104 | BNE :- 105 | : 106 | LDA APUIO0 107 | CMP #$7D 108 | BEQ :+ 109 | JMP End 110 | : 111 | 112 | LDA #$D7 113 | STA APUIO0 114 | 115 | : 116 | LDA APUIO0 117 | CMP #$D7 118 | BNE :- 119 | 120 | LDX #$00 121 | 122 | : 123 | LDA SOUND_EMULATOR_BUFFER_START, X 124 | STA APUIO1 125 | STX APUIO0 126 | 127 | INX 128 | 129 | : CPX APUIO1 130 | BNE :- 131 | 132 | CPX #$17 133 | BNE :-- 134 | 135 | LDA #$0F 136 | STA $A15 137 | 138 | stz $0A16 139 | 140 | End: 141 | PLP 142 | PLA 143 | PLY 144 | PLX 145 | RTL 146 | -------------------------------------------------------------------------------- /src/wram_routines_v0.asm: -------------------------------------------------------------------------------- 1 | .SEGMENT "WRAM_ROUTINES" 2 | 3 | ; APU Update routines (much more simplistic than current version) 4 | routines_start: 5 | WriteAPUSq0Ctrl0: 6 | sta APUBase 7 | rts 8 | 9 | WriteAPUSq0Ctrl0_I_Y: 10 | sta APUBase, y 11 | rts 12 | 13 | WriteAPUSq0Ctrl0_I_X: 14 | sta APUBase, x 15 | rts 16 | 17 | WriteAPUSq0Ctrl0_Y: 18 | sty APUBase 19 | rts 20 | 21 | WriteAPUSq0Ctrl0_X: 22 | stx APUBase 23 | rts 24 | 25 | WriteAPUSq0Ctrl1: 26 | sta APUBase+$01 27 | rts 28 | 29 | WriteAPUSq0Ctrl1_Y: 30 | sty APUBase+$01 31 | rts 32 | 33 | WriteAPUSq0Ctrl1_I_Y: 34 | sta APUBase+$01, y 35 | rts 36 | 37 | WriteAPUSq0Ctrl1_I_X: 38 | sta APUBase+$01, x 39 | rts 40 | 41 | WriteAPUSq0Ctrl2: 42 | sta APUBase+$02 43 | rts 44 | 45 | WriteAPUSq0Ctrl2_X: 46 | stx APUBase+$02 47 | rts 48 | 49 | WriteAPUSq0Ctrl2_I_Y: 50 | sta APUBase+$02, y 51 | rts 52 | 53 | WriteAPUSq0Ctrl2_I_X: 54 | sta APUBase+$02, x 55 | rts 56 | 57 | 58 | WriteAPUSq0Ctrl3: 59 | sta APUSq0Length 60 | rts 61 | 62 | WriteAPUSq0Ctrl3_X: 63 | stx APUBase+$03 64 | rts 65 | 66 | WriteAPUSq0Ctrl3_I_Y: 67 | sta APUBase+$03, y 68 | rts 69 | 70 | WriteAPUSq0Ctrl3_I_X: 71 | sta APUBase+$03, x 72 | rts 73 | 74 | WriteAPUSq1Ctrl0: 75 | sta APUBase+$04 76 | rts 77 | 78 | WriteAPUSq1Ctrl0_X: 79 | stx APUBase+$04 80 | rts 81 | 82 | WriteAPUSq1Ctrl0_Y: 83 | sty APUBase+$04 84 | rts 85 | 86 | WriteAPUSq1Ctrl1: 87 | sta APUBase+$05 88 | rts 89 | 90 | WriteAPUSq1Ctrl1_X: 91 | stx APUBase+$05 92 | rts 93 | 94 | WriteAPUSq1Ctrl1_Y: 95 | sty APUBase+$05 96 | rts 97 | 98 | WriteAPUSq1Ctrl2: 99 | sta APUBase+$06 100 | rts 101 | 102 | WriteAPUSq1Ctrl2_X: 103 | stx APUBase+$06 104 | rts 105 | 106 | WriteAPUSq1Ctrl3: 107 | sta APUBase+$07 108 | rts 109 | 110 | WriteAPUSq1Ctrl3_X: 111 | stx APUBase+$07 112 | rts 113 | 114 | WriteAPUTriCtrl0: 115 | sta APUBase+$08 116 | rts 117 | 118 | WriteAPUTriCtrl1: 119 | sta APUBase+$09 120 | rts 121 | 122 | WriteAPUTriCtrl2: 123 | sta APUBase+$0A 124 | rts 125 | 126 | WriteAPUTriCtrl2_X: 127 | stx APUBase+$0A 128 | rts 129 | 130 | WriteAPUTriCtrl3: 131 | sta APUBase+$0B 132 | rts 133 | 134 | WriteAPUNoiseCtrl0: 135 | sta APUBase+$0C 136 | rts 137 | 138 | WriteAPUNoiseCtrl1: 139 | sta APUBase+$0D 140 | rts 141 | 142 | WriteAPUNoiseCtrl2: 143 | sta APUBase+$0E 144 | rts 145 | 146 | WriteAPUNoiseCtrl2_X: 147 | stx APUBase+$0E 148 | rts 149 | 150 | WriteAPUNoiseCtrl3: 151 | sta APUBase+$0F 152 | rts 153 | 154 | WriteAPUControl: 155 | sta APUBase + $15 156 | rts 157 | 158 | routines_end: -------------------------------------------------------------------------------- /src/2a03_variables.inc: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | TEMP_DATA = $7C 5 | 6 | .DEFINE SOUND_IO_BANK $7E 7 | .DEFINE SOUND_IO_BASE SOUND_EMULATOR_BUFFER_START 8 | 9 | ;; Sound emulation write only registers 10 | SOUND_EMULATOR_BUFFER_START = $0A00 11 | 12 | ; for total's emulator 13 | APUBase = SOUND_EMULATOR_BUFFER_START 14 | APUExtraControl = SOUND_EMULATOR_BUFFER_START + $16 15 | APUSq0Length = SOUND_EMULATOR_BUFFER_START + $20 16 | APUSq1Length = SOUND_EMULATOR_BUFFER_START + $22 17 | APUTriLength = SOUND_EMULATOR_BUFFER_START + $24 18 | APUNoiLength = SOUND_EMULATOR_BUFFER_START + $26 19 | APUIOTemp = SOUND_EMULATOR_BUFFER_START + $28 20 | 21 | .DEFINE SNDSQR1CTRL4000 SOUND_IO_BASE + 0 22 | .DEFINE SNDSQR1E4001 SOUND_IO_BASE + 1 23 | .DEFINE SNDSQR1PERIOD4002 SOUND_IO_BASE + 2 24 | .DEFINE SNDSQR1LENPH4003 SOUND_IO_BASE + 3 25 | .DEFINE SNDSQR2CTRL4004 SOUND_IO_BASE + 4 26 | .DEFINE SNDSQR2E4005 SOUND_IO_BASE + 5 27 | .DEFINE SNDSQR2PERIOD4006 SOUND_IO_BASE + 6 28 | .DEFINE SNDSQR2LENPH4007 SOUND_IO_BASE + 7 29 | .DEFINE SNDTRIACTRL4008 SOUND_IO_BASE + 8 30 | .DEFINE SNDTRIAPERIOD4009 SOUND_IO_BASE + 9 31 | .DEFINE SNDTRIALENPH400A SOUND_IO_BASE + 10 32 | .DEFINE SNDNOISECTRL400B SOUND_IO_BASE + 11 33 | .DEFINE SNDNOISESHM400C SOUND_IO_BASE + 12 34 | .DEFINE SNDNOISELEN400D SOUND_IO_BASE + 13 35 | .DEFINE SNDDMCCTRL400E SOUND_IO_BASE + 14 36 | .DEFINE SNDDMCDAC400F SOUND_IO_BASE + 15 37 | .DEFINE SNDDMCSADDR4010 SOUND_IO_BASE + 16 38 | .DEFINE SNDDMCSLEN4011 SOUND_IO_BASE + 17 39 | .DEFINE SNDCOMONCTRL14012 SOUND_IO_BASE + 18 40 | .DEFINE SNDCOMONCTRL24013 SOUND_IO_BASE + 19 41 | .DEFINE SNDWDMASPRUNUSED SOUND_IO_BASE + 20 42 | .DEFINE SNDCHANSW4015 SOUND_IO_BASE + 21 43 | .DEFINE SNDEMU4016 SOUND_IO_BASE + 22 44 | 45 | .DEFINE SNDTMP4000 SOUND_IO_BASE + 23 46 | .DEFINE SNDTMP4001 SOUND_IO_BASE + 24 47 | .DEFINE SNDTMP4002 SOUND_IO_BASE + 25 48 | .DEFINE SNDTMP4003 SOUND_IO_BASE + 26 49 | .DEFINE SNDTMP4004 SOUND_IO_BASE + 27 50 | .DEFINE SNDTMP4005 SOUND_IO_BASE + 28 51 | .DEFINE SNDTMP4006 SOUND_IO_BASE + 29 52 | .DEFINE SNDTMP4007 SOUND_IO_BASE + 30 ; No backup 53 | .DEFINE SNDTMP4008 SOUND_IO_BASE + 31 54 | .DEFINE SNDTMP4009 SOUND_IO_BASE + 32 55 | .DEFINE SNDTMP400A SOUND_IO_BASE + 33 56 | .DEFINE SNDTMP400B SOUND_IO_BASE + 34 ; No backup 57 | .DEFINE SNDTMP400C SOUND_IO_BASE + 35 58 | .DEFINE SNDTMP400D SOUND_IO_BASE + 36 59 | .DEFINE SNDTMP400E SOUND_IO_BASE + 37 60 | .DEFINE SNDTMP400F SOUND_IO_BASE + 38 ; No backup 61 | .DEFINE SNDTMP4010 SOUND_IO_BASE + 39 62 | .DEFINE SNDTMP4011 SOUND_IO_BASE + 40 63 | .DEFINE SNDTMP4012 SOUND_IO_BASE + 41 64 | .DEFINE SNDTMP4013 SOUND_IO_BASE + 42 65 | .DEFINE SNDTMP4014 SOUND_IO_BASE + 43 66 | .DEFINE SNDTMP4015 SOUND_IO_BASE + 44 67 | .DEFINE SNDTMP4016 SOUND_IO_BASE + 45 68 | 69 | .DEFINE noise_length SOUND_IO_BASE + 46 70 | .DEFINE triangle_length SOUND_IO_BASE + 47 71 | .DEFINE square0_length SOUND_IO_BASE + 48 72 | .DEFINE square1_length SOUND_IO_BASE + 49 73 | 74 | .DEFINE TMPVTIMEL SOUND_IO_BASE + 50 75 | .DEFINE TMPVTIMEH SOUND_IO_BASE + 51 76 | .DEFINE APUInit SOUND_IO_BASE + 52 77 | SPC700CodeBank = $8C -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Life Force SNES Port - V 1.0 2 | 3 | This is a 1:1 port of the NES version of Life Force, running on the SNES. It is utilizing FastROM/HiROM. 4 | 5 | This has been tested in Mesen2, MiSTer, on original hardware via FxPak Pro, as well as a physical cart using a MouseBite Labs board. 6 | 7 | NES sytle music is provided via Memblers 2A03 Emulator 8 | 9 | ## Additional Features 10 | 11 | MSU-1 Audio music is supported. If your platform supports MSU-1 Audio, there are 5 included packs available. 12 | 13 | Additionally, the following Quality of Life options are available: 14 | 1. Set lives to values from 3 to 99 15 | 2. Set the difficulty from easy, medium and hard without having to loop the game 16 | 3. 8 different palettes to choose from. you can select it on the intro options, or while paused you can press SELECT to cylce through them. 17 | 18 | ## MSU-1 Track List 19 | Track Indexes: 20 | 01 - Level 1 21 | 02 - Level 2 22 | 03 - Level 3 23 | 04 - Level 4 24 | 05 - Level 5 25 | 06 - Level 6 26 | 07 - Boss 27 | 08 - Death 28 | 09 - Ending 29 | 10 - Level 5 Mini Boss 30 | 11 - Level 5 2nd half 31 | 32 | Additionally, this romhack supports 5 playlists. For each playlist after the first, add 16 to each track number for the next playlist (1-11, 17-27, 33-43, etc) 33 | 34 | Included are 5 sets of PCMs for Life Force: 35 | Rock AST by Relikk 36 | Synth AST by Batty 37 | VRC6 Cover by Batty 38 | Arcade by Batty 39 | X68000 Midi by Relikk 40 | 41 | ## Prerequisites 42 | 43 | * [cc65](https://www.cc65.org/) - the 65c816 compiler and linker 44 | * [Go](https://go.dev/) - Go is used for a few useful scripts/tools 45 | 46 | 47 | ## Other Userful Tools I've used for this project 48 | 49 | * [Mesen2](https://github.com/SourMesen/Mesen2) - A fantastic emulator for development on a bunch of platforms 50 | * [HxD](https://mh-nexus.de/en/hxd/) - A Hex Editor 51 | * [Visual Studio Code](https://code.visualstudio.com/) - Used as the development environment 52 | 53 | ## Structure of the Project 54 | 55 | * `bankX.asm` - The NES memory PRG banks, there are 8 of them. This code is heavily edited/altered for the port 56 | * `chrom-tiles-X.asm` - The NES CHR ROM banks, also 8 of them. These are untouched aside from converting them to the SNES tile format that we use. The go script takes care of that for you. 57 | * `2a03_xxxxx.asm` - Sound emulation related code 58 | * `bank-snes.asm` - All the code that runs in the `A0` bank, this is where we put most of our routines and logic that we need that is SNES specific. Also includes various included asm files: 59 | 60 | * `attributes.asm` - dealing with tile and sprite attributes 61 | * `hardware-status-switches.asm` - various useful methods to handle differences in hardware registers 62 | * `hud-hdma.asm` - HDMA logic for the player health bars and names to be shown 63 | * `intro_screen.asm` - Title card that is shown at the start of the game 64 | * `palette_lookup.asm` and `palette_updates.asm` - palette logic 65 | * `sprites.asm` - sprite conversion and DMA'ing 66 | * `msu.asm` - MSU-1 Support Code 67 | * `main.asm` - the main file, root for the project 68 | * `options_xxxx.asm` - Options screen related code. Parts of this are genearted by generate_options_asm.go in the utilities directory 69 | * `qol.asm` - various Quality of Life routines are here 70 | * `vars.inc`, `registers.inc`, `macros.inc` - helpful includes 71 | * `resetvector.asm` - the reset vector code 72 | * `hirom.cfg` - defines how our ROM is laid out, where each bank lives and how large they are 73 | * `windows.asm` - used for managing the windows that sometimes hide the left side of the screen. 74 | * `wram_routines.bin` - binary copy of audio routines that we put in work ram to make them available to all banks. 75 | 76 | ## Building 77 | 78 | * Update the `build.sh` file with the location of your cc65 install 79 | * make sure you've extracted and copied the rom banks to `/src` 80 | * port all the changes you need to port! (magic) 81 | * run `build.sh` 82 | * The output will be in `out/` 83 | -------------------------------------------------------------------------------- /utilities/parseNesFileToBanks.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "flag" 5 | "fmt" 6 | "io/ioutil" 7 | "os" 8 | ) 9 | 10 | // This utility will take an NES rom as input, and split it up into 4k banks 11 | // It currently assumes a lot about the game, and is set up to parse the game 12 | // Super Dodge Ball, a MMC1 game, where banks 8+ are CHR ROM banks and within those banks 13 | // banks at memory 1A000 - 1FFFF are data and 8000 - 19FFF are tiles. It will automatically 14 | // convert the 2bpp tiles into 4bpp SNES format, but leave the data parts as is. 15 | // 16 | // For all banks it'll break up and label every 0x100 bytes, as well as setting a segment directive 17 | // 18 | // This script also assumes that the file will have a 16 byte header that we skip. 19 | // 20 | // It very naively will just print out the code as: 21 | // 22 | // .byte $HL, $HL, ...... 23 | // 24 | // with 16 bytes per line 25 | func main() { 26 | inputFile := flag.String("in", "Lifeforce (U).nes", "input file to split out") 27 | 28 | inputBytes, _ := ioutil.ReadFile(*inputFile) 29 | var banks [][]byte 30 | var bankSize = 0x4000 31 | 32 | // remove the header 33 | headerLess := inputBytes[0x10:] 34 | 35 | for i := 0; i < len(headerLess); i += bankSize { 36 | end := i + bankSize 37 | 38 | if end > len(headerLess) { 39 | end = len(headerLess) 40 | } 41 | 42 | banks = append(banks, headerLess[i:end]) 43 | } 44 | var byteOffset = 0x8000 45 | for i := 0; i < 8; i++ { 46 | if i == 7 { 47 | byteOffset = 0xC000 48 | } 49 | 50 | var bankFile, _ = os.Create(fmt.Sprintf("bank%d.asm", i)) 51 | defer bankFile.Close() 52 | if i != 7 { 53 | bankFile.WriteString(fmt.Sprintf(".segment \"PRGA%d\"", i+1)) 54 | } 55 | bankFile.WriteString(fmt.Sprintf("; Bank %d\n", i)) 56 | for byteIndex := 0; byteIndex < len(banks[i]); byteIndex++ { 57 | if byteIndex <= 0x1FFFF { 58 | if byteIndex%0x100 == 0 { 59 | bankFile.WriteString(fmt.Sprintf("\n\n; %04X - bank %d\n", byteIndex+byteOffset, i)) 60 | } 61 | if byteIndex%0x10 == 0 { 62 | bankFile.WriteString(".byte ") 63 | } 64 | 65 | bankFile.WriteString(fmt.Sprintf("$%02X", banks[i][byteIndex])) 66 | 67 | if byteIndex%0x10 == 0x0F { 68 | bankFile.WriteString("\n") 69 | } else { 70 | bankFile.WriteString(", ") 71 | } 72 | } 73 | } 74 | if i != 7 { 75 | bankFile.WriteString(fmt.Sprintf( 76 | ".segment \"PRGA%dC\"\nfixeda%d:\n.include \"bank7.asm\"\nfixeda%d_end:", 77 | i+1, i+1, i+1, 78 | )) 79 | } 80 | } 81 | // CHR banks 82 | // tileset := 0 83 | // for i := 8; i < 16; i++ { 84 | // var bankFile, _ = os.Create(fmt.Sprintf("chrom-tiles-%d.asm", i-8)) 85 | // defer bankFile.Close() 86 | // bankFile.WriteString(fmt.Sprintf(".segment \"PRGA%X\"\n", i)) 87 | // for byteIndex := 0; byteIndex < len(banks[i]); byteIndex += 0x10 { 88 | // if byteIndex%0x1000 == 0 { 89 | // bankFile.WriteString(fmt.Sprintf("chrom_bank_%d_tileset_%d:\n", i-8, tileset)) 90 | // tileset++ 91 | // } 92 | 93 | // // if i < 14 || (byteIndex < 0x2000 && i == 14) { 94 | // // converts these to SNES expected format 95 | // bankFile.WriteString( 96 | // fmt.Sprintf( 97 | // ".byte $%02X, $%02X, $%02X, $%02X, $%02X, $%02X, $%02X, $%02X, $%02X,"+ 98 | // " $%02X, $%02X, $%02X, $%02X, $%02X, $%02X, $%02X\n", 99 | // banks[i][byteIndex], 100 | // banks[i][byteIndex+8], 101 | // banks[i][byteIndex+1], 102 | // banks[i][byteIndex+1+8], 103 | // banks[i][byteIndex+2], 104 | // banks[i][byteIndex+2+8], 105 | // banks[i][byteIndex+3], 106 | // banks[i][byteIndex+3+8], 107 | // banks[i][byteIndex+4], 108 | // banks[i][byteIndex+4+8], 109 | // banks[i][byteIndex+5], 110 | // banks[i][byteIndex+5+8], 111 | // banks[i][byteIndex+6], 112 | // banks[i][byteIndex+6+8], 113 | // banks[i][byteIndex+7], 114 | // banks[i][byteIndex+7+8], 115 | // ), 116 | // ) 117 | // bankFile.WriteString(".byte $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00\n") 118 | // // If some of the banks in the PRG rom are actually data banks, then we need to _not_ format them at 4bpp. 119 | // // for Double Dragon all of the banks are just tile data. 120 | // // } else { 121 | // // // these are data banks that need to be formatted differently 122 | // // bankFile.WriteString( 123 | // // fmt.Sprintf( 124 | // // ".byte $%02X, $00, $%02X, $00, $%02X, $00, $%02X, $00, $%02X, $00, $%02X, $00, $%02X, $00, $%02X, $00\n"+ 125 | // // ".byte $%02X, $00, $%02X, $00, $%02X, $00, $%02X, $00, $%02X, $00, $%02X, $00, $%02X, $00, $%02X, $00\n", 126 | // // banks[i][byteIndex], 127 | // // banks[i][byteIndex+1], 128 | // // banks[i][byteIndex+2], 129 | // // banks[i][byteIndex+3], 130 | // // banks[i][byteIndex+4], 131 | // // banks[i][byteIndex+5], 132 | // // banks[i][byteIndex+6], 133 | // // banks[i][byteIndex+7], 134 | // // banks[i][byteIndex+8], 135 | // // banks[i][byteIndex+9], 136 | // // banks[i][byteIndex+10], 137 | // // banks[i][byteIndex+11], 138 | // // banks[i][byteIndex+12], 139 | // // banks[i][byteIndex+13], 140 | // // banks[i][byteIndex+14], 141 | // // banks[i][byteIndex+15], 142 | // // ), 143 | // // ) 144 | // // } 145 | // } 146 | // } 147 | 148 | } 149 | -------------------------------------------------------------------------------- /src/scrolling-mmc3.asm: -------------------------------------------------------------------------------- 1 | ; SCANLINE_FOR_IRQ ; line to start non-hud IRQ 2 | ; SCROLL_HDMA_LINE_TO_START_OFFSET ; line we have to start adjusting for attr 3 | ; LINE_TO_START_HUD ; line we start for HUD, always #191 4 | ; LINES_COMPLETE ; lines we've handled 5 | 6 | ; ordering can be: 7 | ; IRQ -> HUD 8 | ; ATTR -> HUD (no IRQ set) 9 | ; IRQ -> ATTR -> HUD 10 | ; ATTR -> IRQ -> HUD 11 | calculate_hdma_l: 12 | LDA SCANLINE_FOR_IRQ 13 | CMP #$FF 14 | BNE :+ 15 | jsl simple_scrolling 16 | rtl 17 | : 18 | jsr calculate_hdma 19 | rtl 20 | calculate_hdma: 21 | ; HUD is always last, so the two main cases are ATTR or IRQ first 22 | ; first easy case is that ATTR > HUD, in which case we don't care about ATTR 23 | STZ LINES_COMPLETE 24 | LDX #$00 25 | LDA #nes_attribute_scanline 26 | SEC 27 | SBC curr_voff_low 28 | SBC #$01 29 | STA SCROLL_HDMA_LINE_TO_START_OFFSET 30 | CMP #LINE_TO_START_HUD 31 | BCC :++ 32 | ; no need to handle attr 33 | ; might have IRQ though 34 | LDA SCANLINE_FOR_IRQ 35 | CMP #$B8 36 | BCS :+ 37 | jsr store_hdma_entry 38 | jsr set_values_for_irq 39 | : 40 | LDA #LINE_TO_START_HUD 41 | SEC 42 | SBC LINES_COMPLETE 43 | jsr store_hdma_entry 44 | jsr write_adjusted_hud_values 45 | jsr write_ending_values 46 | ; done! 47 | rts 48 | : 49 | 50 | LDA $08AF 51 | CMP #$B8 52 | ; game sets B8 for hud, so if it's less than that, then we have a value 53 | ; that we need to handle an IRQ for 54 | 55 | BCC :++ 56 | ; no irq, does have attr 57 | ; might have IRQ though 58 | LDA SCROLL_HDMA_LINE_TO_START_OFFSET 59 | beq :+ 60 | ; sometimes attr are right at the top! 61 | jsr store_hdma_entry 62 | : 63 | LDA curr_voff_low 64 | CLC 65 | ADC #$10 66 | STA curr_voff_low 67 | 68 | LDA #LINE_TO_START_HUD 69 | SEC 70 | SBC LINES_COMPLETE 71 | 72 | jsr store_hdma_entry 73 | jsr write_adjusted_hud_values 74 | jsr write_ending_values 75 | ; done! 76 | rts 77 | 78 | : 79 | 80 | ; has attr and irq 81 | LDA SCROLL_HDMA_LINE_TO_START_OFFSET 82 | CMP SCANLINE_FOR_IRQ 83 | BCS irq_first 84 | JMP attr_first 85 | 86 | irq_first: 87 | LDA SCANLINE_FOR_IRQ 88 | jsr store_hdma_entry 89 | 90 | ; values for h/v offsets is dependant on the value in F4 91 | ; handle irq for lines from IRQ -> ATTR 92 | jsr set_values_for_irq 93 | 94 | LDA #LINE_TO_START_HUD ; SCROLL_HDMA_LINE_TO_START_OFFSET 95 | SEC 96 | SBC SCANLINE_FOR_IRQ 97 | jsr store_hdma_entry 98 | 99 | ; now that irq is done, prep for doing attr skip 100 | ; LDA curr_voff_low 101 | ; CLC 102 | ; ADC #$10 103 | ; STA curr_voff_low 104 | 105 | ; ; do this until hud, no other changes to values 106 | ; LDA #LINE_TO_START_HUD 107 | ; SEC 108 | ; SBC LINES_COMPLETE 109 | ; jsr store_hdma_entry 110 | 111 | jsr write_adjusted_hud_values 112 | jsr write_ending_values 113 | ; done! 114 | rts 115 | 116 | attr_first: 117 | 118 | LDA SCROLL_HDMA_LINE_TO_START_OFFSET 119 | BEQ :+ 120 | jsr store_hdma_entry 121 | : 122 | ; handle attributes 123 | LDA curr_voff_low 124 | CLC 125 | ADC #$10 126 | STA curr_voff_low 127 | 128 | LDA SCANLINE_FOR_IRQ 129 | SEC 130 | SBC SCROLL_HDMA_LINE_TO_START_OFFSET 131 | jsr store_hdma_entry 132 | 133 | 134 | jsr set_values_for_irq 135 | LDA #LINE_TO_START_HUD 136 | SEC 137 | SBC SCANLINE_FOR_IRQ 138 | jsr store_hdma_entry 139 | 140 | jsr write_adjusted_hud_values 141 | jsr write_ending_values 142 | ; done! 143 | rts 144 | 145 | set_values_for_irq: 146 | LDA $0662 147 | sta curr_hoff_low 148 | 149 | LDA $F4 150 | AND #$01 151 | beq :+ 152 | ; f4 = 1 or 3 153 | LDA $0661 154 | sta curr_voff_low 155 | LDA $0663 156 | AND #$02 157 | LSR 158 | sta VOFS_HB 159 | rts 160 | : 161 | ; f4 = 2 162 | LDA #$00 163 | sta curr_voff_low 164 | LDA #$01 165 | sta VOFS_HB 166 | rts 167 | 168 | write_ending_values: 169 | LDA #$00 170 | STA SCROLL_HDMA_START, X 171 | STA SCROLL_HDMA_START + 1, X 172 | rts 173 | 174 | write_adjusted_hud_values: 175 | stz curr_hoff_low 176 | LDA #$0A 177 | sta curr_voff_low 178 | 179 | LDA $0663 180 | AND #$02 181 | LSR 182 | EOR #$01 183 | STA VOFS_HB 184 | 185 | LDA #(240 - LINE_TO_START_HUD) 186 | jsr store_hdma_entry 187 | 188 | rts 189 | 190 | ; stores an entry in the hdma table 191 | ; for value in A lines 192 | ; expects curr_hoff_low, curr_voff_low, VOFS_HB, to be set 193 | ; always sets HOFS_HB to 0 194 | ; 195 | ; increments LINES_COMPLETE by A 196 | ; X should be at the current offset, and will be 197 | ; increased by 5 (prepping for the next entry) 198 | store_hdma_entry: 199 | PHA 200 | CMP #$80 201 | BCC :+ 202 | LDA #127 203 | STA SCROLL_HDMA_START, X 204 | 205 | LDA curr_hoff_low 206 | STA SCROLL_HDMA_START + 1, X ;hoffl 207 | 208 | LDA #0 209 | STA SCROLL_HDMA_START + 2, X ; hoffh 210 | 211 | LDA curr_voff_low 212 | STA SCROLL_HDMA_START + 3, X ; voffl 213 | 214 | LDA VOFS_HB 215 | STA SCROLL_HDMA_START + 4, X ; voffh 216 | 217 | INX 218 | INX 219 | INX 220 | INX 221 | INX 222 | 223 | PLA 224 | PHA 225 | SEC 226 | SBC #127 227 | : 228 | STA SCROLL_HDMA_START, X 229 | 230 | LDA curr_hoff_low 231 | STA SCROLL_HDMA_START + 1, X ;hoffl 232 | 233 | LDA #0 234 | STA SCROLL_HDMA_START + 2, X ; hoffh 235 | 236 | LDA curr_voff_low 237 | STA SCROLL_HDMA_START + 3, X ; voffl 238 | 239 | LDA VOFS_HB 240 | STA SCROLL_HDMA_START + 4, X ; voffh 241 | 242 | INX 243 | INX 244 | INX 245 | INX 246 | INX 247 | 248 | PLA 249 | CLC 250 | ADC LINES_COMPLETE 251 | STA LINES_COMPLETE 252 | 253 | rts -------------------------------------------------------------------------------- /src/intro_screen.asm: -------------------------------------------------------------------------------- 1 | .segment "PRGB1" 2 | 3 | intro_screen_data: 4 | .byte $e2, $20, $29, $28, $2b, $2d, $1e, $1d, $00 ; Ported 5 | .byte $1b, $32, $00 ; by 6 | .byte $2b, $2e, $26, $1b, $25, $1e, $26, $22, $27, $33, $1e, $00 ; Rumbleminze, 7 | .byte $12, $10, $12, $15, $ff ; 2024 8 | 9 | ; MSU1 Arrangements By Batty and Relikk 10 | .byte $82, $22, $26, $2c, $2e, $11, $34 11 | .byte $1a, $2b, $2b, $1a, $27, $20, $1e, $26, $1e, $27, $2d, $2c, $FF 12 | 13 | .byte $A6, $22, $1b, $32, $34 14 | .byte $1b, $1a, $2d, $2d, $32, $34 15 | .byte $1A, $27, $1D, $34 16 | .byte $2B, $1E, $25, $22, $24, $24, $ff 17 | 18 | .byte $01, $23, $12, $1a, $10, $13, $00 ; 2A03 19 | .byte $2c, $28, $2e, $27, $1d, $00 ; SOUND 20 | .byte $1e, $26, $2e, $25, $1a, $2d, $28, $2b, $00 ; EMULATOR 21 | .byte $1b, $32, $00 ; BY 22 | .byte $26, $1e, $26, $1b, $25, $1e, $2b, $2c, $ff ; MEMBLERS 23 | 24 | .byte $78, $23, $2b, $1e, $2f, $1A, $ff ; Version (REV0) 25 | .byte $ff, $ff 26 | 27 | write_intro_palette: 28 | STZ CGADD 29 | LDA #$00 30 | STA CGDATA 31 | STA CGDATA 32 | 33 | LDA #$FF 34 | STA CGDATA 35 | STA CGDATA 36 | 37 | LDA #$B5 38 | STA CGDATA 39 | LDA #$56 40 | STA CGDATA 41 | 42 | LDA #$29 43 | STA CGDATA 44 | LDA #$25 45 | STA CGDATA 46 | 47 | ; sprite default colors 48 | LDA #$80 49 | STA CGADD 50 | LDA #$D0 51 | STA CGDATA 52 | LDA #$00 53 | STA CGDATA 54 | 55 | LDA #$b5 56 | STA CGDATA 57 | LDA #$56 58 | STA CGDATA 59 | 60 | LDA #$d0 61 | STA CGDATA 62 | LDA #$00 63 | STA CGDATA 64 | 65 | LDA #$00 66 | STA CGDATA 67 | LDA #$00 68 | STA CGDATA 69 | 70 | 71 | LDA #$90 72 | STA CGADD 73 | LDA #$D0 74 | STA CGDATA 75 | LDA #$00 76 | STA CGDATA 77 | 78 | LDA #$00 79 | STA CGDATA 80 | LDA #$00 81 | STA CGDATA 82 | 83 | LDA #$d6 84 | STA CGDATA 85 | LDA #$10 86 | STA CGDATA 87 | 88 | LDA #$41 89 | STA CGDATA 90 | LDA #$02 91 | STA CGDATA 92 | 93 | 94 | LDA #$A0 95 | STA CGADD 96 | LDA #$D0 97 | STA CGDATA 98 | LDA #$00 99 | STA CGDATA 100 | 101 | LDA #$00 102 | STA CGDATA 103 | LDA #$00 104 | STA CGDATA 105 | 106 | LDA #$33 107 | STA CGDATA 108 | LDA #$01 109 | STA CGDATA 110 | 111 | LDA #$D0 112 | STA CGDATA 113 | LDA #$00 114 | STA CGDATA 115 | 116 | 117 | LDA #$B0 118 | STA CGADD 119 | LDA #$D0 120 | STA CGDATA 121 | LDA #$00 122 | STA CGDATA 123 | 124 | LDA #$33 125 | STA CGDATA 126 | LDA #$01 127 | STA CGDATA 128 | 129 | LDA #$33 130 | STA CGDATA 131 | LDA #$01 132 | STA CGDATA 133 | 134 | LDA #$6a 135 | STA CGDATA 136 | LDA #$00 137 | STA CGDATA 138 | 139 | RTS 140 | 141 | write_intro_tiles: 142 | LDY #$00 143 | 144 | next_line: 145 | ; get starting address 146 | LDA intro_screen_data, Y 147 | CMP #$FF 148 | BEQ exit_intro_write 149 | 150 | PHA 151 | INY 152 | LDA intro_screen_data, Y 153 | STA VMADDH 154 | PLA 155 | STA VMADDL 156 | INY 157 | 158 | next_tile: 159 | LDA intro_screen_data, Y 160 | INY 161 | 162 | CMP #$FF 163 | BEQ next_line 164 | 165 | STA VMDATAL 166 | BRA next_tile 167 | 168 | exit_intro_write: 169 | RTS 170 | 171 | do_intro: 172 | JSR load_intro_tilesets 173 | JSR write_intro_palette 174 | JSL write_default_palettes_jsl 175 | 176 | PHK 177 | PLB 178 | JSR write_intro_tiles 179 | ; JSR write_intro_sprites 180 | 181 | LDA #$0F 182 | STA INIDISP 183 | LDX #$FF 184 | 185 | 186 | : 187 | jsr check_for_code_input 188 | ; jsr check_for_sprite_swap 189 | ; jsr check_for_msu 190 | 191 | ; check for "start" 192 | LDA JOYTRIGGER1 193 | AND #$10 194 | CMP #$10 195 | BNE :- 196 | 197 | LDA INIDISP_STATE 198 | ORA #$8F 199 | STA INIDISP_STATE 200 | STA INIDISP 201 | 202 | 203 | 204 | : 205 | 206 | LDA NMITIMEN_STATE 207 | STA NMITIMEN 208 | JSR show_options_screen 209 | RTL 210 | check_for_sprite_swap: 211 | 212 | LDA JOYTRIGGER1 213 | AND #$20 214 | CMP #$20 215 | BNE :- 216 | jsr load_intro_tilesets 217 | LDA #$0F 218 | STA INIDISP 219 | : rts 220 | check_for_msu: 221 | LDA JOYTRIGGER1 222 | AND #$01 223 | CMP #$01 224 | BEQ :+ 225 | LDA JOYTRIGGER1 226 | AND #$02 227 | CMP #$02 228 | BNE :- 229 | : LDA MSU_SELECTED 230 | EOR #$01 231 | STA MSU_SELECTED 232 | 233 | LDA SNES_OAM_START + (4*9 - 1) 234 | EOR #$40 235 | STA SNES_OAM_START + (4*9 - 1) 236 | JSR dma_oam_table 237 | RTS 238 | 239 | ; if a sprite wants to be on the intro screen, 240 | ; can put the data here 241 | intro_sprite_info: 242 | ; x, y, sprite 243 | .byte $80, $30, $00, $00 244 | .byte $80, $38, $01, $00 245 | .byte $88, $30, $02, $00 246 | .byte $88, $38, $03, $00 247 | .byte $80, $40, $08, $00 248 | .byte $80, $48, $09, $00 249 | .byte $88, $40, $0a, $00 250 | .byte $88, $48, $0B, $00 251 | .byte $80, $78, $54, $40 252 | .byte $ff 253 | 254 | write_intro_sprites: 255 | LDY #$00 256 | LDX #$09 257 | 258 | : LDA intro_sprite_info, y 259 | STA SNES_OAM_START, y 260 | INY 261 | LDA intro_sprite_info, y 262 | STA SNES_OAM_START, y 263 | INY 264 | LDA intro_sprite_info, y 265 | STA SNES_OAM_START, y 266 | INY 267 | LDA intro_sprite_info, y 268 | STA SNES_OAM_START, y 269 | INY 270 | DEX 271 | BNE :- 272 | 273 | JSR dma_oam_table 274 | 275 | rts 276 | 277 | ; loads up the tileset that has the tiles for the intro 278 | load_intro_tilesets: 279 | lda #$01 280 | sta NMITIMEN 281 | LDA VMAIN_STATE 282 | AND #$0F 283 | STA VMAIN 284 | LDA #$8F 285 | STA INIDISP 286 | STA INIDISP_STATE 287 | 288 | ; load index 20 bank into both sets of tiles 289 | ; 20 is our custom intro screen tiles 290 | LDA #$00 291 | STA CHR_BANK_BANK_TO_LOAD 292 | LDA #$01 293 | STA CHR_BANK_TARGET_BANK 294 | JSL load_chr_table_to_vm 295 | 296 | LDA #$00 297 | STA CHR_BANK_BANK_TO_LOAD 298 | LDA #$00 299 | STA CHR_BANK_TARGET_BANK 300 | JSL load_chr_table_to_vm 301 | 302 | LDA #$01 303 | STA CHR_BANK_BANK_TO_LOAD 304 | LDA #$04 305 | STA CHR_BANK_TARGET_BANK 306 | JSL load_chr_table_to_vm 307 | 308 | LDA #$02 309 | STA CHR_BANK_BANK_TO_LOAD 310 | LDA #$05 311 | STA CHR_BANK_TARGET_BANK 312 | JSL load_chr_table_to_vm 313 | 314 | rts 315 | 316 | .include "options_screen.asm" 317 | .include "qol.asm" 318 | .include "konamicode.asm" -------------------------------------------------------------------------------- /src/scrolling.asm: -------------------------------------------------------------------------------- 1 | 2 | infidelitys_scroll_handling: 3 | 4 | ; LDA $F1 5 | ; AND #$01 6 | LDA curr_ppu_ctrl_value 7 | PHA 8 | AND #$80 9 | BNE :+ 10 | LDA #$00 11 | BRA :++ 12 | : LDA #$80 13 | : STA NMITIMEN 14 | PLA 15 | PHA 16 | AND #$04 17 | ; A now has the BG table address 18 | BNE :+ 19 | LDA #$00 20 | BRA :++ 21 | : LDA #$01 22 | : STA VMAIN 23 | PLA 24 | AND #$03 25 | BEQ :+ 26 | CMP #$01 27 | BEQ :++ 28 | CMP #$02 29 | BEQ :+++ 30 | CMP #$03 31 | BEQ :++++ 32 | : STZ HOFS_HB 33 | STZ VOFS_HB 34 | BRA :++++ ; RTL 35 | : LDA #$01 36 | STA HOFS_HB 37 | STZ VOFS_HB 38 | BRA :+++ ; RTL 39 | : STZ HOFS_HB 40 | LDA #$01 41 | ; STA VOFS_HB 42 | BRA :++ ; RTL 43 | : LDA #$01 44 | STA HOFS_HB 45 | ; STA VOFS_HB 46 | 47 | : RTL 48 | 49 | 50 | setup_hdma: 51 | LDA $200 52 | CMP #$C5 53 | BEQ :+ 54 | JMP nohud 55 | : 56 | 57 | ; line count 58 | ; HOFS_LB, HOFS_HB, VOFS_LB, VOFS_LB 59 | ; x3 60 | ; 00 61 | 62 | LDX curr_voff_low 63 | LDA $A0A080,X 64 | STA SCROLL_HDMA_START + 0 65 | LDA $A0A180,X 66 | STA SCROLL_HDMA_START + 3 67 | LDA $A0A280,X 68 | 69 | STA SCROLL_HDMA_START + 5 70 | LDA $A0A380,X 71 | STA SCROLL_HDMA_START + 8 72 | 73 | LDA $A0A480,X 74 | STA SCROLL_HDMA_START + 10 75 | LDA $A0A560,X 76 | STA SCROLL_HDMA_START + 13 77 | 78 | LDA curr_hoff_low 79 | STA SCROLL_HDMA_START + 1 80 | STA SCROLL_HDMA_START + 6 81 | STA SCROLL_HDMA_START + 11 82 | 83 | ; lda $F1 84 | ; AND #$01 85 | ; lda #$00 86 | LDA curr_ppu_ctrl_value 87 | AND #$01 88 | STA SCROLL_HDMA_START + 2 89 | STA SCROLL_HDMA_START + 7 90 | STA SCROLL_HDMA_START + 12 91 | 92 | ; v-hi byte 93 | LDX curr_ppu_ctrl_value 94 | LDA $A0A610,X 95 | STA SCROLL_HDMA_START + 4 96 | STA SCROLL_HDMA_START + 9 97 | STA SCROLL_HDMA_START + 14 98 | 99 | 100 | LDY #$0A 101 | LDA SCROLL_HDMA_START 102 | STA LINES_COMPLETE 103 | 104 | 105 | LDA SCROLL_HDMA_START + 5 106 | CLC 107 | ADC LINES_COMPLETE 108 | STA LINES_COMPLETE 109 | SEC 110 | SBC #LINE_TO_START_HUD 111 | 112 | BMI :+ 113 | ; hit the end on 2nd one, back it up 114 | STA LINES_COMPLETE 115 | LDA SCROLL_HDMA_START + 5 116 | SEC 117 | SBC LINES_COMPLETE 118 | STA SCROLL_HDMA_START + 5 119 | BRA write_hud_values 120 | : 121 | 122 | LDY #$0F 123 | LDA SCROLL_HDMA_START + 10 124 | CLC 125 | ADC LINES_COMPLETE 126 | STA LINES_COMPLETE 127 | SEC 128 | SBC #LINE_TO_START_HUD 129 | BMI :+ 130 | ; hit the end on the 3rd one, back it up 131 | STA LINES_COMPLETE 132 | LDA SCROLL_HDMA_START + 10 133 | SEC 134 | SBC LINES_COMPLETE 135 | STA SCROLL_HDMA_START + 10 136 | BRA write_hud_values 137 | : 138 | ; didn't get to enough lines, we actually have to bump up the last one 139 | LDA #LINE_TO_START_HUD 140 | SBC LINES_COMPLETE 141 | ADC SCROLL_HDMA_START + 10 142 | STA SCROLL_HDMA_START + 10 143 | 144 | write_hud_values: 145 | ; 1 line (last write) 146 | ; HOFS_LB (always 0), HOFS_HB, VOFS_LB, VOFS_LB 147 | 148 | 149 | 150 | LDA $40 ; 00 = Horizontal LVL, 01 = Vertical 151 | Beq :+ 152 | ; 8 pixels of empty tiles 153 | LDA #08 154 | STA SCROLL_HDMA_START, Y 155 | 156 | INY 157 | LDA #$00 158 | STA SCROLL_HDMA_START, Y 159 | 160 | INY 161 | LDA #$01 162 | STA SCROLL_HDMA_START, Y 163 | 164 | INY 165 | LDA #$3C 166 | STA SCROLL_HDMA_START, Y 167 | 168 | INY 169 | LDA #$00 170 | STA SCROLL_HDMA_START, Y 171 | 172 | ; now hud 173 | LDA #01 174 | STA SCROLL_HDMA_START, Y 175 | 176 | INY 177 | LDA #$00 178 | STA SCROLL_HDMA_START, Y 179 | 180 | INY 181 | LDA #$01 182 | STA SCROLL_HDMA_START, Y 183 | INY 184 | LDA #$30 185 | STA SCROLL_HDMA_START, Y 186 | INY 187 | LDA #$00 188 | STA SCROLL_HDMA_START, Y 189 | 190 | BRA :++ 191 | : 192 | ; for horizontal levels. some of them need to be adjusted 193 | ; because for some god-forsaken reason 194 | ; they moved the hud around by 8 pixels. 195 | 196 | LDA #01 197 | STA SCROLL_HDMA_START, Y 198 | 199 | INY 200 | LDA #$00 201 | STA SCROLL_HDMA_START, Y 202 | 203 | INY 204 | LDA #$01 205 | STA SCROLL_HDMA_START, Y 206 | INY 207 | LDA #$38 208 | STA SCROLL_HDMA_START, Y 209 | INY 210 | LDA #$00 211 | STA SCROLL_HDMA_START, Y 212 | 213 | : 214 | 215 | 216 | 217 | end_hdma: 218 | ; end hdma byte 219 | LDA #$00 220 | INY 221 | STA SCROLL_HDMA_START, Y 222 | 223 | 224 | RTL 225 | 226 | adjust_previous_hdma_for_attributes: 227 | ; Y - 2 is the line count, change that to #08 228 | LDA #$08 229 | STA SCROLL_HDMA_START - 2, Y 230 | 231 | ; pull the other values from Y - 5 (previous set) 232 | LDA SCROLL_HDMA_START - 6, Y 233 | STA SCROLL_HDMA_START - 1, Y 234 | 235 | LDA SCROLL_HDMA_START - 5, Y 236 | STA SCROLL_HDMA_START, Y 237 | 238 | LDA SCROLL_HDMA_START - 4, Y 239 | STA SCROLL_HDMA_START + 1, Y 240 | 241 | LDA SCROLL_HDMA_START - 3, Y 242 | STA SCROLL_HDMA_START + 2, Y 243 | 244 | INY 245 | INY 246 | INY 247 | LDA #01 248 | STA SCROLL_HDMA_START, Y 249 | 250 | INY 251 | LDA #$00 252 | STA SCROLL_HDMA_START, Y 253 | 254 | INY 255 | LDA #$01 256 | STA SCROLL_HDMA_START, Y 257 | 258 | LDA VOFS_LB ; #$00 259 | CLC 260 | ADC #$08 261 | RTS 262 | 263 | nohud: 264 | 265 | LDX curr_voff_low 266 | LDA $A0A080,X 267 | STA SCROLL_HDMA_START + 0 268 | LDA $A0A180,X 269 | STA SCROLL_HDMA_START + 3 270 | 271 | LDA $A0A280,X 272 | STA SCROLL_HDMA_START + 5 273 | LDA $A0A380,X 274 | STA SCROLL_HDMA_START + 8 275 | 276 | LDA $A0A480,X 277 | STA SCROLL_HDMA_START + 10 278 | LDA $A0A560,X 279 | STA SCROLL_HDMA_START + 13 280 | 281 | LDA curr_hoff_low 282 | STA SCROLL_HDMA_START + 1 283 | STA SCROLL_HDMA_START + 6 284 | STA SCROLL_HDMA_START + 11 285 | 286 | LDA HOFS_HB 287 | STA SCROLL_HDMA_START + 2 288 | STA SCROLL_HDMA_START + 7 289 | STA SCROLL_HDMA_START + 12 290 | 291 | ; v-hi byte, always 0 for BM 292 | ; LDX VOFS_HB 293 | ; LDA $A0A610,X 294 | STZ SCROLL_HDMA_START + 4 295 | STZ SCROLL_HDMA_START + 9 296 | STZ SCROLL_HDMA_START + 14 297 | 298 | STZ SCROLL_HDMA_START + 15 299 | 300 | RTL 301 | 302 | default_scrolling_hdma_values: 303 | .byte $6F, $00, $92, $00, $C9, $58, $00, $92, $00, $C9, $27, $00, $00, $00, $01, $00 304 | 305 | set_scrolling_hdma_defaults: 306 | 307 | LDA $3D 308 | AND #$04 309 | BEQ :+ 310 | LDA $3E 311 | AND #$01 312 | BEQ :+ 313 | jmp simple_scrolling 314 | 315 | : PHY 316 | PHB 317 | LDA #$A0 318 | PHA 319 | PLB 320 | LDY #$00 321 | : LDA default_scrolling_hdma_values, Y 322 | CPY #$0f 323 | BEQ :+ 324 | STA SCROLL_HDMA_START, Y 325 | INY 326 | BRA :- 327 | 328 | : PLB 329 | PLY 330 | RTL 331 | 332 | ; used where we just want to set the scroll to 0,0 and not worry about 333 | ; attributes, because they'll naturally be offscreen 334 | simple_scrolling: 335 | LDA #$00 336 | STA BG1VOFS 337 | LDA #$00 338 | STA BG1VOFS 339 | STZ BG1HOFS 340 | STZ BG1HOFS 341 | STZ SCROLL_HDMA_START 342 | STZ SCROLL_HDMA_START + 1 343 | STZ SCROLL_HDMA_START + 2 344 | : RTL 345 | 346 | -------------------------------------------------------------------------------- /src/palette_lookup.asm: -------------------------------------------------------------------------------- 1 | ; lookup table for all of the NES colors 2 | palette_adddresses: 3 | .byte palette_1_lookup 4 | .byte palette_2_lookup 5 | .byte palette_3_lookup 6 | .byte palette_4_lookup 7 | .byte palette_5_lookup 8 | .byte palette_6_lookup 9 | .byte palette_7_lookup 10 | .byte palette_8_lookup 11 | 12 | palette_1_lookup: 13 | .byte $8C, $31 ; $00 dark grey 14 | .byte $A0, $44 ; $01 15 | .byte $42, $50 ; $02 dark blue 16 | .byte $07, $50 ; $03 dark purple blue 17 | .byte $0B, $3C ; $04 dark purple 18 | .byte $0D, $20 ; $05 maroon 19 | .byte $0D, $00 ; $06 burgandy 20 | .byte $6A, $00 ; $07 dark brown 21 | .byte $C6, $00 ; $08 mud green 22 | .byte $21, $01 ; $09 green 23 | .byte $40, $01 ; $0A dark green 24 | .byte $20, $05 ; $0B another dark green 25 | .byte $00, $25 ; $0C dark teal 26 | .byte $00, $00 ; $0D Black 27 | .byte $00, $00 ; $0E Black 28 | .byte $00, $00 ; $0F Black 29 | 30 | .byte $B5, $56 ; $10 light grey 31 | .byte $62, $6D ; $11 blue 32 | .byte $08, $7D ; $12 light dark blue 33 | .byte $8E, $7C ; $13 purple 34 | .byte $74, $64 ; $14 35 | .byte $76, $3C ; $15 dark pink 36 | .byte $D6, $10 ; $16 red 37 | .byte $33, $01 ; $17 Brown 0133 38 | .byte $AD, $01 ; $18 yellow brown 39 | .byte $07, $02 ; $19 40 | .byte $41, $02 ; $1A green 41 | .byte $20, $1A ; $1B green 42 | .byte $E0, $45 ; $1C teal 43 | .byte $00, $00 ; $1D Black 44 | .byte $00, $00 ; $1E Black 45 | .byte $00, $00 ; $1F Black 46 | 47 | .byte $FF, $7F ; $20 white 48 | .byte $CC, $7E ; $21 sky blue 49 | .byte $52, $7E ; $22 light purple 50 | .byte $D8, $7D ; $23 51 | .byte $BE, $7D ; $24 pink 52 | .byte $BF, $65 ; $25 53 | .byte $1F, $3A ; $26 peach 54 | .byte $7D, $12 ; $27 orange 55 | .byte $F7, $02 ; $28 56 | .byte $71, $03 ; $29 neon green 57 | .byte $8B, $1B ; $2A bright green 58 | .byte $88, $43 ; $2B bright teal green 59 | .byte $29, $6F ; $2C bright light blue 60 | .byte $29, $25 ; $2D dark grey 61 | .byte $00, $00 ; $2E Black 62 | .byte $00, $00 ; $2F Black 63 | 64 | .byte $FF, $7F ; $30 white 65 | .byte $78, $7F ; $31 light blue 66 | .byte $5A, $7F ; $32 pink grey 67 | .byte $3D, $7F ; $33 pink 68 | .byte $1F, $7F ; $34 69 | .byte $1F, $77 ; $35 another pink 70 | .byte $3F, $63 ; $36 71 | .byte $7E, $53 ; $37 72 | .byte $9C, $4B ; $38 nyi 73 | .byte $B9, $4B ; $39 nyi 74 | .byte $D7, $57 ; $3A nyi 75 | .byte $D6, $67 ; $3B light greenish blue 76 | .byte $B6, $7B ; $3C nyi 77 | .byte $00, $00 ; $3D nyi 78 | .byte $00, $00 ; $3E Black 79 | .byte $00, $00 ; $3F Black 80 | 81 | 82 | palette_2_lookup: 83 | .byte $CE, $39 84 | .byte $64, $44 85 | .byte $00, $54 86 | .byte $08, $4C 87 | .byte $11, $38 88 | .byte $15, $08 89 | .byte $14, $00 90 | .byte $2F, $00 91 | .byte $A8, $00 92 | .byte $00, $01 93 | .byte $40, $01 94 | .byte $E0, $08 95 | .byte $E3, $2C 96 | .byte $00, $00 97 | .byte $00, $00 98 | .byte $00, $00 99 | .byte $F7, $5E 100 | .byte $C0, $75 101 | .byte $E4, $74 102 | .byte $10, $78 103 | .byte $17, $5C 104 | .byte $1C, $2C 105 | .byte $BB, $00 106 | .byte $39, $05 107 | .byte $D1, $01 108 | .byte $40, $02 109 | .byte $A0, $02 110 | .byte $40, $1E 111 | .byte $00, $46 112 | .byte $00, $00 113 | .byte $00, $00 114 | .byte $00, $00 115 | .byte $FF, $7F 116 | .byte $E7, $7E 117 | .byte $4B, $7E 118 | .byte $39, $7E 119 | .byte $FE, $7D 120 | .byte $DF, $59 121 | .byte $DF, $31 122 | .byte $7F, $1E 123 | .byte $FE, $1E 124 | .byte $50, $0B 125 | .byte $69, $27 126 | .byte $EB, $4F 127 | .byte $A0, $6F 128 | .byte $EF, $3D 129 | .byte $00, $00 130 | .byte $00, $00 131 | .byte $FF, $7F 132 | .byte $95, $7F 133 | .byte $58, $7F 134 | .byte $3A, $7F 135 | .byte $1F, $7F 136 | .byte $1F, $6F 137 | .byte $FF, $5A 138 | .byte $7F, $57 139 | .byte $9F, $53 140 | .byte $FC, $53 141 | .byte $D5, $5F 142 | .byte $F6, $67 143 | .byte $F3, $7B 144 | .byte $18, $63 145 | .byte $00, $00 146 | .byte $00, $00 147 | 148 | ; greyscale 149 | palette_3_lookup: 150 | .byte $CE, $39, $E7, $1C, $C6, $18, $A5, $14, $E7, $1C, $C6, $18, $C6, $18, $42, $08 151 | .byte $63, $0C, $E7, $1C, $08, $21, $E7, $1C, $E7, $1C, $00, $00, $21, $04, $21, $04 152 | .byte $D6, $5A, $EF, $3D, $AD, $35, $8C, $31, $CE, $39, $AD, $35, $AD, $35, $8C, $31 153 | .byte $CE, $39, $EF, $3D, $31, $46, $10, $42, $EF, $3D, $C6, $18, $21, $04, $21, $04 154 | .byte $DE, $7B, $F7, $5E, $94, $52, $52, $4A, $94, $52, $73, $4E, $94, $52, $B5, $56 155 | .byte $D6, $5A, $F7, $5E, $39, $67, $18, $63, $18, $63, $8C, $31, $21, $04, $21, $04 156 | .byte $DE, $7B, $BD, $77, $7B, $6F, $39, $67, $39, $67, $39, $67, $39, $67, $5A, $6B 157 | .byte $7B, $6F, $7B, $6F, $7B, $6F, $7B, $6F, $7B, $6F, $F7, $5E, $21, $04, $21, $04 158 | 159 | 160 | ;nes classic fbx 161 | palette_4_lookup: 162 | .byte $8C, $31, $00, $44, $23, $4C, $46, $3C, $4A, $30, $0B, $08, $2A, $00, $87, $04 163 | .byte $C4, $04, $01, $05, $02, $09, $E0, $0C, $A0, $28, $00, $00, $00, $00, $00, $00 164 | .byte $B5, $56, $21, $61, $89, $6C, $4D, $64, $52, $54, $73, $24, $D2, $00, $4E, $01 165 | .byte $AB, $09, $E2, $09, $02, $06, $C2, $25, $83, $49, $00, $00, $00, $00, $00, $00 166 | .byte $FF, $7F, $6C, $7E, $F1, $7D, $B6, $7D, $BB, $79, $DC, $55, $1C, $2E, $79, $12 167 | .byte $D5, $02, $0E, $03, $2B, $27, $06, $47, $E9, $66, $08, $21, $00, $00, $00, $00 168 | .byte $FF, $7F, $57, $7F, $39, $7F, $1B, $7F, $1D, $7F, $1F, $73, $3E, $63, $3C, $53 169 | .byte $7B, $4F, $99, $4F, $97, $5F, $B6, $67, $96, $77, $B5, $56, $00, $00, $00, $00 170 | 171 | ; pvm 172 | palette_5_lookup: 173 | .byte $AD, $31, $40, $38, $03, $40, $06, $38, $0A, $28, $0B, $08, $6A, $00, $87, $00 174 | .byte $C4, $00, $E0, $00, $E0, $00, $E0, $0C, $C0, $24, $00, $00, $00, $00, $00, $00 175 | .byte $F7, $5A, $42, $5D, $A9, $6C, $6C, $6C, $73, $4C, $93, $20, $F4, $00, $51, $01 176 | .byte $AC, $01, $E5, $01, $00, $02, $E0, $21, $E0, $45, $00, $00, $00, $00, $00, $00 177 | .byte $FF, $7F, $AD, $7E, $52, $7E, $36, $7E, $FD, $7D, $FE, $61, $3E, $2E, $BC, $12 178 | .byte $3A, $03, $72, $03, $8C, $1F, $88, $3F, $49, $6F, $49, $25, $00, $00, $00, $00 179 | .byte $FF, $7F, $BA, $7F, $9C, $7F, $7D, $7F, $5E, $7F, $7F, $77, $7F, $5F, $BF, $4F 180 | .byte $DE, $47, $FA, $4B, $F7, $57, $F5, $67, $D9, $7B, $17, $5F, $00, $00, $00, $00 181 | 182 | ; real 183 | palette_6_lookup: 184 | .byte $AD, $35, $80, $44, $00, $54, $08, $48, $0E, $38, $0F, $20, $0E, $00, $4C, $00 185 | .byte $88, $00, $C6, $00, $40, $01, $00, $21, $00, $31, $00, $00, $42, $08, $42, $08 186 | .byte $F7, $5E, $64, $6D, $E7, $7C, $90, $78, $18, $60, $5A, $38, $9A, $10, $15, $09 187 | .byte $4F, $01, $8B, $01, $20, $02, $C0, $35, $C0, $4D, $84, $10, $42, $08, $42, $08 188 | .byte $FF, $7F, $89, $7E, $31, $7E, $B8, $7D, $5F, $7D, $9F, $5D, $FF, $3D, $5F, $1E 189 | .byte $BB, $02, $34, $13, $69, $27, $25, $53, $03, $77, $6B, $2D, $42, $08, $42, $08 190 | .byte $FF, $7F, $56, $7F, $18, $7F, $FD, $7E, $DF, $7E, $FF, $76, $1F, $63, $5F, $57 191 | .byte $BF, $4B, $DE, $53, $F8, $63, $D5, $7B, $B4, $7F, $18, $63, $84, $10, $42, $08 192 | 193 | ; smooth y2 FBX 194 | palette_7_lookup: 195 | .byte $AD, $35, $40, $44, $03, $4C, $07, $44, $0C, $30, $0C, $08, $2A, $00, $67, $00 196 | .byte $C3, $00, $00, $01, $00, $01, $E0, $0C, $C0, $2C, $00, $00, $00, $00, $00, $00 197 | .byte $F7, $5E, $21, $69, $A8, $74, $6D, $6C, $53, $54, $74, $24, $D3, $00, $2F, $01 198 | .byte $8A, $01, $E3, $01, $E0, $01, $C0, $1D, $80, $45, $00, $00, $00, $00, $00, $00 199 | .byte $FF, $7F, $8D, $7E, $71, $7E, $16, $7E, $DB, $7D, $DC, $5D, $3C, $36, $7A, $16 200 | .byte $B6, $06, $0F, $0B, $2A, $23, $28, $43, $08, $63, $29, $25, $00, $00, $00, $00 201 | .byte $FF, $7F, $B9, $7F, $7B, $7F, $7D, $7F, $5F, $7F, $5F, $7B, $7F, $67, $9F, $5B 202 | .byte $DE, $57, $FB, $57, $F9, $5F, $F8, $6B, $D8, $7B, $F7, $5E, $00, $00, $00, $00 203 | 204 | ; GB 205 | palette_8_lookup: 206 | .word $0020, $0040, $0240, $0340, $0320, $0120, $0100, $0200 207 | .word $0200, $0100, $0000, $0000, $0020, $0000, $0000, $0000 208 | .word $0140, $0260, $0060, $0260, $0060, $0220, $0200, $0300 209 | .word $0100, $0300, $0100, $0000, $0040, $0000, $0000, $0000 210 | .word $0360, $0060, $0260, $0060, $0260, $0360, $0320, $0100 211 | .word $0300, $0100, $0300, $0040, $0160, $0120, $0000, $0000 212 | .word $0360, $0060, $0260, $0160, $0360, $0360, $0360, $0240 213 | .word $0040, $0140, $0340, $0260, $0260, $0000, $0000, $0000 -------------------------------------------------------------------------------- /src/palette_updates.asm: -------------------------------------------------------------------------------- 1 | check_for_palette_updates: 2 | PHA 3 | LDA PALETTE_NEEDS_UPDATING 4 | BNE :+ 5 | PLA 6 | rtl 7 | : pla 8 | stz PALETTE_NEEDS_UPDATING 9 | 10 | write_palette_data: 11 | PHX 12 | PHY 13 | PHA 14 | 15 | setAXY8 16 | PHK 17 | PLB 18 | 19 | LDA $00 20 | PHA 21 | LDA $01 22 | PHA 23 | 24 | LDA OPTIONS_PALETTE 25 | ASL 26 | TAY 27 | LDA palette_adddresses, Y 28 | STA $00 29 | LDA palette_adddresses + 1, Y 30 | STA $01 31 | 32 | LDX #$00 33 | STZ CURR_PALETTE_ADDR 34 | STZ CGADD 35 | 36 | ; lookup our 2 byte color from palette_lookup, color * 2 37 | ; Our palettes are written by writing to CGDATA 38 | ; PALETTE_UPDATE_START contains the first byte of palette data to update. 39 | palette_entry: 40 | 41 | LDA PALETTE_UPDATE_START, X 42 | AND PALETTE_FILTER 43 | ASL A 44 | TAY 45 | LDA ($00), Y 46 | STA CGDATA 47 | INY 48 | LDA ($00), Y 49 | STA CGDATA 50 | 51 | LDA PALETTE_UPDATE_START + 1, X 52 | AND PALETTE_FILTER 53 | ASL A 54 | TAY 55 | 56 | LDA ($00), Y 57 | STA CGDATA 58 | INY 59 | LDA ($00), Y 60 | STA CGDATA 61 | 62 | LDA PALETTE_UPDATE_START + 2, X 63 | AND PALETTE_FILTER 64 | ASL A 65 | TAY 66 | 67 | LDA ($00), Y 68 | STA CGDATA 69 | INY 70 | LDA ($00), Y 71 | STA CGDATA 72 | 73 | LDA PALETTE_UPDATE_START + 3, X 74 | AND PALETTE_FILTER 75 | ASL A 76 | TAY 77 | 78 | LDA ($00), Y 79 | STA CGDATA 80 | INY 81 | LDA ($00), Y 82 | STA CGDATA 83 | 84 | LDA CURR_PALETTE_ADDR 85 | CLC 86 | ADC #$10 87 | STA CGADD 88 | STA CURR_PALETTE_ADDR 89 | 90 | INX 91 | INX 92 | INX 93 | INX 94 | ; CPY #$10 95 | ; BNE palette_entry 96 | 97 | TXA 98 | AND #$0F 99 | CMP #$00 100 | BNE skip_writing_four_empties 101 | 102 | ; after 16 entries we write an empty set of palettes 103 | CLC 104 | LDA CURR_PALETTE_ADDR 105 | ADC #$40 106 | STA CGADD 107 | STA CURR_PALETTE_ADDR 108 | 109 | skip_writing_four_empties: 110 | CPX #$20 111 | BEQ :+ 112 | jmp palette_entry 113 | : 114 | 115 | 116 | LDA ACTIVE_NES_BANK 117 | INC A 118 | ORA #$A0 119 | PHA 120 | PLB 121 | 122 | PLA 123 | STA $01 124 | PLA 125 | STA $00 126 | 127 | PLA 128 | PLY 129 | PLX 130 | ; done after $20 131 | RTL 132 | 133 | zero_all_palette_long: 134 | jsr zero_all_palette 135 | rtl 136 | 137 | zero_all_palette: 138 | LDY #$00 139 | LDX #$02 140 | 141 | STZ CGADD 142 | 143 | : STZ CGDATA 144 | DEY 145 | BNE :- 146 | DEX 147 | BNE :- 148 | 149 | RTS 150 | 151 | snes_default_bg_palette: 152 | .byte $00, $00, $FF, $7F, $B5, $56, $29, $25, $00, $00, $00, $00, $00, $00, $00, $00 153 | .byte $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00 154 | .byte $00, $00, $FF, $7F, $B5, $56, $29, $25, $00, $00, $00, $00, $00, $00, $00, $00 155 | .byte $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00 156 | .byte $00, $00, $FF, $7F, $B5, $56, $29, $25, $00, $00, $00, $00, $00, $00, $00, $00 157 | .byte $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00 158 | .byte $00, $00, $FF, $7F, $B5, $56, $29, $25, $00, $00, $00, $00, $00, $00, $00, $00 159 | .byte $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00 160 | 161 | snes_sprite_palatte: 162 | .byte $00, $00, $FF, $7F, $B5, $56, $29, $25, $00, $00, $00, $00, $00, $00, $00, $00 163 | .byte $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00 164 | .byte $00, $00, $FF, $7F, $B5, $56, $29, $25, $00, $00, $00, $00, $00, $00, $00, $00 165 | .byte $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00 166 | .byte $00, $00, $FF, $7F, $B5, $56, $29, $25, $00, $00, $00, $00, $00, $00, $00, $00 167 | .byte $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00 168 | .byte $00, $00, $FF, $7F, $B5, $56, $29, $25, $00, $00, $00, $00, $00, $00, $00, $00 169 | .byte $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00 170 | 171 | write_default_palettes_jsl: 172 | jsr write_default_palettes 173 | rtl 174 | 175 | write_default_palettes: 176 | STZ CGADD 177 | sta CGADD 178 | LDY #$00 179 | : LDA snes_sprite_palatte, y 180 | STA CGDATA 181 | INY 182 | CMP #$40 183 | BNE :- 184 | 185 | 186 | LDA #$80 187 | sta CGADD 188 | LDY #$00 189 | : LDA snes_sprite_palatte, y 190 | STA CGDATA 191 | INY 192 | CMP #$40 193 | BNE :- 194 | rts 195 | 196 | ; assumes CGADD is already set 197 | ; nes color is in A 198 | store_nes_color_in_palette: 199 | PHX 200 | ASL A 201 | TAX 202 | LDA $A086E0, X ; palette_lookup, X 203 | STA CGDATA 204 | LDA $A086E1, X ; palette_lookup + 1, X 205 | STA CGDATA 206 | 207 | PLX 208 | RTL 209 | 210 | 211 | 212 | write_option_palette: 213 | PHK 214 | PLB 215 | LDA RDNMI 216 | : LDA RDNMI 217 | BPL :- 218 | 219 | LDA OPTIONS_PALETTE 220 | ASL 221 | TAY 222 | LDA palette_adddresses, Y 223 | STA $00 224 | INY 225 | LDA palette_adddresses, Y 226 | STA $01 227 | 228 | LDY #$00 229 | 230 | LDA #$41 231 | STA CGADD 232 | LDX #$80 233 | LDY #$00 234 | 235 | : LDA ($00), Y 236 | STA CGDATA 237 | INY 238 | DEX 239 | BNE :- 240 | 241 | RTL 242 | 243 | write_option_palette_from_indexes: 244 | PHK 245 | PLB 246 | LDA RDNMI 247 | : LDA RDNMI 248 | BPL :- 249 | 250 | STZ CGADD 251 | LDY #$00 252 | LDX #$00 253 | 254 | LDA OPTIONS_PALETTE 255 | ASL 256 | TAY 257 | LDA palette_adddresses, Y 258 | STA $00 259 | INY 260 | LDA palette_adddresses, Y 261 | STA $01 262 | 263 | LDY #$00 264 | 265 | option_palette_loop: 266 | LDA default_options_bg_palette_indexes, X 267 | ASL A 268 | TAY 269 | 270 | LDA ($00), Y 271 | STA CGDATA 272 | INY 273 | 274 | LDA ($00), Y 275 | STA CGDATA 276 | INY 277 | 278 | ; every 4 we need to write a bunch of empty palette entries 279 | INX 280 | TXA 281 | AND #$03 282 | BNE :+ 283 | 284 | CLC 285 | LDA CURR_PALETTE_ADDR 286 | ADC #$10 287 | STA CGADD 288 | STA CURR_PALETTE_ADDR 289 | 290 | : 291 | TXA 292 | AND #$0F 293 | CMP #$00 294 | BNE :+ 295 | ; after 16 entries we write an empty set of palettes 296 | CLC 297 | LDA CURR_PALETTE_ADDR 298 | ADC #$40 299 | STA CGADD 300 | STA CURR_PALETTE_ADDR 301 | 302 | : 303 | CPX #$20 304 | BNE option_palette_loop 305 | rtl 306 | 307 | 308 | default_options_bg_palette_indexes: 309 | .byte $0F, $07, $00, $01, $0F, $02, $01, $1C, $0F, $0A, $18, $28, $0F, $17, $19, $10 310 | 311 | default_options_sprite_palette_indexes: 312 | .byte $0F, $30, $15, $0F, $0F, $30, $00, $0F, $0F, $3B, $1B, $0F, $0F, $06, $16, $38 313 | 314 | default_options_palette: 315 | .byte $00, $00, $FF, $7F, $74, $64, $42, $50, $00, $00, $00, $00, $00, $00, $00, $00 316 | .byte $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00 317 | .byte $00, $00, $F7, $02, $33, $01, $6A, $00, $00, $00, $00, $00, $00, $00, $00, $00 318 | .byte $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00 319 | .byte $00, $00, $29, $6F, $07, $02, $A0, $44, $00, $00, $00, $00, $00, $00, $00, $00 320 | .byte $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00 321 | .byte $00, $00, $BF, $65, $8C, $31, $76, $3C, $00, $00, $00, $00, $00, $00, $00, $00 322 | .byte $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00 323 | 324 | options_sprite_palette: 325 | .byte $00, $00, $FF, $7F, $1F, $3A, $6A, $00, $00, $00, $00, $00, $00, $00, $00, $00 326 | .byte $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00 327 | .byte $00, $00, $78, $7F, $42, $50, $76, $3C, $00, $00, $00, $00, $00, $00, $00, $00 328 | .byte $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00 329 | .byte $00, $00, $08, $7D, $D8, $7D, $78, $7F, $00, $00, $00, $00, $00, $00, $00, $00 330 | .byte $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00 331 | .byte $00, $00, $0D, $00, $D6, $10, $9C, $4B, $00, $00, $00, $00, $00, $00, $00, $00 332 | .byte $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00 333 | 334 | -------------------------------------------------------------------------------- /src/wram_routines.asm: -------------------------------------------------------------------------------- 1 | .SEGMENT "WRAM_ROUTINES" 2 | 3 | ; APU Update routines 4 | routines_start: 5 | LoadSFXRegisters: 6 | lda $e0 7 | cmp #$00 8 | beq sq1_r 9 | cmp #$04 10 | beq sq2_r 11 | cmp #$08 12 | beq tri_r 13 | noise_r: 14 | lda ($e2), y 15 | jsr WriteAPUNoiseCtrl0 16 | iny 17 | lda ($e2), y 18 | jsr WriteAPUNoiseCtrl1 19 | iny 20 | lda ($e2), y 21 | jsr WriteAPUNoiseCtrl2 22 | iny 23 | lda ($e2), y 24 | jsr WriteAPUNoiseCtrl3 25 | iny 26 | bra end_r 27 | sq1_r: 28 | lda ($e2), y 29 | jsr WriteAPUSq0Ctrl0 30 | iny 31 | lda ($e2), y 32 | jsr WriteAPUSq0Ctrl1 33 | iny 34 | lda ($e2), y 35 | jsr WriteAPUSq0Ctrl2 36 | iny 37 | lda ($e2), y 38 | jsr WriteAPUSq0Ctrl3 39 | iny 40 | bra end_r 41 | sq2_r: 42 | lda ($e2), y 43 | jsr WriteAPUSq1Ctrl0 44 | iny 45 | lda ($e2), y 46 | jsr WriteAPUSq1Ctrl1 47 | iny 48 | lda ($e2), y 49 | jsr WriteAPUSq1Ctrl2 50 | iny 51 | lda ($e2), y 52 | jsr WriteAPUSq1Ctrl3 53 | iny 54 | bra end_r 55 | tri_r: 56 | lda ($e2), y 57 | jsr WriteAPUTriCtrl0 58 | iny 59 | lda ($e2), y 60 | jsr WriteAPUTriCtrl1 61 | iny 62 | lda ($e2), y 63 | jsr WriteAPUTriCtrl2 64 | iny 65 | lda ($e2), y 66 | jsr WriteAPUTriCtrl3 67 | iny 68 | bra end_r 69 | end_r: 70 | lda #$00 71 | rts 72 | 73 | WriteAPUSq0Ctrl0: 74 | sta APUBase 75 | rts 76 | 77 | WriteAPUSq0Ctrl0_I_Y: 78 | sta APUBase, y 79 | rts 80 | 81 | WriteAPUSq0Ctrl0_I_X: 82 | sta APUBase, x 83 | rts 84 | 85 | WriteAPUSq0Ctrl0_Y: 86 | sty APUBase 87 | rts 88 | 89 | WriteAPUSq0Ctrl0_X: 90 | stx APUBase 91 | rts 92 | 93 | WriteAPUSq0Ctrl1: 94 | xba 95 | lda #$40 96 | tsb APUBase+$16 97 | xba 98 | sta APUBase+$01 99 | rts 100 | 101 | WriteAPUSq0Ctrl1_Y: 102 | xba 103 | lda #$40 104 | tsb APUBase+$16 105 | xba 106 | sty APUBase+$01 107 | rts 108 | 109 | WriteAPUSq0Ctrl1_I_Y: 110 | cpy #$00 111 | bne :+ 112 | jsr WriteAPUSq0Ctrl1 113 | rts 114 | : 115 | cpy #$04 116 | bne :+ 117 | jsr WriteAPUSq1Ctrl1 118 | rts 119 | : 120 | sta APUBase+$01, y 121 | rts 122 | 123 | WriteAPUSq0Ctrl1_I_X: 124 | cpx #$00 125 | bne :+ 126 | jsr WriteAPUSq0Ctrl1 127 | rts 128 | : 129 | cpx #$04 130 | bne :+ 131 | jsr WriteAPUSq1Ctrl1 132 | rts 133 | : 134 | sta APUBase+$01, x 135 | rts 136 | 137 | WriteAPUSq0Ctrl2: 138 | sta APUBase+$02 139 | rts 140 | 141 | WriteAPUSq0Ctrl2_X: 142 | stx APUBase+$02 143 | rts 144 | 145 | WriteAPUSq0Ctrl2_I_Y: 146 | sta APUBase+$02, y 147 | rts 148 | 149 | WriteAPUSq0Ctrl2_I_X: 150 | sta APUBase+$02, x 151 | rts 152 | 153 | 154 | WriteAPUSq0Ctrl3: 155 | phx 156 | sta APUBase+$03 157 | tax 158 | lda Sound__EmulateLengthCounter_length_d3_mixed, x 159 | sta APUSq0Length 160 | xba 161 | lda #$01 162 | tsb APUBase+$15 163 | tsb APUExtraControl 164 | plx 165 | xba 166 | rts 167 | 168 | WriteAPUSq0Ctrl3_X: 169 | pha 170 | stx APUBase+$03 171 | lda Sound__EmulateLengthCounter_length_d3_mixed, x 172 | sta APUSq0Length 173 | lda #$01 174 | tsb APUBase+$15 175 | tsb APUExtraControl 176 | pla 177 | rts 178 | 179 | WriteAPUSq0Ctrl3_I_Y: 180 | cpy #$00 181 | bne :+ 182 | jsr WriteAPUSq0Ctrl3 183 | rts 184 | : 185 | cpy #$04 186 | bne :+ 187 | jsr WriteAPUSq1Ctrl3 188 | rts 189 | : 190 | cpy #$08 191 | bne :+ 192 | jsr WriteAPUTriCtrl3 193 | rts 194 | : 195 | jsr WriteAPUNoiseCtrl3 196 | rts 197 | 198 | WriteAPUSq0Ctrl3_I_X: 199 | cpx #$00 200 | bne :+ 201 | jsr WriteAPUSq0Ctrl3 202 | rts 203 | : 204 | cpx #$04 205 | bne :+ 206 | jsr WriteAPUSq1Ctrl3 207 | rts 208 | : 209 | cpx #$08 210 | bne :+ 211 | jsr WriteAPUTriCtrl3 212 | rts 213 | : 214 | jsr WriteAPUNoiseCtrl3 215 | rts 216 | 217 | WriteAPUSq1Ctrl0: 218 | sta APUBase+$04 219 | rts 220 | 221 | WriteAPUSq1Ctrl0_X: 222 | stx APUBase+$04 223 | rts 224 | 225 | WriteAPUSq1Ctrl0_Y: 226 | sty APUBase+$04 227 | rts 228 | 229 | WriteAPUSq1Ctrl1: 230 | xba 231 | lda #$80 232 | tsb APUBase+$16 233 | xba 234 | sta APUBase+$05 235 | rts 236 | 237 | WriteAPUSq1Ctrl1_X: 238 | xba 239 | lda #$80 240 | tsb APUBase+$16 241 | xba 242 | stx APUBase+$05 243 | rts 244 | 245 | WriteAPUSq1Ctrl1_Y: 246 | xba 247 | lda #$80 248 | tsb APUBase+$16 249 | xba 250 | sty APUBase+$05 251 | rts 252 | 253 | WriteAPUSq1Ctrl2: 254 | sta APUBase+$06 255 | rts 256 | 257 | WriteAPUSq1Ctrl2_X: 258 | stx APUBase+$06 259 | rts 260 | 261 | WriteAPUSq1Ctrl3: 262 | phx 263 | sta APUBase+$07 264 | tax 265 | lda Sound__EmulateLengthCounter_length_d3_mixed, x 266 | sta APUSq1Length 267 | xba 268 | lda #$02 269 | tsb APUBase+$15 270 | tsb APUExtraControl 271 | plx 272 | xba 273 | rts 274 | 275 | WriteAPUSq1Ctrl3_X: 276 | pha 277 | stx APUBase+$07 278 | lda Sound__EmulateLengthCounter_length_d3_mixed, x 279 | sta APUSq1Length 280 | lda #$02 281 | tsb APUBase+$15 282 | tsb APUExtraControl 283 | pla 284 | rts 285 | 286 | WriteAPUTriCtrl0: 287 | sta APUBase+$08 288 | rts 289 | 290 | WriteAPUTriCtrl1: 291 | sta APUBase+$09 292 | rts 293 | 294 | WriteAPUTriCtrl2: 295 | sta APUBase+$0A 296 | rts 297 | 298 | WriteAPUTriCtrl2_X: 299 | stx APUBase+$0A 300 | rts 301 | 302 | WriteAPUTriCtrl3: 303 | phx 304 | sta APUBase+$0B 305 | tax 306 | lda #$04 307 | tsb APUExtraControl 308 | tsb APUBase+$15 309 | lda Sound__EmulateLengthCounter_length_d3_mixed, x 310 | sta APUTriLength 311 | txa 312 | plx 313 | rts 314 | 315 | WriteAPUNoiseCtrl0: 316 | sta APUBase+$0C 317 | rts 318 | 319 | WriteAPUNoiseCtrl1: 320 | sta APUBase+$0D 321 | rts 322 | 323 | WriteAPUNoiseCtrl2: 324 | sta APUBase+$0E 325 | rts 326 | 327 | WriteAPUNoiseCtrl2_X: 328 | stx APUBase+$0E 329 | rts 330 | 331 | WriteAPUNoiseCtrl3: 332 | phx 333 | sta APUBase+$0F 334 | tax 335 | lda #$08 336 | tsb APUExtraControl 337 | tsb APUBase+$15 338 | lda Sound__EmulateLengthCounter_length_d3_mixed, x 339 | sta APUNoiLength 340 | txa 341 | plx 342 | rts 343 | 344 | WriteAPUControl: 345 | sta APUIOTemp 346 | xba 347 | lda APUIOTemp 348 | eor #$ff 349 | and #$1f 350 | trb APUBase+$15 351 | trb APUExtraControl 352 | lsr APUIOTemp 353 | bcs :+ 354 | stz APUBase+$03 355 | stz APUSq0Length 356 | : 357 | lsr APUIOTemp 358 | bcs :+ 359 | stz APUBase+$07 360 | stz APUSq1Length 361 | : 362 | lsr APUIOTemp 363 | bcs :+ 364 | stz APUBase+$0B 365 | stz APUTriLength 366 | : 367 | lsr APUIOTemp 368 | bcs :+ 369 | stz APUBase+$0F 370 | stz APUNoiLength 371 | : 372 | lsr APUIOTemp 373 | bcc :+ 374 | lda #$10 375 | tsb APUBase+$15 376 | bne :+ 377 | tsb APUExtraControl 378 | : 379 | xba 380 | rts 381 | 382 | Sound__EmulateLengthCounter_length_d3_mixed: 383 | .byte $06,$06,$06,$06,$06,$06,$06,$06,$80,$80,$80,$80,$80,$80,$80,$80 384 | .byte $0B,$0B,$0B,$0B,$0B,$0B,$0B,$0B,$02,$02,$02,$02,$02,$02,$02,$02 385 | .byte $15,$15,$15,$15,$15,$15,$15,$15,$03,$03,$03,$03,$03,$03,$03,$03 386 | .byte $29,$29,$29,$29,$29,$29,$29,$29,$04,$04,$04,$04,$04,$04,$04,$04 387 | .byte $51,$51,$51,$51,$51,$51,$51,$51,$05,$05,$05,$05,$05,$05,$05,$05 388 | .byte $1F,$1F,$1F,$1F,$1F,$1F,$1F,$1F,$06,$06,$06,$06,$06,$06,$06,$06 389 | .byte $08,$08,$08,$08,$08,$08,$08,$08,$07,$07,$07,$07,$07,$07,$07,$07 390 | .byte $0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F,$08,$08,$08,$08,$08,$08,$08,$08 391 | .byte $07,$07,$07,$07,$07,$07,$07,$07,$09,$09,$09,$09,$09,$09,$09,$09 392 | .byte $0D,$0D,$0D,$0D,$0D,$0D,$0D,$0D,$0A,$0A,$0A,$0A,$0A,$0A,$0A,$0A 393 | .byte $19,$19,$19,$19,$19,$19,$19,$19,$0B,$0B,$0B,$0B,$0B,$0B,$0B,$0B 394 | .byte $31,$31,$31,$31,$31,$31,$31,$31,$0C,$0C,$0C,$0C,$0C,$0C,$0C,$0C 395 | .byte $61,$61,$61,$61,$61,$61,$61,$61,$0D,$0D,$0D,$0D,$0D,$0D,$0D,$0D 396 | .byte $25,$25,$25,$25,$25,$25,$25,$25,$0E,$0E,$0E,$0E,$0E,$0E,$0E,$0E 397 | .byte $09,$09,$09,$09,$09,$09,$09,$09,$0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F 398 | .byte $11,$11,$11,$11,$11,$11,$11,$11,$10,$10,$10,$10,$10,$10,$10,$10 399 | 400 | routines_end: -------------------------------------------------------------------------------- /src/hirom.cfg: -------------------------------------------------------------------------------- 1 | MEMORY { 2 | 3 | PRE_WRAM: start = $0000, size = $1C00, fill = yes, type = rw; 4 | WRAM_ROUTINES: start = $1C00, size = $400, fill = yes, type = ro; 5 | ROM0: start = $2000, size = $E000, fill = yes, type = rw; 6 | 7 | EMPTY_SPACE: start = $010000, size = $1F0000, fill = yes; 8 | 9 | SRAM0: start = $200000, size = $8000, type = rw, fill = yes; 10 | ROM1: start = $208000, size = $8000, fill = yes; 11 | 12 | SRAM1: start = $210000, size = $8000, type = rw, fill = yes, fillval = 1; 13 | PRGA1: start = $218000, size = $4000, fill = yes; 14 | PRGA1C: start = $21C000, size = $4000, fill = yes; 15 | 16 | SRAM2: start = $220000, size = $8000, type = rw, fill = yes, fillval = 2; 17 | PRGA2: start = $228000, size = $4000, fill = yes; 18 | PRGA2C: start = $22C000, size = $4000, fill = yes; 19 | 20 | SRAM3: start = $230000, size = $8000, type = rw, fill = yes, fillval = 3; 21 | PRGA3: start = $238000, size = $4000, fill = yes; 22 | PRGA3C: start = $23C000, size = $4000, fill = yes; 23 | 24 | SRAM4: start = $240000, size = $8000, type = rw, fill = yes; 25 | PRGA4: start = $248000, size = $4000, fill = yes; 26 | PRGA4C: start = $24C000, size = $4000, fill = yes; 27 | 28 | SRAM5: start = $250000, size = $8000, type = rw, fill = yes; 29 | PRGA5: start = $258000, size = $4000, fill = yes; 30 | PRGA5C: start = $25C000, size = $4000, fill = yes; 31 | 32 | SRAM6: start = $260000, size = $8000, type = rw, fill = yes; 33 | PRGA6: start = $268000, size = $4000, fill = yes; 34 | PRGA6C: start = $26C000, size = $4000, fill = yes; 35 | 36 | SRAM7: start = $270000, size = $8000, type = rw, fill = yes; 37 | PRGA7: start = $278000, size = $4000, fill = yes; 38 | PRGA7C: start = $27C000, size = $4000, fill = yes; 39 | 40 | # CHROM banks 41 | SRAM8: start = $280000, size = $8000, type = rw, fill = yes; 42 | PRGA8: start = $288000, size = $8000, fill = yes; 43 | SRAM9: start = $290000, size = $8000, type = rw, fill = yes; 44 | PRGA9: start = $298000, size = $8000, fill = yes; 45 | SRAMA: start = $2A0000, size = $8000, type = rw, fill = yes; 46 | PRGAA: start = $2A8000, size = $8000, fill = yes; 47 | SRAMB: start = $2B0000, size = $8000, type = rw, fill = yes; 48 | PRGAB: start = $2B8000, size = $8000, fill = yes; 49 | SRAMC: start = $2C0000, size = $8000, type = rw, fill = yes; 50 | PRGAC: start = $2C8000, size = $8000, fill = yes; 51 | SRAMD: start = $2D0000, size = $8000, type = rw, fill = yes; 52 | PRGAD: start = $2D8000, size = $8000, fill = yes; 53 | SRAME: start = $2E0000, size = $8000, type = rw, fill = yes; 54 | PRGAE: start = $2E8000, size = $8000, fill = yes; 55 | SRAMF: start = $2F0000, size = $8000, type = rw, fill = yes; 56 | PRGAF: start = $2F8000, size = $8000, fill = yes; 57 | SRAMB0: start = $300000, size = $8000, type = rw, fill = yes; 58 | PRGB0: start = $308000, size = $8000, fill = yes; 59 | SRAMB1: start = $310000, size = $8000, type = rw, fill = yes; 60 | PRGB1: start = $318000, size = $8000, fill = yes; 61 | SRAMB2: start = $320000, size = $8000, type = rw, fill = yes; 62 | PRGB2: start = $328000, size = $8000, fill = yes; 63 | SRAMB3: start = $330000, size = $8000, type = rw, fill = yes; 64 | PRGB3: start = $338000, size = $8000, fill = yes; 65 | 66 | SRAMB4: start = $340000, size = $8000, type = rw, fill = yes; 67 | PRGB4: start = $348000, size = $8000, fill = yes; 68 | SRAMB5: start = $350000, size = $8000, type = rw, fill = yes; 69 | PRGB5: start = $358000, size = $8000, fill = yes; 70 | SRAMB6: start = $360000, size = $8000, type = rw, fill = yes; 71 | PRGB6: start = $368000, size = $8000, fill = yes; 72 | SRAMB7: start = $370000, size = $8000, type = rw, fill = yes; 73 | PRGB7: start = $378000, size = $8000, fill = yes; 74 | SRAMB8: start = $380000, size = $8000, type = rw, fill = yes; 75 | PRGB8: start = $388000, size = $8000, fill = yes; 76 | SRAMB9: start = $390000, size = $8000, type = rw, fill = yes; 77 | PRGB9: start = $398000, size = $8000, fill = yes; 78 | SRAMBA: start = $3A0000, size = $8000, type = rw, fill = yes; 79 | PRGBA: start = $3A8000, size = $8000, fill = yes; 80 | SRAMBB: start = $3B0000, size = $8000, type = rw, fill = yes; 81 | PRGBB: start = $3B8000, size = $8000, fill = yes; 82 | SRAMBC: start = $3C0000, size = $8000, type = rw, fill = yes; 83 | PRGBV: start = $3C8000, size = $8000, fill = yes; 84 | SRAMBD: start = $3D0000, size = $8000, type = rw, fill = yes; 85 | PRGBD: start = $3D8000, size = $8000, fill = yes; 86 | SRAMBE: start = $3E0000, size = $8000, type = rw, fill = yes; 87 | PRGBE: start = $3E8000, size = $8000, fill = yes; 88 | SRAMBF: start = $3F0000, size = $8000, type = rw, fill = yes; 89 | PRGBF: start = $3F8000, size = $8000, fill = yes; 90 | } 91 | 92 | SEGMENTS { 93 | # ZEROPAGE: load = ZEROPAGE, type = zp; 94 | WRAM_ROUTINES: load = WRAM_ROUTINES, start = $001C00 type = ro; 95 | ROM0: load = ROM0, start = $008000; 96 | SOUND_EMU: load = ROM0, start = $00AA00; 97 | CODE: load = ROM0, start = $00FE00; 98 | HEADER: load = ROM0, start = $00FFC0; 99 | ROMSPEC: load = ROM0, start = $00FFD5; 100 | VECTOR: load = ROM0, start = $00FFE0; 101 | 102 | EMPTY_SPACE: load = EMPTY_SPACE, start = $010000; 103 | 104 | msu_video_player_0000: load = EMPTY_SPACE, start = $070000; 105 | msu_video_player_fed0: load = EMPTY_SPACE, start = $07FED0; 106 | 107 | EMU_2A03_B1: load = EMPTY_SPACE, start = $0C8000; 108 | EMU_2A03_B2: load = EMPTY_SPACE, start = $0D8000; 109 | 110 | SRAM0: load = SRAM1, start = $200000; 111 | PRGA0: load = ROM1, start = $208000; 112 | HDMA_LOOKUP:load = ROM1, start = $20A000; 113 | PRGA0C: load = ROM1, start = $20C000; 114 | 115 | SRAM1: load = SRAM1, start = $210000; 116 | PRGA1: load = PRGA1, start = $218000; 117 | PRGA1C: load = PRGA1C, start = $21C000; 118 | 119 | SRAM2: load = SRAM2, start = $220000; 120 | PRGA2: load = PRGA2, start = $228000; 121 | PRGA2C: load = PRGA2C, start = $22C000; 122 | 123 | SRAM3: load = SRAM3, start = $230000; 124 | PRGA3: load = PRGA3, start = $238000; 125 | PRGA3C: load = PRGA3C, start = $23C000; 126 | 127 | SRAM4: load = SRAM4, start = $240000; 128 | PRGA4: load = PRGA4, start = $248000; 129 | PRGA4C: load = PRGA4C, start = $24C000; 130 | 131 | SRAM5: load = SRAM5, start = $250000; 132 | PRGA5: load = PRGA5, start = $258000; 133 | PRGA5C: load = PRGA5C, start = $25C000; 134 | 135 | SRAM6: load = SRAM6, start = $260000; 136 | PRGA6: load = PRGA6, start = $268000; 137 | PRGA6C: load = PRGA6C, start = $26C000; 138 | 139 | SRAM7: load = SRAM7, start = $270000; 140 | PRGA7: load = PRGA7 , start = $278000; 141 | PRGA7C: load = PRGA7C, start = $27C000; 142 | 143 | SRAM8: load = SRAM8, start = $280000; 144 | PRGA8: load = PRGA8 , start = $288000; 145 | SRAM9: load = SRAM9, start = $290000; 146 | PRGA9: load = PRGA9 , start = $298000; 147 | SRAMA: load = SRAMA, start = $2A0000; 148 | PRGAA: load = PRGAA , start = $2A8000; 149 | SRAMB: load = SRAMB, start = $2B0000; 150 | PRGAB: load = PRGAB, start = $2B8000; 151 | SRAMC: load = SRAMC, start = $2C0000; 152 | PRGAC: load = PRGAC, start = $2C8000; 153 | SRAMD: load = SRAMD, start = $2D0000; 154 | PRGAD: load = PRGAD, start = $2D8000; 155 | SRAME: load = SRAME, start = $2E0000; 156 | PRGAE: load = PRGAE, start = $2E8000; 157 | SRAMF: load = SRAMF, start = $2F0000; 158 | PRGAF: load = PRGAF, start = $2F8000; 159 | 160 | PRGB0: load = PRGB0, start = $308000; 161 | PRGB1: load = PRGB1, start = $318000; 162 | 163 | SRAMB2: load = SRAMB2, start = $320000; 164 | PRGB2: load = PRGB2, start = $328000; 165 | SRAMB3: load = SRAMB3, start = $330000; 166 | PRGB3: load = PRGB3, start = $338000; 167 | 168 | } -------------------------------------------------------------------------------- /src/vars.inc: -------------------------------------------------------------------------------- 1 | ; useful build modifications to build with or without things present in the rom 2 | .define DEBUG_MOD 1 3 | .define ENABLE_MSU 0 4 | .define OLD_2A03 1 ; 0 = use updated vers, 1 = use original 5 | 6 | ; constants 7 | LINE_TO_START_HUD = 199 8 | NUM_SCANLINES = 240 ; overscan on 9 | 10 | ; These values are almost always used by NES game, but the values will be different 11 | ; for each game. They will almost always be in the zero page, or close to it. 12 | HOFS_LB = $FD ; BG H Scroll position [x] updated 13 | VOFS_LB = $FC ; BG V Scroll position [x] updated 14 | 15 | PPU_CONTROL_STATE = $FF ;updated ; Current state of the PPU Control register 16 | PPU_MASK_STATE = $FE ;needs updating ; Current state of the PPU Mask register 17 | ACTIVE_NES_BANK = $08AE ; Current bank loaded into the 8000-BFFF bank (for UNROM and MMC1) 18 | 19 | CURRENT_SPRITE_BANK = $D5 20 | CURRENT_BG_BANK = $D6 21 | 22 | ; NES RAM MAP Values 23 | P1_HEALTH = $041E 24 | P2_HEALTH = $041F 25 | ENEMY_1_HEALTH = $0420 26 | ENEMY_2_HEALTH = $0421 27 | CURR_AREA = $0422 28 | P1_LIVES = $0432 29 | P2_LIVES = $0433 30 | NUM_PLAYERS = $0434 ; 00 for 1 player, 01 for 2 players 31 | DIFFICULTY = $0435 ; 00 - 02 32 | ; max level per difficulty 33 | ; A794E4 - A794E6 34 | ; Health to refill when loading level? 35 | ; a7959B - a7959d 36 | 37 | ; SNES Register Value storage 38 | ; since SNES Registers don't line up with NES registers 1:1 39 | ; we have to store the state of SNES registers separately 40 | .define NMITIMEN_STATE $1706 41 | .define VMAIN_STATE $1705 42 | .define INIDISP_STATE $1704 43 | .define TM_STATE $1707 44 | 45 | ; NES stores only the lb for h/v offset 46 | ; for SNES we also need to store the HB 47 | 48 | 49 | curr_ppu_ctrl_value = $089F 50 | curr_hoff_low = $08A0 51 | HOFS_HB = $08A1 52 | curr_voff_low = $08A2 53 | VOFS_HB = $08A3 54 | lines_left_to_handle = $08A4 55 | current_voff_offset = $08A5 56 | 57 | PALETTE_HAS_BEEN_SET_TO_GREYSCALE = $083E 58 | PALETTE_NEEDS_UPDATING = $083F 59 | PALETTE_UPDATE_START = $0840 60 | PALETTE_ENTRY_CNT = $08A6 61 | PALETTE_OFFSET = $08A7 62 | PALETTE_FILTER = $083D 63 | 64 | ; MSU_SELECTED = $084C 65 | QOL_SETTINGS = $084D 66 | 67 | ; 0850 - 085F are used for options 68 | OPTIONS_START_ADDR = $0860 69 | ; which options are stored at which address 70 | OPTIONS_PALETTE = OPTIONS_START_ADDR 71 | OPTIONS_LIVES = OPTIONS_START_ADDR + 1 72 | OPTIONS_STARTING_LEVEL = OPTIONS_START_ADDR + 2 73 | OPTIONS_MSU_SELECTED = OPTIONS_START_ADDR + 3 74 | OPTIONS_MSU_PLAYLIST = OPTIONS_START_ADDR + 4 75 | OPTIONS_DIFFICULTY = OPTIONS_START_ADDR + 5 76 | 77 | REUSABLE_CALC_BYTE = $08A8 78 | LEVEL_SELECT_INDEX = $08A9 79 | CHEATS_ENABLED = $08AA 80 | APU_INITIALIZED = $08AB 81 | NEED_TO_CLEAR_8x16_SPRITES = $08AC 82 | BANK_SWITCH_CTRL_REGS = $08AD 83 | SCANLINE_FOR_IRQ = $08AF 84 | CURRENT_ATTRIBUTES = $08B0 85 | 86 | SPRITE_LOOP_JUNK = $A0 87 | 88 | FULL_ATTRIBUTE_COPY_SRC_LB = $AD 89 | FULL_ATTRIBUTE_COPY_SRC_HB = $AE 90 | FULL_ATTRIBUTE_COPY_HB = $AF 91 | 92 | SOUND_HIJACK_ROUTINE_START = $0830 93 | STACK_ADJUSTMENT_ROUTINE_START = $0800 94 | STACK_ADJUSTMENT_RETURN_LO = $90 95 | STACK_ADJUSTMENT_RETURN_HI = $FE 96 | 97 | 98 | PPU_CURR_VRAM_ADDR = $0992 99 | PPU_TILE_COUNT = $0994 100 | PPU_TILE_ATTR = $0996 101 | PPU_COL_OFFSET = $0998 102 | PPU_ROW_OFFSET = $099A 103 | TILES_TO_WRITE = $099C 104 | TILES_TO_WRITE_HB = $099D 105 | 106 | BANK_SWITCH_LB = $0960 107 | BANK_SWITCH_HB = $0961 108 | BANK_SWITCH_DB = $0962 109 | 110 | BANK_SWITCH_X = $0963 111 | BANK_SWITCH_Y = $0964 112 | BANK_SWITCH_A = $0965 113 | 114 | STACK_RETURN_LB = $0966 115 | STACK_RETURN_HB = $0967 116 | STACK_RETURN_DB = $0968 117 | 118 | RESET_VECTOR_BS_LB = $096A 119 | RESET_VECTOR_BS_HB = $096B 120 | RESET_VECTOR_BS_DB = $096C 121 | 122 | ; HDMA for Scrolling, needs ~0x20 bytes 123 | SCROLL_HDMA_START = $0900 124 | SCROLL_HDMA_SAVED = $0920 125 | 126 | ; HDMA for scrolling normally handled by IRQ 127 | IRQ_SCROLL_HDMA_START = $08E0 128 | SCROLL_HDMA_LINE_TO_START_OFFSET = $08E1 129 | SCROLL_HDMA_LINES_HANDLED = $08E2 130 | SCROLL_HDMA_NEXT_TO_HANDLE = $08E3 ; 0 = handle Attr next, 1 = handle irq next 131 | 132 | 133 | LINES_COMPLETE = $0969 134 | 135 | CHR_BANK_LOADED_TABLE = $8F0 136 | OBJ_CHR_BANK_SWITCH = $0890 137 | BG_CHR_BANK_SWITCH = $0891 138 | CHR_BANK_CURR_P1 = $0892 139 | BG_CHR_BANK_CURR = $0893 140 | DATA_CHR_BANK_CURR = $0894 141 | TARGET_BANK_OFFSET = $0895 142 | OBJ_CHR_HB = $0896 143 | CHR_BANK_BANK_TO_LOAD = $0897 144 | CHR_BANK_TARGET_BANK = $0898 145 | CHR_BANK_NEXT_OBJ_BANK = $0899 146 | CHR_BANK_READ_LB = $089A 147 | CHR_BANK_READ_HB = $089B 148 | CHR_BANK_READ_DB = $089C 149 | CURRENT_LVL_OBJ_LOAD= $089D 150 | CHR_BANK_SEGMENT_LOAD = $089E 151 | 152 | FULL_ATTRIBUTE_QUARTER_COUNTER = $0930 153 | FAQ_OFFSET = $0931 154 | ATTR_NES_SIZE = $0932 155 | ATTR_NES_CURR_CALC_OFFSET = $0933 156 | ATTR_PARTIAL_CURR_OFFSET = $0934 157 | ; 940 -947 - which enemy is on which sprite table 158 | SPRITE_LOADED_TABLE = $0940 159 | CURRENT_ENEMY_LOADED = $094A 160 | 161 | CURRENT_ENEMY_TILE_OFFSET = $094B ; either $80 or $00, controls the HB of the tile 162 | CURRENT_SPRITE_TABLE_OFFSET = $094C ; either $00 or $01, $00 if we're the first table, $01 if we're the 2nd 163 | ENEMY_TO_LOAD = $094D 164 | CURRENT_ENEMY_SLOT = $094E 165 | ACTIVE_SPRITE_SECOND_BANK_SLOT = $094F 166 | 167 | 168 | .define TILE_CHUNK_COUNT $0950 169 | .define TILE_DEST_LB_SETS $0951 170 | .define TILE_DEST_HB $0952 171 | .define TILE_SRC_LB_BANK $0953 172 | .define TILE_SRC_HB $0954 173 | 174 | .define TILE_WORK_SIZE_LB $0955 175 | .define TILE_WORK_SIZE_HB $0956 176 | 177 | VRAM_UPDATE_ADDR_LB = $0970 178 | VRAM_UPDATE_ADDR_HB = $0971 179 | VRAM_UPDATE_DATA = $0972 180 | EXTRA_VRAM_UPDATE = $0980 181 | STACK_TEMP_STORAGE = $0981 182 | 183 | 184 | ATTR_VM_DATA_MAYBE_ATTR = $0990 185 | ATTR_PARAM_LB = $0991 186 | ATTR_PARAM_HB = $0992 187 | ATTR_PARAM_SIZE = $0993 188 | ATTR_PARAM_IMMEDIATE = $0994 189 | 190 | ATTR_NES_HAS_VALUES = $09A0 191 | ATTR_NES_VM_ADDR_HB = $09A1 192 | ATTR_NES_VM_ADDR_LB = $09A2 193 | ATTR_NES_VM_COUNT = $09A3 194 | ATTR_NES_VM_ATTR_START = $09a4 195 | 196 | ATTR2_NES_HAS_VALUES = $09D0 197 | ATTR2_NES_VM_ADDR_HB = $09D1 198 | ATTR2_NES_VM_ADDR_LB = $09D2 199 | ATTR2_NES_VM_COUNT = $09D3 200 | ATTR2_NES_VM_ATTR_START = $09d4 201 | 202 | ; used for decompressing tiles 203 | VM_CACHE = $0B00 204 | 205 | HUD_VOFFS_HDMA_TABLE = $0F10 206 | HUD_HOFFS_HDMA_TABLE = $0F00 207 | DMA_ENABLED_STATE = $0EFF 208 | HDMA_ENABLED_STATE = $0EFE 209 | 210 | ; MSU Variables 1220 - 129F 211 | ; 1220 - 123f - 0x20 track availability (does .pcm file exist on game start) 212 | ; 1240 - 125f - 0x20 track enabled (do we want to use it) 213 | ; 1260 - 126f - various msu variabes 214 | ; 127f - 129f - currently unused 215 | TRACKS_AVAILABLE = $1220 ; Is MSU track present 216 | TRACKS_ENABLED = $1240 ; Is MSU track enabled 217 | 218 | .DEFINE CURRENT_NSF $126F 219 | .DEFINE MSU_TRACK_IDX $126E 220 | .DEFINE MSU_AVAILABLE $126D 221 | .DEFINE MSU_PLAYING $126C 222 | .DEFINE MSU_TRIGGER $126B 223 | .DEFINE MSU_SELECTED $126A 224 | 225 | .DEFINE MSU_CURR_VOLUME $1269 226 | .DEFINE MSU_CURR_CTRL $1268 227 | 228 | ; timers aren't used in this game, so we can reuse these 229 | .DEFINE MSU_TIMER_HB $1267 230 | .DEFINE MSU_TIMER_LB $1266 231 | .DEFINE MSU_TIMER_ON $1265 232 | .DEFINE MSU_TIMER_INDX $1264 233 | 234 | .DEFINE MSU_FADE_IN_PROGRESS $1267 235 | .DEFINE MSU_FADE_TO_TRACK $1266 236 | .DEFINE MSU_CURR_FADE_VOLUME $1265 237 | 238 | 239 | 240 | 241 | .DEFINE SPRITE_TRANSLATION_UNREADY $1263 242 | .DEFINE MSU_SONG_PLAYING $1262 243 | 244 | SNES_OAM_TRANSLATE_NEEDED = $12E0 245 | SNES_OAM_START = $1000 246 | 247 | SNES_OAM_SECOND_BLOCK = SNES_OAM_START + $100 248 | 249 | WHICH_ATTR_TO_USE_NEXT = $17D0 250 | CURR_PALETTE_ADDR = $17E0 251 | ATT1 = $17E2 252 | ATT2 = $17E3 253 | ATT3 = $17E4 254 | ATT4 = $17E5 255 | 256 | ATTRIBUTE_DMA = $12F0 257 | ATTR_DMA_SRC_HB = $12F2 258 | ATTR_DMA_SRC_LB = $12F4 259 | ATTR_DMA_SIZE_LB = $12F6 260 | ATTR_DMA_SIZE_HB = $12F8 261 | ATTR_DMA_VMADDH = $12FA 262 | ATTR_DMA_VMADDL = $12FC 263 | ATTRIBUTE_CACHE = $1300 264 | 265 | ATTRIBUTE2_DMA = $12C0 266 | ATTR2_DMA_SRC_HB = $12C2 267 | ATTR2_DMA_SRC_LB = $12C4 268 | ATTR2_DMA_SIZE_LB = $12C6 269 | ATTR2_DMA_SIZE_HB = $12C8 270 | ATTR2_DMA_VMADDH = $12CA 271 | ATTR2_DMA_VMADDL = $12CC 272 | ATTRIBUTE2_CACHE = $1500 273 | 274 | 275 | ATTR_WORK_BYTE_0 = $20 276 | ATTR_WORK_BYTE_1 = ATTR_WORK_BYTE_0 + 1 277 | ATTR_WORK_BYTE_2 = ATTR_WORK_BYTE_0 + 2 278 | ATTR_WORK_BYTE_3 = ATTR_WORK_BYTE_0 + 3 -------------------------------------------------------------------------------- /utilities/generate_options_asm.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "strings" 5 | "fmt" 6 | "os" 7 | ) 8 | 9 | const startingAddress = 0x2062 10 | const startingOptionAddress = 0x0860 11 | var charToTile = map[rune]byte{ 12 | '0': 0x10, '1': 0x11, '2': 0x12, '3': 0x13, '4': 0x14, 13 | '5': 0x15, '6': 0x16, '7': 0x17, '8': 0x18, '9': 0x19, 14 | 'A': 0x1A, 'B': 0x1B, 'C': 0x1C, 'D': 0x1D, 'E': 0x1E, 15 | 'F': 0x1F, 'G': 0x20, 'H': 0x21, 'I': 0x22, 'J': 0x23, 16 | 'K': 0x24, 'L': 0x25, 'M': 0x26, 'N': 0x27, 'O': 0x28, 17 | 'P': 0x29, 'Q': 0x2A, 'R': 0x2B, 'S': 0x2C, 'T': 0x2D, 18 | 'U': 0x2E, 'V': 0x2F, 'W': 0x30, 'X': 0x31, 'Y': 0x32, 19 | 'Z': 0x33, ' ': 0x34, '.': 0x35, '-': 0x36, '=': 0x37, 20 | '?': 0x38, '!': 0x39, 21 | } 22 | 23 | type Option struct { 24 | Index int 25 | Name string 26 | Values []string 27 | } 28 | 29 | const update_option_asm_template =` 30 | decrement_{option_name_lower}: 31 | dec {wram_address} 32 | BPL :+ 33 | LDA #{num_values} 34 | DEC A 35 | STA {wram_address} 36 | : 37 | BRA update_{option_name_lower} 38 | 39 | increment_{option_name_lower}: 40 | inc {wram_address} 41 | lda {wram_address} 42 | CMP #{num_values} 43 | BNE :+ 44 | LDA #$00 45 | : 46 | STA {wram_address} 47 | BRA update_{option_name_lower} 48 | 49 | update_{option_name_lower}: 50 | LDA RDNMI 51 | : LDA RDNMI 52 | BPL :- 53 | 54 | LDA {wram_address} 55 | ASL 56 | ASL 57 | ASL 58 | ASL 59 | ASL 60 | TAY 61 | LDA #{option_vmaddh} 62 | STA VMADDH 63 | 64 | LDA #{option_vmaddl} 65 | STA VMADDL 66 | 67 | LDX #$00 68 | : LDA option_{option_name_lower}_choice_tiles, Y 69 | STA VMDATAH 70 | LDA option_{option_name_lower}_choice_tiles + 1, Y 71 | STA VMDATAL 72 | INX 73 | INY 74 | INY 75 | CPX #$10 76 | BNE :- 77 | 78 | jsr option_{index}_side_effects 79 | rts 80 | 81 | ` 82 | 83 | 84 | func generate_options(index int, name string, values []string, outFile *os.File, outAsmFile *os.File) { 85 | generate_options_tiles(index, name, values, outFile, outAsmFile) 86 | // outAsmFile.WriteString(fmt.Sprintf("update_option \"%s\", %d, $%04X, %d\n", strings.ToLower(name), index, startingOptionAddress + index, len(values))) 87 | 88 | option_asm := strings.ReplaceAll(update_option_asm_template, "{wram_address}", fmt.Sprintf("$%04X", startingOptionAddress + index)) 89 | option_asm = strings.ReplaceAll(option_asm, "{num_values}", fmt.Sprintf("%d", len(values))) 90 | option_asm = strings.ReplaceAll(option_asm, "{index}", fmt.Sprintf("%d", index)) 91 | option_asm = strings.ReplaceAll(option_asm, "{option_name}", name) 92 | option_asm = strings.ReplaceAll(option_asm, "{option_name_lower}", strings.ToLower(name)) 93 | 94 | option_vm_add := startingAddress + index * 0x20 + 0x0A 95 | option_asm = strings.ReplaceAll(option_asm, "{option_vmaddh}", fmt.Sprintf("$%02X", byte(option_vm_add >> 8 & 0xFF))) 96 | option_asm = strings.ReplaceAll(option_asm, "{option_vmaddl}", fmt.Sprintf("$%02X", byte(option_vm_add & 0xFF))) 97 | outAsmFile.WriteString(option_asm) 98 | } 99 | 100 | func generate_options_tiles(index int, name string, values []string, outFile *os.File, outAsmFile *os.File) { 101 | 102 | // .word $2000 ; address on screen 103 | // .byte $03 ; length of option name 104 | // .byte $18, $1A, $1B ; tiles for option name 105 | // each option will be 16 tiles long, we'll pad with spaces 106 | 107 | // option_x: 108 | // $2080, 3, MSU 109 | // option_x_choice_tiles: 110 | // _______ABC________ ; 16 tiles 111 | // _______DEF________ ; 16 tiles 112 | // FFFFFFFFFFFFFFFFFF ; end of coices 113 | optionAddress := startingAddress + index * 0x20 114 | outFile.Write([]byte{byte(optionAddress & 0xFF), byte(optionAddress >> 8 & 0xFF)}) 115 | outFile.Write([]byte{byte(len(name))}) 116 | outFile.Write(convertStringToTiles(name)) 117 | outAsmFile.WriteString(fmt.Sprintf("option_%s_choice_tiles:\n", strings.ToLower(name))) 118 | 119 | for _, value := range values { 120 | 121 | valueBytes := convertStringToTiles(formatStringTo16Chars(value)) 122 | outAsmFile.WriteString(".byte ") 123 | for i, b := range valueBytes { 124 | outAsmFile.WriteString(fmt.Sprintf("$%02X", b)) 125 | if i != len(valueBytes) - 1 { 126 | outAsmFile.WriteString(", ") 127 | } 128 | } 129 | outAsmFile.WriteString("\n") 130 | } 131 | 132 | 133 | return 134 | } 135 | 136 | func formatStringTo16Chars(input string) string { 137 | // Convert the string to uppercase 138 | upper := strings.ToUpper(input) 139 | 140 | // Calculate padding needed 141 | totalLength := 16 142 | padding := totalLength - len(upper) 143 | leftPadding := padding / 2 144 | rightPadding := padding - leftPadding 145 | 146 | // Add spaces to the left and right 147 | return strings.Repeat(" ", leftPadding) + upper + strings.Repeat(" ", rightPadding) 148 | } 149 | 150 | func convertStringToTiles(name string) []byte { 151 | var tiles []byte = make([]byte, len(name) * 2) 152 | for i := 0; i < len(name) * 2; i += 2 { 153 | tiles[i] = 0x18 154 | tiles[i + 1] = charToTile[rune(name[i/2])] 155 | } 156 | 157 | return tiles 158 | } 159 | 160 | func write_options_sprites(options []Option, outAsmFile *os.File) { 161 | 162 | outAsmFile.WriteString("\n\n; Which Option are we on sprites\n") 163 | outAsmFile.WriteString("option_sprite_y_pos:\n") 164 | for i := 0; i < len(options); i++ { 165 | outAsmFile.WriteString(fmt.Sprintf(".byte $%02X\n", 0x17 + i * 0x08)) 166 | } 167 | outAsmFile.WriteString("; X, Y, Tile, attributes\n") 168 | outAsmFile.WriteString("options_sprites:\n") 169 | outAsmFile.WriteString(".byte $04, $17, $3B, $42 ; Option Selection\n") 170 | 171 | // we also have some sprites for the palette previews 172 | palette_preview_sprites := ` 173 | .byte 120, 184, $B0, $40 ; tank sprite 1/6 174 | .byte 128, 184, $A0, $40 ; tank sprite 2/6 175 | .byte 136, 184, $A5, $20 ; tank sprite 3/6 176 | .byte 120, 192, $C0, $20 ; tank sprite 4/6 177 | .byte 128, 192, $E0, $20 ; tank sprite 5/6 178 | .byte 136, 192, $D0, $20 ; tank sprite 6/6 179 | 180 | .byte 104, 184, $e2, $22 ; Enemy Sprite x/4 181 | .byte 96, 184, $e1, $22 ; Enemy Sprite x/4 182 | .byte 104, 192, $e4, $22 ; Enemy Sprite x/4 183 | .byte 96, 192, $e3, $22 ; Enemy Sprite x/4 184 | .byte $FF 185 | ` 186 | outAsmFile.WriteString(palette_preview_sprites) 187 | } 188 | 189 | func write_toggle_current_option(options []Option, outAsmFile *os.File) { 190 | outAsmFile.WriteString("\n\n; Toggle current option\n") 191 | outAsmFile.WriteString( 192 | `toggle_current_option: 193 | LDA #$01 194 | sta NEEDS_OAM_DMA 195 | LDA CURR_OPTION 196 | `) 197 | for _, option := range options { 198 | outAsmFile.WriteString(fmt.Sprintf(" CMP #%d\n", option.Index)) 199 | outAsmFile.WriteString(fmt.Sprintf(" BNE :+\n")) 200 | outAsmFile.WriteString(fmt.Sprintf(" JMP increment_%s\n", strings.ToLower(option.Name))) 201 | outAsmFile.WriteString(":\n") 202 | } 203 | outAsmFile.WriteString("RTS\n") 204 | } 205 | 206 | func write_decrement_current_option(options []Option, outAsmFile *os.File) { 207 | outAsmFile.WriteString("\n\n; Decrement current option\n") 208 | outAsmFile.WriteString( 209 | `decrement_current_option: 210 | LDA #$01 211 | sta NEEDS_OAM_DMA 212 | LDA CURR_OPTION 213 | `) 214 | for _, option := range options { 215 | outAsmFile.WriteString(fmt.Sprintf(" CMP #%d\n", option.Index)) 216 | outAsmFile.WriteString(fmt.Sprintf(" BNE :+\n")) 217 | outAsmFile.WriteString(fmt.Sprintf(" JMP decrement_%s\n", strings.ToLower(option.Name))) 218 | outAsmFile.WriteString(":\n") 219 | } 220 | outAsmFile.WriteString("RTS\n") 221 | 222 | 223 | outAsmFile.WriteString("\n") 224 | outAsmFile.WriteString("initialize_options:\n") 225 | for _, option := range options { 226 | outAsmFile.WriteString(fmt.Sprintf(" jsr update_%s\n", strings.ToLower(option.Name))) 227 | } 228 | outAsmFile.WriteString(" rts\n\n") 229 | } 230 | 231 | func main() { 232 | var outFile, _ = os.Create("options.bin") 233 | defer outFile.Close() 234 | 235 | var outAsmFile, _ = os.Create("options_macro_defs.asm") 236 | defer outAsmFile.Close() 237 | options := []Option{ 238 | {Index: 0, Name: "PALETTE", Values: []string{"NES", "FCEUX", "GREYSCALE", "NES CLASSIC FBX", "PVM", "REAL", "SMOOTH Y2 FBX", "APPLE II"}}, 239 | {Index: 1, Name: "LIVES", Values: []string{"3", "10", "30", "99"}}, 240 | // {Index: 2, Name: "UPGRADES", Values: []string{"LOSE ON DEATH", "KEEP ON DEATH"}}, 241 | {Index: 2, Name: "LEVEL", Values: []string{"1", "2", "3", "4", "5", "6"}}, 242 | {Index: 3, Name: "MSU1", Values: []string{"ON","OFF"}}, 243 | {Index: 4, Name: "PLAYLIST", Values: []string{"ROCK AST","VRC6 COVER","SYNTH","ARCADE","X68000"}}, 244 | {Index: 5, Name: "DIFFICULTY", Values: []string{"EASY", "NORMAL", "HARD"}}, 245 | } 246 | outAsmFile.WriteString(fmt.Sprintf("NUM_OPTIONS = %d\n", len(options))) 247 | write_toggle_current_option(options, outAsmFile) 248 | write_decrement_current_option(options, outAsmFile) 249 | for _, option := range options { 250 | generate_options(option.Index, option.Name, option.Values, outFile, outAsmFile) 251 | } 252 | 253 | write_options_sprites(options, outAsmFile) 254 | } -------------------------------------------------------------------------------- /src/hdma_scroll_lookups.asm: -------------------------------------------------------------------------------- 1 | ; HDMA Scroll Lookup Tables 2 | ; INF addr A0:A0A0 3 | .segment "HDMA_LOOKUP" 4 | ; not sure what this is used for, it doesn't seem to be used 5 | .byte $A6, $FC, $BF, $80, $A0, $A0, $8D, $00, $09, $BF, $70, $A1, $A0, $8D, $03, $09 6 | .byte $BF, $60, $A2, $A0, $8D, $05, $09, $BF, $50, $A3, $A0, $8D, $08, $09, $BF, $30 7 | .byte $A4, $A0, $8D, $0A, $09, $BF, $20, $A5, $A0, $8D, $0D, $09, $A5, $FD, $8D, $01 8 | .byte $09, $8D, $06, $09, $A5, $FF, $8D, $02, $09, $8D, $07, $09, $8D, $0C, $09, $A6 9 | .byte $FF, $BF, $10, $A6, $A0, $8D, $04, $09, $8D, $09, $09, $8D, $0E, $09, $9C, $0B 10 | .byte $09, $9C, $0F, $09, $A9, $7E, $8D, $14, $43, $A9, $09, $8D, $13, $43, $9C, $12 11 | .byte $43, $A9, $0D, $8D, $11, $43, $A9, $03, $8D, $10, $43, $A9, $02, $8D, $0C, $42 12 | .byte $6B, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00 13 | 14 | 15 | scroll_lookup_1: 16 | .byte $6F, $6E, $6D, $6C, $6B, $6A, $69, $68, $67, $66, $65, $64, $63, $62, $61, $60 17 | .byte $5F, $5E, $5D, $5C, $5B, $5A, $59, $58, $57, $56, $55, $54, $53, $52, $51, $50 18 | .byte $4F, $4E, $4D, $4C, $4B, $4A, $49, $48, $47, $46, $45, $44, $43, $42, $41, $40 19 | .byte $3F, $3E, $3D, $3C, $3B, $3A, $39, $38, $37, $36, $35, $34, $33, $32, $31, $30 20 | .byte $2F, $2E, $2D, $2C, $2B, $2A, $29, $28, $27, $26, $25, $24, $23, $22, $21, $20 21 | .byte $1F, $1E, $1D, $1C, $1B, $1A, $19, $18, $17, $16, $15, $14, $13, $12, $11, $10 22 | .byte $0F, $0E, $0D, $0C, $0B, $0A, $09, $08, $07, $06, $05, $04, $03, $02, $01, $80 23 | .byte $7F, $7E, $7D, $7C, $7B, $7A, $79, $78, $77, $76, $75, $74, $73, $72, $71, $70 24 | .byte $6F, $6E, $6D, $6C, $6B, $6A, $69, $68, $67, $66, $65, $64, $63, $62, $61, $60 25 | .byte $5F, $5E, $5D, $5C, $5B, $5A, $59, $58, $57, $56, $55, $54, $53, $52, $51, $50 26 | .byte $4F, $4E, $4D, $4C, $4B, $4A, $49, $48, $47, $46, $45, $44, $43, $42, $41, $40 27 | .byte $3F, $3E, $3D, $3C, $3B, $3A, $39, $38, $37, $36, $35, $34, $33, $32, $31, $30 28 | .byte $2F, $2E, $2D, $2C, $2B, $2A, $29, $28, $27, $26, $25, $24, $23, $22, $21, $20 29 | .byte $1F, $1E, $1D, $1C, $1B, $1A, $19, $18, $17, $16, $15, $14, $13, $12, $11, $10 30 | .byte $0F, $0E, $0D, $0C, $0B, $0A, $09, $08, $07, $06, $05, $04, $03, $02, $01, $6F 31 | .byte $6F, $6F, $6F, $6F, $6F, $6F, $6F, $6F, $6F, $6F, $6F, $6F, $6F, $6F, $6F, $6F 32 | 33 | scroll_lookup_2: 34 | .byte $00, $01, $02, $03, $04, $05, $06, $07, $08, $09, $0A, $0B, $0C, $0D, $0E, $0F 35 | .byte $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $1A, $1B, $1C, $1D, $1E, $1F 36 | .byte $20, $21, $22, $23, $24, $25, $26, $27, $28, $29, $2A, $2B, $2C, $2D, $2E, $2F 37 | .byte $30, $31, $32, $33, $34, $35, $36, $37, $38, $39, $3A, $3B, $3C, $3D, $3E, $3F 38 | .byte $40, $41, $42, $43, $44, $45, $46, $47, $48, $49, $4A, $4B, $4C, $4D, $4E, $4F 39 | .byte $50, $51, $52, $53, $54, $55, $56, $57, $58, $59, $5A, $5B, $5C, $5D, $5E, $5F 40 | .byte $60, $61, $62, $63, $64, $65, $66, $67, $68, $69, $6A, $6B, $6C, $6D, $6E, $6F 41 | .byte $70, $71, $72, $73, $74, $75, $76, $77, $78, $79, $7A, $7B, $7C, $7D, $7E, $7F 42 | .byte $80, $81, $82, $83, $84, $85, $86, $87, $88, $89, $8A, $8B, $8C, $8D, $8E, $8F 43 | .byte $90, $91, $92, $93, $94, $95, $96, $97, $98, $99, $9A, $9B, $9C, $9D, $9E, $9F 44 | .byte $A0, $A1, $A2, $A3, $A4, $A5, $A6, $A7, $A8, $A9, $AA, $AB, $AC, $AD, $AE, $AF 45 | .byte $B0, $B1, $B2, $B3, $B4, $B5, $B6, $B7, $B8, $B9, $BA, $BB, $BC, $BD, $BE, $BF 46 | .byte $C0, $C1, $C2, $C3, $C4, $C5, $C6, $C7, $C8, $C9, $CA, $CB, $CC, $CD, $CE, $CF 47 | .byte $D0, $D1, $D2, $D3, $D4, $D5, $D6, $D7, $D8, $D9, $DA, $DB, $DC, $DD, $DE, $DF 48 | .byte $E0, $E1, $E2, $E3, $E4, $E5, $E6, $E7, $E8, $E9, $EA, $EB, $EC, $ED, $EE, $FF 49 | .byte $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00 50 | 51 | scroll_lookup_3: 52 | .byte $80, $80, $80, $80, $80, $80, $80, $80, $80, $80, $80, $80, $80, $80, $80, $80 53 | .byte $80, $80, $80, $80, $80, $80, $80, $80, $80, $80, $80, $80, $80, $80, $80, $80 54 | .byte $80, $80, $80, $80, $80, $80, $80, $80, $80, $80, $80, $80, $80, $80, $80, $80 55 | .byte $80, $80, $80, $80, $80, $80, $80, $80, $80, $80, $80, $80, $80, $80, $80, $80 56 | .byte $80, $80, $80, $80, $80, $80, $80, $80, $80, $80, $80, $80, $80, $80, $80, $80 57 | .byte $80, $80, $80, $80, $80, $80, $80, $80, $80, $80, $80, $80, $80, $80, $80, $80 58 | .byte $80, $80, $80, $80, $80, $80, $80, $80, $80, $80, $80, $80, $80, $80, $80, $6F 59 | .byte $70, $71, $72, $73, $74, $75, $76, $77, $78, $79, $7A, $7B, $7C, $7D, $7E, $7F 60 | .byte $80, $01, $02, $03, $04, $05, $06, $07, $08, $09, $0A, $0B, $0C, $0D, $0E, $0F 61 | .byte $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $1A, $1B, $1C, $1D, $1E, $1F 62 | .byte $20, $21, $22, $23, $24, $25, $26, $27, $28, $29, $2A, $2B, $2C, $2D, $2E, $2F 63 | .byte $30, $31, $32, $33, $34, $35, $36, $37, $38, $39, $3A, $3B, $3C, $3D, $3E, $3F 64 | .byte $40, $41, $42, $43, $44, $45, $46, $47, $48, $49, $4A, $4B, $4C, $4D, $4E, $4F 65 | .byte $50, $51, $52, $53, $54, $55, $56, $57, $58, $59, $5A, $5B, $5C, $5D, $5E, $5F 66 | .byte $60, $61, $62, $63, $64, $65, $66, $67, $68, $69, $6A, $6B, $6C, $6D, $6E, $80 67 | .byte $80, $80, $80, $80, $80, $80, $80, $80, $80, $80, $80, $80, $80, $80, $80, $80 68 | 69 | scroll_lookup_4: 70 | .byte $00, $01, $02, $03, $04, $05, $06, $07, $08, $09, $0A, $0B, $0C, $0D, $0E, $0F 71 | .byte $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $1A, $1B, $1C, $1D, $1E, $1F 72 | .byte $20, $21, $22, $23, $24, $25, $26, $27, $28, $29, $2A, $2B, $2C, $2D, $2E, $2F 73 | .byte $30, $31, $32, $33, $34, $35, $36, $37, $38, $39, $3A, $3B, $3C, $3D, $3E, $3F 74 | .byte $40, $41, $42, $43, $44, $45, $46, $47, $48, $49, $4A, $4B, $4C, $4D, $4E, $4F 75 | .byte $50, $51, $52, $53, $54, $55, $56, $57, $58, $59, $5A, $5B, $5C, $5D, $5E, $5F 76 | .byte $60, $61, $62, $63, $64, $65, $66, $67, $68, $69, $6A, $6B, $6C, $6D, $6E, $7F 77 | .byte $80, $81, $82, $83, $84, $85, $86, $87, $88, $89, $8A, $8B, $8C, $8D, $8E, $8F 78 | .byte $90, $91, $92, $93, $94, $95, $96, $97, $98, $99, $9A, $9B, $9C, $9D, $9E, $9F 79 | .byte $A0, $A1, $A2, $A3, $A4, $A5, $A6, $A7, $A8, $A9, $AA, $AB, $AC, $AD, $AE, $AF 80 | .byte $B0, $B1, $B2, $B3, $B4, $B5, $B6, $B7, $B8, $B9, $BA, $BB, $BC, $BD, $BE, $BF 81 | .byte $C0, $C1, $C2, $C3, $C4, $C5, $C6, $C7, $C8, $C9, $CA, $CB, $CC, $CD, $CE, $CF 82 | .byte $D0, $D1, $D2, $D3, $D4, $D5, $D6, $D7, $D8, $D9, $DA, $DB, $DC, $DD, $DE, $DF 83 | .byte $E0, $E1, $E2, $E3, $E4, $E5, $E6, $E7, $E8, $E9, $EA, $EB, $EC, $ED, $EE, $EF 84 | .byte $F0, $F1, $F2, $F3, $F4, $F5, $F6, $F7, $F8, $F9, $FA, $FB, $FC, $FD, $FE, $FF 85 | .byte $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00 86 | 87 | scroll_lookup_5: 88 | .byte $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $1A, $1B, $1C, $1D, $1E, $1F 89 | .byte $20, $21, $22, $23, $24, $25, $26, $27, $28, $29, $2A, $2B, $2C, $2D, $2E, $2F 90 | .byte $30, $31, $32, $33, $34, $35, $36, $37, $38, $39, $3A, $3B, $3C, $3D, $3E, $3F 91 | .byte $40, $41, $42, $43, $44, $45, $46, $47, $48, $49, $4A, $4B, $4C, $4D, $4E, $4F 92 | .byte $50, $51, $52, $53, $54, $55, $56, $57, $58, $59, $5A, $5B, $5C, $5D, $5E, $5F 93 | .byte $60, $61, $62, $63, $64, $65, $66, $67, $68, $69, $6A, $6B, $6C, $6D, $6E, $80 94 | .byte $80, $80, $80, $80, $80, $80, $80, $80, $80, $80, $80, $80, $80, $80, $80, $80 95 | .byte $80, $80, $80, $80, $80, $80, $80, $80, $80, $80, $80, $80, $80, $80, $80, $80 96 | .byte $80, $80, $80, $80, $80, $80, $80, $80, $80, $80, $80, $80, $80, $80, $80, $80 97 | .byte $80, $80, $80, $80, $80, $80, $80, $80, $80, $80, $80, $80, $80, $80, $80, $80 98 | .byte $80, $80, $80, $80, $80, $80, $80, $80, $80, $80, $80, $80, $80, $80, $80, $80 99 | .byte $80, $80, $80, $80, $80, $80, $80, $80, $80, $80, $80, $80, $80, $80, $80, $80 100 | .byte $80, $80, $80, $80, $80, $80, $80, $80, $80, $80, $80, $80, $80, $80, $80, $80 101 | .byte $80, $80, $80, $80, $80, $80, $80, $80, $80, $80, $80, $80, $80, $80, $80, $00 102 | scroll_lookup_6: 103 | .byte $00, $11, $12, $13, $14, $15, $16, $17, $18, $19, $1A, $1B, $1C, $1D, $1E, $1F 104 | .byte $20, $21, $22, $23, $24, $25, $26, $27, $28, $29, $2A, $2B, $2C, $2D, $2E, $2F 105 | .byte $30, $31, $32, $33, $34, $35, $36, $37, $38, $39, $3A, $3B, $3C, $3D, $3E, $3F 106 | .byte $40, $41, $42, $43, $44, $45, $46, $47, $48, $49, $4A, $4B, $4C, $4D, $4E, $4F 107 | .byte $50, $51, $52, $53, $54, $55, $56, $57, $58, $59, $5A, $5B, $5C, $5D, $5E, $5F 108 | .byte $60, $61, $62, $63, $64, $65, $66, $67, $68, $69, $6A, $6B, $6C, $6D, $6E, $6F 109 | .byte $70, $71, $72, $73, $74, $75, $76, $77, $78, $79, $7A, $7B, $7C, $7D, $7E, $7E 110 | .byte $7E, $7E, $7E, $7E, $7E, $7E, $7E, $7E, $7E, $7E, $7E, $7E, $7E, $7E, $7E, $7E 111 | .byte $7E, $91, $92, $93, $94, $95, $96, $97, $98, $99, $9A, $9B, $9C, $9D, $9E, $9F 112 | .byte $A0, $A1, $A2, $A3, $A4, $A5, $A6, $A7, $A8, $A9, $AA, $AB, $AC, $AD, $AE, $AF 113 | .byte $B0, $B1, $B2, $B3, $B4, $B5, $B6, $B7, $B8, $B9, $BA, $BB, $BC, $BD, $BE, $BF 114 | .byte $C0, $C1, $C2, $C3, $C4, $C5, $C6, $C7, $C8, $C9, $CA, $CB, $CC, $CD, $CE, $CF 115 | .byte $D0, $D1, $D2, $D3, $D4, $D5, $D6, $D7, $D8, $D9, $DA, $DB, $DC, $DD, $DE, $DF 116 | .byte $E0, $E1, $E2, $E3, $E4, $E5, $E6, $E7, $E8, $E9, $EA, $EB, $EC, $ED, $EE, $EF 117 | .byte $F0, $F1, $F2, $F3, $F4, $F5, $F6, $F7, $F8, $F9, $FA, $FB, $FC, $FD, $FE, $FE 118 | scroll_lookup_7: 119 | .byte $80, $80, $81, $81, $82, $82, $83, $83, $84, $84, $85, $85, $86, $86, $87, $87 120 | .byte $88, $88, $89, $89, $8A, $8A, $8B, $8B, $8C, $8C, $8D, $8D, $8E, $8E, $8F, $8F 121 | .byte $90, $90, $91, $91, $92, $92, $93, $93, $94, $94, $95, $95, $96, $96, $97, $97 122 | .byte $98, $98, $99, $99, $9A, $9A, $9B, $9B, $9C, $9C, $9D, $9D, $9E, $9E, $9F, $9F 123 | .byte $A0, $A0, $A1, $A1, $A2, $A2, $A3, $A3, $A4, $A4, $A5, $A5, $A6, $A6, $A7, $A7 124 | .byte $A8, $A8, $A9, $A9, $AA, $AA, $AB, $AB, $AC, $AC, $AD, $AD, $AE, $AE, $AF, $AF 125 | .byte $B0, $B0, $B1, $B1, $B2, $B2, $B3, $B3, $B4, $B4, $B5, $B5, $B6, $B6, $B7, $B7 126 | .byte $B8, $B8, $B9, $B9, $BA, $BA, $BB, $BB, $BC, $BC, $BD, $BD, $BE, $BE, $BF, $BF 127 | .byte $C0, $C0, $C1, $C1, $C2, $C2, $C3, $C3, $C4, $C4, $C5, $C5, $C6, $C6, $C7, $C7 128 | .byte $C8, $C8, $C9, $C9, $CA, $CA, $CB, $CB, $CC, $CC, $CD, $CD, $CE, $CE, $CF, $CF 129 | .byte $D0, $D0, $D1, $D1, $D2, $D2, $D3, $D3, $D4, $D4, $D5, $D5, $D6, $D6, $D7, $D7 130 | .byte $D8, $D8, $D9, $D9, $DA, $DA, $DB, $DB, $DC, $DC, $DD, $DD, $DE, $DE, $DF, $DF 131 | .byte $E0, $E0, $E1, $E1, $E2, $E2, $E3, $E3, $E4, $E4, $E5, $E5, $E6, $E6, $E7, $E7 132 | .byte $E8, $E8, $E9, $E9, $EA, $EA, $EB, $EB, $EC, $EC, $ED, $ED, $EE, $EE, $EF, $EF 133 | .byte $F0, $F0, $F1, $F1, $F2, $F2, $F3, $F3, $F4, $F4, $F5, $F5, $F6, $F6, $F7, $F7 134 | .byte $F8, $F8, $F9, $F9, $FA, $FA, $FB, $FB, $FC, $FC, $FD, $FD, $FE, $FE, $FF, $FF -------------------------------------------------------------------------------- /src/bank-snes.asm: -------------------------------------------------------------------------------- 1 | ; bank 0 - this houses our init routine and setup stuff 2 | .segment "PRGA0" 3 | init_routine: 4 | PHK 5 | PLB 6 | BRA initialize_registers 7 | 8 | initialize_registers: 9 | setAXY16 10 | setA8 11 | 12 | LDA #$8F 13 | STA INIDISP 14 | STA INIDISP_STATE 15 | STZ OBSEL 16 | STZ OAMADDL 17 | STZ OAMADDH 18 | STZ BGMODE 19 | STZ MOSAIC 20 | STZ BG1SC 21 | STZ BG2SC 22 | STZ BG3SC 23 | STZ BG4SC 24 | STZ BG12NBA 25 | STZ BG34NBA 26 | STZ BG1HOFS 27 | STZ BG1HOFS 28 | STZ BG1VOFS 29 | STZ BG1VOFS 30 | STZ BG2HOFS 31 | STZ BG2HOFS 32 | STZ BG2VOFS 33 | STZ BG2VOFS 34 | STZ BG3HOFS 35 | STZ BG3HOFS 36 | STZ BG3VOFS 37 | STZ BG3VOFS 38 | STZ BG4HOFS 39 | STZ BG4HOFS 40 | STZ BG4VOFS 41 | STZ BG4VOFS 42 | 43 | LDA #$80 44 | STA VMAIN 45 | STZ VMADDL 46 | STZ VMADDH 47 | STZ M7SEL 48 | STZ M7A 49 | 50 | LDA #$01 51 | STA M7A 52 | STA MEMSEL 53 | STZ M7B 54 | STZ M7B 55 | STZ M7C 56 | STZ M7C 57 | STZ M7D 58 | STA M7D 59 | STZ M7X 60 | STZ M7X 61 | STZ M7Y 62 | STZ M7Y 63 | STZ CGADD 64 | STZ W12SEL 65 | STZ W34SEL 66 | STZ WOBJSEL 67 | STZ WH0 68 | STZ WH1 69 | STZ WH2 70 | STZ WH3 71 | STZ WBGLOG 72 | STZ WOBJLOG 73 | STZ TM 74 | STZ TS 75 | STZ TMW 76 | 77 | LDA #$30 78 | STA CGWSEL 79 | STZ CGADSUB 80 | 81 | ; STZ SETINI 82 | LDA #$00 83 | ; LDA #$01 ; uncomment this to use auto-joypoll 84 | STA NMITIMEN 85 | STA NMITIMEN_STATE 86 | STZ VMAIN_STATE 87 | 88 | STZ SNES_OAM_TRANSLATE_NEEDED 89 | 90 | LDA #$FF 91 | STA WRIO 92 | STZ WRMPYA 93 | STZ WRMPYB 94 | STZ WRDIVL 95 | STZ WRDIVH 96 | STZ WRDIVB 97 | STZ HTIMEL 98 | STZ HTIMEH 99 | STZ VTIMEL 100 | STZ VTIMEH 101 | STZ MDMAEN 102 | STZ HDMAEN 103 | STZ MEMSEL 104 | 105 | STZ EXTRA_VRAM_UPDATE 106 | STZ LEVEL_SELECT_INDEX 107 | 108 | setAXY8 109 | LDA #$00 110 | LDY #$0F 111 | : STA ATTRIBUTE_DMA, Y 112 | DEY 113 | BNE :- 114 | 115 | LDY #$40 116 | : DEY 117 | STA $0900, y 118 | BNE :- 119 | 120 | JSR clear_zp 121 | JSR clear_buffers 122 | 123 | LDA #$20 124 | STA $00 125 | JSR clear_bg 126 | LDA #$24 127 | STA $00 128 | JSR clear_bg 129 | JSR clearvm 130 | LDA #$E0 131 | STA COLDATA 132 | LDA #$0F 133 | STA INIDISP_STATE 134 | 135 | JSR zero_oam 136 | JSR dma_oam_table 137 | JSR zero_all_palette 138 | 139 | STA OBSEL 140 | LDA #$11 141 | STA BG12NBA 142 | LDA #$77 143 | STA BG34NBA 144 | LDA #$01 145 | STA BGMODE 146 | LDA #$21 147 | STA BG1SC 148 | ; LDA #$32 149 | ; STA BG2SC 150 | ; LDA #$28 151 | ; STA BG3SC 152 | ; LDA #$7C 153 | ; STA BG4SC 154 | LDA #$80 155 | STA OAMADDH 156 | LDA #$11 157 | STA TMW 158 | LDA #$02 159 | STA W12SEL 160 | STA WOBJSEL 161 | 162 | lda #%00010001 163 | STA TM 164 | LDA #$01 165 | STA MEMSEL 166 | ; Use #$04 to enable overscan if we can. 167 | LDA #$04 168 | LDA #$00 169 | STA SETINI 170 | 171 | 172 | lda #%0000000 173 | sta OBSEL 174 | 175 | STZ ATTR_NES_HAS_VALUES 176 | STZ ATTR_NES_VM_ADDR_HB 177 | STZ ATTR_NES_VM_ADDR_LB 178 | STZ ATTR_NES_VM_ATTR_START 179 | STZ ATTRIBUTE2_DMA 180 | STZ ATTRIBUTE_DMA 181 | LDA #$00 182 | ; LDA #$01 ; uncomment this to use auto-poll joypad 183 | STA NMITIMEN_STATE 184 | 185 | ; jsl spc_init_dpcm 186 | jsl spc_init_driver 187 | jsr write_sound_wram_routines 188 | STZ MSU_SELECTED 189 | jslb check_if_msu_is_available, $b2 190 | LDA MSU_AVAILABLE 191 | beq :+ 192 | LDA #$01 193 | STA MSU_SELECTED 194 | jslb check_for_all_tracks_present, $b2 195 | : 196 | jslb do_intro, $b1 197 | 198 | PHK 199 | PLB 200 | 201 | intro_done: 202 | STZ TM 203 | STZ TS 204 | STZ TMW 205 | LDA #$30 206 | STA CGWSEL 207 | STZ CGADSUB 208 | 209 | JSR setup_hide_left_8_pixel_window 210 | JSL disable_hide_left_8_pixel_window 211 | JSR clearvm_to_12 212 | JSR write_default_palettes 213 | LDA #$FF 214 | STA PALETTE_FILTER 215 | ; JSR write_stack_adjustment_routine_to_ram 216 | ; JSR write_sound_hijack_routine_to_ram 217 | LDA #$03 218 | STA ACTIVE_NES_BANK 219 | 220 | LDA #$02 221 | STA $4D 222 | 223 | LDA #$A4 224 | PHA 225 | PLB 226 | JML $A4E70A 227 | 228 | 229 | snes_nmi: 230 | LDA RDNMI 231 | 232 | ; jsr make_the_game_easier 233 | ; jslb update_values_for_ppu_mask, $a0 234 | jslb infidelitys_scroll_handling, $a0 235 | jslb setup_hdma, $a0 236 | ; jslb calculate_hdma_l, $a0 237 | 238 | JSR check_and_copy_nes_attributes_to_buffer 239 | jsr check_for_palette_swap 240 | 241 | ; JSR dma_oam_table 242 | RTL 243 | 244 | store_current_hdma_values: 245 | 246 | LDX #$1F 247 | : LDA SCROLL_HDMA_START, X 248 | STA SCROLL_HDMA_SAVED, X 249 | DEX 250 | BPL :- 251 | 252 | LDA #$7E 253 | STA A1B3 254 | LDA #$09 255 | STA A1T3H 256 | LDA #$20 257 | STA A1T3L 258 | 259 | LDA #<(BG1HOFS) 260 | STA BBAD3 261 | LDA #$03 262 | STA DMAP3 263 | 264 | LDA #%00001000 265 | jsr disable_sprites_under_hud 266 | STA HDMAEN 267 | rtl 268 | 269 | disable_sprites_under_hud: 270 | 271 | PHA 272 | LDA $200 273 | CMP #$C5 274 | BNE :+ 275 | LDA #^sprite_disable_hud 276 | STA A1B4 277 | LDA #>sprite_disable_hud 278 | STA A1T4H 279 | LDA #dma_values 339 | STA A1T0H 340 | LDA #dma_values 379 | STA A1T0H 380 | LDA #SNES_OAM_START 421 | STA A1T2H 422 | LDA # NES FCEUX ???? 4 | ; Continue > Yes No 5 | ; Area: X 6 | ; 7 | ; [graphic] 8 | 9 | ; layout: 10 | ; address, # tiles, tile values. 11 | 12 | 13 | option_tiles: 14 | 15 | .byte $2B, $20, $08, P6, $28, P6, $29, P6, $2d, P6, $22, P6, $28, P6, $27, P6, $2C, P6, $36 ; Options- 16 | 17 | .incbin "options.bin" 18 | 19 | 20 | ; PRESS START 21 | .byte $64, $21, $0B, P6, $29, P6, $2b, P6, $1e, P6, $2c, P6, $2c, P6, $34, P6, $2c, P6, $2d, P6, $1a, P6, $2b, P6, $2d 22 | 23 | ; PRESS SELECT FOR MSU-1 OPTIONS 24 | ; .addr $2277 25 | ; .byte $05, P6, $29, P6, $2b, P6, $1e, P6, $2c, P6, $2c; PRESS 26 | 27 | ; .addr $2297 28 | ; .byte $06, P6, $2c, P6, $1e, P6, $25, P6, $1e, P6, $1c, P6, $2d ; SELECT 29 | 30 | ; .addr $22B7 31 | ; .byte $08, P6, $1f, P6, $28, P6, $2b, P6, $34, P6, $26, P6, $2c, P6, $2e, P6, $11 ; FOR MSU1 32 | 33 | ; .addr $22D7 34 | ; .byte $07, P6, $28, P6, $29, P6, $2d, P6, $22, P6, $28, P6, $27, P6, $2C ; OPTIONS 35 | 36 | P0 = $00 37 | P1 = $04 38 | P2 = $08 39 | P3 = $0C 40 | P4 = $10 41 | P5 = $14 42 | P6 = $18 43 | P7 = $1C 44 | 45 | P0_3 = $12 46 | P1_3 = $16 47 | P2_3 = $1A 48 | P3_3 = $1E 49 | 50 | ; fun 8 x 8 BG 51 | .byte $6C, $22, $08, P0, $9A, P0, $6D, P0, $6D, P0, $6D, P0, $6D, P0, $6D, P0, $6D, P0, $6A 52 | .byte $8C, $22, $08, P0, $8D, P0, $9D, P0, $6A, P0, $7A, P0, $8A, P0, $6D, P0, $6D, P0, $7D 53 | .byte $AC, $22, $08, P0, $8E, P0, $9E, P0, $6B, P0, $7B, P0, $8B, P0, $9B, P0, $6E, P0, $7E 54 | .byte $CC, $22, $08, P0, $8F, P0, $9F, P0, $6C, P0, $7C, P0, $8C, P0, $9C, P0, $6F, P0, $7F 55 | .byte $EC, $22, $08, P0, $40, P0, $40, P0, $40, P0, $40, P0, $40, P0, $40, P0, $40, P0, $40 56 | .byte $0C, $23, $08, P0, $40, P0, $40, P0, $40, P0, $40, P0, $40, P0, $40, P0, $40, P0, $40 57 | 58 | .byte $2C, $23, $08, P3, $42, P3, $51, P3, $51, P3, $51, P3, $51, P3, $51, P3, $51, P3, $52 59 | .byte $4C, $23, $08, P3, $46, P3, $56, P3, $46, P3, $56, P3, $46, P3, $56, P3, $46, P3, $56 60 | 61 | ; full palette preview 62 | .byte $A3, $21, $10, P0_3, $00, P0_3, $01, P0_3, $02, P0_3, $03, P0_3, $04, P0_3, $05, P0_3, $06, P0_3, $07, P0_3, $08, P0_3, $09, P0_3, $0A, P0_3, $0B, P0_3, $0C, P0_3, $0D, P0_3, $0E, P0_3, $0F 63 | .byte $C3, $21, $10, P1_3, $00, P1_3, $01, P1_3, $02, P1_3, $03, P1_3, $04, P1_3, $05, P1_3, $06, P1_3, $07, P1_3, $08, P1_3, $09, P1_3, $0A, P1_3, $0B, P1_3, $0C, P1_3, $0D, P1_3, $0E, P1_3, $0F 64 | .byte $E3, $21, $10, P2_3, $00, P2_3, $01, P2_3, $02, P2_3, $03, P2_3, $04, P2_3, $05, P2_3, $06, P2_3, $07, P2_3, $08, P2_3, $09, P2_3, $0A, P2_3, $0B, P2_3, $0C, P2_3, $0D, P2_3, $0E, P2_3, $0F 65 | .byte $03, $22, $10, P3_3, $00, P3_3, $01, P3_3, $02, P3_3, $03, P3_3, $04, P3_3, $05, P3_3, $06, P3_3, $07, P3_3, $08, P3_3, $09, P3_3, $0A, P3_3, $0B, P3_3, $0C, P3_3, $0D, P3_3, $0E, P3_3, $0F 66 | 67 | .byte $FF 68 | 69 | 70 | show_options_screen: 71 | 72 | LDX #$20 73 | LDA RDNMI 74 | : LDA RDNMI 75 | BPL :- 76 | DEX 77 | BPL :- 78 | 79 | 80 | STZ CURR_OPTION 81 | 82 | LDA VMAIN_STATE 83 | AND #$0F 84 | STA VMAIN 85 | LDA #$80 86 | STA INIDISP 87 | jslb clearvm_jsl, $a0 88 | 89 | LDA #$00 90 | STA CHR_BANK_BANK_TO_LOAD 91 | LDA #$00 92 | STA CHR_BANK_TARGET_BANK 93 | JSL load_chr_table_to_vm 94 | 95 | LDA #$00 96 | STA CHR_BANK_BANK_TO_LOAD 97 | LDA #$01 98 | STA CHR_BANK_TARGET_BANK 99 | JSL load_chr_table_to_vm 100 | 101 | ; ; if MSU starts here at 0 then it's not available at all 102 | ; LDA MSU_SELECTED 103 | ; BNE :+ 104 | ; INC MSU_UNAVAILABLE 105 | ; : 106 | JSR write_option_tiles 107 | jslb write_option_palette, $a0 108 | jslb write_option_palette_from_indexes, $a0 109 | PHK 110 | PLB 111 | JSR load_options_sprites 112 | jsr write_single_color_tiles_to_3000 113 | jsr initialize_options 114 | jslb dma_oam_table_long, $a0 115 | LDA #$0F 116 | STA INIDISP 117 | LDX #$FF 118 | 119 | 120 | ; check for input 121 | NEEDS_OAM_DMA = $11 122 | input_loop: 123 | LDA RDNMI 124 | BPL :+ 125 | LDA NEEDS_OAM_DMA 126 | BEQ :+ 127 | jslb dma_oam_table_long, $a0 128 | 129 | STZ NEEDS_OAM_DMA 130 | : 131 | jslb msu_nmi_check, $b2 132 | jsr read_input 133 | LDA JOYTRIGGER1 134 | 135 | CMP #DOWN_BUTTON 136 | BNE :+ 137 | jsr next_option 138 | bra input_loop 139 | 140 | : CMP #UP_BUTTON 141 | BNE :+ 142 | jsr prev_option 143 | bra input_loop 144 | 145 | : CMP #RIGHT_BUTTON 146 | BNE :+ 147 | jsr toggle_current_option 148 | bra input_loop 149 | 150 | : CMP #LEFT_BUTTON 151 | BNE :+ 152 | jsr decrement_current_option 153 | bra input_loop 154 | 155 | : CMP #START_BUTTON 156 | BNE:+ 157 | bra exit_options 158 | 159 | : CMP #SELECT_BUTTON 160 | BNE input_loop 161 | 162 | LDA MSU_AVAILABLE 163 | beq input_loop 164 | 165 | ; JSR show_msu_track_screen 166 | JMP show_options_screen 167 | 168 | exit_options: 169 | ; stop msu1 170 | LDA RDNMI 171 | : LDA RDNMI 172 | BPL :- 173 | STZ $2007 174 | STZ MSU_CURR_CTRL 175 | STZ MSU_PLAYING 176 | STZ CURRENT_NSF 177 | jslb msu_nmi_check, $b2 178 | 179 | jsr clear_extra_palattes 180 | LDA #$FF 181 | LDY #$00 182 | 183 | : STA CHR_BANK_LOADED_TABLE, Y 184 | INY 185 | CPY #$08 186 | BNE :- 187 | 188 | STZ CURR_OPTION 189 | 190 | ; ; for now go to MSU- would like this to happen when we hit SELECT or something 191 | ; jsr show_msu_track_screen 192 | 193 | LDA INIDISP_STATE 194 | STA INIDISP 195 | 196 | RTS 197 | 198 | clear_sprites: 199 | LDA #$F0 200 | LDY #$00 201 | : STA SNES_OAM_START+1, Y 202 | INY 203 | INY 204 | INY 205 | INY 206 | BNE :- 207 | rts 208 | 209 | 210 | clear_extra_palattes: 211 | LDA RDNMI 212 | : LDA RDNMI 213 | BPL :- 214 | LDA #$40 215 | STA CGADD 216 | : STZ CGDATA 217 | DEC 218 | BNE :- 219 | rts 220 | 221 | CURR_OPTION = $10 222 | ; MSU_UNAVAILABLE = $12 223 | 224 | next_option: 225 | LDA CURR_OPTION 226 | INC 227 | STA CURR_OPTION 228 | CMP #NUM_OPTIONS 229 | BNE :+ 230 | STZ CURR_OPTION 231 | : jsr update_option_pos 232 | RTS 233 | 234 | prev_option: 235 | LDA CURR_OPTION 236 | BNE :+ 237 | LDA #NUM_OPTIONS 238 | : DEC 239 | STA CURR_OPTION 240 | jsr update_option_pos 241 | RTS 242 | 243 | update_option_pos: 244 | LDA CURR_OPTION 245 | TAY 246 | LDA option_sprite_y_pos, Y 247 | STA SNES_OAM_START + 1 248 | LDA #$01 249 | sta NEEDS_OAM_DMA 250 | rts 251 | 252 | .include "options_macro_defs.asm" 253 | 254 | 255 | write_option_tiles: 256 | setXY16 257 | LDY #$0000 258 | 259 | next_option_bg_line: 260 | ; get starting address 261 | LDA option_tiles, Y 262 | CMP #$FF 263 | BEQ exit_options_write 264 | 265 | PHA 266 | INY 267 | LDA option_tiles, Y 268 | STA VMADDH 269 | PLA 270 | STA VMADDL 271 | INY 272 | LDA option_tiles, Y 273 | TAX 274 | INY 275 | 276 | : LDA option_tiles, Y 277 | STA VMDATAH 278 | INY 279 | LDA option_tiles, Y 280 | STA VMDATAL 281 | INY 282 | DEX 283 | BEQ next_option_bg_line 284 | BRA :- 285 | 286 | exit_options_write: 287 | setAXY8 288 | RTS 289 | 290 | 291 | 292 | load_options_sprites: 293 | LDY #$00 294 | : LDA options_sprites, Y 295 | CMP #$FF 296 | BEQ :+ 297 | STA SNES_OAM_START, Y 298 | INY 299 | BRA :- 300 | RTS 301 | 302 | read_input: 303 | lda #$01 304 | STA JOYSER0 305 | STA buttons 306 | LSR A 307 | sta JOYSER0 308 | @loop: 309 | lda JOYSER0 310 | lsr a 311 | rol buttons 312 | bcc @loop 313 | 314 | lda buttons 315 | ldy JOYPAD1 316 | sta JOYPAD1 317 | tya 318 | eor JOYPAD1 319 | and JOYPAD1 320 | sta JOYTRIGGER1 321 | beq :+ 322 | 323 | tya 324 | and JOYPAD1 325 | sta JOYHELD1 326 | : rts 327 | 328 | 329 | write_single_color_tiles_to_3000: 330 | LDA #$30 331 | STA VMADDH 332 | LDA #$00 333 | STA VMADDL 334 | 335 | LDY #$00 336 | LDX #$02 337 | 338 | : 339 | LDA single_color_tiles + 1, Y 340 | STA VMDATAH 341 | LDA single_color_tiles, Y 342 | STA VMDATAL 343 | INY 344 | INY 345 | 346 | BNE :- 347 | 348 | : LDA single_color_tiles + $100 + 1, Y 349 | STA VMDATAH 350 | LDA single_color_tiles + $100, Y 351 | STA VMDATAL 352 | INY 353 | INY 354 | 355 | BNE :- 356 | 357 | rts 358 | 359 | ; override these if changing an option needs to have side efffects 360 | option_0_side_effects: 361 | jslb write_option_palette_from_indexes, $a0 362 | jslb write_option_palette, $a0 363 | PHK 364 | PLB 365 | rts 366 | 367 | 368 | option_3_side_effects: 369 | LDA OPTIONS_MSU_SELECTED 370 | EOR #$01 371 | STA MSU_SELECTED 372 | 373 | ; fall through to option 5 side effects 374 | 375 | option_4_side_effects: 376 | 377 | LDA RDNMI 378 | : LDA RDNMI 379 | BPL :- 380 | STZ $2007 381 | STZ MSU_CURR_CTRL 382 | STZ MSU_PLAYING 383 | STZ CURRENT_NSF 384 | jslb msu_nmi_check, $b2 385 | 386 | 387 | LDA RDNMI 388 | : LDA RDNMI 389 | BPL :- 390 | LDA #$25 391 | jslb msu_check, $B2 392 | rts 393 | 394 | option_1_side_effects: 395 | option_2_side_effects: 396 | option_5_side_effects: 397 | option_6_side_effects: 398 | option_7_side_effects: 399 | option_8_side_effects: 400 | option_9_side_effects: 401 | rts 402 | 403 | 404 | ; 16 4bpp tiles that use all of a single color 405 | ; used to show the full NES palette we're currently using 406 | single_color_tiles: 407 | .byte $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00 408 | .byte $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00 409 | .byte $FF, $00, $FF, $00, $FF, $00, $FF, $00, $FF, $00, $FF, $00, $FF, $00, $FF, $00 410 | .byte $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00 411 | .byte $00, $FF, $00, $FF, $00, $FF, $00, $FF, $00, $FF, $00, $FF, $00, $FF, $00, $FF 412 | .byte $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00 413 | .byte $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF 414 | .byte $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00 415 | 416 | .byte $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00 417 | .byte $FF, $00, $FF, $00, $FF, $00, $FF, $00, $FF, $00, $FF, $00, $FF, $00, $FF, $00 418 | .byte $FF, $00, $FF, $00, $FF, $00, $FF, $00, $FF, $00, $FF, $00, $FF, $00, $FF, $00 419 | .byte $FF, $00, $FF, $00, $FF, $00, $FF, $00, $FF, $00, $FF, $00, $FF, $00, $FF, $00 420 | .byte $00, $FF, $00, $FF, $00, $FF, $00, $FF, $00, $FF, $00, $FF, $00, $FF, $00, $FF 421 | .byte $FF, $00, $FF, $00, $FF, $00, $FF, $00, $FF, $00, $FF, $00, $FF, $00, $FF, $00 422 | .byte $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF 423 | .byte $FF, $00, $FF, $00, $FF, $00, $FF, $00, $FF, $00, $FF, $00, $FF, $00, $FF, $00 424 | 425 | .byte $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00 426 | .byte $00, $FF, $00, $FF, $00, $FF, $00, $FF, $00, $FF, $00, $FF, $00, $FF, $00, $FF 427 | .byte $FF, $00, $FF, $00, $FF, $00, $FF, $00, $FF, $00, $FF, $00, $FF, $00, $FF, $00 428 | .byte $00, $FF, $00, $FF, $00, $FF, $00, $FF, $00, $FF, $00, $FF, $00, $FF, $00, $FF 429 | .byte $00, $FF, $00, $FF, $00, $FF, $00, $FF, $00, $FF, $00, $FF, $00, $FF, $00, $FF 430 | .byte $00, $FF, $00, $FF, $00, $FF, $00, $FF, $00, $FF, $00, $FF, $00, $FF, $00, $FF 431 | .byte $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF 432 | .byte $00, $FF, $00, $FF, $00, $FF, $00, $FF, $00, $FF, $00, $FF, $00, $FF, $00, $FF 433 | 434 | .byte $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00 435 | .byte $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF 436 | .byte $FF, $00, $FF, $00, $FF, $00, $FF, $00, $FF, $00, $FF, $00, $FF, $00, $FF, $00 437 | .byte $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF 438 | .byte $00, $FF, $00, $FF, $00, $FF, $00, $FF, $00, $FF, $00, $FF, $00, $FF, $00, $FF 439 | .byte $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF 440 | .byte $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF 441 | .byte $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF 442 | 443 | ; .include "msu_track_selection_screen.asm" -------------------------------------------------------------------------------- /src/tiles.asm: -------------------------------------------------------------------------------- 1 | ; This is used for bankswapping CHR Rom banks quickly by putting various banks 2 | ; at places in VRAM and changing where the BG tiles are loaded from 3 | bankswap_table: 4 | ; bank #$20, my basic intro tiles 5 | .byte <(basic_intro_tiles), >(basic_intro_tiles), $B0 6 | ; banks of msu tiles for the video 7 | .if ENABLE_MSU = 1 8 | .byte <(msu_intro_tiles_0), >(msu_intro_tiles_0), $B1 9 | .byte <(msu_intro_tiles_1), >(msu_intro_tiles_1), $B1 10 | .byte <(msu_intro_tiles_2), >(msu_intro_tiles_2), $B1 11 | .byte <(msu_intro_tiles_3), >(msu_intro_tiles_3), $B1 12 | .endif 13 | 14 | ; .byte .lobyte(chrom_bank_0_tileset_0), .hibyte(chrom_bank_0_tileset_0), $A8 15 | ; .byte .lobyte(chrom_bank_0_tileset_1), .hibyte(chrom_bank_0_tileset_1), $A8 16 | ; .byte .lobyte(chrom_bank_0_tileset_2), .hibyte(chrom_bank_0_tileset_2), $A8 17 | ; .byte .lobyte(chrom_bank_0_tileset_3), .hibyte(chrom_bank_0_tileset_3), $A8 18 | 19 | ; .byte .lobyte(chrom_bank_1_tileset_4), .hibyte(chrom_bank_1_tileset_4), $A9 20 | ; .byte .lobyte(chrom_bank_1_tileset_5), .hibyte(chrom_bank_1_tileset_5), $A9 21 | ; .byte .lobyte(chrom_bank_1_tileset_6), .hibyte(chrom_bank_1_tileset_6), $A9 22 | ; .byte .lobyte(chrom_bank_1_tileset_7), .hibyte(chrom_bank_1_tileset_7), $A9 23 | 24 | ; .byte .lobyte(chrom_bank_2_tileset_8), .hibyte(chrom_bank_2_tileset_8), $AA 25 | ; .byte .lobyte(chrom_bank_2_tileset_9), .hibyte(chrom_bank_2_tileset_9), $AA 26 | ; .byte .lobyte(chrom_bank_2_tileset_10), .hibyte(chrom_bank_2_tileset_10), $AA 27 | ; .byte .lobyte(chrom_bank_2_tileset_11), .hibyte(chrom_bank_2_tileset_11), $AA 28 | 29 | ; .byte .lobyte(chrom_bank_3_tileset_12), .hibyte(chrom_bank_3_tileset_12), $AB 30 | ; .byte .lobyte(chrom_bank_3_tileset_13), .hibyte(chrom_bank_3_tileset_13), $AB 31 | ; .byte .lobyte(chrom_bank_3_tileset_14), .hibyte(chrom_bank_3_tileset_14), $AB 32 | ; .byte .lobyte(chrom_bank_3_tileset_15), .hibyte(chrom_bank_3_tileset_15), $AB 33 | 34 | ; .byte .lobyte(chrom_bank_4_tileset_16), .hibyte(chrom_bank_4_tileset_16), $AC 35 | ; .byte .lobyte(chrom_bank_4_tileset_17), .hibyte(chrom_bank_4_tileset_17), $AC 36 | ; .byte .lobyte(chrom_bank_4_tileset_18), .hibyte(chrom_bank_4_tileset_18), $AC 37 | ; .byte .lobyte(chrom_bank_4_tileset_19), .hibyte(chrom_bank_4_tileset_19), $AC 38 | 39 | ; .byte .lobyte(chrom_bank_5_tileset_20), .hibyte(chrom_bank_5_tileset_20), $AD 40 | ; .byte .lobyte(chrom_bank_5_tileset_21), .hibyte(chrom_bank_5_tileset_21), $AD 41 | ; .byte .lobyte(chrom_bank_5_tileset_22), .hibyte(chrom_bank_5_tileset_22), $AD 42 | ; .byte .lobyte(chrom_bank_5_tileset_23), .hibyte(chrom_bank_5_tileset_23), $AD 43 | 44 | ; .byte .lobyte(chrom_bank_6_tileset_24), .hibyte(chrom_bank_6_tileset_24), $AE 45 | ; .byte .lobyte(chrom_bank_6_tileset_25), .hibyte(chrom_bank_6_tileset_25), $AE 46 | ; .byte .lobyte(chrom_bank_6_tileset_26), .hibyte(chrom_bank_6_tileset_26), $AE 47 | ; .byte .lobyte(chrom_bank_6_tileset_27), .hibyte(chrom_bank_6_tileset_27), $AE 48 | 49 | ; .byte .lobyte(chrom_bank_7_tileset_28), .hibyte(chrom_bank_7_tileset_28), $AF 50 | ; .byte .lobyte(chrom_bank_7_tileset_29), .hibyte(chrom_bank_7_tileset_29), $AF 51 | ; .byte .lobyte(chrom_bank_7_tileset_30), .hibyte(chrom_bank_7_tileset_30), $AF 52 | ; .byte .lobyte(chrom_bank_7_tileset_31), .hibyte(chrom_bank_7_tileset_31), $AF 53 | 54 | ; rewrite of E6CA - need to keep db set to wherever we came from 55 | ; track how many PPU bytes we've writen to the cache 56 | 57 | 58 | ; use $10/$11 to point to VM cache write 59 | VM_CACHE_PTR = $10 60 | 61 | write_vm_cache: 62 | ; assume VM addres is already set 63 | LDX #$00 64 | LDY #$08 65 | 66 | : 67 | LDA VM_CACHE, Y 68 | STA VMDATAH 69 | LDA VM_CACHE, X 70 | STA VMDATAL 71 | 72 | INX 73 | INY 74 | 75 | CPY #$10 76 | BNE :- 77 | 78 | STZ VMDATAL 79 | STZ VMDATAL 80 | STZ VMDATAL 81 | STZ VMDATAL 82 | STZ VMDATAL 83 | STZ VMDATAL 84 | STZ VMDATAL 85 | STZ VMDATAL 86 | 87 | STZ VM_CACHE_PTR 88 | RTS 89 | 90 | write_to_vm_cache: 91 | PHX 92 | PHY 93 | PHA 94 | 95 | LDY #$00 96 | STA (VM_CACHE_PTR), Y 97 | INC VM_CACHE_PTR 98 | 99 | LDA VM_CACHE_PTR 100 | CMP #$10 101 | BNE :+ 102 | jsr write_vm_cache 103 | : 104 | 105 | PLA 106 | PLY 107 | PLX 108 | RTS 109 | 110 | load_tileset_x: 111 | LDA VM_CACHE_PTR 112 | PHA 113 | LDA VM_CACHE_PTR + 1 114 | PHA 115 | 116 | LDA #VM_CACHE 119 | STA VM_CACHE_PTR + 1 120 | 121 | LDA $E6EE,X 122 | STA $00 123 | LDA $E6EF,X 124 | STA $01 125 | 126 | ; JMP $F09E 127 | JSR $E8C3 128 | STA $21 129 | STA $FC 130 | STA $FD 131 | LDA RDNMI 132 | 133 | ; get the starting VM Address 134 | LDY #$01 135 | LDA ($00),Y 136 | STA VMADDH ; PpuAddr_2006 137 | DEY 138 | LDA ($00),Y 139 | STA VMADDL ; PpuAddr_2006 140 | 141 | LDX #$00 142 | LDA #$02 143 | JSR $EF37 144 | 145 | nes_F0BE: 146 | LDY #$00 147 | LDA ($00),Y 148 | 149 | ; check for done 150 | CMP #$FF 151 | BEQ return_load_tileset_x 152 | 153 | CMP #$7F 154 | BEQ nes_F0FC 155 | 156 | ; not special control values (FF = done, 7F = ???) 157 | TAY 158 | BPL nes_F0EA 159 | 160 | AND #$7F 161 | STA $02 162 | LDY #$01 163 | 164 | nes_F0D3: 165 | LDA ($00),Y 166 | jsr write_to_vm_cache ; STA PpuData_2007 167 | CPY $02 168 | BEQ nes_F0DF 169 | INY 170 | BNE nes_F0D3 171 | 172 | nes_F0DF: 173 | LDA #$01 174 | CLC 175 | ADC $02 176 | 177 | nes_F0E4: 178 | JSR $EF37 179 | JMP nes_F0BE 180 | 181 | ; positive values of rle 182 | nes_F0EA: 183 | LDY #$01 184 | STA $02 185 | LDA ($00),Y 186 | LDY $02 187 | : jsr write_to_vm_cache ; STA PpuData_2007 188 | DEY 189 | BNE :- 190 | LDA #$02 191 | BNE nes_F0E4 192 | 193 | nes_F0FC: 194 | LDA #$01 195 | JSR $EF37 196 | JMP $F0A7 197 | JMP $E893 198 | 199 | return_load_tileset_x: 200 | PLA 201 | STA VM_CACHE_PTR + 1 202 | PLA 203 | STA VM_CACHE_PTR 204 | 205 | RTL 206 | 207 | 208 | : RTL 209 | check_for_chr_bankswap: 210 | 211 | LDA OBJ_CHR_BANK_SWITCH 212 | CMP #$FF 213 | BEQ :- 214 | CMP CHR_BANK_CURR_P1 215 | BEQ :- 216 | 217 | LDA OBJ_CHR_BANK_SWITCH 218 | STA CHR_BANK_CURR_P1 219 | ; LDA #$FF 220 | ; STA OBJ_CHR_BANK_SWITCH 221 | 222 | PHB 223 | LDA #$A0 224 | PHA 225 | PLB 226 | 227 | ; looks like we need to switch CHR Banks 228 | ; we fake this by DMA'ing tiles from the right tileset 229 | ; multiply by 3 to get the offset 230 | LDA CHR_BANK_CURR_P1 231 | ASL A 232 | ADC CHR_BANK_CURR_P1 233 | TAY 234 | 235 | LDA #$80 236 | STA VMAIN 237 | 238 | LDA #$01 239 | STA DMAP0 240 | 241 | LDA #$18 242 | STA BBAD0 243 | 244 | ; source LB 245 | LDA bankswap_table, Y 246 | STA A1T0L 247 | 248 | ; source HB 249 | INY 250 | LDA bankswap_table, y 251 | STA A1T0H 252 | 253 | ; source DB 254 | INY 255 | LDA bankswap_table, y 256 | STA A1B0 257 | 258 | ; 0x2000 bytes 259 | LDA #$20 260 | STA DAS0H 261 | STZ DAS0L 262 | 263 | ; page 1 is at $0000 264 | LDA #$00 265 | STZ VMADDH 266 | STZ VMADDL 267 | 268 | LDA #$01 269 | STA MDMAEN 270 | 271 | PLB 272 | 273 | LDA VMAIN_STATE 274 | STA VMAIN 275 | 276 | : RTL 277 | 278 | 279 | ; we'll put the data at $7000 always 280 | swap_data_bg_chr: 281 | LDA BG_CHR_BANK_SWITCH 282 | CMP DATA_CHR_BANK_CURR 283 | BEQ :- 284 | STA DATA_CHR_BANK_CURR 285 | LDA #$60 286 | STA TARGET_BANK_OFFSET 287 | JMP bankswap_start 288 | 289 | 290 | check_for_bg_chr_bankswap: 291 | LDA BG_CHR_BANK_SWITCH 292 | CMP #$FF 293 | BEQ :- 294 | 295 | ; CMP #$1A 296 | ; BPL swap_data_bg_chr 297 | 298 | CMP BG_CHR_BANK_CURR 299 | BEQ :- 300 | 301 | bankswap_start: 302 | LDA NMITIMEN_STATE 303 | AND #$7F 304 | STA NMITIMEN 305 | 306 | LDA INIDISP_STATE 307 | ORA #$80 308 | STA INIDISP 309 | 310 | ; LDA RDNMI 311 | : LDA RDNMI 312 | AND #$80 313 | BEQ :- 314 | 315 | ; LDA #$80 316 | ; STA INIDISP 317 | ; STZ TM 318 | 319 | LDA BG_CHR_BANK_SWITCH 320 | STA BG_CHR_BANK_CURR 321 | ; LDA #$FF 322 | ; STA OBJ_CHR_BANK_SWITCH 323 | 324 | PHB 325 | LDA #$A0 326 | PHA 327 | PLB 328 | 329 | ; looks like we need to switch CHR Banks 330 | ; we fake this by DMA'ing tiles from the right tileset 331 | ; multiply by 3 to get the offset 332 | LDA BG_CHR_BANK_CURR 333 | ASL A 334 | ADC BG_CHR_BANK_CURR 335 | TAY 336 | 337 | LDA #$80 338 | STA VMAIN 339 | 340 | LDA #$01 341 | STA DMAP1 342 | 343 | LDA #$18 344 | STA BBAD1 345 | 346 | ; source LB 347 | LDA bankswap_table, Y 348 | STA A1T1L 349 | 350 | ; source HB 351 | INY 352 | LDA bankswap_table, y 353 | STA A1T1H 354 | 355 | ; source DB 356 | INY 357 | LDA bankswap_table, y 358 | STA A1B1 359 | 360 | ; 0x2000 bytes 361 | LDA #$20 362 | STA DAS1H 363 | STZ DAS1L 364 | 365 | ; page 2 is at $1000, data bank will add 6000 to that 366 | LDA #$10 367 | ADC TARGET_BANK_OFFSET 368 | STA VMADDH 369 | STZ VMADDL 370 | STZ TARGET_BANK_OFFSET 371 | 372 | LDA #$02 373 | STA MDMAEN 374 | PLB 375 | LDA VMAIN_STATE 376 | STA VMAIN 377 | 378 | LDA INIDISP_STATE 379 | STA INIDISP 380 | 381 | LDA NMITIMEN_STATE 382 | STA NMITIMEN 383 | 384 | ; LDA #$11 385 | ; STA TM 386 | ; LDA INIDISP_STATE 387 | ; STA INIDISP 388 | 389 | RTL 390 | 391 | bankswitch_bg_chr_data: 392 | PHB 393 | LDA #$A0 394 | PHA 395 | PLB 396 | 397 | ; bgs are on 1000, 3000, 5000, 7000. 398 | LDY #$01 399 | : LDA CHR_BANK_LOADED_TABLE, y 400 | CMP CHR_BANK_BANK_TO_LOAD 401 | BEQ switch_bg_to_y 402 | CPY #$07 403 | BEQ new_bg_bank 404 | INY 405 | INY 406 | BRA :- 407 | RTL 408 | 409 | new_bg_bank: 410 | 411 | LDA CHR_BANK_BANK_TO_LOAD 412 | 413 | CMP #$19 414 | BPL new_data_bank 415 | PLB 416 | RTL 417 | 418 | switch_bg_to_y: 419 | TYA 420 | ORA #$10 421 | STA BG12NBA 422 | 423 | PLB 424 | RTL 425 | new_data_bank: 426 | 427 | STZ CHR_BANK_TARGET_BANK 428 | INC CHR_BANK_TARGET_BANK 429 | jslb load_chr_table_to_vm, $a0 430 | 431 | PLB 432 | RTL 433 | 434 | bankswitch_obj_chr_data: 435 | ; this is a hack that happens to work most of the time. 436 | PHB 437 | LDA #$A0 438 | PHA 439 | PLB 440 | 441 | LDY #$00 442 | : LDA CHR_BANK_LOADED_TABLE, y 443 | CMP CHR_BANK_BANK_TO_LOAD 444 | BEQ switch_to_y 445 | CPY #$06 446 | BEQ new_obj_bank 447 | INY 448 | INY 449 | BRA :- 450 | 451 | new_obj_bank: 452 | ; todo load the bank into 0000, 4000, or 6000 453 | LDA INIDISP_STATE 454 | ORA #$80 455 | STA INIDISP 456 | 457 | LDA CHR_BANK_BANK_TO_LOAD 458 | TAY 459 | LDA target_obj_banks, Y 460 | STA CHR_BANK_TARGET_BANK 461 | PHA 462 | jslb load_chr_table_to_vm, $a0 463 | 464 | ; sometimes there's additional logic. for Super Dodgeball 465 | ; banks 0a - 19 always loaded with 17 466 | ; 467 | ; this is between 0A and 19, so we load 17 too 468 | ; LDA #$17 469 | ; STA CHR_BANK_BANK_TO_LOAD 470 | ; LDA #$04 471 | ; STA CHR_BANK_TARGET_BANK 472 | ; jsl load_chr_table_to_vm 473 | 474 | ; : 475 | LDA INIDISP_STATE 476 | STA INIDISP 477 | PLA 478 | TAY 479 | bra switch_to_y 480 | 481 | switch_to_y: 482 | ; our target bank is loaded at #$y000 483 | ; so just update our obj definition to use that for sprites 484 | TYA 485 | LSR ; for updating obsel, we have to halve y. 486 | STA OBSEL 487 | PLB 488 | RTL 489 | 490 | 491 | load_chr_table_to_vm: 492 | LDA CHR_BANK_TARGET_BANK 493 | TAY 494 | LDA CHR_BANK_BANK_TO_LOAD 495 | STA CHR_BANK_LOADED_TABLE, Y 496 | 497 | JSR dma_chr_to_vm 498 | 499 | RTL 500 | 501 | dma_chr_to_vm: 502 | PHB 503 | LDA #$A0 504 | PHA 505 | PLB 506 | 507 | ; looks like we need to switch CHR Banks 508 | ; we fake this by DMA'ing tiles from the right tileset 509 | ; multiply by 3 to get the offset 510 | LDA CHR_BANK_BANK_TO_LOAD 511 | ASL A 512 | ADC CHR_BANK_BANK_TO_LOAD 513 | TAY 514 | 515 | LDA #$80 516 | STA VMAIN 517 | 518 | LDA #$01 519 | STA DMAP1 520 | 521 | LDA #$18 522 | STA BBAD1 523 | 524 | ; source LB 525 | LDA bankswap_table, Y 526 | STA A1T1L 527 | 528 | ; source HB 529 | INY 530 | LDA bankswap_table, y 531 | STA A1T1H 532 | 533 | ; source DB 534 | INY 535 | LDA bankswap_table, y 536 | STA A1B1 537 | 538 | ; 0x2000 bytes 539 | LDA #$20 540 | STA DAS1H 541 | STZ DAS1L 542 | 543 | ; 544 | LDA CHR_BANK_TARGET_BANK 545 | ASL 546 | ASL 547 | ASL 548 | ASL 549 | STA VMADDH 550 | STZ VMADDL 551 | 552 | LDA #$02 553 | STA MDMAEN 554 | PLB 555 | LDA VMAIN_STATE 556 | STA VMAIN 557 | 558 | RTS 559 | 560 | ; todo update 561 | ; which bank we should swap the sprite into, 00 - 0A aren't sprites so we set it to 0 562 | ; we only use 00, 10, and 11 for sprite locations, which are 00, 04, and 06 563 | ; if they're all the same it'll not save any time when swapping banks. 564 | target_obj_banks: 565 | .byte $00 ; 00 - Sprites 566 | .byte $00 ; 01 - Sprites 567 | .byte $00 ; 02 - Sprites 568 | .byte $00 ; 03 - Sprites 569 | .byte $00 ; 04 - Sprites 570 | .byte $00 ; 05 - Sprites 571 | .byte $00 ; 06 - Sprites 572 | .byte $00 ; 07 - Sprites 573 | .byte $00 ; 08 - Sprites 574 | .byte $00 ; 09 - Sprites 575 | .byte $00 ; 0A - Sprites 576 | .byte $00 ; 0B - Sprites 577 | .byte $04 ; 0C - Sprites 578 | .byte $06 ; 0D - Sprites / Letters 579 | .byte $06 ; 0E - Sprites / Letters 580 | .byte $06 ; 0F - Sprites / Letters 581 | .byte $00 ; 10 - BG Tiles 582 | .byte $00 ; 11 - BG Tiles 583 | .byte $00 ; 12 - BG Tiles 584 | .byte $00 ; 13 - BG Tiles 585 | .byte $00 ; 14 - BG Tiles 586 | .byte $00 ; 15 - BG Tiles 587 | .byte $00 ; 16 - BG Tiles 588 | .byte $00 ; 17 - BG Tiles 589 | .byte $00 ; 18 - BG Tiles 590 | .byte $00 ; 19 - BG Tiles 591 | .byte $00 ; 1A - BG Tiles 592 | .byte $00 ; 1B - BG Tiles 593 | .byte $00 ; 1C - BG Tiles 594 | .byte $00 ; 1D - BG Tiles 595 | .byte $00 ; 1E - BG Tiles 596 | .byte $00 ; 1F - BG Tiles 597 | .byte $00 ; 20 - intro bg tiles 598 | .byte $00 ; 21 - fancy intro tiles 599 | .byte $00 ; 22 - more fancy intro tiles 600 | 601 | 602 | -------------------------------------------------------------------------------- /src/dpcm_audio.asm: -------------------------------------------------------------------------------- 1 | .segment "PRGB3" 2 | ; Waits for SPC to finish booting. Call before first 3 | ; using SPC or after bootrom has been re-run. 4 | ; Preserved: X, Y 5 | spc_wait_boot: 6 | lda #$AA 7 | @wait: 8 | cmp $2140 9 | bne @wait 10 | 11 | ; Clear in case it already has $CC in it 12 | ; (this actually occurred in testing) 13 | sta $2140 14 | 15 | lda #$BB 16 | @wait2: 17 | cmp $2141 18 | bne @wait2 19 | rts 20 | 21 | ; Starts upload to SPC addr Y and sets Y to 22 | ; 0 for use as index with spc_upload_byte. 23 | ; Preserved: X 24 | spc_begin_upload: 25 | sty $2142 26 | 27 | ; Send command 28 | lda $2140 29 | clc 30 | adc #$22 31 | bne skip ; special case fully verified 32 | inc 33 | skip: 34 | sta $2141 35 | sta $2140 36 | 37 | ; Wait for acknowledgement 38 | waitUploadStartAck: 39 | cmp $2140 40 | bne waitUploadStartAck 41 | 42 | ; Initialize index 43 | .byte $A0, $00, $00 ; ldy #$0000 44 | rts 45 | 46 | ; Uploads byte A to SPC and increments Y. The low byte 47 | ; of Y must not changed between calls. 48 | ; Preserved: X 49 | spc_upload_byte: 50 | sta $2141 51 | 52 | ; Signal that it's ready 53 | tya 54 | sta $2140 55 | iny 56 | 57 | ; Wait for acknowledgement 58 | waitUploadByteAck: 59 | cmp $2140 60 | bne waitUploadByteAck 61 | rts 62 | 63 | spc_init_driver: 64 | pha 65 | phx 66 | phy 67 | phb 68 | php 69 | 70 | setAXY16 71 | ldy #.loword(spc_driver) 72 | 73 | phk 74 | plb 75 | jsr send_apu_data 76 | 77 | plp 78 | plb 79 | ply 80 | plx 81 | pla 82 | rtl 83 | 84 | ;;; SPC Upload Code Borrowed from Super Metroid ;;; 85 | ;;; $8059: Send APU data ;;; 86 | send_apu_data: 87 | ;; Parameters: 88 | ;; Y: Address of data 89 | ;; DB: Bank of data 90 | 91 | ; Data format: 92 | ; ssss dddd [xx xx...] (data block 0) 93 | ; ssss dddd [xx xx...] (data block 1) 94 | ; ... 95 | ; 0000 aaaa 96 | ; Where: 97 | ; s = data block size in bytes 98 | ; d = destination address 99 | ; x = data 100 | ; a = entry address. Ignored by SPC engine after first APU transfer 101 | 102 | ; The xx data can cross bank boundaries, but the data block entries otherwise can't (i.e. s, d, a and 0000) unless they're word-aligned 103 | 104 | ; Wait until APU sets APU IO 0..1 = AAh BBh 105 | ; Kick = CCh 106 | ; For each data block: 107 | ; APU IO 2..3 = destination address 108 | ; APU IO 1 = 1 (arbitrary non-zero value) 109 | ; APU IO 0 = kick 110 | ; Wait until APU echoes kick back through APU IO 0 111 | ; Index = 0 112 | ; For each data byte 113 | ; APU IO 1 = data byte 114 | ; APU IO 0 = index 115 | ; Wait until APU echoes index back through APU IO 0 116 | ; Increment index 117 | ; Increment index (and again if resulting in 0) 118 | ; Kick = index 119 | ; Send entry address through APU IO 2..3 120 | ; APU IO 1 = 0 121 | ; APU IO 0 = kick 122 | ; (Optionally wait until APU echoes kick back through APU IO 0) 123 | 124 | PHP 125 | REP #$30 126 | LDA #$3000 ;\ 127 | STA $000641 ;| 128 | ;| 129 | apuWait: 130 | LDA #$BBAA ;| 131 | CMP $002140 ;| 132 | BEQ apuReady ;} Wait until [APU IO 0..1] = AAh BBh 133 | LDA $000641 ;| 134 | DEC A ;| 135 | STA $000641 ;| 136 | BNE apuWait ;/ 137 | crash: 138 | BRA crash ; If exceeded 3000h attempts: crash 139 | 140 | apuReady: 141 | SEP #$20 142 | LDA #$CC ; Kick = CCh 143 | BRA processDataBlock ; Go to BRANCH_PROCESS_DATA_BLOCK 144 | 145 | ; BRANCH_UPLOAD_DATA_BLOCK 146 | uploadDataBlock: 147 | LDA $0000,y ;\ 148 | JSR incY ;} Data = [[Y++]] 149 | XBA ;/ 150 | LDA #$00 ; Index = 0 151 | BRA uploadData ; Go to BRANCH_UPLOAD_DATA 152 | 153 | ; LOOP_NEXT_DATA 154 | loopNextData: 155 | XBA ;\ 156 | LDA $0000,y ;| 157 | JSR incY ;} Data = [[Y++]] 158 | XBA 159 | : ;/ 160 | CMP $002140 ;\ 161 | BNE :- ;} Wait until APU IO 0 echoes 162 | INC A ; Increment index 163 | 164 | ; BRANCH_UPLOAD_DAT 165 | uploadData: 166 | REP #$20 167 | STA $002140 ; APU IO 0..1 = [index] [data] 168 | SEP #$20 169 | DEX ; Decrement X (block size) 170 | BNE loopNextData ; If [X] != 0: go to LOOP_NEXT_DATA 171 | : 172 | CMP $002140 ;\ 173 | BNE :- ;} Wait until APU IO 0 echoes 174 | 175 | ensureKick: 176 | ADC #$03 ; Kick = [index] + 4 177 | BEQ ensureKick ; Ensure kick != 0 178 | 179 | ; BRANCH_PROCESS_DATA_BLOCK 180 | processDataBlock: 181 | PHA 182 | REP #$20 183 | LDA $0000,y ;\ 184 | JSR incY2 ;} X = [[Y]] (block size) 185 | TAX ;} Y += 2 186 | LDA $0000,y ;\ 187 | JSR incY2 ;} APU IO 2..3 = [[Y]] (destination address) 188 | STA $002142 ;} Y += 2 189 | SEP #$20 190 | CPX #$0001 ;\ 191 | LDA #$00 ;| 192 | ROL A ;} If block size = 0: APU IO 1 = 0 (EOF), else APU IO 1 = 1 (arbitrary non-zero value) 193 | STA $002141 ;/ 194 | ADC #$7F ; Set overflow if block size != 0, else clear overflow 195 | PLA ;\ 196 | STA $002140 ;} APU IO 0 = kick 197 | PHX 198 | LDX #$1000 ;\ 199 | 200 | : ;| 201 | DEX ;} Wait until APU IO 0 echoes 202 | BEQ ret ;} If exceeded 1000h attempts: return 203 | CMP $002140 ;| 204 | BNE :- ;/ 205 | 206 | PLX 207 | BVS uploadDataBlock ; If block size != 0: go to BRANCH_UPLOAD_DATA_BLOCK 208 | SEP #$20 209 | STZ $2141 210 | STZ $2142 211 | STZ $2143 212 | PLP 213 | RTS 214 | ret: 215 | SEP #$20 216 | STZ $2141 217 | STZ $2142 218 | STZ $2143 219 | PLX 220 | PLP 221 | RTS 222 | 223 | ;;; $8100: Increment Y twice, bank overflow check ;;; 224 | incY2: 225 | ; Only increments Y once if overflows bank first time (which is a bug scenario) 226 | INY 227 | BEQ next 228 | 229 | 230 | ;;; $8103: Increment Y, bank overflow check ;;; 231 | incY: 232 | INY 233 | BEQ next 234 | RTS 235 | next: 236 | INC $02 ; Increment $02 237 | PEI ($01) ;\ 238 | PLB ;} DB = [$02] 239 | PLB ;/ 240 | LDY #$8000 ; Y = 8000h 241 | RTS 242 | 243 | ; spc_init_dpcm: 244 | ; PHA 245 | ; PHX 246 | ; PHY 247 | ; PHB 248 | ; PHP 249 | 250 | ; sep #$20 251 | 252 | ; ldy #$4000 253 | ; jsr spc_begin_upload 254 | 255 | ; ; Starts upload to SPC addr Y and sets Y to 256 | ; ; 0 for use as index with spc_upload_byte. 257 | ; ; Preserved: X 258 | ; spc_begin_upload: 259 | ; sty $2142 260 | 261 | ; ; Send command 262 | ; lda $2140 263 | ; clc 264 | ; adc #$22 265 | ; bne skip ; special case fully verified 266 | ; inc 267 | ; skip: 268 | ; sta $2141 269 | ; sta $2140 270 | 271 | ; ; Wait for acknowledgement 272 | ; waitUploadStartAck: 273 | ; cmp $2140 274 | ; bne waitUploadStartAck 275 | 276 | ; ; Initialize index 277 | ; ldy #$0000 278 | ; rts 279 | 280 | 281 | dmc_lookup_start_pos = $4060 282 | spc_init_dpcm: 283 | pha 284 | phx 285 | phy 286 | phb 287 | php 288 | 289 | setAXY16 290 | setA8 291 | ; sep #$20 ; 8-bit A 292 | 293 | jsr spc_wait_boot 294 | 295 | ; $4000-$400f: dmc address bytes (see ../nes-spc/spc.asm:267) 296 | ldy #$4000 ; Start an upload at $4000 aram 297 | jsr spc_begin_upload 298 | 299 | lda #$1e 300 | jsr spc_upload_byte 301 | lda #$1d 302 | jsr spc_upload_byte 303 | ; lda #$20 304 | ; jsr spc_upload_byte 305 | ; lda #$4c 306 | ; jsr spc_upload_byte 307 | ; lda #$80 308 | ; jsr spc_upload_byte 309 | 310 | ; $4010-$401f: frequency cutoff values (see ../nes-spc/spc.asm:268) 311 | ldy #$4010 ; Start an upload at $4010 aram 312 | jsr spc_begin_upload 313 | 314 | lda #$0f 315 | jsr spc_upload_byte 316 | lda #$0f 317 | jsr spc_upload_byte 318 | ; lda #$0f 319 | ; jsr spc_upload_byte 320 | ; lda #$0f 321 | ; jsr spc_upload_byte 322 | ; lda #$0d 323 | ; jsr spc_upload_byte 324 | 325 | ; $4020-$405f: SRCN lookup entries (see ../nes-spc/spc.asm:271) 326 | ldy #$4020 ; Start an upload at $4020 aram 327 | jsr spc_begin_upload 328 | 329 | ; upload entry for knee 330 | rep #$30 ; 16-bit load 331 | lda #dmc_lookup_start_pos 332 | sep #$20 ; 8-bit A 333 | jsr spc_upload_byte 334 | xba 335 | jsr spc_upload_byte 336 | 337 | rep #$30 ; 16-bit load 338 | lda #dmc_lookup_start_pos 339 | sep #$20 ; 8-bit A 340 | jsr spc_upload_byte 341 | xba 342 | jsr spc_upload_byte 343 | 344 | ; upload entry for contra file 345 | rep #$30 ; 16-bit load 346 | lda #(dmc_lookup_start_pos + flying_knee_end - flying_knee) 347 | sep #$20 ; 8-bit A 348 | jsr spc_upload_byte 349 | xba 350 | jsr spc_upload_byte 351 | 352 | rep #$30 ; 16-bit load 353 | lda #(dmc_lookup_start_pos + flying_knee_end - flying_knee) 354 | sep #$20 ; 8-bit A 355 | jsr spc_upload_byte 356 | xba 357 | jsr spc_upload_byte 358 | 359 | ldy #$4060 ; Start an upload at $4060 aram 360 | jsr spc_begin_upload 361 | ldx #$0000 362 | 363 | nextbyte: 364 | lda flying_knee,x 365 | jsr spc_upload_byte 366 | inx 367 | cpx #(flying_knee_end-flying_knee) 368 | bne nextbyte 369 | 370 | ldx #$0000 371 | 372 | nextbyte2: 373 | lda contra_brr,x 374 | jsr spc_upload_byte 375 | inx 376 | cpx #(contra_brr_end-contra_brr) 377 | bne nextbyte2 378 | 379 | 380 | jsr reset_to_ipc_rom 381 | 382 | plp 383 | plb 384 | ply 385 | plx 386 | pla 387 | rtl 388 | 389 | ; Execute spc starting at location in Destination (the IPC rom at $ffc0) 390 | reset_to_ipc_rom: 391 | Destination = $ffc0 ; Program's address in SPC700 RAM 392 | lda #Destination & $00ff 393 | sta $2142 394 | lda #Destination>>8 395 | sta $2143 396 | 397 | stz $2141 ; Zero = start the program that was sent over 398 | 399 | lda $2140 ; Must be at least 2 higher than the previous APUIO0 value. 400 | inc 401 | inc 402 | sta $2140 ; Tell the SPC700 to start running the new program. 403 | 404 | wait: ; Wait for the SPC700 to acknowledge this. 405 | cmp $2140 406 | bne wait 407 | 408 | rts 409 | 410 | brr: 411 | flying_knee: 412 | ; .incbin "../sfx/brrs/e1-flyingknee.brr" 413 | flying_knee_end: 414 | 415 | contra_brr: 416 | .byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$98,$00,$00,$00,$00,$00,$1A 417 | .byte $F5,$0F,$64,$EA,$C0,$9B,$F8,$EC,$80,$9B,$08,$7C,$2F,$D4,$C0,$2B 418 | .byte $3F,$D4,$B1,$2B,$6C,$7C,$B7,$81,$38,$5D,$C6,$82,$28,$6C,$6C,$C6 419 | .byte $82,$38,$DF,$EF,$C5,$08,$6C,$6B,$D5,$0E,$1F,$AC,$FE,$D4,$18,$68 420 | .byte $DE,$DD,$3F,$A9,$CE,$CD,$DC,$E2,$6C,$09,$E4,$FE,$1E,$AB,$0E,$C5 421 | .byte $E9,$6C,$E3,$1F,$F0,$FF,$0B,$BF,$C6,$DB,$6C,$5A,$E5,$FA,$B0,$DF 422 | .byte $C0,$4B,$A1,$6C,$3B,$A1,$21,$EF,$0F,$0E,$AC,$33,$64,$F9,$A0,$FF 423 | .byte $0F,$98,$88,$8D,$0F,$6C,$00,$0F,$1F,$2E,$9E,$34,$00,$10,$5C,$03 424 | .byte $02,$13,$12,$23,$23,$32,$6D,$6C,$AE,$67,$01,$4E,$A7,$7F,$32,$23 425 | .byte $78,$20,$4F,$E1,$22,$62,$EF,$20,$54,$5C,$35,$70,$D4,$33,$42,$43 426 | .byte $43,$25,$74,$30,$45,$33,$33,$33,$33,$33,$33,$4C,$76,$65,$76,$65 427 | .byte $76,$65,$76,$57,$4C,$56,$66,$57,$56,$66,$65,$66,$56,$6C,$12,$12 428 | .byte $11,$3D,$E1,$0F,$37,$6F,$7C,$21,$DE,$10,$00,$14,$12,$FD,$F1,$64 429 | .byte $EE,$DD,$DC,$CD,$BB,$41,$BB,$BB,$64,$AB,$A9,$C2,$4E,$9A,$A9,$99 430 | .byte $99,$6C,$D0,$42,$DA,$D0,$DF,$43,$BB,$DF,$6C,$EE,$FD,$EE,$D4,$F9 431 | .byte $ED,$12,$AC,$6C,$EE,$C4,$F8,$E2,$1E,$0B,$AF,$C3,$6C,$F9,$E1,$2E 432 | .byte $9C,$FD,$EC,$11,$9C,$6C,$11,$09,$E2,$83,$E9,$4F,$FE,$83,$6C,$F9 433 | .byte $40,$BC,$22,$AC,$31,$AD,$22,$6C,$BA,$FD,$13,$EB,$E4,$E0,$F0,$F0 434 | .byte $6C,$CB,$EE,$23,$FF,$1D,$A4,$2F,$00,$68,$E0,$FE,$1C,$A5,$E9,$05 435 | .byte $1F,$00,$64,$FA,$B1,$41,$BA,$F4,$33,$51,$C2,$68,$3F,$11,$01,$20 436 | .byte $22,$1A,$F1,$27,$74,$42,$F3,$34,$4F,$23,$F4,$1F,$FE,$6C,$75,$11 437 | .byte $4D,$B7,$18,$37,$32,$22,$74,$2E,$04,$11,$40,$25,$45,$11,$55,$74 438 | .byte $2F,$0F,$35,$45,$54,$F0,$35,$56,$74,$12,$51,$F2,$56,$12,$51,$E3 439 | .byte $40,$78,$51,$D7,$D2,$5B,$61,$C3,$35,$FD,$74,$36,$40,$F3,$40,$36 440 | .byte $46,$56,$51,$74,$F3,$66,$41,$01,$F2,$65,$72,$16,$78,$ED,$64,$D3 441 | .byte $6F,$2D,$36,$C3,$5B,$7C,$61,$E2,$E3,$3F,$01,$11,$D4,$3F,$74,$F4 442 | .byte $40,$52,$16,$31,$F0,$53,$E0,$74,$51,$15,$01,$74,$03,$64,$40,$16 443 | .byte $78,$E2,$F1,$52,$D1,$6E,$07,$E1,$12,$7C,$1E,$F1,$F4,$4F,$DE,$43 444 | .byte $C3,$2B,$78,$21,$01,$52,$EE,$6C,$16,$0D,$E3,$74,$40,$05,$45,$2F 445 | .byte $F2,$54,$F3,$3E,$74,$F2,$63,$F4,$2F,$50,$14,$FF,$E0,$7C,$4C,$23 446 | .byte $B0,$00,$F5,$EE,$51,$DF,$64,$7F,$BC,$C4,$2A,$C3,$73,$CA,$23,$6D 447 | .byte $96,$6C,$A7,$F8,$27,$E8,$27,$DC,$31,$32,$32,$5F,$31,$2D,$2D,$2D 448 | .byte $2D,$2D,$2D,$2D,$2D,$2D,$3E 449 | contra_brr_end: 450 | 451 | spc_driver: 452 | .incbin "./spc/spc.bin" 453 | spc_driver_end: --------------------------------------------------------------------------------