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:
paul eeepc 2016-12-09 01:58:34 -06:00
parent a89caf2454
commit dff396a1c2
10 changed files with 241 additions and 59 deletions

Binary file not shown.

View File

@ -158,7 +158,7 @@ int detect_mirroring( cartridge *cart, USBtransfer *transfer )
//detecting mapper and memories ends up being one big operation //detecting mapper and memories ends up being one big operation
int detect_map_mem( cartridge *cart, USBtransfer *transfer, int oper ) int detect_map_mem( cartridge *cart, USBtransfer *transfer, int oper )
{ {
debug("detecting mapping"); //debug("detecting mapping");
//always start with resetting i/o //always start with resetting i/o
io_reset( transfer ); io_reset( transfer );
@ -176,7 +176,7 @@ int detect_map_mem( cartridge *cart, USBtransfer *transfer, int oper )
case FC_CART: case FC_CART:
case NES_CART: case NES_CART:
nes_init(transfer); nes_init(transfer);
debug("NES cart mapping"); //debug("NES cart mapping");
//gather other helpful info //gather other helpful info
//result of chr-ram test //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"); debug("CHR-RAM detected @ PPU $0000");
cart->sec_rom->manf = SRAM; cart->sec_rom->manf = SRAM;
cart->sec_rom->part = 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 ) { if ( read_flashID_chrrom_8K( transfer, cart->sec_rom ) == SUCCESS ) {
//8KB bank with no banking operations //8KB bank with no banking operations
debug("8K CHR-ROM flash detected"); debug("8K CHR-ROM flash detected");
cart->sec_rom->size = 8 * KBYTE; cart->sec_rom->size = 8 * KBYTE;
} }
}
//perform WRAM test without corrupting results //exp0 pullup test passes on many INL boards
//TODO store result in save_mem 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 16KB banks writing 0xFF to mapper reg should set A14 bit
if ( exp0_pullup_test(transfer) == SUCCESS) { //That will cause flash detection to fail.
debug("EXP0 pullup cart mapping"); //TODO handle bus conflicts...?
//if passed exp0 test try 16/32KB bank flash check dictionary_call( transfer, DICT_NES, NES_CPU_WR, 0x8000, 0xFF,
USB_IN, NULL, 1);
//if 16KB banks writing 0xFF to mapper reg should set A14 bit //if ID check passes, the should be 32KB PRG-ROM banking
//That will cause flash detection to fail. if ( read_flashID_prgrom_exp0( transfer, cart->pri_rom ) == SUCCESS ) {
//TODO handle bus conflicts...? //32KB bank with EXP0->WE PRG-ROM sensed
dictionary_call( transfer, DICT_NES, NES_CPU_WR, 0x8000, 0xFF, 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); 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 ){
if ( read_flashID_prgrom_exp0( transfer, cart->pri_rom ) == SUCCESS ) { //16KB bank with EXP0->WE PRG-ROM sensed
//32KB bank with EXP0->WE PRG-ROM sensed debug("16KB banking NES EXP0 enabled flash");
debug("32KB banking NES EXP0 enabled flash"); cart->pri_rom->bank_size = 16 * KBYTE;
cart->pri_rom->bank_size = 32 * KBYTE; cart->mapper = UxROM;
} 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;
}
} }
//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; break;
//================ //================
// SNES // SNES

View File

@ -12,8 +12,34 @@
#define SNES_CART 'S' #define SNES_CART 'S'
#define BKWD_CART 'B' #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 { enum mirroring {
MIR_FIXED = 10, MIR_FIXED = 10,
MIR_VERT,
MIR_HORIZ,
MIR_ANROM, MIR_ANROM,
MIR_MMC1, MIR_MMC1,
MIR_MMC3 MIR_MMC3

View File

@ -1,19 +1,33 @@
#include "file.h" #include "file.h"
#define SIZE_NES_HEADER 16 void init_rom_elements( rom_image *rom )
#define SIZE_PRG_BANK 16384 {
#define SIZE_CHR_BANK 8192 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 //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 //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 //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.. //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 //first open file
*fptr = fopen( filename, "rb"); //*fptr = fopen( filename, "rb");
rom->fileptr = fopen( filename, "rb");
//returns file ptr on success, NULL on fail //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; return SUCCESS;
error: error:
@ -78,3 +92,16 @@ int detect_file( rom_image *rom )
error: error:
return -1; 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;
}

View File

