diff --git a/src/smb.cfg b/src/smb.cfg index c7b9569..24a4491 100644 --- a/src/smb.cfg +++ b/src/smb.cfg @@ -3,17 +3,23 @@ MEMORY { OAM: file = "", start = $0200, size = $0100, define = yes; RAM: file = "", start = $0300, size = $0500; HDR: file = %O, start = $0000, size = $0010, fill = yes; - PRG0: file = %O, start = $8000, size = $7FFA, fill = yes, fillval = $FF; + PRG0: file = %O, start = $8000, size = $4000, fill = yes, fillval = $FF; + PRG1: file = %O, start = $8000, size = $4000, fill = yes, fillval = $FF; + PRG2: file = %O, start = $8000, size = $4000, fill = yes, fillval = $FF; + PRG3: file = %O, start = $C000, size = $3FFA, fill = yes, fillval = $FF; PRGV: file = %O, start = $FFFA, size = $0006, fill = yes, fillval = $FF; - CHR: file = %O, start = $0000, size = $2000, fill = yes, fillval = $FF; } SEGMENTS { - ZEROPAGE: load = ZP, type = zp, optional = yes; - SPRITE: load = OAM, type = bss, optional = yes; - BSS: load = RAM, type = bss, optional = yes; - HEADER: load = HDR, type = ro; - STARTUP: load = PRG0, type = ro; - VECTORS: load = PRGV, type = ro; - CHARS: load = CHR, type = ro, optional = yes; + ZEROPAGE: load = ZP, type = zp, optional = yes; + SPRITE: load = OAM, type = bss, optional = yes; + BSS: load = RAM, type = bss, optional = yes; + HEADER: load = HDR, type = ro; + STARTUP: load = PRG0, type = ro; + CHARS: load = PRG2, type = ro, optional = yes; + COPYCHARS: load = PRG2, type = ro, optional = yes; + SOUNDENGINE: load = PRG2, type = ro, optional = yes; + CODE: load = PRG3, type = ro, optional = yes; + BANKSWITCH: load = PRG3, type = ro, optional = yes; + VECTORS: load = PRGV, type = ro; } diff --git a/src/smbdis.asm b/src/smbdis.asm index 9ae5063..a09a9ce 100644 --- a/src/smbdis.asm +++ b/src/smbdis.asm @@ -529,6 +529,9 @@ PauseModeFlag = $07c6 GroundMusicHeaderOfs = $07c7 AltRegContentFlag = $07ca +CurrentBank = $15 ; The mapper is read-only; need to track its state separately +CharsCopy = $41 ; Reserving $41 and $42 + ;------------------------------------------------------------------------------------- ;CONSTANTS @@ -647,14 +650,14 @@ GameOverModeValue = 3 .segment "HEADER" .byte "NES", $1a ; Identification String "NES" -.byte 2 ; PRG-ROM is 32 KiB -.byte 1 ; CHR-ROM is 16 KiB -.byte %00000001 ; Mapper 0 (NROM), Vertical hard-wired mirroring (horizontal arrangement) +.byte 4 ; PRG-ROM is 64 KiB +.byte 0 ; CHR-ROM is 0 KiB +.byte %00100001 ; Mapper 2 (UNROM), Vertical hard-wired mirroring (horizontal arrangement) .byte %00001000 ; NES 2.0 header format, Nintendo Entertainment System/Family Computer .byte %00000000 .byte %00000000 .byte %00000000 -.byte %00000000 +.byte %00000111 ; CHR-RAM is 8192 bytes .byte %00000010 ; Multiple-region .byte %00000000 .byte %00000000 @@ -697,6 +700,7 @@ ColdBoot: jsr InitializeMemory ;clear memory using pointer in Y jsr MoveAllSpritesOffscreen jsr InitializeNameTables ;initialize both name tables inc DisableScreenFlag ;set flag to disable screen output + jsr CopyCharsBankSwitch lda Mirror_PPU_CTRL_REG1 ora #%10000000 ;enable NMIs jsr WritePPUReg1 @@ -766,7 +770,7 @@ InitBuffer: ldx VRAM_Buffer_Offset,y sta VRAM_Buffer_AddrCtrl ;reinit address control to $0301 lda Mirror_PPU_CTRL_REG2 ;copy mirror of $2001 to register sta PPU_CTRL_REG2 - jsr SoundEngine ;play sound + jsr SoundEngineBankSwitch ;play sound jsr ReadJoypads ;read joypads jsr PauseRoutine ;handle pause jsr UpdateTopScore @@ -835,7 +839,7 @@ SkipMainOper: lda PPU_STATUS ;reset flip-flop pla ora #%10000000 ;reactivate NMIs sta PPU_CTRL_REG1 - rti ;we are done until the next frame! + rts ;we are done until the next frame! ;------------------------------------------------------------------------------------- @@ -7685,6 +7689,8 @@ RedPTroopaGrav: ldx ObjectOffset ;get enemy object offset and leave rts +.segment "CODE" + ;------------------------------------------------------------------------------------- ;$00 - used for downward force ;$01 - used for upward force @@ -15031,6 +15037,8 @@ SetHFAt: ora $04 ;add other OAM attributes if necessary ;------------------------------------------------------------------------------------- +.segment "SOUNDENGINE" + SoundEngine: lda OperMode ;are we in title screen mode? bne SndOn @@ -16335,14 +16343,77 @@ BrickShatterEnvData: ;------------------------------------------------------------------------------------- +.segment "BANKSWITCH" + +StartBankSwitch: + ldx #$00 + jsr BankSwitch + jmp Start + +NonMaskableInterruptBankSwitch: + ldx #$00 + jsr BankSwitchNoSave + jsr NonMaskableInterrupt + ldx CurrentBank + jsr BankSwitchNoSave + rti + +CopyCharsBankSwitch: + ldx #$02 + jsr BankSwitch + jsr CopyChars + ldx #$00 + jsr BankSwitch + rts + +SoundEngineBankSwitch: + ldx #$02 + jsr BankSwitchNoSave + jsr SoundEngine + ldx #$00 + jsr BankSwitchNoSave + rts + +BankSwitch: + stx CurrentBank ; save the current bank in RAM so the NMI handler can restore it +BankSwitchNoSave: + lda BankTable,x ; remap from the convenient banks numbered 0 through 2 to the value needed by the hardware + sta BankTable,x ; and write it to the corresponding entry, switching banks + rts + +BankTable: + .byte $00, $01, $02 + .segment "VECTORS" ;INTERRUPT VECTORS - .addr NonMaskableInterrupt - .addr Start + .addr NonMaskableInterruptBankSwitch + .addr StartBankSwitch .addr $fff0 ;unused .segment "CHARS" -.incbin "smb.chr" +Chars: .incbin "smb.chr" + +.segment "COPYCHARS" + +CopyChars: + lda #Chars + sta CharsCopy+1 + ldy #$0 ; starting index into the first page + sty PPU_CTRL_REG2 ; turn off rendering just in case + sty PPU_ADDRESS ; load the destination address into the PPU + sty PPU_ADDRESS + ldx #$20 ; number of 256-byte pages to copy +LoopCopyChars: + lda (CharsCopy),y ; copy one byte + sta PPU_DATA + iny + bne LoopCopyChars ; repeat until we finish the page + inc CharsCopy+1 ; go to the next page + dex + bne LoopCopyChars ; repeat until we've copied enough pages + rts