Skip to content
7 changes: 7 additions & 0 deletions build.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ if (args.includes('-h')) {
-k Famicom Keyboard support
-w force WASM compiler
-c force PNG to CHR conversion
-i use iNES header instead of NES2.0
-o override autodetect mmc1 header with cnrom
-t run tests (requires cargo)
-h you are here
Expand Down Expand Up @@ -79,9 +80,15 @@ if (args.includes('-k')) {

if (args.includes('-s')) {
compileFlags.push('-D', 'SAVE_HIGHSCORES=0');
compileFlags.push('-D', 'HAS_SRAM=0');
console.log('highscore saving disabled');
}

if (args.includes('-i')) {
compileFlags.push('-D', 'INES_OVERRIDE=1');
console.log('iNES header override');
}

if (args.includes('-o')) {
compileFlags.push('-D', 'CNROM_OVERRIDE=1');
console.log('cnrom override for autodetect');
Expand Down
8 changes: 8 additions & 0 deletions src/constants.asm
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ INES_MAPPER := 1000 ; 0 (NROM), 1 (MMC1), 3 (CNROM), 4 (MMC3), 5 (MMC5), and 100
SAVE_HIGHSCORES := 1
.endif

.ifndef HAS_SRAM
HAS_SRAM := 1
.endif

.ifndef AUTO_WIN
; faster aeppoz + press select to end game
AUTO_WIN := 0
Expand All @@ -15,6 +19,10 @@ AUTO_WIN := 0
KEYBOARD := 0
.endif

.ifndef INES_OVERRIDE
INES_OVERRIDE := 0
.endif

.ifndef CNROM_OVERRIDE
CNROM_OVERRIDE := 0
.endif
Expand Down
35 changes: 29 additions & 6 deletions src/header.asm
Original file line number Diff line number Diff line change
@@ -1,16 +1,20 @@
;
; iNES header
; NES2.0 header
; https://www.nesdev.org/wiki/NES_2.0
;

; This iNES header is from Brad Smith (rainwarrior)
; iNES header adapted from Brad Smith (rainwarrior)
; https://github.com/bbbradsmith/NES-ca65-example

.segment "HEADER"

.include "constants.asm" ; for INES_HEADER

INES_MIRROR = 0 ; 0 = horizontal mirroring, 1 = vertical mirroring (ignored in MMC1)
INES_SRAM = 1 ; 1 = battery backed SRAM at $6000-7FFF
INES_SRAM = HAS_SRAM ; 1 = battery backed SRAM at $6000-7FFF
NES2_SRAM_SHIFT = HAS_SRAM * 7 ; if SRAM present, set shift to 7 for (64 << 7) = 8KiB size
NES2_REGION = 2 ; 0 = NTSC, 1 = PAL, 2 = multi-region, 3 = UA6538 ("Dendy")
NES2_INPUT = 0 ; 0 = unspecified, 1 = standard NES/FC controllers, $23 = Family BASIC Keyboard

; Override INES_MAPPER for mode 1000 (auto detect)
.if INES_MAPPER = 1000
Expand All @@ -20,12 +24,31 @@ INES_SRAM = 1 ; 1 = battery backed SRAM at $6000-7FFF
_INES_MAPPER = 1 ; MMC1 for Emulator/Flashcart
.endif
.else
_INES_MAPPER = INES_MAPPER ; use actual INES_MAPPER otherwise
_INES_MAPPER = INES_MAPPER ; use actual INES_MAPPER otherwise
.endif

; Pick the appropriate NES2_SUBMAPPER
.if _INES_MAPPER = 1
NES2_SUBMAPPER = 5 ; MMC1 fixed PRG
.elseif _INES_MAPPER = 3
NES2_SUBMAPPER = 2 ; CNROM bus conflicts
.else
NES2_SUBMAPPER = 0 ; otherwise don't specify submapper
.endif

; Construct header
.byte 'N', 'E', 'S', $1A ; ID
.byte $02 ; 16k PRG chunk count
.byte $02 ; 8k CHR chunk count
.byte INES_MIRROR | (INES_SRAM << 1) | ((_INES_MAPPER & $f) << 4)
.byte (_INES_MAPPER & %11110000)
.byte $0, $0, $0, $0, $0, $0, $0, $0 ; padding

.if INES_OVERRIDE = 0
.byte (_INES_MAPPER & %11110000) | %00001000 ; NES2.0 header identifier
.byte ((NES2_SUBMAPPER & $f) << 4) | ((_INES_MAPPER & $f00) >> 8) ; submapper/mapper MSB
.byte $0, (NES2_SRAM_SHIFT << 4) ; PRG MSB, SRAM shift count
.byte $0, NES2_REGION, $0, $0, NES2_INPUT ; misc. fields, region, input device
.else
.byte (_INES_MAPPER & %11110000)
.byte $0, $0, $0, $0, $0, $0, $0, $0 ; padding
.endif