diff --git a/firmware/source/buffer.c b/firmware/source/buffer.c index daf8ba1..0efce25 100644 --- a/firmware/source/buffer.c +++ b/firmware/source/buffer.c @@ -8,6 +8,9 @@ buffer *cur_usb_load_buff; //uint16_t incoming_bytes_remain; uint8_t incoming_bytes_remain; +//host means of communicating to buffer manager +uint8_t operation; + //min define of two buffers static buffer buff0; static buffer buff1; @@ -176,6 +179,9 @@ uint8_t buffer_opcode_no_return( uint8_t opcode, buffer *buff, case RAW_BUFFER_RESET: raw_buffer_reset(); break; + case SET_BUFFER_OPERATION: + operation = operLSB; + break; case SET_MEM_N_PART: buff->mem_type = operMSB; buff->part_num = operLSB; @@ -470,50 +476,165 @@ uint8_t allocate_buffer( buffer *buff, uint8_t new_id, uint8_t base_bank, uint8_ } +//used to determine how many buffers are in use at start of new operation +//assume buffers are instantiated in order starting with zero. +uint8_t num_alloc_buffers( void ) +{ + uint8_t rv = 0; + if ( buff0.status != UNALLOC ) rv = 1; + if ( buff1.status != UNALLOC ) rv = 2; +#if ( defined(NUM_BUFFERS_4) || (defined(NUM_BUFFERS_8)) ) + if ( buff2.status != UNALLOC ) rv = 3; + if ( buff3.status != UNALLOC ) rv = 4; +#endif +#ifdef NUM_BUFFERS_8 + if ( buff4.status != UNALLOC ) rv = 5; + if ( buff5.status != UNALLOC ) rv = 6; + if ( buff6.status != UNALLOC ) rv = 7; + if ( buff7.status != UNALLOC ) rv = 8; +#endif + + return rv; +} + +//get next buffer provide a buffer pointer and number of buffers in use +//return pointer to next buffer in sequence +buffer * get_next_buff( buffer *buff, uint8_t num ) +{ + + //if there's 2 buffers need to toggle between 0 & 1 + if ( num == 2 ) { + if ( buff == &buff0 ) return &buff1; + if ( buff == &buff1 ) return &buff0; + } +#if ( defined(NUM_BUFFERS_4) || (defined(NUM_BUFFERS_8)) ) + //if there's 3-4 buffers cycle through + if ( num == 3 ) { + if ( buff == &buff0 ) return &buff1; + if ( buff == &buff1 ) return &buff2; + if ( buff == &buff2 ) return &buff0; + } + if ( num == 4 ) { + if ( buff == &buff0 ) return &buff1; + if ( buff == &buff1 ) return &buff2; + if ( buff == &buff2 ) return &buff3; + if ( buff == &buff3 ) return &buff0; + } +#endif +#ifdef NUM_BUFFERS_8 + if ( num == 5 ) { + if ( buff == &buff0 ) return &buff1; + if ( buff == &buff1 ) return &buff2; + if ( buff == &buff2 ) return &buff3; + if ( buff == &buff3 ) return &buff4; + if ( buff == &buff4 ) return &buff0; + } + if ( num == 6 ) { + if ( buff == &buff0 ) return &buff1; + if ( buff == &buff1 ) return &buff2; + if ( buff == &buff2 ) return &buff3; + if ( buff == &buff3 ) return &buff4; + if ( buff == &buff4 ) return &buff5; + if ( buff == &buff5 ) return &buff0; + } + if ( num == 7 ) { + if ( buff == &buff0 ) return &buff1; + if ( buff == &buff1 ) return &buff2; + if ( buff == &buff2 ) return &buff3; + if ( buff == &buff3 ) return &buff4; + if ( buff == &buff4 ) return &buff5; + if ( buff == &buff5 ) return &buff6; + if ( buff == &buff6 ) return &buff0; + } + if ( num == 8 ) { + if ( buff == &buff0 ) return &buff1; + if ( buff == &buff1 ) return &buff2; + if ( buff == &buff2 ) return &buff3; + if ( buff == &buff3 ) return &buff4; + if ( buff == &buff4 ) return &buff5; + if ( buff == &buff5 ) return &buff6; + if ( buff == &buff6 ) return &buff7; + if ( buff == &buff7 ) return &buff0; + } +#endif + + //if there's only one buffer, or if some other error, just return sent buffer ptr + //if ( num == 1 ) return buff; + return buff; + +} + //check buffer status' and instruct them to //flash/dump as needed to keep data moving void update_buffers() { uint8_t result = 0; - buffer *buff = &buff0; + static uint8_t num_buff; + static buffer *cur_buff; //when dumping we don't actually know when the buffer has been fully //read back through USB IN transfer. But we know when the next buffer //is requested to read back, so we'll dump the second page into the second buffer //after the first page has been requested for IN transfer //need to get data dumped before in transfer.. + + + //operations start by host resetting and initializing buffers + //this buffer manager is blind to the size of buffers and other such details + //this manager only needs to know which buffers are active + //but the host sets operation when it wants this manager to send + //little buffers out to start dumping/flashing + if ( (operation == STARTDUMP) || (operation == STARTFLASH ) ) { + //only want to do this once per operation at the start + //figure out how many buffers are in operation + //assume buff0 is first and follows 1, 2, etc + num_buff = num_alloc_buffers(); + + //now that we know how many buffers there are in use + //we always start with buff0 + cur_buff = &buff0; + //now we can get_next_buff by passing cur_buff + } + if (operation == STARTDUMP) { + //don't want to reenter start initialiation again + operation = DUMPING; + } + if (operation == STARTFLASH) { + //don't want to reenter start initialiation again + operation = FLASHING; + } //to start let's sense dumping operation by buffer status //host updates status of buffer, then we go off and dump as appropriate //might be best to add some opcode to kick things off. - if ( buff->function == DUMPING ) { +// if ( buff->function == DUMPING ) { - buff->cur_byte = 0; - //to start lets just dump the first page of PRG-ROM - result = dump_page( buff ); - - if (result == SUCCESS) { - buff->status = DUMPED; - } - - //now it can be read back in next IN transfer - } +// buff->cur_byte = 0; +// //to start lets just dump the first page of PRG-ROM +// result = dump_page( buff ); +// +// if (result == SUCCESS) { +// buff->status = DUMPED; +// } +// +// //now it can be read back in next IN transfer +// } //for now lets use one buffer to flash a cartridge //later try a second one to double buffer, might not actually matter much.. // buffer *buff = &buff0; //check if buffer is full and update status accordingly - if (cur_usb_load_buff->last_idx == cur_usb_load_buff->cur_byte) { - cur_usb_load_buff->status = USB_FULL; - - //update other buffer so it can be filled by incoming USB data now - //if buffer size is smaller than data transfer lengths this must be done quickly - //enough for usbFunction write to not notice - } else { - //if there are no full buffers yet simply exit - //return; - } +// if (cur_usb_load_buff->last_idx == cur_usb_load_buff->cur_byte) { +// cur_usb_load_buff->status = USB_FULL; +// +// //update other buffer so it can be filled by incoming USB data now +// //if buffer size is smaller than data transfer lengths this must be done quickly +// //enough for usbFunction write to not notice +// } else { +// //if there are no full buffers yet simply exit +// //return; +// } //found a buffer that's full and ready to flash onto cart @@ -523,19 +644,21 @@ void update_buffers() //update any other necessary elements //send it off to it's flashing routine - if ( buff->function == FLASHING ) { - - - buff->cur_byte = 0; - //to start lets just dump the first page of PRG-ROM - result = flash_page( buff ); - - if (result == SUCCESS) { - buff->status = DUMPED; - } - - //now it can be read back in next IN transfer - } +// if ( buff->function == FLASHING ) { +// +// +// buff->cur_byte = 0; +// //to start lets just dump the first page of PRG-ROM +// result = flash_page( buff ); +// +// if (result == SUCCESS) { +// buff->status = FLASHED; +// } else { +// buff->status = PROBLEM; +// } +// +// //now it can be read back in next IN transfer +// } //now that it's flashed perform verifications if needed diff --git a/firmware/source/dump.c b/firmware/source/dump.c index eebabb3..83b8f7f 100644 --- a/firmware/source/dump.c +++ b/firmware/source/dump.c @@ -1,8 +1,5 @@ #include "dump.h" - - - /* Desc:Dump cart memory into buffer's data array * Pre: buffer elements must be updated to designate how/where to dump * buffer's cur_byte must be cleared or set to where to start dumping @@ -11,15 +8,46 @@ */ uint8_t dump_page( buffer *buff ) { - uint8_t addrH = (buff->page_num | 0x80); //or in $8000 to set equiv CPU address + uint8_t addrH = buff->page_num; //A15:8 while accessing page + uint8_t addrX; //A23:16 while accessing page + + //TODO use mapper to set mapper controlled address bits + + //use mem_type to set addrH/X as needed for dump loop + //also use to get read function pointer + switch ( buff->mem_type ) { + case PRGROM: + addrH |= 0x80; //$8000 + //uint8_t nes_cpu_page_rd( uint8_t *data, uint8_t addrH, uint8_t first, uint8_t last ) + buff->cur_byte = nes_cpu_page_rd( buff->data, addrH, buff->id, + //id contains MSb of page when <256B buffer + (buff->last_idx | buff->id) ); + break; + case CHRROM: //$0000 + //buff->cur_byte = nes_ppu_page_rd( buff->data, addrH, buff->id, + // (buff->last_idx | buff->id) ); + break; + case PRGRAM: + addrH |= 0x60; //$6000 + buff->cur_byte = nes_cpu_page_rd( buff->data, addrH, buff->id, + (buff->last_idx | buff->id) ); + break; + case SNESROM: + case SNESRAM: + addrX = ((buff->page_num)>>8); + break; + default: + return ERR_BUFF_UNSUP_MEM_TYPE; + } + //lets start just reading first page of PRG-ROM then get fancy - while (buff->cur_byte < buff->last_idx) { - - //might be faster to put some of these in new pointers, but not sure.. - buff->data[buff->cur_byte] = nes_cpu_rd( addrH, buff->cur_byte ); - buff->cur_byte++; - } +// while (buff->cur_byte < buff->last_idx) { +// +// //might be faster to put some of these in new pointers, but not sure.. +// buff->data[buff->cur_byte] = nes_cpu_rd( addrH, buff->cur_byte ); +// buff->cur_byte++; +// } return SUCCESS; } diff --git a/firmware/source/dump.h b/firmware/source/dump.h index e7ae7ac..4b33d9f 100644 --- a/firmware/source/dump.h +++ b/firmware/source/dump.h @@ -8,6 +8,7 @@ #include "nes.h" #include "shared_dictionaries.h" #include "shared_errors.h" +#include "shared_enums.h" uint8_t dump_page( buffer *buff ) ; diff --git a/firmware/source/io.c b/firmware/source/io.c index d1ffdc4..74bd222 100644 --- a/firmware/source/io.c +++ b/firmware/source/io.c @@ -150,11 +150,6 @@ void nes_init() _DATA_IP(); _DATA_HI(); - //turn LED off - _LED_OFF(); - //set as OP for future commands to utilize - _LED_OP(); - } @@ -208,11 +203,6 @@ void snes_init() _DATA_IP(); _DATA_HI(); - //turn LED off - _LED_OFF(); - //set as OP for future commands to utilize - _LED_OP(); - } //Test starts by verifying EXP0 can be driven low, if not, will return one byte of AUX_PIN diff --git a/firmware/source/nes.c b/firmware/source/nes.c index 7c7e5c4..091eafc 100644 --- a/firmware/source/nes.c +++ b/firmware/source/nes.c @@ -59,6 +59,9 @@ uint8_t nes_opcode_16b_operand_8b_return( uint8_t opcode, uint8_t addrH, uint8_t case NES_PPU_RD: *data = nes_ppu_rd( addrH, addrL ); break; + case CIRAM_A10_MIRROR: + *data = ciram_a10_mirroring( ); + break; default: //macro doesn't exist return ERR_UNKN_NES_OPCODE_16BOP_8BRV; @@ -342,3 +345,97 @@ void nes_ppu_wr( uint8_t addrH, uint8_t addrL, uint8_t data ) _DATA_IP(); } + + +/* Desc:PPU CIRAM A10 NT arrangement sense + * Toggle A11 and A10 and read back CIRAM A10 + * report back if vert/horiz/1scnA/1scnB + * reports nesdev defined mirroring + * does not report Nintendo's "Name Table Arrangement" + * Pre: nes_init() setup of io pins + * Post:address left on bus + * Rtn: MIR_VERT, MIR_HORIZ, MIR_1SCNA, MIR_1SCNB + * errors not really possible since all combinations + * of CIRAM A10 level designate something valid + */ +uint8_t ciram_a10_mirroring( void ) +{ + uint8_t readV, readH; + + //will need output majority of function + _DATA_OP(); + + //set A10, clear A11 + DATA_OUT = A10; + _AHL_CLK(); + readV = AUX_IN & (1< 1 screen A + if ((readV==0) & (readH==0)) return MIR_1SCNA; + //if CIRAM A10 was always hight -> 1screen B + if ((readV!=0) & (readH!=0)) return MIR_1SCNB; + //if CIRAM A10 toggled with A10 -> Vertical mirroring, horizontal arrangement + if ((readV!=0) & (readH==0)) return MIR_VERT; + //if CIRAM A10 toggled with A11 -> Horizontal mirroring, vertical arrangement + if ((readV==0) & (readH!=0)) return MIR_HORIZ; + + //shouldn't be here... + return UNKNOWN; +} + +/* Desc:NES CPU Page Read + * decode A15 from addrH to set /ROMSEL as expected + * float EXP0 + * toggle M2 as NES would + * Pre: nes_init() setup of io pins + * num_bytes can't exceed 256B page boundary + * Post:address left on bus + * data bus left clear + * EXP0 left floating + * data buffer filled starting at first to last + * Rtn: Index of last byte read + */ +uint8_t nes_cpu_page_rd( uint8_t *data, uint8_t addrH, uint8_t first, uint8_t last ) +{ + uint8_t i; + + //set address bus + _ADDRH_SET(addrH); + + //set M2 and /ROMSEL + _M2_HI(); + if( addrH >= 0x80 ) { //addressing cart rom space + _ROMSEL_LO(); //romsel trails M2 during CPU operations + } + + ADDR_OUT = first; //doing this prior to entry and right after latching + //gives longest delay between address out and latching data + for( i=0; i<=last; i++ ) { + //set lower address bits + //couple more NOP's waiting for data + //zero nop's returned previous databus value + NOP(); //one nop got most of the bits right + NOP(); //two nop got all the bits right + NOP(); //add third nop for some extra + //might need to wait longer for some carts... + + //latch data + data[i] = DATA_IN; + ADDR_OUT = ++first; + } + + //return bus to default + _M2_LO(); + _ROMSEL_HI(); + + //return index of last byte read + return i; +} diff --git a/firmware/source/nes.h b/firmware/source/nes.h index 6d94873..d35abd3 100644 --- a/firmware/source/nes.h +++ b/firmware/source/nes.h @@ -5,6 +5,7 @@ #include "pinport.h" #include "shared_dictionaries.h" #include "shared_errors.h" +#include "shared_enums.h" uint8_t nes_opcode_only( uint8_t opcode ); uint8_t nes_opcode_24b_operand( uint8_t opcode, uint8_t addrH, uint8_t addrL, uint8_t data ); @@ -15,5 +16,7 @@ uint8_t nes_cpu_rd( uint8_t addrH, uint8_t addrL ); void nes_cpu_wr( uint8_t addrH, uint8_t addrL, uint8_t data ); uint8_t nes_ppu_rd( uint8_t addrH, uint8_t addrL ); void nes_ppu_wr( uint8_t addrH, uint8_t addrL, uint8_t data ); +uint8_t ciram_a10_mirroring( void ); +uint8_t nes_cpu_page_rd( uint8_t *data, uint8_t addrH, uint8_t first, uint8_t last ); #endif diff --git a/firmware/source/pinport.h b/firmware/source/pinport.h index e49a397..1a596f7 100644 --- a/firmware/source/pinport.h +++ b/firmware/source/pinport.h @@ -434,5 +434,8 @@ void software_AXL_CLK(); //PPU /A13 is ADDRH bit 7 #define PPU_A13N 0x80 +//PPU and CPU +#define A10 0x04 +#define A11 0x08 #endif diff --git a/host/source/buffer.c b/host/source/buffer.c new file mode 100644 index 0000000..3c62b57 --- /dev/null +++ b/host/source/buffer.c @@ -0,0 +1,73 @@ +#include "buffer.h" + +/* Desc:Reset buffers on device + * Pre: + * Post:All buffers and raw sram unallocated + * Rtn: SUCCESS if no errors + */ +int reset_buffers( USBtransfer *transfer ) +{ + return dictionary_call( transfer, DICT_BUFFER, RAW_BUFFER_RESET, NILL, NILL, + USB_IN, NULL, 1); +} + +/* Desc:allocate buffers on device + * Pre: buffers must be reset + * Post:All buffers and raw sram unallocated + * Sets id, status to EMPTY, and last_idx. + * All other elements set to zero + * Rtn: SUCCESS if no errors + */ +int allocate_buffers( USBtransfer *transfer, int num_buffers, int buff_size ) { + + //TODO verify number of banks doesn't exceed devices' configuration +// uint8_t rv[RV_DATA0_IDX]; +// uint8_t rv; + int rv; + int buff0id = 0; + int buff0basebank = 0; + int buff1id = 0; + int buff1basebank = 0; + int numbanks= 0; + + //want to allocate buffers as makes sense based on num and size + //Ideally a buffer will be 256Bytes which equals a page size + //256Bytes doesn't work well with dumping though as max xfr size is 254Bytes + //So for simplicity dumping starts with 128B buffers + //But this means a single buffer can't hold a full page + //In this case the missing bits between buffer size and page_num must be contained + //in upper bits of the buffer id. + if( (num_buffers == 2) && (buff_size == 128)) { + //MSB tells buffer value of A7 when operating + buff0id = 0x00; + buff0basebank = 0; + numbanks= buff_size/RAW_BANK_SIZE; + buff1id = 0x80; + buff1basebank= numbanks; //buff1 starts right after buff0 + } else { + sentinel("Not setup to handle this buffer config"); + } + + //allocate buffer0 + rv = dictionary_call_debug( transfer, DICT_BUFFER, ALLOCATE_BUFFER0, + ( (buff0id<<8)|(buff0basebank) ), numbanks, + USB_IN, NULL, 1); + if ( rv != SUCCESS ){ + //failed to allocate pass error code back + return rv; + } + //allocate buffer1 + rv = dictionary_call_debug( transfer, DICT_BUFFER, ALLOCATE_BUFFER1, + ( (buff1id<<8)|(buff1basebank) ), numbanks, + USB_IN, NULL, 1); + if ( rv != SUCCESS ){ + //failed to allocate pass error code back + return rv; + } + + return SUCCESS; +error: + return ~SUCCESS; +} + + diff --git a/host/source/buffer.h b/host/source/buffer.h new file mode 100644 index 0000000..f3f4f50 --- /dev/null +++ b/host/source/buffer.h @@ -0,0 +1,27 @@ +#ifndef _buffer_h +#define _buffer_h + +#include +#include +#include +#include + +//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 +//"make debug" to get DEBUG msgs on entire program +#include "dbg.h" + +#include "shared_errors.h" +#include "shared_dictionaries.h" +#include "dictionary.h" +#include "memory.h" +// "cartridge.h" is above the scope of this module don't include + +#include "pindef.h" + +int reset_buffers( USBtransfer *transfer ); +int allocate_buffers( USBtransfer *transfer, int num_buffers, int buff_size ); + +#endif diff --git a/host/source/cartridge.c b/host/source/cartridge.c index 2a2319f..19d4f3b 100644 --- a/host/source/cartridge.c +++ b/host/source/cartridge.c @@ -133,17 +133,36 @@ error: //roms are still visible when /RESET low, but SRAM isn't +/* Desc:Run through supported mapper mirroring modes to help detect mapper. + * Pre: + * Post:cart mirroring set to found mirroring + * Rtn: SUCCESS if nothing bad happened, neg if error with kazzo etc + */ int detect_mirroring( cartridge *cart, USBtransfer *transfer ) { //always start with resetting i/o io_reset( transfer ); if ( (cart->console == NES_CART) || (cart->console == FC_CART) ) { - //For now just assume mirroring is fixed until start adding support for other mappers - cart->mirroring = MIR_FIXED; - } + nes_init(transfer); + //TODO call mmc3 detection function - //always end with resetting i/o + //TODO call mmc1 detection function + + //fme7 and many other ASIC mappers + + //none of ASIC mappers passed, assume fixed/discrete style mirroring + cart->mirroring = ciram_A10_mirroring( transfer ); + switch (cart->mirroring) { + case MIR_1SCNA: debug("detected mirroring: 1scnA"); break; + case MIR_1SCNB: debug("detected mirroring: 1scnB"); break; + case MIR_VERT: debug("detected mirroring: Vert"); break; + case MIR_HORIZ: debug("detected mirroring: Horiz"); break; + default: debug("detected mirroring: %x", cart->mirroring); + } + } + + //always end with reset io_reset( transfer ); return SUCCESS; @@ -189,19 +208,24 @@ int detect_map_mem( cartridge *cart, USBtransfer *transfer, int oper ) //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: + case MIR_1SCNA: + case MIR_1SCNB: + break; + case MIR_VERT: + case MIR_HORIZ: //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; + cart->sec_rom->size = 8 * KByte; } } //exp0 pullup test passes on many INL boards @@ -218,7 +242,7 @@ switch (cart->mirroring) { 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; + 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, @@ -226,7 +250,7 @@ switch (cart->mirroring) { 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->pri_rom->bank_size = 16 * KByte; cart->mapper = UxROM; } } @@ -237,14 +261,14 @@ switch (cart->mirroring) { //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->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."); + sentinel("Problem with map mem detect based on mirroring switch statement."); } //mapper select switch<<<<------------------------------------------------------------- break; @@ -269,3 +293,4 @@ error: io_reset( transfer ); return -1; } + diff --git a/host/source/cartridge.h b/host/source/cartridge.h index 453084b..0d40e45 100644 --- a/host/source/cartridge.h +++ b/host/source/cartridge.h @@ -18,7 +18,7 @@ #include "shared_errors.h" #include "shared_dictionaries.h" #include "dictionary.h" -#include "enums.h" +#include "shared_enums.h" #include "io.h" #include "nes.h" @@ -47,6 +47,7 @@ int init_cart_elements( cartridge *cart ); int detect_console( cartridge *cart, USBtransfer *transfer ); int detect_mirroring( cartridge *cart, USBtransfer *transfer ); int detect_map_mem( cartridge *cart, USBtransfer *transfer, int oper ); +int detect_mirroring( cartridge *cart, USBtransfer *transfer ); #endif diff --git a/host/source/dump.c b/host/source/dump.c new file mode 100644 index 0000000..291a20b --- /dev/null +++ b/host/source/dump.c @@ -0,0 +1,61 @@ +#include "dump.h" + +/* Desc: + * Pre: + * Post: + * Rtn: + */ +//main collected as much data about cart as possible without reading roms +//now it's time to start running CRC's to try and finalize mapper/config +//Once final mapper is known store header data in rom file and start dumping! +int dump_cart( USBtransfer* transfer, rom_image *rom, cartridge *cart ) +{ + debug("dumping cart"); + + //TODO provide user arg to force all these checks passed + //first check if any provided args differ from what was detected + check( cart->console != UNKNOWN, + "cartridge not detected, must provide console if autodetection is off"); + + if ( rom->console != UNKNOWN ) { + check( rom->console == cart->console, + "request system dump doesn't match detected cartridge"); + } + if ( (cart->mapper != UNKNOWN) && (rom->mapper != UNKNOWN) ) { + check( rom->mapper == cart->mapper, + "request mapper dump doesn't match detected mapper"); + } + + //Run some CRC's to determine size of memories + + //setup buffers and manager + //reset buffers first + check(! reset_buffers( transfer ), "Unable to reset device buffers"); + //need to allocate some buffers for dumping + //2x 128Byte buffers + int num_buffers = 2; + int buff_size = 128; + check(! allocate_buffers( transfer, num_buffers, buff_size ), "Unable to allocate buffers"); + + //set buffer elements as needed + //set reload which gets added to page_num after each buffer read + //set page_num to non-zero if offset arg sent + //set mem_type and part_num to designate how to get/write data + //set multiple and add_mult only when flashing + //set mapper, map_var, and function to designate read/write algo + + //tell buffers what function to use for dumping + + //inform buffer manager to start dumping operation now that buffers are initialized + + //manager updates buffer status' so they'll start dumping + //once they're full manager prepares them to be read back on USB payloads + //once the next payload request happens manager knows last buffer can start dumping again + //buffer updates it's elements and goes off to dump next page + //tell buffer manager when to stop + //reset buffers and setup to dump CHR-ROM + + return SUCCESS; +error: + return ~SUCCESS; +} diff --git a/host/source/dump.h b/host/source/dump.h new file mode 100644 index 0000000..17f2a93 --- /dev/null +++ b/host/source/dump.h @@ -0,0 +1,34 @@ +#ifndef _dump_h +#define _dump_h + +#include +#include +#include +#include +#include + +//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 +//"make debug" to get DEBUG msgs on entire program +#include "dbg.h" + +#include "usb_operations.h" +#include "shared_errors.h" +#include "shared_dictionaries.h" +#include "dictionary.h" +#include "shared_enums.h" + +#include "io.h" +#include "nes.h" +#include "snes.h" +#include "memory.h" +#include "cartridge.h" +#include "file.h" +#include "buffer.h" + +int dump_cart( USBtransfer* transfer, rom_image *rom, cartridge *cart ); + + +#endif diff --git a/host/source/enums.h b/host/source/enums.h deleted file mode 100644 index 5b629be..0000000 --- a/host/source/enums.h +++ /dev/null @@ -1,55 +0,0 @@ -#ifndef _enums_h -#define _enums_h - -//One concise place to list all enums used for setting cartridge and memory elements - -//used to denote when any cartridge element is not known -#define UNKNOWN -1 - -//console options -#define NES_CART 'N' -#define FC_CART 'F' -#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 -}; - -enum operations { - READ = 10, - WRITE, - CHECK -}; - - -#endif diff --git a/host/source/file.h b/host/source/file.h index bd7abae..407003a 100644 --- a/host/source/file.h +++ b/host/source/file.h @@ -15,7 +15,7 @@ //TODO put defintions in separate project wide .h file #include "cartridge.h" -#include "enums.h" +#include "shared_enums.h" #define SIZE_NES_HEADER 16 #define SIZE_PRG_BANK 16384 diff --git a/host/source/inlprog.c b/host/source/inlprog.c index 068011e..5d41481 100644 --- a/host/source/inlprog.c +++ b/host/source/inlprog.c @@ -19,7 +19,8 @@ #include "test.h" #include "cartridge.h" #include "file.h" -#include "enums.h" +#include "dump.h" +#include "shared_enums.h" int main(int argc, char *argv[]) @@ -127,11 +128,11 @@ int main(int argc, char *argv[]) } - debug("flags= o:%d n:%d e:%d f:%d h:%d i:%d t:%d x:%d y:%d T:%d", - o_flag, n_flag, e_flag, f_flag, h_flag, i_flag, t_flag, x_flag, y_flag, T_flag ); - debug("args= b:%s c:%s d:%s m:%s p:%s", b_value, c_value, d_value, m_value, p_value); - debug("args= s:%s v:%s C:%s L:%s K:%s", s_value, v_value, C_value, L_value, K_value); - debug("args= O:%s P:%s S:%s W:%s", O_value, P_value, S_value, W_value); +// debug("flags= o:%d n:%d e:%d f:%d h:%d i:%d t:%d x:%d y:%d T:%d", +// o_flag, n_flag, e_flag, f_flag, h_flag, i_flag, t_flag, x_flag, y_flag, T_flag ); +// debug("args= b:%s c:%s d:%s m:%s p:%s", b_value, c_value, d_value, m_value, p_value); +// debug("args= s:%s v:%s C:%s L:%s K:%s", s_value, v_value, C_value, L_value, K_value); +// debug("args= O:%s P:%s S:%s W:%s", O_value, P_value, S_value, W_value); for( index = optind; index < argc; index++) { log_err("Non-option arguement: %s \n", argv[index]); @@ -143,6 +144,10 @@ int main(int argc, char *argv[]) return 0; } + if ( O_value || v_value || s_value || b_value || y_flag || t_flag || f_flag ) { + printf("option not currently supported sorry...\n"); + } + //Determine overall operation being performed based on user args //Also don't want to continue if conflicting args are being used @@ -242,20 +247,22 @@ int main(int argc, char *argv[]) if ( strcmp( "FC", c_value ) == 0 ) rom->console = FC_CART; if ( strcmp( "SNES", c_value ) == 0 ) rom->console = SNES_CART; } + //TODO interpret provided file extension to determine desired console 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; + rom->prg_size = 32 * KByte; + rom->chr_size = 8 * KByte; } //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); + + //collected as much info as can dump cart without reading any data + check( !dump_cart( transfer, rom, cart ), "Error while dumping cart"); } if ( p_value ) { @@ -270,7 +277,7 @@ int main(int argc, char *argv[]) //forced to erase board regardless of current status if (e_flag || p_value) { - erase_nes( transfer ); + // erase_nes( transfer ); } //if flashing determine auto-doubling for oversized flash @@ -282,7 +289,7 @@ int main(int argc, char *argv[]) //determine if snes input rom needs deinterleaved - //dump or flash data based on user args + //dump or program data based on user args //find some fun trivia to present to user while waiting for flash operatoin..? diff --git a/host/source/memory.h b/host/source/memory.h index e4957f4..e5d1ac7 100644 --- a/host/source/memory.h +++ b/host/source/memory.h @@ -18,7 +18,7 @@ #include "shared_errors.h" #include "shared_dictionaries.h" #include "dictionary.h" -#include "enums.h" +#include "shared_enums.h" //SST 39SF0x0 manf/prod IDs #define SST_MANF_ID 0xBF @@ -30,7 +30,7 @@ #define SRAM 0xAA //KByte for easy math -#define KBYTE 1024 +#define KByte 1024 //memory object/struct typedef struct memory{ diff --git a/host/source/nes.c b/host/source/nes.c index c2daa38..f665837 100644 --- a/host/source/nes.c +++ b/host/source/nes.c @@ -412,3 +412,20 @@ int ppu_ram_sense( USBtransfer *transfer, uint16_t addr ) { return SUCCESS; } + + +/* Desc:Just calls CIRAM_A10_MIRROR opcode and returns result. + * result will be return value of opcode + * Pre: nes_init() been called to setup i/o + * Post:address bus left assigned + * Rtn: VERT/HORIZ/1SCNA/1SCNB + */ +int ciram_A10_mirroring( USBtransfer *transfer ) +{ + uint8_t rv[RV_DATA0_IDX]; + + dictionary_call( transfer, DICT_NES, CIRAM_A10_MIRROR, NILL, NILL, + USB_IN, rv, RV_DATA0_IDX+1); + debug("mirroring detected: %x", rv[RV_DATA0_IDX]); + return rv[RV_DATA0_IDX]; +} diff --git a/host/source/nes.h b/host/source/nes.h index 73615ea..f00772c 100644 --- a/host/source/nes.h +++ b/host/source/nes.h @@ -17,6 +17,7 @@ #include "shared_dictionaries.h" #include "dictionary.h" #include "memory.h" +// "cartridge.h" is above the scope of this module don't include #include "pindef.h" @@ -27,5 +28,6 @@ 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 ); +int ciram_A10_mirroring( USBtransfer *transfer ); #endif diff --git a/host/source/test.h b/host/source/test.h index 8d0ef20..3bada9f 100644 --- a/host/source/test.h +++ b/host/source/test.h @@ -18,6 +18,7 @@ #include "usb_operations.h" #include "shared_errors.h" +#include "shared_enums.h" #include "shared_dictionaries.h" #include "dictionary.h" diff --git a/shared/shared_dict_buffer.h b/shared/shared_dict_buffer.h index 60ae402..d94d1c5 100644 --- a/shared/shared_dict_buffer.h +++ b/shared/shared_dict_buffer.h @@ -44,23 +44,6 @@ #define NUM_BUFFERS_4 4 //#define NUM_BUFFERS_8 8 -//defined here so identical to host and firmware -//status values -#define EMPTY 0x00 -#define PROBLEM 0x10 -#define USB_UNLOADING 0x80 -#define USB_LOADING 0x90 -#define USB_FULL 0x98 -#define CHECKING 0xC0 -#define DUMPING 0xD0 -#define DUMPED 0xD8 -#define ERASING 0xE0 -#define FLASHING 0xF0 -#define FLASH_WAIT 0xF8 -#define UNALLOC 0xFF - - - //============================================================================================= // OPCODES with up to 24bit operand and optional return value besides SUCCESS/ERROR_CODE @@ -104,6 +87,10 @@ //no operands no return value #define RAW_BUFFER_RESET 0x00 +//set buffer manager operation value +//lower operand byte sets value +#define SET_BUFFER_OPERATION 0x01 + //------------------------------------------------------------------------------------------------ diff --git a/shared/shared_dict_nes.h b/shared/shared_dict_nes.h index 6286b37..7293f01 100644 --- a/shared/shared_dict_nes.h +++ b/shared/shared_dict_nes.h @@ -76,4 +76,8 @@ #define NES_PPU_RD 0x82 +//doesn't have operands just returns sensed CIRAM A10 mirroring +//returns VERT/HORIZ/1SCNA/1SCNB from shared_enums.h +#define CIRAM_A10_MIRROR 0x83 + #endif diff --git a/shared/shared_enums.h b/shared/shared_enums.h new file mode 100644 index 0000000..3c764a6 --- /dev/null +++ b/shared/shared_enums.h @@ -0,0 +1,84 @@ +#ifndef _shared_enums_h +#define _shared_enums_h + +//One concise place to list all enums used +//for setting cartridge and memory elements on the host +//which end up getting communicated between device and host + +//used to denote when any cartridge element is not known +#define UNKNOWN 0xFF + +//console options +#define NES_CART 'N' +#define FC_CART 'F' +#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 +// UNKNOWN 255 don't assign to something meaningful + +enum mirroring { + MIR_1SCNA = 0x10, //SCNA + MIR_1SCNB = 0x11, //SCNB + MIR_VERT = 0x12, //VERT + MIR_HORIZ = 0x13, //HORIZ + MIR_ANROM, + MIR_MMC1, + MIR_MMC3, + MIR_FME7 +}; + +enum operations { + READ = 10, + WRITE, + CHECK +}; + +enum buff_mem_type { + PRGROM = 10, + CHRROM, + PRGRAM, + SNESROM, + SNESRAM +}; + +//buffer status values +#define EMPTY 0x00 +#define PROBLEM 0x10 +#define USB_UNLOADING 0x80 +#define USB_LOADING 0x90 +#define USB_FULL 0x98 +#define CHECKING 0xC0 +#define DUMPING 0xD0 +#define STARTDUMP 0xD2 +#define DUMPED 0xD8 +#define ERASING 0xE0 +#define FLASHING 0xF0 +#define STARTFLASH 0xF2 +#define FLASHED 0xF4 +#define FLASH_WAIT 0xF8 +#define UNALLOC 0xFF + +#endif diff --git a/shared/shared_errors.h b/shared/shared_errors.h index cfd8a62..14f5a01 100644 --- a/shared/shared_errors.h +++ b/shared/shared_errors.h @@ -42,6 +42,7 @@ #define ERR_BUFF_ID_ALREADY_ALLOC 192 #define ERR_BUFF_RAW_ALREADY_ALLOC 193 #define ERR_BUFF_ALLOC_SIZE_ZERO 194 +#define ERR_BUFF_UNSUP_MEM_TYPE 195 #define ERR_OUT_CURLDBUF_STATUS 200 #define ERR_OUT_CURLDBUF_TO_SMALL 201