From 26f403d9f650acfc90d91c8a11c8a20da3f1050d Mon Sep 17 00:00:00 2001 From: beyondcoast Date: Sun, 2 Dec 2018 13:06:22 -0600 Subject: [PATCH] Change interface to process() for all NES mappers to make higher level scripts more flexible in using them, eliminate hardcoded prg,chr,ram sizes. Add CLI options to drive all this functionality directly. Note: Option letters are chosen somewhat arbitarily, next change will be to use argp so more descriptive flag names can be used ex: --nes_prg_rom_size_kb=16 in addition to single character shortnames. This will be important as console support expands. --- host/scripts/inlretro.lua | 128 ++++++++--------------------- host/scripts/inlretro2.lua | 59 ++++++++++++- host/scripts/nes/action53.lua | 12 ++- host/scripts/nes/action53_tsop.lua | 12 ++- host/scripts/nes/bnrom.lua | 17 +++- host/scripts/nes/cdream.lua | 16 +++- host/scripts/nes/cninja.lua | 11 ++- host/scripts/nes/cnrom.lua | 16 +++- host/scripts/nes/dualport.lua | 13 ++- host/scripts/nes/easyNSF.lua | 12 ++- host/scripts/nes/fme7.lua | 21 ++++- host/scripts/nes/mapper30.lua | 17 +++- host/scripts/nes/mmc1.lua | 21 ++++- host/scripts/nes/mmc3.lua | 21 ++++- host/scripts/nes/mmc4.lua | 21 ++++- host/scripts/nes/nrom.lua | 19 +++-- host/scripts/nes/unrom.lua | 18 ++-- host/source/inlprog.c | 71 +++++++++++++++- 18 files changed, 353 insertions(+), 152 deletions(-) diff --git a/host/scripts/inlretro.lua b/host/scripts/inlretro.lua index 25d3b87..60dd98d 100644 --- a/host/scripts/inlretro.lua +++ b/host/scripts/inlretro.lua @@ -97,6 +97,37 @@ function main () --local cart_console = "GBA" --local cart_console = "SMS" +-- ===================================================== +-- USERS: Change process options to define interactions with cartridge. +-- +-- Note: RAM is not present in all carts, related settings +-- will be ignored by mappers that don't support RAM. +-- ===================================================== + local process_opts = { + test = true, + read = true, + erase = false, + program = false, + verify = false, + dumpram = false, + writeram = false, + dumpfile = "ignore/dump.bin", + flashfile = "", + verifyfile = "", + dumpram_filename = "", + writeram_filename = "", + } +-- ===================================================== +-- USERS: Change console options to define interactions with cartridge. +-- These options can vary from cartridge to cartridge depending on specific hardware it contains. +-- ===================================================== + local console_opts = { + mirror = "V", -- Only used by NROM, also possible to set to "H" + prg_rom_size_kb = 128, -- Size of NES PRG-ROM in kb + chr_rom_size_kb = 128, -- Size of NES CHR-ROM in kb + wram_size_kb = 0, -- Size of NES wram in kb + } + local rv -- rv = dict.pinport( "DATA_SET", 0xAA ) -- rv = dict.pinport( "DATA_RD" ) @@ -291,101 +322,10 @@ function main () --set rom types and sizes --perform desired operation --CART and programmer should be in a RESET condition upon calling the specific script - - --DUALPORT - --curcart.process( true, false, false, false, false, "ignore/dump.bin", "ignore/ddug2.bin", "ignore/verifyout.bin") - --MM2 - --curcart.process( true, false, true, true, false, "ignore/dump.bin", "ignore/mm2_i0.prg", "ignore/verifyout.bin") - --curcart.process( true, true, false, false, false, "ignore/dump.bin", "ignore/mm2_i0.prg", "ignore/verifyout.bin") - - --UNROM512 mapper 30 - --curcart.process( true, false, true, true, true, "ignore/dump.bin", "ignore/BBC_nonJW.bin", "ignore/verifyout.bin") - --curcart.process( true, false, false, false, false, "ignore/dump.bin", "ignore/MysticOrigins.prg", "ignore/verifyout.bin") - --curcart.process( true, false, true, true, true, "ignore/dump.bin", "ignore/NESmaker.nes", "ignore/verifyout.bin") - --curcart.process( true, false, true, true, true, "ignore/dump.bin", "ignore/tb_map30.prg", "ignore/verifyout.bin") - - - --COLOR NINJA - --curcart.process( true, false, true, true, true, "ignore/dump.bin", "ignore/ninja.bin", "ignore/verifyout.bin") - --curcart.process( true, false, true, true, true, "ignore/dump.bin", "ignore/alfonzo.bin", "ignore/verifyout.bin") - --A53 PLCC - --curcart.process( true, false, true, true, true, "ignore/dump.bin", "ignore/a53v1_SBR2.prg", "ignore/verifyout.bin") - --A53 tssop - --curcart.process( true, false, true, true, true, "ignore/dump.bin", "ignore/a53vol3.prg", "ignore/verifyout.bin") - --curcart.process( true, false, true, true, true, "ignore/dump.bin", "ignore/2a03puritans_RE.prg", "ignore/verifyout.bin") - --curcart.process( true, false, true, true, false, "ignore/dump.bin", "ignore/a53vol3_giftmsg_0xFF.prg", "ignore/verifyout.bin") - --curcart.process( true, false, false, false, false, "ignore/dump.bin", "ignore/writethe actual message.prg", "ignore/verifyout.bin") - --curcart.process( true, false, true, true, true, "ignore/dump.bin", "ignore/mappertests/test28-8Mbit.prg", "ignore/verifyout.bin") - --curcart.process( true, false, true, true, true, "ignore/dump.bin", "ignore/mappertests/M28_P1M_CR32K.prg", "ignore/verifyout.bin") - - --easy NSF tssop - --curcart.process( true, false, true, true, false, "ignore/dump.bin", "ignore/2a03puritans_RE.prg", "ignore/verifyout.bin") - --curcart.process( true, false, true, true, false, "ignore/dump.bin", "ignore/rndm2_1MB.prg", "ignore/verifyout.bin") - --curcart.process( true, false, true, true, false, "ignore/dump.bin", "ignore/pico2015_RELEASE_1MB.prg", "ignore/verifyout.bin") - - - - - --later scripts which don't require specific firmware functions - --goal is to convert scripts above to be more like the ones below now that - --have a better idea of what works best and minimizing firmware compilation and updates - - --NROM - --curcart.process( true, false, true, true, true, "ignore/dump.bin", "ignore/M0_P32K_C8K.bin", "ignore/verifyout.bin") - --curcart.process( true, true, true, true, true, "ignore/dump.bin", "ignore/ddug2.bin", "ignore/verifyout.bin") - --curcart.process( true, false, true, true, false, "ignore/dump.bin", "ignore/NTB_RE.bin", "ignore/verifyout.bin") - --curcart.process( true, false, true, true, false, "ignore/dump.bin", "ignore/MM_demo.bin", "ignore/verifyout.bin") - --curcart.process( true, true, true, true, true, "ignore/dump.bin", "ignore/NnD.bin", "ignore/verifyout.bin", "V") - --curcart.process( true, false, true, true, false, "ignore/dump.bin", "ignore/DEMO.bin", "ignore/verifyout.bin") - --curcart.process( true, false, true, true, false, "ignore/dump.bin", "ignore/NES_hb_present.bin", "ignore/verifyout.bin") - - --MMC1 - --curcart.process( true, false, true, true, true, "ignore/dump.bin", "ignore/P256K.bin", "ignore/verifyout.bin") - --curcart.process( true, false, true, true, true, "ignore/dump.bin", "ignore/BB_sgrom.prg", "ignore/verifyout.bin") - --curcart.process( true, false, true, true, true, "ignore/dump.bin", "ignore/Zelda2.bin", "ignore/verifyout.bin") - --curcart.process( true, false, true, true, true, "ignore/dump.bin", "ignore/Zelda2_doubleprg.bin", "ignore/verifyout.bin") - --curcart.process( true, false, true, true, true, "ignore/dump.bin", "ignore/alfonzoMMC1.bin", "ignore/verifyout.bin") - --curcart.process( true, false, false, false, false, nil, nil, nil, true, false, "ignore/ramdump.bin", "ignore/zelda2_pauliscool.bin") - - - --UxROM - --curcart.process( true, false, true, true, true, "ignore/dump.bin", "ignore/AFB_128.prg", "ignore/verifyout.bin") - --curcart.process( true, false, true, true, true, "ignore/dump.bin", "ignore/nomolosFINAL.prg", "ignore/verifyout.bin") - --curcart.process( true, false, true, true, false, "ignore/dump.bin", "ignore/owlia_revb.prg", "ignore/verifyout.bin") - --curcart.process( true, false, false, false, false, "ignore/dump.bin", "ignore/rushnattack.prg", "ignore/verifyout.bin") - --curcart.process( true, false, false, false, false, "ignore/dump.bin", "ignore/TDfix.prg", "ignore/verifyout.bin") - - --CNROM - --curcart.process( true, false, true, true, true, "ignore/dump.bin", "ignore/galf.bin", "ignore/verifyout.bin") - - --MMC3 - --curcart.process( true, false, true, true, false, "ignore/dump.bin", "ignore/P512K_C256K.bin", "ignore/verifyout.bin") - --curcart.process( true, false, true, true, false, "ignore/dump.bin", "ignore/P256K_C128K.bin", "ignore/verifyout.bin") - --curcart.process( true, true, true, false, true, "ignore/dump.bin", "ignore/kirby.nes", "ignore/verifyout.bin") - --curcart.process( true, false, true, true, true, "ignore/dump.bin", "ignore/kirby.bin", "ignore/verifyout.bin", false, false, "ignore/ramdump.bin", "ignore/ramwrite.bin") - --curcart.process( true, false, false, false, false, "ignore/dump.bin", "ignore/kirby.bin", "ignore/verifyout.bin", true, true, "ignore/ramdump.bin", "ignore/kirby3xSave.bin") - - --MMC2 - --curcart.process( true, false, true, true, true, "ignore/dump.bin", "ignore/punchout.bin", "ignore/verifyout.bin") - --curcart.process( true, false, false, false, false, "ignore/dump.bin", "ignore/P256K_C128K.bin", "ignore/verifyout.bin") - --MMC4 - --curcart.process( true, false, true, true, true, "ignore/dump.bin", "ignore/fe.bin", "ignore/verifyout.bin") - - --COLOR DREAMS - --curcart.process( true, false, true, true, true, "ignore/dump.bin", "ignore/multicart_mojontalesFINAL.prg", "ignore/verifyout.bin") - - --BNROM - --curcart.process( true, false, true, true, true, "ignore/dump.bin", "ignore/lizard_PG.prg", "ignore/verifyout.bin") - curcart.process( true, false, true, true, true, "ignore/dump.bin", "ignore/lizard_v2.prg", "ignore/verifyout.bin") - --curcart.process( true, false, true, true, false, "ignore/dump.bin", "ignore/hh85.prg", "ignore/verifyout.bin") - - --FME7 - --curcart.process( true, false, true, true, false, "ignore/dump.bin", "ignore/P256K_C256K.bin", "ignore/verifyout.bin") - --curcart.process( true, false, true, true, true, "ignore/dump.bin", "ignore/gimmick.bin", "ignore/verifyout.bin") - --curcart.process( true, false, true, true, true, "ignore/dump.bin", "ignore/barcode_prgx2.bin", "ignore/verifyout.bin") - - --curcart.process( true, false, false, false, false, nil, nil, nil, true, true, "ignore/ramdump.bin", "ignore/kirby3xSave.bin") + -- Perform requested operations with provided options. + curcart.process(process_opts, console_opts) + --[[ --FLASHING: --erase cart diff --git a/host/scripts/inlretro2.lua b/host/scripts/inlretro2.lua index 3706484..63d79f3 100644 --- a/host/scripts/inlretro2.lua +++ b/host/scripts/inlretro2.lua @@ -9,10 +9,13 @@ end -- Wrapper for managing NES/Famicom operations. -function nes_exec(mapper, dump_filename, flash_filename, verify_filename) +function nes_exec(mapper, dump_filename, flash_filename, verify_filename, ramdump_filename, ramwrite_filename, console_opts) local dict = require "scripts.app.dict" local nes = require "scripts.app.nes" + -- TODO: This should probably be one level up. + -- TODO: Ram probably needs a verify file as well? + -- Always test! local do_test = true @@ -27,10 +30,48 @@ function nes_exec(mapper, dump_filename, flash_filename, verify_filename) -- If a verify_filename was provided, dump data from cartridge after flash to a file. local do_verify = not isempty(verify_filename) - -- TODO: Add other mappers. + local do_dumpram = not isempty(ramdump_filename) + local do_writeram = not isempty(ramwrite_filename) + + -- Pack main process state into table. + local process_opts = { + test = do_test, + read = do_read, + dump_filename = dump_filename, + erase = do_erase, + program = do_program, + program_filename = flash_filename, + verify = do_verify, + verify_filename = verify_filename, + dumpram = do_dumpram, + dumpram_filename = ramdump_filename, + writeram = do_writeram, + writeram_filename = ramwrite_filename, + } + + -- Defensively filter out any console options that are irrelevant to NES support. + -- This will matter more when software support exists for other consoles. + local nes_opts = { + wram_size_kb = console_opts["wram_size_kb"], + prg_rom_size_kb = console_opts["prg_rom_size_kb"], + chr_rom_size_kb = console_opts["chr_rom_size_kb"], + mirror = nil -- Used by NROM mapper only, "H" or "V". + } + local mappers = { + action53_tsop = require "scripts.nes.action53_tsop", + action53 = require "scripts.nes.action53", + bnrom = require "scripts.nes.bnrom", + cdream = require "scripts.nes.cdream", + cninja = require "scripts.nes.cninja", + cnrom = require "scripts.nes.cnrom", + dualport = require "scripts.nes.dualport", + easynsf = require "scripts.nes.easyNSF", + fme7 = require "scripts.nes.fme7", + mapper30 = require "scripts.nes.mapper30", mmc1 = require "scripts.nes.mmc1", mmc3 = require "scripts.nes.mmc3", + mmc4 = require "scripts.nes.mmc4", nrom = require "scripts.nes.nrom", unrom = require "scripts.nes.unrom" } @@ -46,7 +87,7 @@ function nes_exec(mapper, dump_filename, flash_filename, verify_filename) -- Attempt requested operations with hardware! -- TODO: Do plumbing for interacting with RAM. - m.process(do_test, do_read, do_erase, do_program, do_verify, dump_filename, flash_filename, verify_filename) + m.process(process_opts, console_opts) end end @@ -59,6 +100,9 @@ function main() -- dump_filename: string, filename used for writing dumped data. -- flash_filename: string, filename containing data to write cartridge. -- verify_filename: string, filename used for writing back data written to cartridge for verification. + -- nes_prg_rom_size_kb: int, size of cartridge PRG-ROM in kb. + -- nes_chr_rom_size_kb: int, size of cartridge CHR-ROM in kb. + -- nes_wram_size_kb: int, size of cartridge WRAM in kb. -- TODO: Add SNES support, as it appears to be currently usable? local consoles = { @@ -68,7 +112,14 @@ function main() if f == nil then print("UNSUPPORTED CONSOLE") else - f(mapper_name, dump_filename, flash_filename, verify_filename) + -- TODO: Make anything console specific a dict to make function signatures less terrible. + local console_opts = { + wram_size_kb = nes_wram_size_kb, + prg_rom_size_kb = nes_prg_rom_size_kb, + chr_rom_size_kb = nes_chr_rom_size_kb + } + + f(mapper_name, dump_filename, flash_filename, verify_filename, ramdump_filename, ramwrite_filename, console_opts) end end diff --git a/host/scripts/nes/action53.lua b/host/scripts/nes/action53.lua index 28f6cf6..3c14a7c 100644 --- a/host/scripts/nes/action53.lua +++ b/host/scripts/nes/action53.lua @@ -72,11 +72,19 @@ end --Cart should be in reset state upon calling this function --this function processes all user requests for this specific board/mapper -local function process( test, read, erase, program, verify, dumpfile, flashfile, verifyfile) +local function process(process_opts, console_opts) + local test = process_opts["test"] + local read = process_opts["read"] + local erase = process_opts["erase"] + local program = process_opts["program"] + local verify = process_opts["verify"] + local dumpfile = process_opts["dump_filename"] + local flashfile = process_opts["flash_filename"] + local verifyfile = process_opts["verify_filename"] local rv = nil local file - + -- TODO: Handle variable ROM sizes. --initialize device i/o for NES dict.io("IO_RESET") diff --git a/host/scripts/nes/action53_tsop.lua b/host/scripts/nes/action53_tsop.lua index 6b8e064..092ee0a 100644 --- a/host/scripts/nes/action53_tsop.lua +++ b/host/scripts/nes/action53_tsop.lua @@ -199,11 +199,19 @@ end --Cart should be in reset state upon calling this function --this function processes all user requests for this specific board/mapper -local function process( test, read, erase, program, verify, dumpfile, flashfile, verifyfile) +local function process(process_opts, console_opts) + local test = process_opts["test"] + local read = process_opts["read"] + local erase = process_opts["erase"] + local program = process_opts["program"] + local verify = process_opts["verify"] + local dumpfile = process_opts["dump_filename"] + local flashfile = process_opts["flash_filename"] + local verifyfile = process_opts["verify_filename"] local rv = nil local file - + -- TODO: Handle variable ROM sizes. --initialize device i/o for NES dict.io("IO_RESET") diff --git a/host/scripts/nes/bnrom.lua b/host/scripts/nes/bnrom.lua index d36aa40..fc6c1e2 100644 --- a/host/scripts/nes/bnrom.lua +++ b/host/scripts/nes/bnrom.lua @@ -210,13 +210,22 @@ end --Cart should be in reset state upon calling this function --this function processes all user requests for this specific board/mapper -local function process( test, read, erase, program, verify, dumpfile, flashfile, verifyfile) +--local function process( test, read, erase, program, verify, dumpfile, flashfile, verifyfile) +local function process(process_opts, console_opts) + local test = process_opts["test"] + local read = process_opts["read"] + local erase = process_opts["erase"] + local program = process_opts["program"] + local verify = process_opts["verify"] + local dumpfile = process_opts["dump_filename"] + local flashfile = process_opts["flash_filename"] + local verifyfile = process_opts["verify_filename"] local rv = nil local file - local prg_size = 512 - local chr_size = 0 - local wram_size = 0 + local prg_size = console_opts["prg_rom_size_kb"] + local chr_size = console_opts["chr_rom_size_kb"] + local wram_size = console_opts["wram_size_kb"] --initialize device i/o for NES dict.io("IO_RESET") diff --git a/host/scripts/nes/cdream.lua b/host/scripts/nes/cdream.lua index 72a8103..0bd1e9e 100644 --- a/host/scripts/nes/cdream.lua +++ b/host/scripts/nes/cdream.lua @@ -453,13 +453,21 @@ end --Cart should be in reset state upon calling this function --this function processes all user requests for this specific board/mapper -local function process( test, read, erase, program, verify, dumpfile, flashfile, verifyfile) +local function process(process_opts, console_opts) + local test = process_opts["test"] + local read = process_opts["read"] + local erase = process_opts["erase"] + local program = process_opts["program"] + local verify = process_opts["verify"] + local dumpfile = process_opts["dump_filename"] + local flashfile = process_opts["flash_filename"] + local verifyfile = process_opts["verify_filename"] local rv = nil local file - local prg_size = 512 - local chr_size = 128 - local wram_size = 0 + local prg_size = console_opts["prg_rom_size_kb"] + local chr_size = console_opts["chr_rom_size_kb"] + local wram_size = console_opts["wram_size_kb"] --initialize device i/o for NES dict.io("IO_RESET") diff --git a/host/scripts/nes/cninja.lua b/host/scripts/nes/cninja.lua index c70f8c1..10bcb84 100644 --- a/host/scripts/nes/cninja.lua +++ b/host/scripts/nes/cninja.lua @@ -68,10 +68,19 @@ end --Cart should be in reset state upon calling this function --this function processes all user requests for this specific board/mapper -local function process( test, read, erase, program, verify, dumpfile, flashfile, verifyfile) +local function process(process_opts, console_opts) + local test = process_opts["test"] + local read = process_opts["read"] + local erase = process_opts["erase"] + local program = process_opts["program"] + local verify = process_opts["verify"] + local dumpfile = process_opts["dump_filename"] + local flashfile = process_opts["flash_filename"] + local verifyfile = process_opts["verify_filename"] local rv = nil local file + -- TODO: Support variable ROM sizes. --initialize device i/o for NES dict.io("IO_RESET") diff --git a/host/scripts/nes/cnrom.lua b/host/scripts/nes/cnrom.lua index be489ba..0d23d11 100644 --- a/host/scripts/nes/cnrom.lua +++ b/host/scripts/nes/cnrom.lua @@ -360,13 +360,21 @@ end --Cart should be in reset state upon calling this function --this function processes all user requests for this specific board/mapper -local function process( test, read, erase, program, verify, dumpfile, flashfile, verifyfile) +local function process(process_opts, console_opts) + local test = process_opts["test"] + local read = process_opts["read"] + local erase = process_opts["erase"] + local program = process_opts["program"] + local verify = process_opts["verify"] + local dumpfile = process_opts["dump_filename"] + local flashfile = process_opts["flash_filename"] + local verifyfile = process_opts["verify_filename"] local rv = nil local file - local prg_size = 32 - local chr_size = 32 - local wram_size = 0 + local prg_size = console_opts["prg_rom_size_kb"] + local chr_size = console_opts["chr_rom_size_kb"] + local wram_size = console_opts["wram_size_kb"] --initialize device i/o for NES dict.io("IO_RESET") diff --git a/host/scripts/nes/dualport.lua b/host/scripts/nes/dualport.lua index 9f2eb8d..77132a3 100644 --- a/host/scripts/nes/dualport.lua +++ b/host/scripts/nes/dualport.lua @@ -151,10 +151,19 @@ end --Cart should be in reset state upon calling this function --this function processes all user requests for this specific board/mapper -local function process( test, read, erase, program, verify, dumpfile, flashfile, verifyfile) - +local function process(process_opts, console_opts) + local test = process_opts["test"] + local read = process_opts["read"] + local erase = process_opts["erase"] + local program = process_opts["program"] + local verify = process_opts["verify"] + local dumpfile = process_opts["dump_filename"] + local flashfile = process_opts["flash_filename"] + local verifyfile = process_opts["verify_filename"] + local rv = nil local file + -- TODO: Handle variable rom sizes. --initialize device i/o for NES dict.io("IO_RESET") diff --git a/host/scripts/nes/easyNSF.lua b/host/scripts/nes/easyNSF.lua index b343caa..b35745e 100644 --- a/host/scripts/nes/easyNSF.lua +++ b/host/scripts/nes/easyNSF.lua @@ -71,11 +71,19 @@ end --Cart should be in reset state upon calling this function --this function processes all user requests for this specific board/mapper -local function process( test, read, erase, program, verify, dumpfile, flashfile, verifyfile) +local function process(process_opts, console_opts) + local test = process_opts["test"] + local read = process_opts["read"] + local erase = process_opts["erase"] + local program = process_opts["program"] + local verify = process_opts["verify"] + local dumpfile = process_opts["dump_filename"] + local flashfile = process_opts["flash_filename"] + local verifyfile = process_opts["verify_filename"] local rv = nil local file - + -- TODO: Handle variable rom sizes. --initialize device i/o for NES dict.io("IO_RESET") diff --git a/host/scripts/nes/fme7.lua b/host/scripts/nes/fme7.lua index d296899..ff79516 100644 --- a/host/scripts/nes/fme7.lua +++ b/host/scripts/nes/fme7.lua @@ -520,13 +520,26 @@ end --Cart should be in reset state upon calling this function -local function process( test, read, erase, program, verify, dumpfile, flashfile, verifyfile, dumpram, writeram, ramdumpfile, ramwritefile) +local function process(process_opts, console_opts) + local test = process_opts["test"] + local read = process_opts["read"] + local erase = process_opts["erase"] + local program = process_opts["program"] + local verify = process_opts["verify"] + local dumpfile = process_opts["dump_filename"] + local flashfile = process_opts["flash_filename"] + local verifyfile = process_opts["verify_filename"] + -- FME7 has RAM capability present in some carts. + local dumpram = process_opts["dumpram"] + local ramdump_filename = process_opts["dumpram_filename"] + local writeram = process_opts["writeram"] + local ramwrite_filename = process_opts["writeram_filename"] local rv = nil local file - local prg_size = 256 - local chr_size = 256 - local wram_size = 8 + local prg_size = console_opts["prg_rom_size_kb"] + local chr_size = console_opts["chr_rom_size_kb"] + local wram_size = console_opts["wram_size_kb"] --initialize device i/o for NES dict.io("IO_RESET") diff --git a/host/scripts/nes/mapper30.lua b/host/scripts/nes/mapper30.lua index 9c3b4b3..5a59ec6 100644 --- a/host/scripts/nes/mapper30.lua +++ b/host/scripts/nes/mapper30.lua @@ -47,11 +47,20 @@ end --Cart should be in reset state upon calling this function --this function processes all user requests for this specific board/mapper -local function process( test, read, erase, program, verify, dumpfile, flashfile, verifyfile) - +local function process(process_opts, console_opts) + local test = process_opts["test"] + local read = process_opts["read"] + local erase = process_opts["erase"] + local program = process_opts["program"] + local verify = process_opts["verify"] + local dumpfile = process_opts["dump_filename"] + local flashfile = process_opts["flash_filename"] + local verifyfile = process_opts["verify_filename"] + local rv = nil - local file - local size = 512 + local file + -- TODO: Cleanup needed here, support chrrom, make this look more like other mapper scripts. + local size = console_opts["prg_rom_size_kb"] --local filetype = "nes" local filetype = "bin" diff --git a/host/scripts/nes/mmc1.lua b/host/scripts/nes/mmc1.lua index 049e02a..2377d7e 100644 --- a/host/scripts/nes/mmc1.lua +++ b/host/scripts/nes/mmc1.lua @@ -490,13 +490,26 @@ end --Cart should be in reset state upon calling this function --this function processes all user requests for this specific board/mapper -local function process( test, read, erase, program, verify, dumpfile, flashfile, verifyfile, dumpram, writeram, ramdumpfile, ramwritefile) +local function process(process_opts, console_opts) + local test = process_opts["test"] + local read = process_opts["read"] + local erase = process_opts["erase"] + local program = process_opts["program"] + local verify = process_opts["verify"] + local dumpfile = process_opts["dump_filename"] + local flashfile = process_opts["flash_filename"] + local verifyfile = process_opts["verify_filename"] + -- MMC1 has RAM capability present in some carts. + local dumpram = process_opts["dumpram"] + local ramdump_filename = process_opts["dumpram_filename"] + local writeram = process_opts["writeram"] + local ramwrite_filename = process_opts["writeram_filename"] local rv = nil local file - local prg_size = 256 - local chr_size = 128 - local wram_size = 8 + local prg_size = console_opts["prg_rom_size_kb"] + local chr_size = console_opts["chr_rom_size_kb"] + local wram_size = console_opts["wram_size_kb"] --initialize device i/o for NES dict.io("IO_RESET") diff --git a/host/scripts/nes/mmc3.lua b/host/scripts/nes/mmc3.lua index cea5351..327eda1 100644 --- a/host/scripts/nes/mmc3.lua +++ b/host/scripts/nes/mmc3.lua @@ -504,13 +504,26 @@ end --Cart should be in reset state upon calling this function --this function processes all user requests for this specific board/mapper -local function process( test, read, erase, program, verify, dumpfile, flashfile, verifyfile, dumpram, writeram, ramdumpfile, ramwritefile) +local function process(process_opts, console_opts) + local test = process_opts["test"] + local read = process_opts["read"] + local erase = process_opts["erase"] + local program = process_opts["program"] + local verify = process_opts["verify"] + local dumpfile = process_opts["dump_filename"] + local flashfile = process_opts["flash_filename"] + local verifyfile = process_opts["verify_filename"] + -- MMC3 has RAM capability present in some carts. + local dumpram = process_opts["dumpram"] + local ramdump_filename = process_opts["dumpram_filename"] + local writeram = process_opts["writeram"] + local ramwrite_filename = process_opts["writeram_filename"] local rv = nil local file - local prg_size = 512 - local chr_size = 256 - local wram_size = 8 + local prg_size = console_opts["prg_rom_size_kb"] + local chr_size = console_opts["chr_rom_size_kb"] + local wram_size = console_opts["wram_size_kb"] --initialize device i/o for NES dict.io("IO_RESET") diff --git a/host/scripts/nes/mmc4.lua b/host/scripts/nes/mmc4.lua index 7d6d93a..f965dd1 100644 --- a/host/scripts/nes/mmc4.lua +++ b/host/scripts/nes/mmc4.lua @@ -446,13 +446,26 @@ end --Cart should be in reset state upon calling this function -local function process( test, read, erase, program, verify, dumpfile, flashfile, verifyfile, dumpram, writeram, ramdumpfile, ramwritefile) +local function process(process_opts, console_opts) + local test = process_opts["test"] + local read = process_opts["read"] + local erase = process_opts["erase"] + local program = process_opts["program"] + local verify = process_opts["verify"] + local dumpfile = process_opts["dump_filename"] + local flashfile = process_opts["flash_filename"] + local verifyfile = process_opts["verify_filename"] + -- MMC4 has RAM capability present in some carts. + local dumpram = process_opts["dumpram"] + local ramdump_filename = process_opts["dumpram_filename"] + local writeram = process_opts["writeram"] + local ramwrite_filename = process_opts["writeram_filename"] local rv = nil local file - local prg_size = 256 - local chr_size = 128 - local wram_size = 8 + local prg_size = console_opts["prg_rom_size_kb"] + local chr_size = console_opts["chr_rom_size_kb"] + local wram_size = console_opts["wram_size_kb"] --initialize device i/o for NES dict.io("IO_RESET") diff --git a/host/scripts/nes/nrom.lua b/host/scripts/nes/nrom.lua index c2f6835..012b9ec 100644 --- a/host/scripts/nes/nrom.lua +++ b/host/scripts/nes/nrom.lua @@ -270,17 +270,24 @@ end - - --Cart should be in reset state upon calling this function --this function processes all user requests for this specific board/mapper -local function process( test, read, erase, program, verify, dumpfile, flashfile, verifyfile, mirror) +local function process(process_opts, console_opts) + local test = process_opts["test"] + local read = process_opts["read"] + local erase = process_opts["erase"] + local program = process_opts["program"] + local verify = process_opts["verify"] + local dumpfile = process_opts["dump_filename"] + local flashfile = process_opts["flash_filename"] + local verifyfile = process_opts["verify_filename"] local rv = nil local file - local prg_size = 32 - local chr_size = 8 - local wram_size = 0 + local prg_size = console_opts["prg_rom_size_kb"] + local chr_size = console_opts["chr_rom_size_kb"] + local wram_size = console_opts["wram_size_kb"] + local mirror = console_opts["mirror"] --initialize device i/o for NES dict.io("IO_RESET") diff --git a/host/scripts/nes/unrom.lua b/host/scripts/nes/unrom.lua index 7f2cf5f..3e80da2 100644 --- a/host/scripts/nes/unrom.lua +++ b/host/scripts/nes/unrom.lua @@ -280,13 +280,21 @@ end --Cart should be in reset state upon calling this function --this function processes all user requests for this specific board/mapper -local function process( test, read, erase, program, verify, dumpfile, flashfile, verifyfile) - +local function process(process_opts, console_opts) + local test = process_opts["test"] + local read = process_opts["read"] + local erase = process_opts["erase"] + local program = process_opts["program"] + local verify = process_opts["verify"] + local dumpfile = process_opts["dump_filename"] + local flashfile = process_opts["flash_filename"] + local verifyfile = process_opts["verify_filename"] + local rv = nil local file - local prg_size = 512 - local chr_size = 0 - local wram_size = 0 + local prg_size = console_opts["prg_rom_size_kb"] + local chr_size = console_opts["chr_rom_size_kb"] + local wram_size = console_opts["wram_size_kb"] --initialize device i/o for NES dict.io("IO_RESET") diff --git a/host/source/inlprog.c b/host/source/inlprog.c index b5ad550..d2c3809 100644 --- a/host/source/inlprog.c +++ b/host/source/inlprog.c @@ -31,15 +31,22 @@ // TODO: Finish HELP for all currently supported options. +// TODO: Migrate to argp for more descriptive flags. const char *HELP = "Usage: inlretro [options]\n\n"\ "Options:\n"\ + " -a [dumpram_filename]\tIf provided write ram to this filename\n"\ + " -b [writeram_filename]If provided write this file's contents to ram\n"\ " -c [console]\t\tConsole port, {NES}\n"\ " -d [dump_filename]\tIf provided, dump cartridge ROMs to this filename\n"\ + " -h\t\t\tDisplays this message.\n"\ " -m [mapper]\t\tNES console only, mapper ASIC on cartridge\n"\ " \t\t\t{mmc1,mmc3,nrom}\n"\ " -p [program_filename]\tIf provided, write this data to cartridge\n"\ " -s [lua_script]\tIf provided, use this script for main application logic\n"\ - " -h\t\t\tDisplays this message.\n"; + " -v [verify_filename]\tIf provided, writeback written rom to this filename\n" + " -w [wram_size_kb]\tNES-only, size of WRAM in kb\n"\ + " -x [prg_rom_size_kb]\tNES-only, size of PRG-ROM in kb\n"\ + " -y [chr_rom_size_kb]\tNES-only, size of CHR-ROM in kb\n"; // Struct used to control functionality. typedef struct { @@ -47,16 +54,31 @@ typedef struct { char *mapper_name; int display_help; + // NES Functionality + int chr_rom_size_kb; + int prg_rom_size_kb; + int wram_size_kb; + char *dump_filename; char *program_filename; + char *ramdump_filename; + char *ramwrite_filename; + char *verify_filename; + char *lua_filename; } INLOptions; +// Returns true if given number is a power of 2, and at least minimum size. +int isValidROMSize(int x, int min) { + return ((x & (x - 1)) == 0) && x >= min; +} + + // Parse options and flags, create struct to drive program. INLOptions* parseOptions(int argc, char *argv[]) { // lower case flags suggested for average user - const char *FLAG_FORMAT = "hc:d:m:p:s:"; + const char *FLAG_FORMAT = "a:b:hc:d:m:p:s:v:w:x:y:"; int index = 0; int rv = 0; // opterr = 0; @@ -97,6 +119,8 @@ INLOptions* parseOptions(int argc, char *argv[]) { // case 'n': n_flag = 1; break; // case 'e': e_flag = 1; break; // case 'f': f_flag = 1; break; + case 'a': opts->ramdump_filename = optarg; break; + case 'b': opts->ramwrite_filename = optarg; break; case 'h': opts->display_help = 1; break; // case 'i': i_flag = 1; break; // case 't': t_flag = 1; break; @@ -110,6 +134,10 @@ INLOptions* parseOptions(int argc, char *argv[]) { case 'm': opts->mapper_name = optarg; break; case 'p': opts->program_filename = optarg; break; case 's': opts->lua_filename = optarg; break; + case 'v': opts->verify_filename = optarg; break; + case 'w': opts->wram_size_kb = atoi(optarg); break; + case 'x': opts->prg_rom_size_kb = atoi(optarg); break; + case 'y': opts->chr_rom_size_kb = atoi(optarg); break; // case 'v': v_value = optarg; break; // case 'C': C_value = optarg; break; // case 'L': L_value = optarg; break; @@ -276,6 +304,27 @@ int main(int argc, char *argv[]) return 1; } + // Check for sane user input. + if (strcmp("NES", opts->console_name) == 0) { + // ROM sizes must be non-zero, power of 2, and greater than 16. + if (isValidROMSize(opts->prg_rom_size_kb, 16)) { + printf("PRG-ROM must be non-zero power of 2, 16kb or greater.\n"); + return 1; + } + // Not having CHR-ROM is normal for certain types of carts. + // TODO: Update these checks with known info about mappers/carts. + if (isValidROMSize(opts->chr_rom_size_kb, 8) || opts->chr_rom_size_kb == 0) { + printf("CHR-ROM must be zero or power of 2, 8kb or greater.\n"); + return 1; + } + + // Not having WRAM is very normal. + if (isValidROMSize(opts->wram_size_kb, 8) || opts->wram_size_kb == 0) { + printf("WRAM must be zero or power of 2, 8kb or greater.\n"); + return 1; + } + } + //Start up Lua L = lua_init(); @@ -343,6 +392,24 @@ int main(int argc, char *argv[]) lua_pushstring(L, opts->program_filename); lua_setglobal(L, "flash_filename"); + lua_pushstring(L, opts->verify_filename); + lua_setglobal(L, "verify_filename"); + + lua_pushstring(L, opts->ramdump_filename); + lua_setglobal(L, "ramdump_filename"); + + lua_pushstring(L, opts->ramwrite_filename); + lua_setglobal(L, "ramwrite_filename"); + + lua_pushinteger(L, opts->wram_size_kb); + lua_setglobal(L, "nes_wram_size_kb"); + + lua_pushinteger(L, opts->prg_rom_size_kb); + lua_setglobal(L, "nes_prg_rom_size_kb"); + + lua_pushinteger(L, opts->chr_rom_size_kb); + lua_setglobal(L, "nes_chr_rom_size_kb"); + // USB device is open, pass args and control over to Lua. // If lua_filename isn't set from args, use default script. char *DEFAULT_SCRIPT = "scripts/inlretro.lua";