Compare commits

...

10 Commits

Author SHA1 Message Date
Zorchenhimer 83894d3097
StudyBox host script
This script is from January 2022.  IIRC, it was used for verifying
hardware properties.  Not sure if this script currently works.
2025-11-18 23:10:32 -05:00
Paul Molloy 7f21176c2f Merge branch 'master' into 'master'
Added SNES SuperFX hardware type and fixed save ram header issue with Super Mario World 2: Yoshi's Island and Stunt Race FX

Closes #58 and #35

See merge request InfiniteNesLives/INL-retro-progdump!30
2020-06-13 22:21:56 +00:00
Paul Molloy b08603a27b Merge branch 'master' into 'master'
Fixed off-by-one error with unrom banktables

Closes #31 and #14

See merge request InfiniteNesLives/INL-retro-progdump!33
2020-06-13 22:17:25 +00:00
Paul Molloy e0d4a92f28 Merge branch 'issue50' into 'master'
Firmware fix for MMC3 dumping issues

See merge request InfiniteNesLives/INL-retro-progdump!34
2020-06-13 22:15:40 +00:00
Every Kid Hero ce1323be4b Firmware modification where several NOPs were added to fix problematic
various CHR/PRG ROM dumping problems.
- Fix for issue 50.
- Potential fix for issue 20.
2020-06-13 22:15:40 +00:00
Joel Smith 660f7f1105 Change label to reflect Stunt Race FX 2020-06-01 20:56:46 +00:00
Max ba1d0d3619 Fix issue in inlretro.lua with missing jtag.lua library (doesn't exist in repo) 2020-05-28 08:06:19 -05:00
Max e0fc7956e8 Fixed off-by-one error with unrom banktables 2020-05-28 07:01:28 -05:00
Joel Smith 18e3e3c6a2 wording changes 2020-04-20 19:46:25 -07:00
Joel Smith 13c73053d0 Added support for SNES save ram length from Expansion Ram Header (if valid) fixes issues with SMW 2: Yoshi's Island and Stunt Race FX 2020-04-20 19:21:25 -07:00
6 changed files with 763 additions and 13 deletions

View File

@ -918,6 +918,7 @@ uint8_t nes_cpu_page_rd_toggle( uint8_t *data, uint8_t addrH, uint8_t first, uin
NOP();
NOP();
NOP();
NOP(); // EKH: Needed one more NOP for MMC3 PRG ROM
//latch data
DATA_RD(data[i]);
@ -967,12 +968,14 @@ uint8_t nes_ppu_page_rd_poll( uint8_t *data, uint8_t addrH, uint8_t first, uint8
ADDRL(first); //doing this prior to entry and right after latching
NOP(); //adding extra NOP as it was needed on PRG
//gives longest delay between address out and latching data
NOP(); // EKH: Needed another NOP for the first byte of 4k blocks on several MMC3 carts
for( i=0; i<=len; i++ ) {
//couple more NOP's waiting for data
if ( poll == FALSE ) {
NOP(); //one prob good enough considering the if/else
NOP();
NOP(); // EKH: Needed another one for several MMC3 carts
} else {
usbPoll();
}

View File

@ -48,7 +48,6 @@ function main ()
local erase = require "scripts.app.erase"
local flash = require "scripts.app.flash"
local swim = require "scripts.app.swim"
local jtag = require "scripts.app.jtag"
local ciccom = require "scripts.app.ciccom"
local fwupdate = require "scripts.app.fwupdate"
local files = require "scripts.app.files"

View File

@ -0,0 +1,720 @@
math.randomseed(os.time())
-- create the module's table
local studybox = {}
-- 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 = "SBX"
-- 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)
--local function wr_bank_table(base, entries)
--Action53 not susceptible to bus conflicts, no banktable needed
local function sb_write_string(start_addr, value, log)
value = string.format("'%s' starting at $%04X", value, start_addr)
print(string.format("Writing %s starting at address $%04X\n", value, start_addr))
for i = 1, #value do
local c = value:sub(i,i)
dict.nes("NES_CPU_WR", start_addr + (i - 1), string.byte(c))
end
end
local function sb_write_and_verify(start_addr, stop_addr, value, log)
log:write(string.format("Writing $%X from address $%X to $%X\n", value, start_addr, stop_addr))
addr = start_addr
while (addr < stop_addr) do
dict.nes("NES_CPU_WR", addr, value)
addr = addr + 1
end
log:write("Verifying data\n")
addr = start_addr
while(addr < stop_addr) do
rv = dict.nes("NES_CPU_RD", addr)
if rv ~= value then
log:write(string.format("$%X not $%X\n", addr, value))
end
addr = addr + 1
end
end
-- Write and verify random values in RAM
local function sb_random_ram(start_addr, stop_addr, log)
log:write(string.format("\nStarting random ram test from address $%04X to address $%04X\n", start_addr, stop_addr))
values = {}
for i = 0, (stop_addr - start_addr) do
val = math.random(0, 255)
values[i] = val
dict.nes("NES_CPU_WR", start_addr + i, val)
end
for i = 0, (stop_addr - start_addr) do
rv = dict.nes("NES_CPU_RD", start_addr + i)
if rv ~= values[i] then
log:write(string.format("$%04X: expected $%02X received $%02X\n", start_addr + i, values[i], rv))
end
end
end
local function sb_write_ram(start_addr, stop_addr, value)
print(string.format("Writing $%02X from $%04X to $%04X", value, start_addr, stop_addr))
while (start_addr < stop_addr) do
dict.nes("NES_CPU_WR", start_addr, value)
start_addr = start_addr + 1
end
end
local function sb_verify_value_ram(start_addr, stop_addr, value, log)
print(string.format("Verifying $%02X from $%04X to $%04X", value, start_addr, stop_addr))
while (start_addr < stop_addr) do
rv = dict.nes("NES_CPU_RD", start_addr)
if rv ~= value then
log:write(string.format("$%04X: expected $%02X received $%02X\n", start_addr, value, rv))
end
start_addr = start_addr + 1
end
end
local function sb_ram_dump(start_addr, stop_addr, filename)
file = io.open(filename, "wb")
while (start_addr < stop_addr) do
rv = dict.nes("NES_CPU_RD", start_addr)
file:write(string.char(rv))
start_addr = start_addr + 1
end
file:flush()
file:close()
end
-- Write data to ram and read it back
local function sb_verify_ram()
logfile = io.open("studybox.log", "w")
print("Starting sb_verify_ram()")
--print("Write/Verify $00")
--sb_write_and_verify(0x4020, 0x8000, 0x00, logfile)
--print("Write/Verify $88")
--sb_write_and_verify(0x4020, 0x8000, 0x88, logfile)
--print("Write/Verify $FF")
--sb_write_and_verify(0x4020, 0x8000, 0xFF, logfile)
--print("Write/Verify random")
--sb_random_ram(0x4020, 0x8000, logfile)
-- Select first bank
--sprint("\n$4200 value of $00")
--dict.nes("NES_CPU_WR", 0x4200, 0x00)
--val = math.random(0, 255)
--sb_write_ram(0x5000, 0x5FFF, val)
--sb_verify_value_ram(0x4400, 0x8000, val, logfile)
--sprint("\n$4200 value of $01")
--sdict.nes("NES_CPU_WR", 0x4200, 0x01)
--sval = math.random(0, 255)
--ssb_write_ram(0x5000, 0x5FFF, val)
--ssb_verify_value_ram(0x4400, 0x8000, val, logfile)
--sprint("\n$4200 value of $00 verify")
--sdict.nes("NES_CPU_WR", 0x4200, 0x00)
--ssb_verify_value_ram(0x4400, 0x5FFF, val, logfile)
--print("\n$4200 value of $00")
--dict.nes("NES_CPU_WR", 0x4200, 0x00)
--val = math.random(0, 255)
--sb_write_ram(0x6000, 0x8000, val)
--sb_verify_value_ram(0x6000, 0x8000, val, logfile)
--logfile:write("\n==== Second verify with $4200 value $40 ====\n")
--print("\n$4200 value of $40")
--dict.nes("NES_CPU_WR", 0x4200, 0x40)
--sb_verify_value_ram(0x6000, 0x8000, val, logfile)
print("Clearing ram")
sb_write_ram(0x4400, 0x8000, 0x00)
--41 b01000001
--82 b10000010
--82 b11000011
dict.nes("NES_CPU_WR", 0x4200, 0x41)
sb_write_ram(0x4400, 0x8000, 0x00)
dict.nes("NES_CPU_WR", 0x4200, 0x82)
sb_write_ram(0x4400, 0x8000, 0x00)
dict.nes("NES_CPU_WR", 0x4200, 0xC3)
sb_write_ram(0x4400, 0x8000, 0x00)
print("Writing strings")
dict.nes("NES_CPU_WR", 0x4200, 0x00)
sb_write_string(0x5400, "|< page $00 >|")
sb_write_string(0x6000, "|< page $00 >|")
dict.nes("NES_CPU_WR", 0x4200, 0x41)
sb_write_string(0x5000, "|< page $01 >|")
sb_write_string(0x6000, "|< page $01 >|")
dict.nes("NES_CPU_WR", 0x4200, 0x82)
sb_write_string(0x5000, "|< page $02 >|")
sb_write_string(0x6000, "|< page $02 >|")
dict.nes("NES_CPU_WR", 0x4200, 0xC3)
sb_write_string(0x5000, "|< page $03 >|")
sb_write_string(0x6000, "|< page $03 >|")
--sb_write_string(0x5000, "|< page $00 at $5000 >|")
print("dumping 4200_00.dmp")
dict.nes("NES_CPU_WR", 0x4200, 0x00)
sb_ram_dump(0x4400, 0x8000, "4200_00.dmp")
print("dumping 4200_01.dmp")
dict.nes("NES_CPU_WR", 0x4200, 0x01)
sb_ram_dump(0x4400, 0x8000, "4200_01.dmp")
print("dumping 4200_01.dmp")
dict.nes("NES_CPU_WR", 0x4200, 0x01)
sb_ram_dump(0x4400, 0x8000, "4200_01.dmp")
--print("\n$4200 value of $01")
--dict.nes("NES_CPU_WR", 0x4200, 0x01)
--sb_ram_dump(0x4400, 0x8000, "4200_01.dmp")
--print("\n$4200 value of $02")
--dict.nes("NES_CPU_WR", 0x4200, 0x02)
--sb_ram_dump(0x4400, 0x8000, "4200_02.dmp")
--print("\n$4200 value of $03")
--dict.nes("NES_CPU_WR", 0x4200, 0x03)
--sb_ram_dump(0x4400, 0x8000, "4200_03.dmp")
--print("\n$4200 value of $40")
--dict.nes("NES_CPU_WR", 0x4200, 0x40)
--sb_ram_dump(0x4400, 0x8000, "4200_40.dmp")
--print("\n$4200 value of $80")
--dict.nes("NES_CPU_WR", 0x4200, 0x80)
--sb_ram_dump(0x4400, 0x8000, "4200_80.dmp")
--print("\n$4200 value of $C0")
--dict.nes("NES_CPU_WR", 0x4200, 0x80)
--sb_ram_dump(0x4400, 0x8000, "4200_C0.dmp")
logfile:flush()
logfile:close()
end
--initialize mapper for dump/flash routines
local function init_mapper( debug )
--//Setup as CNROM, then scroll through outer banks.
--cpu_wr(0x5000, 0x80); //reg select mode
--dict.nes("NES_CPU_WR", 0x5000, 0x80)
--// xxSSPPMM SS-size: 0-32KB, PP-prg mode: 0,1 32KB, MM-mirror
--cpu_wr(0x8000, 0b00000000); //reg value 256KB inner, 32KB banks
--dict.nes("NES_CPU_WR", 0x8000, 0x00)
--cpu_wr(0x5000, 0x81); //outer reg select mode
--dict.nes("NES_CPU_WR", 0x5000, 0x81)
--cpu_wr(0x8000, 0x00); //first 32KB bank
--dict.nes("NES_CPU_WR", 0x8000, 0x00)
--
--cpu_wr(0x5000, 0x01); //inner prg reg select
--dict.nes("NES_CPU_WR", 0x5000, 0x01)
--cpu_wr(0x8000, 0x00); //controls nothing in this size
--dict.nes("NES_CPU_WR", 0x8000, 0x00)
--cpu_wr(0x5000, 0x00); //chr reg select
--dict.nes("NES_CPU_WR", 0x5000, 0x00)
--cpu_wr(0x8000, 0x00); //first chr bank
--dict.nes("NES_CPU_WR", 0x8000, 0x00)
--selecting CNROM means that mapper writes to $8000-FFFF will only change the CHR-RAM bank which
--doesn't affect anything we're concerned about
end
local function sb_dump_rom()
file = io.open("prg.dat", "wb")
for i = 0x00,0x0F,1 do
print(string.format("$4201: %02X", i))
dict.nes("NES_CPU_WR", 0x4201, i)
start_addr = 0x8000
stop_addr = 0xC000
while (start_addr < stop_addr) do
rv = dict.nes("NES_CPU_RD", start_addr)
file:write(string.char(rv))
start_addr = start_addr + 1
end
--sb_ram_dump(0x8000, 0xC000, string.format("raw/prg_8000_%02X.dat", i))
end
file:flush()
file:close()
--dict.nes("NES_CPU_WR", 0x4201, 0x00)
--sb_ram_dump(0x8000, 0xC000, "prg_8000_00.dat")
--sb_ram_dump(0xC000, 0x10000, "prg_C000_00.dat")
--dict.nes("NES_CPU_WR", 0x4201, 0x01)
--sb_ram_dump(0x8000, 0xC000, "prg_8000_01.dat")
--sb_ram_dump(0xC000, 0x10000, "prg_C000_01.dat")
--dict.nes("NES_CPU_WR", 0x4201, 0x02)
--sb_ram_dump(0x8000, 0xC000, "prg_8000_02.dat")
--sb_ram_dump(0xC000, 0x10000, "prg_C000_02.dat")
--dict.nes("NES_CPU_WR", 0x4201, 0x03)
--sb_ram_dump(0x8000, 0xC000, "prg_8000_03.dat")
--sb_ram_dump(0xC000, 0x10000, "prg_C000_03.dat")
end
local function sb_write_save()
print("Clearing ram")
dict.nes("NES_CPU_WR", 0x4200, 0x00)
sb_write_ram(0x600, 0x8000, 0x00)
sb_write_string(0x5400, "|< page $00 >|")
sb_write_string(0x6000, "|< page $00 >|")
end
local function sb_dump_save()
print("Dumping ram")
dict.nes("NES_CPU_WR", 0x4200, 0x00)
sb_ram_dump(0x4400, 0x8000, "raw/ram.dat")
end
local function sb_read_registers()
data = dict.nes("NES_CPU_RD", 0x4202)
print(string.format("$4202: $%02X", data))
end
--read PRG-ROM flash ID
local function prgrom_manf_id( debug )
init_mapper()
if debug then print("reading PRG-ROM manf ID") end
--A0-A14 are all directly addressable in CNROM mode
--and mapper writes don't affect PRG banking
dict.nes("NES_CPU_WR", 0xD555, 0xAA)
dict.nes("NES_CPU_WR", 0xAAAA, 0x55)
dict.nes("NES_CPU_WR", 0xD555, 0x90)
rv = dict.nes("NES_CPU_RD", 0x8000)
if debug then print("attempted read PRG-ROM manf ID:", string.format("%X", rv)) end
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("NES_CPU_WR", 0x8000, 0xF0)
end
local function mirror_test( debug )
init_mapper()
end
local function bank0(bank)
dict.nes("NES_CPU_WR", 0x4201, bank)
print("selecting bank: ", bank)
--rv = dict.nes("NES_CPU_RD", 0x8000)
--if debug then print("attempted read PRG-ROM $8000:", string.format("%X", rv)) end
--rv = dict.nes("NES_CPU_RD", 0x8001)
--if debug then print("attempted read PRG-ROM $8001:", string.format("%X", rv)) end
end
local function sb_write_ppu_string(start_addr, value)
value = string.format("'%s' starting at $%04X", value, start_addr)
print(string.format("Writing %s starting at address $%04X\n", value, start_addr))
for i = 1, #value do
local c = value:sub(i,i)
dict.nes("NES_PPU_WR", start_addr + (i - 1), string.byte(c))
end
end
local function sb_ppu_test()
dict.nes("NES_CPU_WR", 0x4200, 0x00)
dict.nes("NES_CPU_WR", 0x4201, 0x00)
dict.nes("NES_CPU_WR", 0x4203, 0x00)
print("Clearing ppu ram")
for i=0x0000,0x2FFF,1 do
dict.nes("NES_PPU_WR", i, 0x00)
end
sb_write_ppu_string(0x0000, "|< chr page $00 >|")
print("Writing nametable 1")
for i=0x2000,0x23FF,1 do
dict.nes("NES_PPU_WR", i, 0x01)
end
print("Writing nametable 2")
for i=0x2400,0x27FF,1 do
dict.nes("NES_PPU_WR", i, 0x02)
end
print("Writing nametable 3")
for i=0x2800,0x2BFF,1 do
dict.nes("NES_PPU_WR", i, 0x03)
end
print("Writing nametable 4")
for i=0x2C00,0x2FFF,1 do
dict.nes("NES_PPU_WR", i, 0x04)
end
print("dumping ppu ram")
dict.nes("NES_CPU_WR", 0x4200, 0xFF)
dict.nes("NES_CPU_WR", 0x4201, 0xFF)
dict.nes("NES_CPU_WR", 0x4203, 0xFF)
file = io.open("raw/ppu.dat", "wb")
for i=0x0000,0x2FFF,1 do
val = dict.nes("NES_PPU_RD", i)
file:write(string.char(val))
end
file:flush()
file:close()
end
local function sb_ppu_high_ram_test()
print("Testing PPU RAM $3000-$3FFF")
file = io.open("raw/ppu_high_init.dmp", "wb")
for i=0x3000,0x3FFF,1 do
val = dict.nes("NES_PPU_RD", i)
file:write(string.char(val))
end
file:flush()
file:close()
print("writing $B1")
for i=0x3000,0x3FFF,1 do
dict.nes("NES_PPU_WR", i, 0xB1)
end
print("dump 2")
file = io.open("raw/ppu_high_post.dmp", "wb")
for i=0x3000,0x3FFF,1 do
val = dict.nes("NES_PPU_RD", i)
file:write(string.char(val))
end
file:flush()
file:close()
print("dump ppu main")
file = io.open("raw/ppu_main.dmp", "wb")
for i=0x0000,0x2FFF,1 do
val = dict.nes("NES_PPU_RD", i)
file:write(string.char(val))
end
file:flush()
file:close()
end
-- Test CPU vs PPU ram
local function sb_ram_full_test()
--print("Clearing ram")
--sb_write_ram(0x4400, 0x8000, 0x00)
--dict.nes("NES_CPU_WR", 0x4200, 0x41)
--sb_write_ram(0x4400, 0x8000, 0x00)
--dict.nes("NES_CPU_WR", 0x4200, 0x82)
--sb_write_ram(0x4400, 0x8000, 0x00)
--dict.nes("NES_CPU_WR", 0x4200, 0xC3)
--sb_write_ram(0x4400, 0x8000, 0x00)
--dict.nes("NES_CPU_WR", 0x4200, 0x00)
--dict.nes("NES_CPU_WR", 0x4201, 0x00)
--dict.nes("NES_CPU_WR", 0x4203, 0x00)
--print("Clearing ppu ram")
--for i=0x0000,0x2FFF,1 do
-- dict.nes("NES_PPU_WR", i, 0x00)
--end
print("Writing values")
-- Only using 0x6000-0x7FFF here because it's
-- the same memory as the first block
dict.nes("NES_CPU_WR", 0x4200, 0x00)
sb_write_ram(0x6000, 0x7FFF, 01)
dict.nes("NES_CPU_WR", 0x4200, 0x40)
sb_write_ram(0x6000, 0x7FFF, 02)
dict.nes("NES_CPU_WR", 0x4200, 0x80)
sb_write_ram(0x6000, 0x7FFF, 03)
dict.nes("NES_CPU_WR", 0x4200, 0xC0)
sb_write_ram(0x6000, 0x7FFF, 04)
--print("Clearing ppu ram")
--for i=0x0000,0x2FFF,1 do
-- dict.nes("NES_PPU_WR", i, 0x00)
--end
-- print("Writing values")
print("Writing nametable 1")
for i=0x2000,0x23FF,1 do
dict.nes("NES_PPU_WR", i, 0xA1)
end
print("Writing nametable 2")
for i=0x2400,0x27FF,1 do
dict.nes("NES_PPU_WR", i, 0xA2)
end
print("Writing nametable 3")
for i=0x2800,0x2BFF,1 do
dict.nes("NES_PPU_WR", i, 0xA3)
end
print("Writing nametable 4")
for i=0x2C00,0x2FFF,1 do
dict.nes("NES_PPU_WR", i, 0xA4)
end
print("writing CHR at 0x0000")
for i=0x0000,0x0FFF,1 do
dict.nes("NES_PPU_WR", i, 0xA5)
end
print("writing CHR at 0x1000")
for i=0x1000,0x1FFF,1 do
dict.nes("NES_PPU_WR", i, 0xA6)
end
print("dumping ppu ram")
--dict.nes("NES_CPU_WR", 0x4200, 0xFF)
--dict.nes("NES_CPU_WR", 0x4201, 0xFF)
--dict.nes("NES_CPU_WR", 0x4203, 0xFF)
file = io.open("raw/cpu-ppu.dmp", "wb")
for i=0x0000,0x2FFF,1 do
val = dict.nes("NES_PPU_RD", i)
file:write(string.char(val))
end
file:flush()
file:close()
print("dumping 4200_00.dmp")
dict.nes("NES_CPU_WR", 0x4200, 0x00)
sb_ram_dump(0x6000, 0x7FFF, "raw/ppu-cpu_4200_00.dmp")
print("dumping 4200_40.dmp")
dict.nes("NES_CPU_WR", 0x4200, 0x40)
sb_ram_dump(0x6000, 0x7FFF, "raw/ppu-cpu_4200_40.dmp")
print("dumping 4200_80.dmp")
dict.nes("NES_CPU_WR", 0x4200, 0x80)
sb_ram_dump(0x6000, 0x7FFF, "raw/ppu-cpu_4200_80.dmp")
print("dumping 4200_C0.dmp")
dict.nes("NES_CPU_WR", 0x4200, 0xC0)
sb_ram_dump(0x6000, 0x7FFF, "raw/ppu-cpu_4200_C0.dmp")
end
local function check_ppu_mirror(a, b)
vala = dict.nes("NES_PPU_RD", 0x2800)
valb = dict.nes("NES_PPU_RD", 0x2C00)
if vala ~= a then
print(string.format("value at $2000 changed to %02X! [%02X]", vala, i & 0x3C))
end
if valb ~= b then
print(string.format("value at $2400 changed to %02X! [%02X]", valb, i & 0x3C))
end
end
local function sb_mirror_test()
dict.nes("NES_PPU_WR", 0x2800, 0xA1)
dict.nes("NES_PPU_WR", 0x2C00, 0xA2)
print("checking $4200")
for i=0xC4,0xFF,4 do
--print(string.format(" %02X", i))
dict.nes("NES_CPU_WR", 0x4200, i)
vala = dict.nes("NES_PPU_RD", 0x2800)
valb = dict.nes("NES_PPU_RD", 0x2C00)
if vala ~= 0xA1 then
print(string.format("value at $2000 changed to %02X! [%02X]", vala, i & 0x3C))
end
if valb ~= 0xA2 then
print(string.format("value at $2400 changed to %02X! [%02X]", valb, i & 0x3C))
end
end
print("checking $4201")
for i=0x00,0xF0,0x10 do
--print(string.format(" %02X", i))
dict.nes("NES_CPU_WR", 0x4201, i)
vala = dict.nes("NES_PPU_RD", 0x2800)
valb = dict.nes("NES_PPU_RD", 0x2C00)
if vala ~= 0xA1 then
print(string.format("value at $2000 changed to %02X! [%02X]", vala, i & 0x3C))
end
if valb ~= 0xA2 then
print(string.format("value at $2400 changed to %02X! [%02X]", valb, i & 0x3C))
end
end
print("checking $4202")
dict.nes("NES_CPU_WR", 0x4202, 0x40)
check_ppu_mirror(0xA1, 0xA2)
dict.nes("NES_CPU_WR", 0x4202, 0x08)
check_ppu_mirror(0xA1, 0xA2)
print("checking $4203")
for i=0x00,0xFF,0x01 do
--print(string.format(" %02X", i))
dict.nes("NES_CPU_WR", 0x4203, i)
vala = dict.nes("NES_PPU_RD", 0x2800)
valb = dict.nes("NES_PPU_RD", 0x2C00)
if vala ~= 0xA1 then
print(string.format("value at $2000 changed to %02X! [%02X]", vala, i & 0x3C))
end
if valb ~= 0xA2 then
print(string.format("value at $2400 changed to %02X! [%02X]", valb, i & 0x3C))
end
end
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(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 = 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")
dict.io("NES_INIT")
mirror_test(true)
--test cart by reading manf/prod ID
if test then
prgrom_manf_id(true)
end
--sb_verify_ram()
--sb_read_registers()
--sb_dump_rom()
--sb_write_save()
--sb_dump_save()
--sb_ppu_test()
--sb_ram_full_test()
--sb_ppu_high_ram_test()
sb_mirror_test()
dict.io("IO_RESET")
do return end
-- Poke some registers
init_mapper(debug)
dict.nes("NES_CPU_WR", 0x4202, 0x20)
--for i=0, 8, 1 do
-- dict.nes("NES_CPU_WR", 0x4202, 0x10)
-- rv = dict.nes("NES_CPU_RD", 0x4201)
-- print(i, "initial read:", string.format("$%02X", rv))
-- while (rv & 0x40 == 0) do
-- rv = dict.nes("NES_CPU_RD", 0x4201)
-- io.write(".")
-- end
-- print("")
--end
--dump the cart to dumpfile
read = false
if read then
print("Attempting to read StudyBox stuff")
--initialize the mapper for dumping
init_mapper(debug)
rv = dict.nes("NES_CPU_RD", 0x4200)
print("$4200:", string.format("$%X", rv))
rv = dict.nes("NES_CPU_RD", 0x4201)
print("$4201:", string.format("$%X", rv))
rv = dict.nes("NES_CPU_RD", 0x4202)
print("$4202:", string.format("$%X", rv))
rv = dict.nes("NES_CPU_RD", 0x4203)
print("$4203:", string.format("$%X", rv))
file = assert(io.open(dumpfile, "wb"))
--create header: pass open & empty file & rom sizes
--create_header(file, prg_size, chr_size)
for bank=0, 16, 1 do
dict.nes("NES_CPU_WR", 0x4201, bank)
print("dumping bank: ", bank)
rv = dict.nes("NES_CPU_RD", 0x4201)
print("$4201:", string.format("$%X", rv))
--dump cart into file
dump.dumptofile( file, prg_size, "186", "PRGROM", true )
end
--close file
assert(file:close())
end
--verify flashfile is on the cart
verify = false
if verify then
--for now let's just dump the file and verify manually
--initialize the mapper for dumping
init_mapper(debug)
file = assert(io.open(verifyfile, "wb"))
--dump cart into file
dump.dumptofile( file, 512, "A53", "PRGROM", true )
--close file
assert(file:close())
end
dict.io("IO_RESET")
end
-- global variables so other modules can use them
-- call functions desired to run when script is called/imported
-- functions other modules are able to call
studybox.process = process
-- return the module's table
return studybox

View File

@ -12,8 +12,10 @@ local buffers = require "scripts.app.buffers"
-- file constants & variables
local mapname = "UxROM"
--local banktable_base = nil
local banktable_base = 0xE473
local banktable_base = nil
-- banktable detection should work now,
-- these curated addresses are probably no longer needed.
--local banktable_base = 0xE473
--Nomolos' bank table is at $CC84
--wr_bank_table(0xCC84, 32)
--Owlia bank table
@ -112,13 +114,14 @@ end
--dump the PRG ROM
local function dump_prgrom( file, rom_size_KB, debug )
local KB_per_read = 16
local num_reads = rom_size_KB / KB_per_read
local read_count = 0
local addr_base = 0x08 -- $8000
local fixed_bank_base = 0x0C -- search in $C000-$F000, the fixed bank
while ( read_count < num_reads ) do
-- Dump all banks except last/fixed bank.
while ( read_count < num_reads - 1) do
if debug then print( "dump PRG part ", read_count, " of ", num_reads) end
@ -130,6 +133,10 @@ local function dump_prgrom( file, rom_size_KB, debug )
read_count = read_count + 1
end
-- Write fixed bank
if debug then print( "dump PRG part ", read_count, " of ", num_reads) end
dump.dumptofile( file, KB_per_read, fixed_bank_base, "NESCPU_4KB", false )
end
@ -331,7 +338,9 @@ local function process(process_opts, console_opts)
--find bank table to avoid bus conflicts
if ( banktable_base == nil ) then
local KB_per_bank = 16
banktable_base = find_banktable( prg_size / KB_per_bank )
-- Size is one byte smaller because table doesn't need fixed bank.
local banktable_size = prg_size / KB_per_bank - 1
banktable_base = find_banktable(banktable_size)
if ( banktable_base == nil ) then
print( "BANKTABLE NOT FOUND" )
return
@ -344,7 +353,6 @@ local function process(process_opts, console_opts)
create_header(file, prg_size, chr_size)
--dump cart into file
--dump.dumptofile( file, prg_size, "UxROM", "PRGROM", true )
dump_prgrom(file, prg_size, false)
--close file

View File

@ -1,4 +1,3 @@
-- create the module's table
local v2proto = {}
@ -26,7 +25,7 @@ local hardware_type = {
[0x03] = "ROM and DSP1",
[0x13] = "ROM and SuperFX",
[0x15] = "ROM and SuperFX and Save RAM",
[0x1A] = "ROM and SuperFX and Save RAM",
[0x1A] = "ROM and SuperFX and Save RAM (Stunt Race FX)",
[0x23] = "ROM and OBC1",
[0x33] = "ROM and SA-1",
[0x43] = "ROM and S-DD1",
@ -65,7 +64,7 @@ local rom_size_kb_tbl = {
}
local ram_size_tbl = {
[0x00] = "No sram",
[0x00] = "None",
[0x01] = "16 kilobits",
[0x02] = "32 kilobits",
[0x03] = "64 kilobits",
@ -308,6 +307,9 @@ function print_header(internal_header)
local sram_size_str = "UNKNOWN - " .. hexfmt(internal_header["sram_size"])
if ram_size_tbl[internal_header["sram_size"]] then sram_size_str = ram_size_tbl[internal_header["sram_size"]] end
local exp_size_str = "UNKNOWN - " .. hexfmt(internal_header["exp_ram_size"])
if ram_size_tbl[internal_header["exp_ram_size"]] then exp_size_str = ram_size_tbl[internal_header["exp_ram_size"]] end
local destination_code_str = "UNKNOWN - " .. hexfmt(internal_header["destination_code"])
if destination_code[internal_header["destination_code"]] then
destination_code_str = destination_code[internal_header["destination_code"]]
@ -323,6 +325,7 @@ function print_header(internal_header)
print("Hardware Type:\t\t" .. rom_type_str)
print("Rom Size Upper Bound:\t" .. rom_size_str)
print("SRAM Size:\t\t" .. sram_size_str)
print("Expansion RAM Size:\t" .. exp_size_str)
print("Destination Code:\t" .. destination_code_str)
print("Developer:\t\t" .. developer_code_str)
print("Version:\t\t" .. hexfmt(internal_header["version"]))
@ -357,6 +360,7 @@ function get_header(map_adjust)
rom_type = dict.snes("SNES_ROM_RD", addr_rom_type),
rom_size = dict.snes("SNES_ROM_RD", addr_rom_size),
sram_size = dict.snes("SNES_ROM_RD", addr_sram_size),
exp_ram_size = dict.snes("SNES_ROM_RD", addr_expansion_ram_size),
destination_code = dict.snes("SNES_ROM_RD", addr_destination_code),
developer_code = dict.snes("SNES_ROM_RD", addr_developer_code),
version = dict.snes("SNES_ROM_RD", addr_version),
@ -876,10 +880,26 @@ local function process(process_opts, console_opts)
end
end
-- Autodetect missing ram size
if (ram_size == 0) or (ram_size == nil) then
ram_size = ram_size_kb_tbl[internal_header["sram_size"]]
assert(ram_size, "SRAM Size unknown and not provided, please add ram size to console_opts")
print("SRAM Size not provided, " .. ram_size_tbl[internal_header["sram_size"]] .. " detected.")
sram_table = ram_size_kb_tbl[internal_header["sram_size"]]
exp_ram_table = ram_size_kb_tbl[internal_header["exp_ram_size"]]
-- Some titles (Yoshi's Story, Stunt Race FX) use expansion ram header value
-- ram_size will use sram value unless a valid size is found in expansion ram header
if (sram_table == 0) or (sram_table == nil) then
if exp_ram_table == nil then
ram_size = sram_table
else
ram_size = exp_ram_table
end
else
ram_size = sram_table
end
assert(ram_size, "Save RAM Size unknown and not provided, please add ram size to console_opts")
print("Save RAM Size not provided, " .. ram_size .. " kilobytes detected.")
end
if (rom_size == 0) or (rom_size == nil) then