Commit 577277cd authored by Paul Molloy's avatar Paul Molloy

Basic NES file header creation. PRG/CHR-ROM sizes are filled in based

on provided prg/chr rom input args for dumping.  Mirroring is sensed &
entered for fixed mirror mappers.  So this is basic iNES file format.

Still don't have automatic banktable locating, nor mapper detection.

But this provides a basic header that should work with most currently
supported NES mappers.  If the headers need tweaked, I recommend opening
in Mesen and using it's header modifcation tool.
parent 5bd4799d
......@@ -390,29 +390,23 @@ SOFTWARE & FIRMWARE BUILDING
Some build instructions follow, but they shouldn't be needed if you're running the
released firmware on Windows.
This section needs some updating.... Don't be afraid to contact me if you'd like to build
your own firmware. Or are having issues building the host application on linux/mac
===================
Linux
Linux/Mac
===================
HOST APPLICATION:
install libusb:
sudo apt-get install libusb-1.0-0-dev
make:
gcc -I include inlretro.c -o inlretro -lusb-1.0
or just run make unix from host folder.
As noted in windows instructions below, lua must be built first
-cd host/source/lua, make o a, then make from host/source
make from host folder:
make unix
run:
./inlretro
AVR FIRMWARE:
If you want to build your own AVR FIRMWARE:
install avr-gcc and avr-libc:
sudo apt-get install gcc-avr
sudo apt-get install avr-libc
......@@ -486,16 +480,10 @@ So that might help if you have similar issues...
Now host app can be built from windows command prompt command make when in host directory
Currently setup to compile lua separate from host app. Need to get better at writing makefiles..
But whatever it works and saves ~12sec of compile time with current setup.
-go to host/source/lua
-make o a
-go back to host
-make
This way lua is compiled separately using it's provided make file.
make clean still deletes lua object files, so this process must be reperformed if cleaned.
-go to host
-make all
AVR FIRMWARE:
If you want to build your own AVR FIRMWARE:
Download and Install WinAVR
optional: install programmer's notepad has handy feature to make clean, all, program in tools menu
this is nifty if you are scared of the command prompt for some strange reason...
......
......@@ -51,6 +51,8 @@ local function update_firmware(newbuild, skip, forceup)
--open new file first, don't bother continuing if can't find it.
file = assert(io.open(newbuild, "rb"))
--TODO REPORT build time stamp so can be certain it was a build just made if desired
--TODO read the fwupdater & app version from the provided file
--compare to current device and determine if they're compatible
--test let's tinker with SRAM
......
......@@ -11,6 +11,163 @@ local PPU_A13_HI = 0x2000 --PPU /A13 is connected to mcu A15
local FC_RF_HI = 0x20 --FC RF audio pin is EXP6 (bit5)
-- local functions
-- pass a file pointer for a file which is already open
-- leave file open when done
local function write_header( file, prgKB, chrKB, mapper, mirroring )
--bytes 0-3 always "NES <eof>"
file:write("NES")
file:write(string.char(0x1A))
--byte 4 PRG-ROM 16KByte banks
file:write(string.char(prgKB / 16))
--byte 5 CHR-ROM 8KByte banks
file:write(string.char(chrKB / 8))
--byte 6 Flags 6
-- D~7654 3210
-- ---------
-- NNNN FTBM
-- |||| |||+-- Hard-wired nametable mirroring type
-- |||| ||| 0: Horizontal or mapper-controlled
-- |||| ||| 1: Vertical
-- |||| ||+--- "Battery" and other non-volatile memory
-- |||| || 0: Not present
-- |||| || 1: Present
-- |||| |+--- 512-byte Trainer
-- |||| | 0: Not present
-- |||| | 1: Present between Header and PRG-ROM data
-- |||| +---- Hard-wired four-screen mode
-- |||| 0: No
-- |||| 1: Yes
-- ++++------ Mapper Number D0..D3
--
--lower 4bits of mapper number
temp = mapper & 0x0F
temp = temp << 4
if mirroring == "VERT" then
temp = temp | 0x01
end
--else "HORZ" bit0 = 0
file:write(string.char(temp))
--byte7 Flags 7
-- D~7654 3210
-- ---------
-- NNNN 10TT
-- |||| ||++- Console type
-- |||| || 0: Nintendo Entertainment System/Family Computer
-- |||| || 1: Nintendo Vs. System
-- |||| || 2: Nintendo Playchoice 10
-- |||| || 3: Extended Console Type
-- |||| ++--- NES 2.0 identifier
-- ++++------ Mapper Number D4..D7
--
--upper 4bits of mapper number
local temp = mapper & 0xF0
file:write(string.char(temp))
--8 Mapper MSB/Submapper
file:write(string.char(0))
-- D~7654 3210
-- ---------
-- SSSS NNNN
-- |||| ++++- Mapper number D8..D11
-- ++++------ Submapper number
--9 PRG-ROM/CHR-ROM size MSB
file:write(string.char(0))
-- D~7654 3210
-- ---------
-- CCCC PPPP
-- |||| ++++- PRG-ROM size MSB
-- ++++------ CHR-ROM size MSB
--
--10 PRG-RAM/EEPROM size
file:write(string.char(0))
-- D~7654 3210
-- ---------
-- pppp PPPP
-- |||| ++++- PRG-RAM (volatile) shift count
-- ++++------ PRG-NVRAM/EEPROM (non-volatile) shift count
-- If the shift count is zero, there is no PRG-(NV)RAM.
-- If the shift count is non-zero, the actual size is
-- "64 << shift count" bytes, i.e. 8192 bytes for a shift count of 7.
--
--11 CHR-RAM size
file:write(string.char(0))
-- D~7654 3210
-- ---------
-- cccc CCCC
-- |||| ++++- CHR-RAM size (volatile) shift count
-- ++++------ CHR-NVRAM size (non-volatile) shift count
-- If the shift count is zero, there is no CHR-(NV)RAM.
-- If the shift count is non-zero, the actual size is
-- "64 << shift count" bytes, i.e. 8192 bytes for a shift count of 7.
--
--12 CPU/PPU Timing
file:write(string.char(0))
-- D~7654 3210
-- ---------
-- .... ..VV
-- ++- CPU/PPU timing mode
-- 0: RP2C02 ("NTSC NES")
-- 1: RP2C07 ("Licensed PAL NES")
-- 2: Multiple-region
-- 3: UMC 6527P ("Dendy")
--
--13 When Byte 7 AND 3 =1: Vs. System Type
file:write(string.char(0))
-- D~7654 3210
-- ---------
-- MMMM PPPP
-- |||| ++++- Vs. PPU Type
-- ++++------ Vs. Hardware Type
--
--When Byte 7 AND 3 =3: Extended Console Type
-- D~7654 3210
-- ---------
-- .... CCCC
-- ++++- Extended Console Type
--
--14 Miscellaneous ROMs
file:write(string.char(0))
-- D~7654 3210
-- ---------
-- .... ..RR
-- ++- Number of miscellaneous ROMs present
--
--15 Default Expansion Device
file:write(string.char(0))
-- D~7654 3210
-- ---------
-- ..DD DDDD
-- ++-++++- Default Expansion Device
end
-- Desc:check if PPU /A13 -> CIRAM /CE jumper present
-- Does NOT check if PPU A13 is inverted and then drives CIRAM /CE
......@@ -346,6 +503,7 @@ nes.test_cic_soft_switch = test_cic_soft_switch
nes.ppu_ram_sense = ppu_ram_sense
nes.read_flashID_chrrom_8K = read_flashID_chrrom_8K
nes.read_flashID_prgrom_exp0 = read_flashID_prgrom_exp0
nes.write_header = write_header
-- return the module's table
return nes
......
......@@ -3,14 +3,24 @@
local action53 = {}
-- import required modules
local nes = require "scripts.app.nes"
local dict = require "scripts.app.dict"
local dump = require "scripts.app.dump"
local flash = require "scripts.app.flash"
local buffers = require "scripts.app.buffers"
-- file constants
local mapname = "A53"
-- local functions
local function create_header( file, prgKB, chrKB )
--write_header( file, prgKB, chrKB, mapper, mirroring )
nes.write_header( file, prgKB, 0, op_buffer[mapname], 0)
end
--local function wr_flash_byte(addr, value, debug)
--base is the actual NES CPU address, not the rom offset (ie $FFF0, not $7FF0)
......@@ -84,7 +94,9 @@ local function process(process_opts, console_opts)
local rv = nil
local file
-- TODO: Handle variable ROM sizes.
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")
......@@ -104,9 +116,11 @@ local function process(process_opts, console_opts)
file = assert(io.open(dumpfile, "wb"))
--TODO find bank table to avoid bus conflicts!
--create header: pass open & empty file & rom sizes
create_header(file, prg_size, chr_size)
--dump cart into file
dump.dumptofile( file, 512, "A53", "PRGROM", true )
dump.dumptofile( file, prg_size, "A53", "PRGROM", true )
--close file
assert(file:close())
......
......@@ -3,14 +3,24 @@
local action53_tsop = {}
-- import required modules
local nes = require "scripts.app.nes"
local dict = require "scripts.app.dict"
local dump = require "scripts.app.dump"
local flash = require "scripts.app.flash"
local buffers = require "scripts.app.buffers"
-- file constants
local mapname = "A53"
-- local functions
local function create_header( file, prgKB, chrKB )
--write_header( file, prgKB, chrKB, mapper, mirroring )
nes.write_header( file, prgKB, 0, op_buffer[mapname], 0)
end
--local function wr_flash_byte(addr, value, debug)
--base is the actual NES CPU address, not the rom offset (ie $FFF0, not $7FF0)
......@@ -135,10 +145,10 @@ local function write_gift(base, off)
--off = off + 1 --increase to start of message but index starting at 1
i = 1
--local msg1 = "Regular Edition"
--regular editions don't have gift messages
--local msg1 = "Contributor Edition"
local msg1 = "Limited Edition"
local msg2 = "82 of 100" -- all flashed
--local msg1 = "Limited Edition"
--local msg2 = "82 of 100" -- all flashed
--local msg1 = " Contributor Edition "
--local msg2 = " PinoBatch " --issue if capital P or R is first char for some reason..
......@@ -211,7 +221,9 @@ local function process(process_opts, console_opts)
local rv = nil
local file
-- TODO: Handle variable ROM sizes.
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")
......@@ -225,9 +237,9 @@ local function process(process_opts, console_opts)
local base = 0x8BD0
local start_offset = 0xC
local len = 80
read_gift(base, len)
--read_gift(base, len)
write_gift(base, start_offset)
--write_gift(base, start_offset)
read_gift(base, len)
end
......@@ -239,9 +251,11 @@ local function process(process_opts, console_opts)
file = assert(io.open(dumpfile, "wb"))
--TODO find bank table to avoid bus conflicts!
--create header: pass open & empty file & rom sizes
create_header(file, prg_size, chr_size)
--dump cart into file
dump.dumptofile( file, 1024, "A53", "PRGROM", true )
dump.dumptofile( file, prg_size, "A53", "PRGROM", true )
--close file
assert(file:close())
......
......@@ -8,6 +8,9 @@ local nes = require "scripts.app.nes"
local dump = require "scripts.app.dump"
local flash = require "scripts.app.flash"
local time = require "scripts.app.time"
local files = require "scripts.app.files"
local swim = require "scripts.app.swim"
local buffers = require "scripts.app.buffers"
-- file constants & variables
local mapname = "BxROM"
......@@ -16,6 +19,31 @@ local banktable_base = 0xFF94 --Lizard
--local rom_FF_addr = 0x8000
-- local functions
local function create_header( file, prgKB, chrKB )
local mirroring = nes.detect_mapper_mirroring()
--write_header( file, prgKB, chrKB, mapper, mirroring )
nes.write_header( file, prgKB, 0, op_buffer[mapname], mirroring)
end
local function dump_cic_message( debug )
--test reading back CIC version
dict.io("SWIM_INIT", "SWIM_ON_A0")
--dict.io("SWIM_INIT", "SWIM_ON_EXP0")
if swim.start() then
swim.read_stack()
else
print("ERROR trying to read back CIC signature stack data")
end
swim.stop_and_reset()
dict.io("IO_RESET")
dict.io("NES_INIT")
end
--read PRG-ROM flash ID
......@@ -239,6 +267,9 @@ local function process(process_opts, console_opts)
print("EXP0 pull-up test:", dict.io("EXP0_PULLUP_TEST"))
prgrom_manf_id(true)
--dump_cic_message( )
--
end
--dump the cart to dumpfile
......@@ -246,6 +277,9 @@ local function process(process_opts, console_opts)
print("\nDumping PRG-ROM...")
file = assert(io.open(dumpfile, "wb"))
--create header: pass open & empty file & rom sizes
create_header(file, prg_size, chr_size)
--TODO find bank table to avoid bus conflicts!
--dump cart into file
time.start()
......@@ -324,6 +358,13 @@ local function process(process_opts, console_opts)
assert(file:close())
print("DONE post dumping PRG-ROM")
--compare the flash file vs post dump file
if (files.compare( verifyfile, flashfile, true ) ) then
print("\nSUCCESS! Flash verified")
else
print("\n\n\n FAILURE! Flash verification did not match")
end
end
dict.io("IO_RESET")
......
......@@ -9,6 +9,7 @@ local dump = require "scripts.app.dump"
local flash = require "scripts.app.flash"
local swim = require "scripts.app.swim"
local ciccom = require "scripts.app.ciccom"
local buffers = require "scripts.app.buffers"
-- file constants & variables
local mapname = "CNROM"
......@@ -17,6 +18,15 @@ local rom_FF_addr = 0x8008 --galf
-- local functions
local function create_header( file, prgKB, chrKB )
local mirroring = nes.detect_mapper_mirroring()
--write_header( file, prgKB, chrKB, mapper, mirroring )
nes.write_header( file, prgKB, chrKB, op_buffer[mapname], mirroring)
end
local function find_banktable( debug )
--TODO find/create the bank table
......@@ -376,6 +386,9 @@ local function process(process_opts, console_opts)
local chr_size = console_opts["chr_rom_size_kb"]
local wram_size = console_opts["wram_size_kb"]
local filetype = "nes"
--local filetype = "bin"
--
--initialize device i/o for NES
dict.io("IO_RESET")
dict.io("NES_INIT")
......@@ -398,8 +411,11 @@ local function process(process_opts, console_opts)
file = assert(io.open(dumpfile, "wb"))
--create header: pass open & empty file & rom sizes
create_header(file, prg_size, chr_size)
--dump cart into file
dump_prgrom(file, prg_size, false)
dump_prgrom(file, prg_size, true)
dump_chrrom(file, chr_size, true)
--close file
......@@ -470,6 +486,23 @@ local function process(process_opts, console_opts)
--open file
file = assert(io.open(flashfile, "rb"))
if filetype == "nes" then
--advance past the 16byte header
--TODO set mirroring bit via ciccom
local buffsize = 1
local byte
local count = 1
for byte in file:lines(buffsize) do
local data = string.unpack("B", byte, 1)
--print(string.format("%X", data))
count = count + 1
if count == 17 then break end
end
end
--flash cart
flash_prgrom(file, prg_size, false)
flash_chrrom(file, chr_size, false)
......
......@@ -6,11 +6,24 @@ local easyNSF = {}
local dict = require "scripts.app.dict"
local dump = require "scripts.app.dump"
local flash = require "scripts.app.flash"
local buffers = require "scripts.app.buffers"
local nes = require "scripts.app.nes"
-- file constants
local mapname = "EZNSF"
-- local functions
local function create_header( file, prgKB, chrKB )
local mirroring = nes.detect_mapper_mirroring()
--write_header( file, prgKB, chrKB, mapper, mirroring )
nes.write_header( file, prgKB, 0, op_buffer[mapname], mirroring)
end
--local function wr_flash_byte(addr, value, debug)
--base is the actual NES CPU address, not the rom offset (ie $FFF0, not $7FF0)
......@@ -83,7 +96,10 @@ local function process(process_opts, console_opts)
local rv = nil
local file
-- TODO: Handle variable rom sizes.
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")
......@@ -102,7 +118,9 @@ local function process(process_opts, console_opts)
file = assert(io.open(dumpfile, "wb"))
--TODO find bank table to avoid bus conflicts!
--create header: pass open & empty file & rom sizes
create_header(file, prg_size, chr_size)
--dump cart into file
dump.dumptofile( file, 1024, "EZNSF", "PRGROM", true )
......
......@@ -7,12 +7,20 @@ local dict = require "scripts.app.dict"
local nes = require "scripts.app.nes"
local dump = require "scripts.app.dump"
local flash = require "scripts.app.flash"
local buffers = require "scripts.app.buffers"
-- file constants
local mapname = "FME7"
-- local functions
local function create_header( file, prgKB, chrKB )
--write_header( file, prgKB, chrKB, mapper, mirroring )
nes.write_header( file, prgKB, chrKB, op_buffer[mapname], 0)
end
--disables WRAM, selects Vertical mirroring
--sets up CHR-ROM flash PT0 for DATA, Commands: $5555->$1555 $2AAA->$1AAA
--sets up PRG-ROM flash DATA: $8000-9FFF, Commands: $5555->D555 $2AAA->$AAAA
......@@ -600,6 +608,9 @@ local function process(process_opts, console_opts)
file = assert(io.open(dumpfile, "wb"))
--create header: pass open & empty file & rom sizes
create_header(file, prg_size, chr_size)
--dump cart into file
dump_prgrom(file, prg_size, false)
dump_chrrom(file, chr_size, false)
......
......@@ -10,12 +10,20 @@ local flash = require "scripts.app.flash"
local time = require "scripts.app.time"
local files = require "scripts.app.files"
local time = require "scripts.app.time"
local buffers = require "scripts.app.buffers"
-- file constants & variables
local mapname = "GTROM"
-- local functions
local function create_header( file, prgKB, chrKB )
--write_header( file, prgKB, chrKB, mapper, mirroring )
nes.write_header( file, prgKB, chrKB, op_buffer[mapname], 0)
end
--read PRG-ROM flash ID
local function prgrom_manf_id( debug )
......@@ -233,8 +241,10 @@ local function process(process_opts, console_opts)
local rv = nil
local file
-- TODO: Cleanup needed here, support chrrom, make this look more like other mapper scripts.
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"]
--local filetype = "nes"
local filetype = "bin"
......@@ -266,6 +276,9 @@ local function process(process_opts, console_opts)
print("\nDumping PRG-ROM...")
file = assert(io.open(dumpfile, "wb"))
--create header: pass open & empty file & rom sizes
create_header(file, prg_size, chr_size)
--dump cart into file
time.start()
dump_prgrom(file, prg_size, false)
......
......@@ -8,11 +8,21 @@ local nes = require "scripts.app.nes"
local dump = require "scripts.app.dump"
local flash = require "scripts.app.flash"
local time = require "scripts.app.time"
local buffers = require "scripts.app.buffers"
-- file constants
local mapname = "MAP30"
-- local functions
local function create_header( file, prgKB, chrKB )
local mirroring = nes.detect_mapper_mirroring()
--write_header( file, prgKB, chrKB, mapper, mirroring )
nes.write_header( file, prgKB, 0, op_buffer[mapname], mirroring)
end
--read PRG-ROM flash ID
local function prgrom_manf_id( debug )
......@@ -61,7 +71,10 @@ local function process(process_opts, console_opts)
local rv = nil
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 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"]
local filetype = "nes"
--local filetype = "bin"
......@@ -89,6 +102,7 @@ local function process(process_opts, console_opts)
dict.nes("NES_PPU_WR", 0x0000, 0x33)
--read back
---[[
local test = true
dict.nes("NES_CPU_WR", 0xC000, 0x00) --CHR bank 0
rv = dict.nes("NES_PPU_RD", 0x0000)
......@@ -122,6 +136,7 @@ local function process(process_opts, console_opts)
if test then
print("CHR-RAM BANKING TEST PASSED")
end
--]]
end
......@@ -130,8 +145,11 @@ local function process(process_opts, console_opts)
if read then
file = assert(io.open(dumpfile, "wb"))
--create header: pass open & empty file & rom sizes
create_header(file, prg_size, chr_size)
--dump cart into file
dump.dumptofile( file, size, "MAP30", "PRGROM", true )
dump.dumptofile( file, prg_size, "MAP30", "PRGROM", true )
--close file
assert(file:close())
......@@ -206,8 +224,8 @@ local function process(process_opts, console_opts)
--flash cart
print("\nFLASHING the PRG-ROM, will take ~20sec please wait...")
time.start()
flash.write_file( file, size, "MAP30", "PRGROM", false )
time.report(size)
flash.write_file( file, prg_size, "MAP30", "PRGROM", false )
time.report(prg_size)
--close file
assert(file:close())
......@@ -220,7 +238,7 @@ local function process(process_opts, console_opts)
file = assert(io.open(verifyfile, "wb"))
--dump cart into file
dump.dumptofile( file, size, "MAP30", "PRGROM", true )
dump.dumptofile( file, prg_size, "MAP30", "PRGROM", true )
--close file
assert(file:close())
......
......@@ -13,12 +13,22 @@ local ciccom = require "scripts.app.ciccom"
local time = require "scripts.app.time"
local swim = require "scripts.app.swim"
local mapper30_legacy = require "scripts.nes.mapper30"
local buffers = require "scripts.app.buffers"
-- file constants & variables
local mapname = "MAP30"
-- local functions
local function create_header( file, prgKB, chrKB )
local mirroring = nes.detect_mapper_mirroring()
--write_header( file, prgKB, chrKB, mapper, mirroring )
nes.write_header( file, prgKB, 0, op_buffer[mapname], mirroring)
end
--read PRG-ROM flash ID
local function prgrom_manf_id( debug )
......@@ -426,9 +436,12 @@ local function process(process_opts, console_opts)
local file
-- TODO: Cleanup needed here, support chrrom, make this look more like other mapper scripts.
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"]
local filetype = "nes"
--local filetype = "bin"
--local filetype = "nes"
local filetype = "bin"
if is_old_firmware(true) then
--call legacy mapper30 script
......@@ -458,13 +471,13 @@ local function process(process_opts, console_opts)
if not rv then return end
--test CHR-RAM
--rv = exercise_chrram()
rv = exercise_chrram()
--exit script if test fails
--if not rv then return end
if not rv then return end
--test software mirroring switch