diff --git a/build.js b/build.js index 2b6eb256..c049dd6d 100644 --- a/build.js +++ b/build.js @@ -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 @@ -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'); diff --git a/src/constants.asm b/src/constants.asm index 3fb96acf..e4ced4d7 100644 --- a/src/constants.asm +++ b/src/constants.asm @@ -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 @@ -15,6 +19,10 @@ AUTO_WIN := 0 KEYBOARD := 0 .endif +.ifndef INES_OVERRIDE +INES_OVERRIDE := 0 +.endif + .ifndef CNROM_OVERRIDE CNROM_OVERRIDE := 0 .endif diff --git a/src/header.asm b/src/header.asm index dea15da7..62e8bbb9 100644 --- a/src/header.asm +++ b/src/header.asm @@ -1,8 +1,9 @@ ; -; 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" @@ -10,7 +11,10 @@ .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 @@ -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 +