Successful detection of UNROM512 mapper30 PRG-ROM flash
Processing input args to create rom file when dumping Adding create_rom function in file.c working but need to add check if file already exists Listing out number of mappers which planning to support
This commit is contained in:
parent
a89caf2454
commit
dff396a1c2
Binary file not shown.
|
|
@ -158,7 +158,7 @@ int detect_mirroring( cartridge *cart, USBtransfer *transfer )
|
|||
//detecting mapper and memories ends up being one big operation
|
||||
int detect_map_mem( cartridge *cart, USBtransfer *transfer, int oper )
|
||||
{
|
||||
debug("detecting mapping");
|
||||
//debug("detecting mapping");
|
||||
//always start with resetting i/o
|
||||
io_reset( transfer );
|
||||
|
||||
|
|
@ -176,7 +176,7 @@ int detect_map_mem( cartridge *cart, USBtransfer *transfer, int oper )
|
|||
case FC_CART:
|
||||
case NES_CART:
|
||||
nes_init(transfer);
|
||||
debug("NES cart mapping");
|
||||
//debug("NES cart mapping");
|
||||
//gather other helpful info
|
||||
|
||||
//result of chr-ram test
|
||||
|
|
@ -184,57 +184,69 @@ int detect_map_mem( cartridge *cart, USBtransfer *transfer, int oper )
|
|||
debug("CHR-RAM detected @ PPU $0000");
|
||||
cart->sec_rom->manf = SRAM;
|
||||
cart->sec_rom->part = SRAM;
|
||||
} else
|
||||
//check for CHR-ROM flash
|
||||
}
|
||||
|
||||
//perform WRAM test without corrupting results
|
||||
//TODO store result in save_mem
|
||||
|
||||
//mapper select switch<<<<-------------------------------------------------------------
|
||||
switch (cart->mirroring) {
|
||||
case MIR_MMC1:
|
||||
break;
|
||||
case MIR_MMC3:
|
||||
break;
|
||||
case MIR_FIXED:
|
||||
//check for CHR-ROM flash
|
||||
if ( cart->sec_rom->part != SRAM ) {
|
||||
if ( read_flashID_chrrom_8K( transfer, cart->sec_rom ) == SUCCESS ) {
|
||||
//8KB bank with no banking operations
|
||||
debug("8K CHR-ROM flash detected");
|
||||
cart->sec_rom->size = 8 * KBYTE;
|
||||
}
|
||||
|
||||
//perform WRAM test without corrupting results
|
||||
//TODO store result in save_mem
|
||||
}
|
||||
//exp0 pullup test passes on many INL boards
|
||||
if ( exp0_pullup_test(transfer) == SUCCESS) {
|
||||
debug("EXP0 pullup cart mapping");
|
||||
//if passed exp0 test try 16/32KB bank flash check
|
||||
|
||||
//exp0 pullup test passes on many INL boards
|
||||
if ( exp0_pullup_test(transfer) == SUCCESS) {
|
||||
debug("EXP0 pullup cart mapping");
|
||||
//if passed exp0 test try 16/32KB bank flash check
|
||||
|
||||
//if 16KB banks writing 0xFF to mapper reg should set A14 bit
|
||||
//That will cause flash detection to fail.
|
||||
//TODO handle bus conflicts...?
|
||||
dictionary_call( transfer, DICT_NES, NES_CPU_WR, 0x8000, 0xFF,
|
||||
//if 16KB banks writing 0xFF to mapper reg should set A14 bit
|
||||
//That will cause flash detection to fail.
|
||||
//TODO handle bus conflicts...?
|
||||
dictionary_call( transfer, DICT_NES, NES_CPU_WR, 0x8000, 0xFF,
|
||||
USB_IN, NULL, 1);
|
||||
//if ID check passes, the should be 32KB PRG-ROM banking
|
||||
if ( read_flashID_prgrom_exp0( transfer, cart->pri_rom ) == SUCCESS ) {
|
||||
//32KB bank with EXP0->WE PRG-ROM sensed
|
||||
debug("32KB banking NES EXP0 enabled flash");
|
||||
cart->pri_rom->bank_size = 32 * KBYTE;
|
||||
} else {
|
||||
//set mapper reg to 0 if present which sets A14 low when needed if 16KB banks
|
||||
dictionary_call( transfer, DICT_NES, NES_CPU_WR, 0x8000, 0x00,
|
||||
USB_IN, NULL, 1);
|
||||
//if ID check passes, the should be 32KB PRG-ROM banking
|
||||
if ( read_flashID_prgrom_exp0( transfer, cart->pri_rom ) == SUCCESS ) {
|
||||
//32KB bank with EXP0->WE PRG-ROM sensed
|
||||
debug("32KB banking NES EXP0 enabled flash");
|
||||
cart->pri_rom->bank_size = 32 * KBYTE;
|
||||
} else {
|
||||
//set mapper reg to 0 if present which sets A14 low when needed if 16KB banks
|
||||
dictionary_call( transfer, DICT_NES, NES_CPU_WR, 0x8000, 0x00,
|
||||
USB_IN, NULL, 1);
|
||||
if ( read_flashID_prgrom_exp0( transfer, cart->pri_rom ) == SUCCESS ){
|
||||
//16KB bank with EXP0->WE PRG-ROM sensed
|
||||
debug("16KB banking NES EXP0 enabled flash");
|
||||
cart->pri_rom->bank_size = 16 * KBYTE;
|
||||
}
|
||||
if ( read_flashID_prgrom_exp0( transfer, cart->pri_rom ) == SUCCESS ){
|
||||
//16KB bank with EXP0->WE PRG-ROM sensed
|
||||
debug("16KB banking NES EXP0 enabled flash");
|
||||
cart->pri_rom->bank_size = 16 * KBYTE;
|
||||
cart->mapper = UxROM;
|
||||
}
|
||||
//TODO determine how many banks are present
|
||||
//best to do this by writing last bank, then see if
|
||||
//blank banks can be found
|
||||
}
|
||||
|
||||
switch (cart->mirroring) {
|
||||
case MIR_MMC1:
|
||||
break;
|
||||
case MIR_MMC3:
|
||||
break;
|
||||
case MIR_FIXED:
|
||||
break;
|
||||
default:
|
||||
sentinel("Problem with mapper detect mirroring switch statement.");
|
||||
}
|
||||
//TODO determine how many banks are present
|
||||
//best to do this by writing last bank, then see if
|
||||
//blank banks can be found
|
||||
}
|
||||
//check for mapper 30 controlled PRG-ROM writes
|
||||
if ( read_flashID_prgrom_map30( transfer, cart->pri_rom ) == SUCCESS ){
|
||||
debug("16KB mapper30 flash writes enabled");
|
||||
cart->pri_rom->bank_size = 16 * KBYTE;
|
||||
cart->mapper = UNROM512;
|
||||
}
|
||||
//TODO check for mapper 31 EZ-NSF
|
||||
debug("PRG-ROM manfID: %x, prodID: %x", cart->pri_rom->manf, cart->pri_rom->part);
|
||||
break;
|
||||
default:
|
||||
sentinel("Problem with mapper detect mirroring switch statement.");
|
||||
}
|
||||
//mapper select switch<<<<-------------------------------------------------------------
|
||||
break;
|
||||
//================
|
||||
// SNES
|
||||
|
|
|
|||
|
|
@ -12,8 +12,34 @@
|
|||
#define SNES_CART 'S'
|
||||
#define BKWD_CART 'B'
|
||||
|
||||
//NES mappers
|
||||
#define NROM 0
|
||||
#define MMC1 1
|
||||
#define CNROM 2
|
||||
#define UxROM 3
|
||||
#define MMC3 4
|
||||
#define MMC5 5
|
||||
#define AxROM 7
|
||||
#define MMC2 9
|
||||
#define MMC4 10
|
||||
#define CDREAMS 11
|
||||
#define A53 28
|
||||
#define UNROM512 30
|
||||
#define EZNSF 31
|
||||
#define BxROM 34
|
||||
#define RAMBO 64
|
||||
#define H3001 65 //IREM mapper
|
||||
#define GxROM 66
|
||||
#define SUN3 67
|
||||
#define SUN4 68
|
||||
#define FME7 69 //SUNSOFT-5 with synth
|
||||
#define HDIVER 78
|
||||
#define DxROM 205
|
||||
|
||||
enum mirroring {
|
||||
MIR_FIXED = 10,
|
||||
MIR_VERT,
|
||||
MIR_HORIZ,
|
||||
MIR_ANROM,
|
||||
MIR_MMC1,
|
||||
MIR_MMC3
|
||||
|
|
|
|||
|
|
@ -1,19 +1,33 @@
|
|||
#include "file.h"
|
||||
|
||||
#define SIZE_NES_HEADER 16
|
||||
#define SIZE_PRG_BANK 16384
|
||||
#define SIZE_CHR_BANK 8192
|
||||
void init_rom_elements( rom_image *rom )
|
||||
{
|
||||
rom->console = UNKNOWN;
|
||||
rom->mapper = UNKNOWN;
|
||||
rom->submap = UNKNOWN;
|
||||
rom->mapvariant = UNKNOWN;
|
||||
rom->prg_size = UNKNOWN;
|
||||
rom->chr_size = UNKNOWN;
|
||||
rom->ram_size = UNKNOWN;
|
||||
rom->battery = UNKNOWN;
|
||||
rom->mirroring = UNKNOWN;
|
||||
rom->fileptr = NULL;
|
||||
|
||||
}
|
||||
|
||||
//Need to pass in pointer to a filepointer to properly pass by reference
|
||||
//the OS/stdio creates a FILE struct and returns the address of that struct
|
||||
//so when this function opens a file it's setting the value of a pointer
|
||||
//for the calling function. To set a pointer we must have a pointer to that pointer..
|
||||
int open_file( FILE **fptr, char *filename )
|
||||
//int open_file( FILE **fptr, char *filename )
|
||||
int open_rom( rom_image *rom, char *filename )
|
||||
{
|
||||
//first open file
|
||||
*fptr = fopen( filename, "rb");
|
||||
//*fptr = fopen( filename, "rb");
|
||||
rom->fileptr = fopen( filename, "rb");
|
||||
//returns file ptr on success, NULL on fail
|
||||
check( *fptr, "Unable to open file: %s in read binary mode", filename);
|
||||
//check( *fptr, "Unable to open file: %s in read binary mode", filename);
|
||||
check( rom->fileptr, "Unable to open file: %s in read binary mode", filename);
|
||||
|
||||
return SUCCESS;
|
||||
error:
|
||||
|
|
@ -78,3 +92,16 @@ int detect_file( rom_image *rom )
|
|||
error:
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int create_file( rom_image *rom, char *filename )
|
||||
{
|
||||
//TODO check if file already exists, if so prompt if user would like to overwrite
|
||||
|
||||
rom->fileptr = fopen( filename, "wb+");
|
||||
check( rom->fileptr, "Unable to create file: %s in read/write binary mode", filename);
|
||||
|
||||
return SUCCESS;
|
||||
error:
|
||||
return -1;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,6 +15,11 @@
|
|||
|
||||
//TODO put defintions in separate project wide .h file
|
||||
#include "cartridge.h"
|
||||
#include "enums.h"
|
||||
|
||||
#define SIZE_NES_HEADER 16
|
||||
#define SIZE_PRG_BANK 16384
|
||||
#define SIZE_CHR_BANK 8192
|
||||
|
||||
//cartridge object/struct
|
||||
typedef struct rom_image{
|
||||
|
|
@ -30,7 +35,9 @@ typedef struct rom_image{
|
|||
FILE *fileptr;
|
||||
} rom_image;
|
||||
|
||||
int open_file( FILE **fptr, char *filename );
|
||||
void init_rom_elements(rom_image *rom);
|
||||
int open_rom( rom_image *rom, char *filename );
|
||||
int detect_file( rom_image *rom );
|
||||
int create_file( rom_image *rom, char *filename );
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -170,10 +170,10 @@ int main(int argc, char *argv[])
|
|||
|
||||
//create file object/struct
|
||||
rom_image *rom = malloc( sizeof(rom_image));
|
||||
rom->fileptr = NULL;
|
||||
|
||||
check_mem(transfer);
|
||||
check_mem(rom);
|
||||
init_rom_elements(rom);
|
||||
|
||||
|
||||
//command line arg L_value to set different LIBUSB debugging options
|
||||
|
|
@ -232,14 +232,37 @@ int main(int argc, char *argv[])
|
|||
|
||||
//read in user files/args that glean info about expected board
|
||||
|
||||
//for now just assume user file/args are correct
|
||||
if ( p_value != NULL ) {
|
||||
//program file provided at commandline
|
||||
check( !open_file( &rom->fileptr, p_value ), "Problem opening file %s", p_value);
|
||||
detect_file( rom );
|
||||
//compare detections to user args and get permission to continue if there are discrepencies
|
||||
|
||||
//just dump based on input args for now
|
||||
if ( d_value ) {
|
||||
//TODO input arg checking
|
||||
if ( c_value ) {
|
||||
if ( strcmp( "NES", c_value ) == 0 ) rom->console = NES_CART;
|
||||
if ( strcmp( "FC", c_value ) == 0 ) rom->console = FC_CART;
|
||||
if ( strcmp( "SNES", c_value ) == 0 ) rom->console = SNES_CART;
|
||||
}
|
||||
debug("console is: %c", rom->console);
|
||||
|
||||
if ( m_value ) rom->mapper = atoi(m_value);
|
||||
debug("mapper is: %d", rom->mapper);
|
||||
|
||||
if ( rom->mapper == NROM ) {
|
||||
rom->prg_size = 32 * KBYTE;
|
||||
rom->chr_size = 8 * KBYTE;
|
||||
//TODO function to check mirroring
|
||||
rom->mirroring = MIR_VERT;
|
||||
}
|
||||
|
||||
//TODO check if enough input args were provided or can be detected
|
||||
check( !create_file( rom, d_value ), "Unable to create file %s", d_value);
|
||||
}
|
||||
|
||||
//compare detections to user args and get permission to continue if there are discrepencies
|
||||
if ( p_value ) {
|
||||
//program file provided at commandline
|
||||
check( !open_rom( rom, p_value ), "Problem opening file %s", p_value);
|
||||
detect_file( rom );
|
||||
}
|
||||
|
||||
//if flashing, determine if erasures are necessary and where
|
||||
|
||||
|
|
|
|||
|
|
@ -7,6 +7,8 @@ void init_memory_elements( memory *mem )
|
|||
mem->volatility = UNKNOWN;
|
||||
mem->size = UNKNOWN;
|
||||
mem->bank_size = UNKNOWN;
|
||||
mem->wr_dict = UNKNOWN;
|
||||
mem->wr_opcode = UNKNOWN;
|
||||
mem->width = UNKNOWN;
|
||||
mem->protocol = UNKNOWN;
|
||||
mem->sector_size = UNKNOWN;
|
||||
|
|
|
|||
|
|
@ -39,6 +39,8 @@ typedef struct memory{
|
|||
int volatility; //sram no batt vs batt, mask rom, erasability, etc
|
||||
int size; //size of the max addressable memory grounding addr pins lowers this value
|
||||
int bank_size; //size of banks/pages of memory created by mapper banking
|
||||
int wr_dict; //dictionary used to write to rom
|
||||
int wr_opcode; //opcode used to write to rom
|
||||
int width; //width of data bus as configured
|
||||
int protocol; //parallel, SPI, I2C, JTAG, custom etc.
|
||||
int sector_size; //minimum eraseable size in bytes
|
||||
|
|
|
|||
|
|
@ -179,6 +179,7 @@ int famicom_sound( USBtransfer *transfer )
|
|||
* if ROM A14 is mapper controlled it must be low when CPU A14 is low
|
||||
* controlling A14 outside of this function acts as a means of bank size detection
|
||||
* Post:memory manf/prod ID set to read values if passed
|
||||
* memory wr_dict and wr_opcode set if successful
|
||||
* Software mode exited if entered successfully
|
||||
* Rtn: SUCCESS if flash sensed, GEN_FAIL if not, neg if error
|
||||
*/
|
||||
|
|
@ -218,6 +219,8 @@ int read_flashID_prgrom_exp0( USBtransfer *transfer, memory *flash ) {
|
|||
//found expected manf and prod ID
|
||||
flash->manf = SST_MANF_ID;
|
||||
flash->part = rv[RV_DATA0_IDX];
|
||||
flash->wr_dict = DICT_NES;
|
||||
flash->wr_opcode = DISCRETE_EXP0_PRGROM_WR;
|
||||
}
|
||||
|
||||
//exit software
|
||||
|
|
@ -233,6 +236,82 @@ int read_flashID_prgrom_exp0( USBtransfer *transfer, memory *flash ) {
|
|||
}
|
||||
|
||||
|
||||
/* Desc:PRG-ROM flash manf/prod ID sense test
|
||||
* Using mapper 30 defined PRG-ROM flash writes
|
||||
* Only senses SST flash ID's
|
||||
* Assumes that isn't getting tricked by having manf/prodID at $8000/8001
|
||||
* could add check and increment read address to ensure doesn't get tricked..
|
||||
* Pre: nes_init() been called to setup i/o
|
||||
* Post:memory manf/prod ID set to read values if passed
|
||||
* memory wr_dict and wr_opcode set if successful
|
||||
* Software mode exited if entered successfully
|
||||
* Rtn: SUCCESS if flash sensed, GEN_FAIL if not, neg if error
|
||||
*/
|
||||
int read_flashID_prgrom_map30( USBtransfer *transfer, memory *flash ) {
|
||||
|
||||
uint8_t rv[RV_DATA0_IDX];
|
||||
|
||||
//enter software mode
|
||||
//$8000-BFFF writes to flash
|
||||
//$C000-FFFF writes to mapper
|
||||
// 15 14 13 12
|
||||
// 0x5 = 0b 0 1 0 1 -> $9555
|
||||
// 0x2 = 0b 0 0 1 0 -> $2AAA
|
||||
//set A14 in mapper reg for $5555 command
|
||||
dictionary_call( transfer, DICT_NES, NES_CPU_WR, 0xC000, 0x01,
|
||||
USB_IN, NULL, 1);
|
||||
//write $5555 0xAA
|
||||
dictionary_call( transfer, DICT_NES, NES_CPU_WR, 0x9555, 0xAA,
|
||||
USB_IN, NULL, 1);
|
||||
//clear A14 in mapper reg for $2AAA command
|
||||
dictionary_call( transfer, DICT_NES, NES_CPU_WR, 0xC000, 0x00,
|
||||
USB_IN, NULL, 1);
|
||||
//write $2AAA 0x55
|
||||
dictionary_call( transfer, DICT_NES, NES_CPU_WR, 0xAAAA, 0x55,
|
||||
USB_IN, NULL, 1);
|
||||
//set A14 in mapper reg for $5555 command
|
||||
dictionary_call( transfer, DICT_NES, NES_CPU_WR, 0xC000, 0x01,
|
||||
USB_IN, NULL, 1);
|
||||
//write $5555 0x90 for software mode
|
||||
dictionary_call( transfer, DICT_NES, NES_CPU_WR, 0x9555, 0x90,
|
||||
USB_IN, NULL, 1);
|
||||
|
||||
//read manf ID
|
||||
dictionary_call( transfer, DICT_NES, NES_CPU_RD, 0x8000, NILL,
|
||||
USB_IN, rv, RV_DATA0_IDX+1);
|
||||
debug("manf id: %x", rv[RV_DATA0_IDX]);
|
||||
if ( rv[RV_DATA0_IDX] != SST_MANF_ID ) {
|
||||
return GEN_FAIL;
|
||||
//no need for software exit since failed to enter
|
||||
}
|
||||
|
||||
//read prod ID
|
||||
dictionary_call( transfer, DICT_NES, NES_CPU_RD, 0x8001, NILL,
|
||||
USB_IN, rv, RV_DATA0_IDX+1);
|
||||
debug("prod id: %x", rv[RV_DATA0_IDX]);
|
||||
if ( (rv[RV_DATA0_IDX] == SST_PROD_128)
|
||||
|| (rv[RV_DATA0_IDX] == SST_PROD_256)
|
||||
|| (rv[RV_DATA0_IDX] == SST_PROD_512) ) {
|
||||
//found expected manf and prod ID
|
||||
flash->manf = SST_MANF_ID;
|
||||
flash->part = rv[RV_DATA0_IDX];
|
||||
flash->wr_dict = DICT_NES;
|
||||
flash->wr_opcode = NES_CPU_WR;
|
||||
}
|
||||
|
||||
//exit software
|
||||
dictionary_call( transfer, DICT_NES, NES_CPU_WR, 0x8000, 0xF0,
|
||||
USB_IN, NULL, 1);
|
||||
|
||||
//verify exited
|
||||
dictionary_call( transfer, DICT_NES, NES_CPU_RD, 0x8000, NILL,
|
||||
USB_IN, rv, RV_DATA0_IDX+1);
|
||||
debug("prod id: %x", rv[RV_DATA0_IDX]);
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/* Desc:CHR-ROM flash manf/prod ID sense test
|
||||
* Only senses SST flash ID's
|
||||
* Does not make CHR bank writes so A14-A13 must be made valid outside of this funciton
|
||||
|
|
@ -242,6 +321,7 @@ int read_flashID_prgrom_exp0( USBtransfer *transfer, memory *flash ) {
|
|||
* could add check and increment read address to ensure doesn't get tricked..
|
||||
* Pre: nes_init() been called to setup i/o
|
||||
* Post:memory manf/prod ID set to read values if passed
|
||||
* memory wr_dict and wr_opcode set if successful
|
||||
* Software mode exited if entered successfully
|
||||
* Rtn: SUCCESS if flash sensed, GEN_FAIL if not, neg if error
|
||||
*/
|
||||
|
|
@ -281,6 +361,8 @@ int read_flashID_chrrom_8K( USBtransfer *transfer, memory *flash ) {
|
|||
//found expected manf and prod ID
|
||||
flash->manf = SST_MANF_ID;
|
||||
flash->part = rv[RV_DATA0_IDX];
|
||||
flash->wr_dict = DICT_NES;
|
||||
flash->wr_opcode = NES_PPU_WR;
|
||||
}
|
||||
|
||||
//exit software
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
//include prior to other file includes
|
||||
//that way DEBUG can be turned on/off for this file alone
|
||||
//uncomment to DEBUG this file alone
|
||||
#define DEBUG
|
||||
//#define DEBUG
|
||||
//"make debug" to get DEBUG msgs on entire program
|
||||
#include "dbg.h"
|
||||
|
||||
|
|
@ -24,6 +24,7 @@ int jumper_ciramce_ppuA13n( USBtransfer *transfer );
|
|||
int ciramce_inv_ppuA13( USBtransfer *transfer );
|
||||
int famicom_sound( USBtransfer *transfer );
|
||||
int read_flashID_prgrom_exp0( USBtransfer *transfer, memory *flash );
|
||||
int read_flashID_prgrom_map30( USBtransfer *transfer, memory *flash );
|
||||
int read_flashID_chrrom_8K( USBtransfer *transfer, memory *flash );
|
||||
int ppu_ram_sense( USBtransfer *transfer, uint16_t addr );
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue