Allow specifying rom size in kilobytes via CLI, do related plumbing to keep Kb as internal representation w/o breaking support for also accepting size in megabits. Cleanup gb scripts to remove unreachable code that was left around from their origin as nes scripts, migrate process()'s to be table driven, add support for gb in inlretro2.lua

This commit is contained in:
beyondcoast 2019-01-14 07:14:15 -06:00
parent a11940f93d
commit f899518989
8 changed files with 130 additions and 426 deletions

View File

@ -8,47 +8,14 @@ local dump = require "scripts.app.dump"
local flash = require "scripts.app.flash"
-- file constants
local mapname = "ROMONLY"
local mapname = "MBC1"
-- local functions
--read PRG-ROM flash ID
local function rom_manf_id( debug )
--init_mapper()
if debug then print("reading PRG-ROM manf ID") end
--enter software mode
--ROMSEL controls PRG-ROM /OE which needs to be low for flash writes
--So unlock commands need to be addressed below $8000
--DISCRETE_EXP0_PRGROM_WR doesn't toggle /ROMSEL by definition though, so A15 is unused
-- 15 14 13 12
-- 0x5 = 0b 0 1 0 1 -> $5555
-- 0x2 = 0b 0 0 1 0 -> $2AAA
dict.nes("DISCRETE_EXP0_PRGROM_WR", 0x5555, 0xAA)
dict.nes("DISCRETE_EXP0_PRGROM_WR", 0x2AAA, 0x55)
dict.nes("DISCRETE_EXP0_PRGROM_WR", 0x5555, 0x90)
--read manf ID
local rv = dict.nes("NES_CPU_RD", 0x8000)
if debug then print("attempted read PRG-ROM manf ID:", string.format("%X", rv)) end
--read prod ID
rv = dict.nes("NES_CPU_RD", 0x8001)
if debug then print("attempted read PRG-ROM prod ID:", string.format("%X", rv)) end
--exit software
dict.nes("DISCRETE_EXP0_PRGROM_WR", 0x8000, 0xF0)
--verify exited
-- rv = dict.nes("NES_CPU_RD", 0x8001)
-- if debug then print("attempted read PRG-ROM prod ID:", string.format("%X", rv)) end
local function unsupported(operation)
print("\nUNSUPPORTED OPERATION: \"" .. operation .. "\" not implemented yet for Gameboy - ".. mapname .. "\n")
end
--dump the ROM
local function dump_rom( file, rom_size_KB, debug )
@ -88,194 +55,60 @@ local function dump_rom( file, rom_size_KB, debug )
end
--write a single byte to ROM flash
local function wr_flash_byte(addr, value, debug)
if (addr < 0x8000 or addr > 0xFFFF) then
print("\n ERROR! flash write to PRG-ROM", string.format("$%X", addr), "must be $8000-FFFF \n\n")
return
end
--send unlock command and write byte
dict.nes("DISCRETE_EXP0_PRGROM_WR", 0x5555, 0xAA)
dict.nes("DISCRETE_EXP0_PRGROM_WR", 0x2AAA, 0x55)
dict.nes("DISCRETE_EXP0_PRGROM_WR", 0x5555, 0xA0)
dict.nes("DISCRETE_EXP0_PRGROM_WR", addr, value)
local rv = dict.nes("NES_CPU_RD", addr)
local i = 0
while ( rv ~= value ) do
rv = dict.nes("NES_CPU_RD", addr)
i = i + 1
end
if debug then print(i, "naks, done writing byte.") end
--TODO handle timeout for problems
--TODO return pass/fail/info
end
--fast host flash one bank at a time...
--this is controlled from the host side one bank at a time
--but requires specific firmware MMC3 flashing functions
--there is super slow version commented out that doesn't require MMC3 specific firmware code
local function flash_rom(file, rom_size_KB, debug)
--init_mapper()
--test some bytes
--wr_flash_byte(0x8000, 0xA5, true)
--wr_flash_byte(0xFFFF, 0x5A, true)
print("\nProgramming PRG-ROM flash")
--most of this is overkill for NROM, but it's how we want to handle things for bigger mappers
local base_addr = 0x8000 --writes occur $8000-9FFF
local bank_size = 32*1024 --MMC3 8KByte per PRG bank
local buff_size = 1 --number of bytes to write at a time
local cur_bank = 0
local total_banks = rom_size_KB*1024/bank_size
local byte_num --byte number gets reset for each bank
local byte_str, data, readdata
while cur_bank < total_banks do
if (cur_bank %8 == 0) then
print("writting PRG bank: ", cur_bank, " of ", total_banks-1)
end
--program the entire bank's worth of data
flash.write_file( file, 32, mapname, "PRGROM", false )
cur_bank = cur_bank + 1
end
print("Done Programming PRG-ROM flash")
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 rv = nil
-- Cart should be in reset state upon calling this function
-- this function processes all user requests for this specific board/mapper
local function process(process_opts, console_opts)
local file
local rom_size = 256
local ram_size = 0
--initialize device i/o for NES
-- Initialize device i/o for Gameboy
dict.io("IO_RESET")
dict.io("GAMEBOY_INIT")
dict.io("GB_POWER_5V") --gameboy carts prob run fine at 3v if want to be safe
dict.io("GB_POWER_5V") -- Gameboy carts prob run fine at 3v if want to be safe
--test the cart
if test then
-- print("Testing ", mapname)
-- nes.detect_mapper_mirroring(true)
-- print("EXP0 pull-up test:", dict.io("EXP0_PULLUP_TEST"))
-- --nes.read_flashID_prgrom_exp0(true)
-- rom_manf_id(true)
-- --nes.read_flashID_chrrom_8K(true)
-- chrrom_manf_id(true)
-- TODO: test the cart
if process_opts["test"] then
unsupported("test")
end
--dump the cart to dumpfile
if read then
-- Dump the cart to dumpfile
if process_opts["read"] then
print("\nDumping ROM...")
--init_mapper()
file = assert(io.open(process_opts["dump_filename"], "wb"))
file = assert(io.open(dumpfile, "wb"))
-- Dump cart into file
dump_rom(file, console_opts["rom_size_kbyte"], false)
--dump cart into file
dump_rom(file, rom_size, false)
--close file
-- Close file
assert(file:close())
print("DONE Dumping ROM")
end
--erase the cart
if erase then
-- print("\nErasing ", mapname);
--
-- --init_mapper()
--
-- print("erasing PRG-ROM");
-- dict.nes("DISCRETE_EXP0_PRGROM_WR", 0x5555, 0xAA)
-- dict.nes("DISCRETE_EXP0_PRGROM_WR", 0x2AAA, 0x55)
-- dict.nes("DISCRETE_EXP0_PRGROM_WR", 0x5555, 0x80)
-- dict.nes("DISCRETE_EXP0_PRGROM_WR", 0x5555, 0xAA)
-- dict.nes("DISCRETE_EXP0_PRGROM_WR", 0x2AAA, 0x55)
-- dict.nes("DISCRETE_EXP0_PRGROM_WR", 0x5555, 0x10)
-- rv = dict.nes("NES_CPU_RD", 0x8000)
--
-- local i = 0
--
-- --TODO create some function to pass the read value
-- --that's smart enough to figure out if the board is actually erasing or not
-- while ( rv ~= 0xFF ) do
-- rv = dict.nes("NES_CPU_RD", 0x8000)
-- i = i + 1
-- end
-- print(i, "naks, done erasing prg.");
--
-- print("erasing CHR-ROM");
-- dict.nes("NES_PPU_WR", 0x1555, 0xAA)
-- dict.nes("NES_PPU_WR", 0x0AAA, 0x55)
-- dict.nes("NES_PPU_WR", 0x1555, 0x80)
-- dict.nes("NES_PPU_WR", 0x1555, 0xAA)
-- dict.nes("NES_PPU_WR", 0x0AAA, 0x55)
-- dict.nes("NES_PPU_WR", 0x1555, 0x10)
-- rv = dict.nes("NES_PPU_RD", 0x0000)
--
-- i = 0
-- while ( rv ~= 0xFF ) do
-- rv = dict.nes("NES_PPU_RD", 0x0000)
-- i = i + 1
-- end
-- print(i, "naks, done erasing chr.\n");
-- TODO: erase the cart
if process_opts["erase"] then
unsupported("erase")
end
--program flashfile to the cart
if program then
-- --open file
-- file = assert(io.open(flashfile, "rb"))
-- --determine if auto-doubling, deinterleaving, etc,
-- --needs done to make board compatible with rom
-- --flash cart
-- flash_rom(file, rom_size, true)
-- --close file
-- assert(file:close())
--
-- TODO: program flashfile to the cart
if process_opts["program"] then
unsupported("program")
end
--verify flashfile is on the cart
if verify then
-- Verify flashfile is on the cart
-- (This is sort of pointless until "program" is supported)
if process_opts["verify"] then
--for now let's just dump the file and verify manually
print("\nPost dumping ROM...")
--init_mapper()
file = assert(io.open(verifyfile, "wb"))
file = assert(io.open(process_opts["verify_filename"], "wb"))
--dump cart into file
dump_rom(file, rom_size, false)
dump_rom(file, console_opts["rom_size_kbyte"], false)
--close file
assert(file:close())
@ -286,12 +119,11 @@ local function process( test, read, erase, program, verify, dumpfile, flashfile,
dict.io("IO_RESET")
end
-- global variables so other modules can use them
-- NONE
-- call functions desired to run when script is called/imported
-- NONE
-- functions other modules are able to call
mbc1.process = process

View File

@ -1,56 +1,20 @@
-- create the module's table
local romonly = {}
-- import required modules
local dict = require "scripts.app.dict"
local dump = require "scripts.app.dump"
local flash = require "scripts.app.flash"
-- file constants
local mapname = "ROMONLY"
-- local functions
--read PRG-ROM flash ID
local function rom_manf_id( debug )
--init_mapper()
if debug then print("reading PRG-ROM manf ID") end
--enter software mode
--ROMSEL controls PRG-ROM /OE which needs to be low for flash writes
--So unlock commands need to be addressed below $8000
--DISCRETE_EXP0_PRGROM_WR doesn't toggle /ROMSEL by definition though, so A15 is unused
-- 15 14 13 12
-- 0x5 = 0b 0 1 0 1 -> $5555
-- 0x2 = 0b 0 0 1 0 -> $2AAA
dict.nes("DISCRETE_EXP0_PRGROM_WR", 0x5555, 0xAA)
dict.nes("DISCRETE_EXP0_PRGROM_WR", 0x2AAA, 0x55)
dict.nes("DISCRETE_EXP0_PRGROM_WR", 0x5555, 0x90)
--read manf ID
local rv = dict.nes("NES_CPU_RD", 0x8000)
if debug then print("attempted read PRG-ROM manf ID:", string.format("%X", rv)) end
--read prod ID
rv = dict.nes("NES_CPU_RD", 0x8001)
if debug then print("attempted read PRG-ROM prod ID:", string.format("%X", rv)) end
--exit software
dict.nes("DISCRETE_EXP0_PRGROM_WR", 0x8000, 0xF0)
--verify exited
-- rv = dict.nes("NES_CPU_RD", 0x8001)
-- if debug then print("attempted read PRG-ROM prod ID:", string.format("%X", rv)) end
local function unsupported(operation)
print("\nUNSUPPORTED OPERATION: \"" .. operation .. "\" not implemented yet for Gameboy - ".. mapname .. "\n")
end
--dump the ROM
local function dump_rom( file, rom_size_KB, debug )
-- dump the ROM
local function dump_rom(file, rom_size_KB, debug)
--ROM ONLY dump all 32KB, most of this code is overkill for no MBC.
-- but follows same format as MBC's
@ -59,209 +23,71 @@ local function dump_rom( file, rom_size_KB, debug )
local read_count = 0
local addr_base = 0x00 -- $0000 base address for ROM
while ( read_count < num_reads ) do
while (read_count < num_reads) do
if debug then print( "dump ROM part ", read_count, " of ", num_reads) end
if debug then print("dump ROM part ", read_count, " of ", num_reads) end
dump.dumptofile( file, KB_per_read, addr_base, "GAMEBOY_PAGE", false )
dump.dumptofile(file, KB_per_read, addr_base, "GAMEBOY_PAGE", false)
read_count = read_count + 1
end
end
--write a single byte to ROM flash
local function wr_flash_byte(addr, value, debug)
if (addr < 0x8000 or addr > 0xFFFF) then
print("\n ERROR! flash write to PRG-ROM", string.format("$%X", addr), "must be $8000-FFFF \n\n")
return
end
--send unlock command and write byte
dict.nes("DISCRETE_EXP0_PRGROM_WR", 0x5555, 0xAA)
dict.nes("DISCRETE_EXP0_PRGROM_WR", 0x2AAA, 0x55)
dict.nes("DISCRETE_EXP0_PRGROM_WR", 0x5555, 0xA0)
dict.nes("DISCRETE_EXP0_PRGROM_WR", addr, value)
local rv = dict.nes("NES_CPU_RD", addr)
local i = 0
while ( rv ~= value ) do
rv = dict.nes("NES_CPU_RD", addr)
i = i + 1
end
if debug then print(i, "naks, done writing byte.") end
--TODO handle timeout for problems
--TODO return pass/fail/info
end
--fast host flash one bank at a time...
--this is controlled from the host side one bank at a time
--but requires specific firmware MMC3 flashing functions
--there is super slow version commented out that doesn't require MMC3 specific firmware code
local function flash_rom(file, rom_size_KB, debug)
--init_mapper()
--test some bytes
--wr_flash_byte(0x8000, 0xA5, true)
--wr_flash_byte(0xFFFF, 0x5A, true)
print("\nProgramming PRG-ROM flash")
--most of this is overkill for NROM, but it's how we want to handle things for bigger mappers
local base_addr = 0x8000 --writes occur $8000-9FFF
local bank_size = 32*1024 --MMC3 8KByte per PRG bank
local buff_size = 1 --number of bytes to write at a time
local cur_bank = 0
local total_banks = rom_size_KB*1024/bank_size
local byte_num --byte number gets reset for each bank
local byte_str, data, readdata
while cur_bank < total_banks do
if (cur_bank %8 == 0) then
print("writting PRG bank: ", cur_bank, " of ", total_banks-1)
end
--program the entire bank's worth of data
flash.write_file( file, 32, mapname, "PRGROM", false )
cur_bank = cur_bank + 1
end
print("Done Programming PRG-ROM flash")
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 rv = nil
-- Cart should be in reset state upon calling this function
-- this function processes all user requests for this specific board/mapper
local function process(process_opts, console_opts)
local file
local rom_size = 32
local ram_size = 0
--initialize device i/o for NES
-- initialize device i/o for Gameboy
dict.io("IO_RESET")
dict.io("GAMEBOY_INIT")
dict.io("GB_POWER_5V") --gameboy carts prob run fine at 3v if want to be safe
--test the cart
if test then
-- print("Testing ", mapname)
-- nes.detect_mapper_mirroring(true)
-- print("EXP0 pull-up test:", dict.io("EXP0_PULLUP_TEST"))
-- --nes.read_flashID_prgrom_exp0(true)
-- rom_manf_id(true)
-- --nes.read_flashID_chrrom_8K(true)
-- chrrom_manf_id(true)
-- test the cart
if process_opts["test"] then
unsupported("test")
end
--dump the cart to dumpfile
if read then
-- dump the cart to dumpfile
if process_opts["read"] then
print("\nDumping ROM...")
--init_mapper()
file = assert(io.open(process_opts["dump_filename"], "wb"))
file = assert(io.open(dumpfile, "wb"))
-- dump cart into file
dump_rom(file, console_opts["rom_size_kbyte"], false)
--dump cart into file
dump_rom(file, rom_size, false)
--close file
-- close file
assert(file:close())
print("DONE Dumping ROM")
end
--erase the cart
if erase then
-- print("\nErasing ", mapname);
--
-- --init_mapper()
--
-- print("erasing PRG-ROM");
-- dict.nes("DISCRETE_EXP0_PRGROM_WR", 0x5555, 0xAA)
-- dict.nes("DISCRETE_EXP0_PRGROM_WR", 0x2AAA, 0x55)
-- dict.nes("DISCRETE_EXP0_PRGROM_WR", 0x5555, 0x80)
-- dict.nes("DISCRETE_EXP0_PRGROM_WR", 0x5555, 0xAA)
-- dict.nes("DISCRETE_EXP0_PRGROM_WR", 0x2AAA, 0x55)
-- dict.nes("DISCRETE_EXP0_PRGROM_WR", 0x5555, 0x10)
-- rv = dict.nes("NES_CPU_RD", 0x8000)
--
-- local i = 0
--
-- --TODO create some function to pass the read value
-- --that's smart enough to figure out if the board is actually erasing or not
-- while ( rv ~= 0xFF ) do
-- rv = dict.nes("NES_CPU_RD", 0x8000)
-- i = i + 1
-- end
-- print(i, "naks, done erasing prg.");
--
-- print("erasing CHR-ROM");
-- dict.nes("NES_PPU_WR", 0x1555, 0xAA)
-- dict.nes("NES_PPU_WR", 0x0AAA, 0x55)
-- dict.nes("NES_PPU_WR", 0x1555, 0x80)
-- dict.nes("NES_PPU_WR", 0x1555, 0xAA)
-- dict.nes("NES_PPU_WR", 0x0AAA, 0x55)
-- dict.nes("NES_PPU_WR", 0x1555, 0x10)
-- rv = dict.nes("NES_PPU_RD", 0x0000)
--
-- i = 0
-- while ( rv ~= 0xFF ) do
-- rv = dict.nes("NES_PPU_RD", 0x0000)
-- i = i + 1
-- end
-- print(i, "naks, done erasing chr.\n");
-- TODO: Erase the cart
if process_opts["erase"] then
unsupported("erase")
end
--program flashfile to the cart
if program then
-- --open file
-- file = assert(io.open(flashfile, "rb"))
-- --determine if auto-doubling, deinterleaving, etc,
-- --needs done to make board compatible with rom
-- --flash cart
-- flash_rom(file, rom_size, true)
-- --close file
-- assert(file:close())
--
-- TODO: program flashfile to the cart
if process_opts["program"] then
unsupported("program")
end
--verify flashfile is on the cart
if verify then
-- Verify flashfile is on the cart
-- (This is sort of pointless until "program" is supported)
if process_opts["verify"] then
--for now let's just dump the file and verify manually
print("\nPost dumping ROM...")
--init_mapper()
file = assert(io.open(verifyfile, "wb"))
file = assert(io.open(process_opts["verify_filename"], "wb"))
--dump cart into file
dump_rom(file, rom_size, false)
dump_rom(file, console_opts["rom_size_kbyte"], false)
--close file
assert(file:close())
print("DONE post dumping ROM")
end
@ -270,10 +96,10 @@ end
-- global variables so other modules can use them
-- NONE
-- call functions desired to run when script is called/imported
-- NONE
-- functions other modules are able to call
romonly.process = process

View File

@ -87,7 +87,7 @@ local function process(process_opts, console_opts)
local rv = nil
local file
local rom_size = console_opts["rom_size_mbit"] * 128
local rom_size = console_opts["rom_size_kbyte"]
local wram_size = console_opts["wram_size_kb"]
local mirror = console_opts["mirror"]

View File

@ -139,7 +139,7 @@ function main ()
prg_rom_size_kb = 256 * 128, -- Size of NES PRG-ROM in KByte
chr_rom_size_kb = 8, -- Size of NES CHR-ROM in KByte
wram_size_kb = 0, -- Size of NES PRG-RAM/WRAM in KByte
rom_size_mbit = 8, -- Size of ROM in Megabits, used for non-NES consoles.
rom_size_kbyte = 8 * 128, -- Size of ROM in Megabits, used for non-NES consoles.
}
@ -231,7 +231,7 @@ function main ()
dict.io("IO_RESET")
curcart.process( true, true, false, false, false, "ignore/dump.bin", "ignore/gameboy.bin", "ignore/verifyout.bin")
curcart.process(process_opts, console_opts)
--[[ --TEST GB power
dict.io("GB_POWER_3V")
print("GBP high 3v GBA")

View File

@ -11,12 +11,32 @@ end
function default_exec(process_opts, console_opts)
-- Defensively filter out any console options that aren't standard.
local default_opts = {
rom_size_mbit = console_opts["rom_size_mbit"],
rom_size_kbyte = console_opts["rom_size_kbyte"],
wram_size_kb = console_opts["wram_size_kb"],
}
console_opts["console_process_script"].process(process_opts, default_opts)
end
-- Wrapper for managing original Gameboy operations.
function gb_exec(process_opts, console_opts)
-- Defensively filter out any console options that aren't standard.
local gb_opts = {
rom_size_kbyte = console_opts["rom_size_kbyte"],
}
local mappers = {
romonly = require "scripts.gb.romonly",
mbc1 = require "scripts.gb.mbc1",
}
m = mappers[console_opts["mapper"]]
if m == nil then
print("UNSUPPORTED MAPPER: ", console_opts["mapper"])
else
-- Attempt requested operations with hardware!
-- TODO: Do plumbing for interacting with RAM.
m.process(process_opts, console_opts)
end
end
-- Wrapper for managing NES/Famicom operations.
function nes_exec(process_opts, console_opts)
local dict = require "scripts.app.dict"
@ -69,15 +89,17 @@ end
function main()
-- Globals passed in from C:
-- console_name: string, name of console.
-- mapper_name: string, name of mapper.
-- 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.
-- console_name: string, name of console.
-- mapper_name: string, name of mapper.
-- 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.
-- ramdump_filename: string, filename used for writing dumped ram data.
-- ramwrite_filename: string, filename containing data to write to ram on cartridge.
-- nes_prg_rom_size_kb: int, size of cartridge PRG-ROM in kilobytes.
-- nes_chr_rom_size_kb: int, size of cartridge CHR-ROM in kilobytes.
-- nes_wram_size_kb: int, size of cartridge WRAM in kilobytes.
-- rom_size_mbit: int, size of cartridge ROM in megabits.
-- rom_size_kbyte: int, size of cartridge ROM in kilobytes.
-- TODO: This should probably be one level up.
-- TODO: Ram probably needs a verify file as well?
@ -119,6 +141,8 @@ function main()
-- TODO: Add SNES support, as it appears to be currently usable?
local consoles = {
dmg = gb_exec,
gb = gb_exec, -- Support two names for gameboy
gba = default_exec,
genesis = default_exec,
n64 = default_exec,
@ -139,7 +163,7 @@ function main()
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,
rom_size_mbit = rom_size_mbit,
rom_size_kbyte = rom_size_kbyte,
console_process_script = console_process_script,
mapper = mapper_name,
}

View File

@ -72,7 +72,7 @@ local function process(process_opts, console_opts)
local rv = nil
local file
local rom_size = console_opts["rom_size_mbit"] * 128
local rom_size = console_opts["rom_size_kbyte"]
local wram_size = console_opts["wram_size_kb"]
local mirror = console_opts["mirror"]

View File

@ -49,7 +49,6 @@ end
--this function processes all user requests for this specific board/mapper
local function process(process_opts, console_opts)
local file
local rom_size = console_opts["rom_size_mbit"] * 128
-- Initialize device i/o for SEGA
dict.io("IO_RESET")
@ -73,7 +72,7 @@ local function process(process_opts, console_opts)
file = assert(io.open(process_opts["dump_filename"], "wb"))
--dump cart into file
dump_rom(file, rom_size, false)
dump_rom(file, console_opts["rom_size_kbyte"], false)
--close file
assert(file:close())

View File

@ -32,6 +32,7 @@ const char *HELP = "Usage: inlretro [options]\n\n"\
" \t\t\t\t\t\t mapper30,mmc1,mmc3,mmc4,mmc5,nrom,unrom}\n"\
" --nes_prg_rom_size_kbyte=size, -x size_kbytes\tNES-only, size of PRG-ROM in kilobytes\n"\
" --nes_chr_rom_size_kbyte=size, -y size_kbytes\tNES-only, size of CHR-ROM in kilobytes\n"\
" --rom_size_kbyte=size, -k size_kbytes\t\tSize of ROM in kilobytes, non-NES systems.\n"\
" --rom_size_mbit=size, -z size_mbits\t\tSize of ROM in megabits, non-NES systems.\n"\
" --verify_filename=filename, -v filename\tIf provided, writeback written rom to this filename\n"\
" --wram_size_kbyte=size, -w size_kbytes\tNES-only, size of WRAM in kilobytes\n"\
@ -50,7 +51,7 @@ typedef struct {
int wram_size_kb;
// General Functionality
int rom_size_mbit;
int rom_size_kbyte;
char *dump_filename;
char *program_filename;
char *ramdump_filename;
@ -90,6 +91,7 @@ INLOptions* parseOptions(int argc, char *argv[]) {
{"nes_prg_rom_size_kbyte", optional_argument, NULL, 'x'},
{"nes_chr_rom_size_kbyte", optional_argument, NULL, 'y'},
{"wram_size_kbyte", optional_argument, NULL, 'w'},
{"rom_size_kbyte", optional_argument, NULL, 'k'},
{"rom_size_mbit", optional_argument, NULL, 'z'},
{0, 0, 0, 0} // longopts must end in {0, 0, 0, 0}
};
@ -98,6 +100,7 @@ INLOptions* parseOptions(int argc, char *argv[]) {
const char *FLAG_FORMAT = "a:b:hc:d:m:p:s:v:w:x:y:z:";
int index = 0;
int rv = 0;
int kbyte = 0;
opterr = 0;
// Create options struct.
@ -123,6 +126,7 @@ INLOptions* parseOptions(int argc, char *argv[]) {
case 'h': opts->display_help = 1; break;
case 'c': opts->console_name = optarg; break;
case 'd': opts->dump_filename = optarg; break;
case 'k': opts->rom_size_kbyte = atoi(optarg); break;
case 'm': opts->mapper_name = optarg; break;
case 'p': opts->program_filename = optarg; break;
case 's': opts->lua_filename = optarg; break;
@ -130,7 +134,13 @@ INLOptions* parseOptions(int argc, char *argv[]) {
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 'z': opts->rom_size_mbit = atoi(optarg); break;
case 'z':
kbyte = atoi(optarg) * 128;
if (opts->rom_size_kbyte && opts->rom_size_kbyte != kbyte) {
printf("rom_size_mbit disagrees with rom_size_kbyte! Using %d Kb as rom size.\n", kbyte);
}
opts->rom_size_kbyte = kbyte;
break;
case '?':
if(
( optopt == 'c' )
@ -232,8 +242,8 @@ lua_State *lua_init(INLOptions *opts) {
lua_pushstring(L, opts->ramwrite_filename);
lua_setglobal(L, "ramwrite_filename");
lua_pushinteger(L, opts->rom_size_mbit);
lua_setglobal(L, "rom_size_mbit");
lua_pushinteger(L, opts->rom_size_kbyte);
lua_setglobal(L, "rom_size_kbyte");
lua_pushinteger(L, opts->wram_size_kb);
lua_setglobal(L, "nes_wram_size_kb");
@ -297,7 +307,7 @@ int main(int argc, char *argv[])
}
// Check for sane user input.
if (strcmp("NES", opts->console_name) == 0) {
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");
@ -317,6 +327,19 @@ int main(int argc, char *argv[])
}
}
if ((strcmp("gba", opts->console_name) == 0) ||
(strcmp("genesis", opts->console_name) == 0) ||
(strcmp("n64", opts->console_name) == 0)) {
if (opts->rom_size_kbyte <= 0) {
printf("ROM size must be greater than 0 kilobytes.\n");
return 1;
}
if (opts->rom_size_kbyte % 128) {
printf("ROM size for this system must translate into megabits with no kilobyte remainder.\n");
return 1;
}
}
// Start up Lua.
L = lua_init(opts);