Compare commits
2 Commits
2c48f59c68
...
2072532f1b
Author | SHA1 | Date |
---|---|---|
|
2072532f1b | |
|
2627bc1ac3 |
|
@ -1,3 +1,3 @@
|
|||
src/smb.chr
|
||||
src/smbdis.o
|
||||
src/chars.bin
|
||||
src/*.o
|
||||
target/
|
||||
|
|
|
@ -24,7 +24,7 @@ $ cd super_mario_bros_tale_of_the_black_koopa
|
|||
Copy the graphics file:
|
||||
|
||||
```shell
|
||||
$ cp <path_to_the_graphics_file> src/smb.chr
|
||||
$ cp <path_to_the_graphics_file> src/chars.bin
|
||||
```
|
||||
|
||||
### Building
|
||||
|
@ -32,12 +32,12 @@ $ cp <path_to_the_graphics_file> src/smb.chr
|
|||
To build the binary, execute:
|
||||
|
||||
```shell
|
||||
$ cl65 -t nes -o target/smb.nes -C src/smb.cfg src/smbdis.asm
|
||||
$ cl65 -t nes -o target/super_mario_bros_tale_of_the_black_koopa.nes -C src/linker.cfg src/main.asm
|
||||
```
|
||||
|
||||
### Running
|
||||
|
||||
To run the game, open the file `target/smb.nes` in your favorite NES emulator. Alternatively you can run it on original hardware.
|
||||
To run the game, open the file `target/super_mario_bros_tale_of_the_black_koopa.nes` in your favorite NES emulator. Alternatively you can run it on original hardware.
|
||||
|
||||
### Playing
|
||||
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
MEMORY {
|
||||
ZP: file = "", start = $0000, size = $0100;
|
||||
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 = $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;
|
||||
}
|
||||
|
||||
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;
|
||||
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;
|
||||
}
|
|
@ -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<EOF>"
|
||||
.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 "chars.bin"
|
||||
|
||||
.segment "COPYCHARS"
|
||||
|
||||
CopyChars:
|
||||
lda #<Chars ; load the source address into a pointer in zero page
|
||||
sta CharsCopy
|
||||
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
|
19
src/smb.cfg
19
src/smb.cfg
|
@ -1,19 +0,0 @@
|
|||
MEMORY {
|
||||
ZP: file = "", start = $0000, size = $0100;
|
||||
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;
|
||||
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;
|
||||
}
|
Loading…
Reference in New Issue