@ -15,6 +15,11 @@
//TODO put defintions in separate project wide .h file //TODO put defintions in separate project wide .h file
#include "cartridge.h" #include "cartridge.h"
#include "enums.h"
#define SIZE_NES_HEADER 16
#define SIZE_PRG_BANK 16384
#define SIZE_CHR_BANK 8192
//cartridge object/struct //cartridge object/struct
typedef struct rom_image{ typedef struct rom_image{
@ -30,7 +35,9 @@ typedef struct rom_image{
FILE *fileptr; FILE *fileptr;
} rom_image; } 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 detect_file( rom_image *rom );
int create_file( rom_image *rom, char *filename );
#endif #endif

View File

@ -170,10 +170,10 @@ int main(int argc, char *argv[])
//create file object/struct //create file object/struct
rom_image *rom = malloc( sizeof(rom_image)); rom_image *rom = malloc( sizeof(rom_image));
rom->fileptr = NULL;
check_mem(transfer); check_mem(transfer);
check_mem(rom); check_mem(rom);
init_rom_elements(rom);
//command line arg L_value to set different LIBUSB debugging options //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 //read in user files/args that glean info about expected board
//for now just assume user file/args are correct //compare detections to user args and get permission to continue if there are discrepencies
if ( p_value != NULL ) {
//program file provided at commandline //just dump based on input args for now
check( !open_file( &rom->fileptr, p_value ), "Problem opening file %s", p_value); if ( d_value ) {
detect_file( rom ); //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 //if flashing, determine if erasures are necessary and where

View File

@ -7,6 +7,8 @@ void init_memory_elements( memory *mem )
mem->volatility = UNKNOWN; mem->volatility = UNKNOWN;
mem->size = UNKNOWN; mem->size = UNKNOWN;
mem->bank_size = UNKNOWN; mem->bank_size = UNKNOWN;
mem->wr_dict = UNKNOWN;
mem->wr_opcode = UNKNOWN;
mem->width = UNKNOWN; mem->width = UNKNOWN;
mem->protocol = UNKNOWN; mem->protocol = UNKNOWN;
mem->sector_size = UNKNOWN; mem->sector_size = UNKNOWN;

View File

@ -39,6 +39,8 @@ typedef struct memory{
int volatility; //sram no batt vs batt, mask rom, erasability, etc 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 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 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 width; //width of data bus as configured
int protocol; //parallel, SPI, I2C, JTAG, custom etc. int protocol; //parallel, SPI, I2C, JTAG, custom etc.
int sector_size; //minimum eraseable size in bytes int sector_size; //minimum eraseable size in bytes

View File

@ -179,6 +179,7 @@ int famicom_sound( USBtransfer *transfer )
* if ROM A14 is mapper controlled it must be low when CPU A14 is low * 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 * 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 * 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 * Software mode exited if entered successfully
* Rtn: SUCCESS if flash sensed, GEN_FAIL if not, neg if error * 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 //found expected manf and prod ID
flash->manf = SST_MANF_ID; flash->manf = SST_MANF_ID;
flash->part = rv[RV_DATA0_IDX]; flash->part = rv[RV_DATA0_IDX];
flash->wr_dict = DICT_NES;
flash->wr_opcode = DISCRETE_EXP0_PRGROM_WR;
} }
//exit software //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 /* Desc:CHR-ROM flash manf/prod ID sense test
* Only senses SST flash ID's * Only senses SST flash ID's
* Does not make CHR bank writes so A14-A13 must be made valid outside of this funciton * 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.. * could add check and increment read address to ensure doesn't get tricked..
* Pre: nes_init() been called to setup i/o * Pre: nes_init() been called to setup i/o
* Post:memory manf/prod ID set to read values if passed * 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 * Software mode exited if entered successfully
* Rtn: SUCCESS if flash sensed, GEN_FAIL if not, neg if error * 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 //found expected manf and prod ID
flash->manf = SST_MANF_ID; flash->manf = SST_MANF_ID;
flash->part = rv[RV_DATA0_IDX]; flash->part = rv[RV_DATA0_IDX];
flash->wr_dict = DICT_NES;
flash->wr_opcode = NES_PPU_WR;
} }
//exit software //exit software

View File

@ -9,7 +9,7 @@
//include prior to other file includes //include prior to other file includes
//that way DEBUG can be turned on/off for this file alone //that way DEBUG can be turned on/off for this file alone
//uncomment to DEBUG this file alone //uncomment to DEBUG this file alone
#define DEBUG //#define DEBUG
//"make debug" to get DEBUG msgs on entire program //"make debug" to get DEBUG msgs on entire program
#include "dbg.h" #include "dbg.h"
@ -24,6 +24,7 @@ int jumper_ciramce_ppuA13n( USBtransfer *transfer );
int ciramce_inv_ppuA13( USBtransfer *transfer ); int ciramce_inv_ppuA13( USBtransfer *transfer );
int famicom_sound( USBtransfer *transfer ); int famicom_sound( USBtransfer *transfer );
int read_flashID_prgrom_exp0( USBtransfer *transfer, memory *flash ); 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 read_flashID_chrrom_8K( USBtransfer *transfer, memory *flash );
int ppu_ram_sense( USBtransfer *transfer, uint16_t addr ); int ppu_ram_sense( USBtransfer *transfer, uint16_t addr );