Basic flashing operatoins working. Still need to do some tests and erasing before flashing.
Need to verify page programmed successfully as it currently just continues even if unable to flash proper data. Need to make write page utilize variables for bank address based on mapper and/or memory as currently doesn't flash CHR-ROM due to $5555 $2AAA being above address space of CHR-ROM
This commit is contained in:
parent
876b526e8c
commit
de9b5d67a4
|
|
@ -333,12 +333,14 @@ uint8_t * buffer_payload( setup_packet *spacket, buffer *buff, uint8_t hostsetbu
|
|||
operation = PROBLEM;
|
||||
}
|
||||
} else {//writes
|
||||
//cur_usb_load_buff = &buff0;
|
||||
cur_usb_load_buff = cur_buff;
|
||||
//buff0.status = USB_LOADING;
|
||||
cur_buff->status = USB_LOADING;
|
||||
if ( cur_buff->status == EMPTY ) {
|
||||
//send cur_buff to usbFunctionWrite to be filled
|
||||
cur_usb_load_buff = cur_buff;
|
||||
cur_buff->status = USB_LOADING;
|
||||
} else {
|
||||
operation = PROBLEM;
|
||||
}
|
||||
}
|
||||
//buff0.cur_byte = 0;
|
||||
cur_buff->cur_byte = 0;
|
||||
|
||||
} else { //host determined the buffer to use
|
||||
|
|
@ -592,6 +594,7 @@ void update_buffers()
|
|||
{
|
||||
uint8_t result = 0;
|
||||
static uint8_t num_buff;
|
||||
buffer *last_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
|
||||
|
|
@ -615,23 +618,10 @@ void update_buffers()
|
|||
//we always start with buff0
|
||||
cur_buff = &buff0;
|
||||
//now we can get_next_buff by passing cur_buff
|
||||
|
||||
}
|
||||
if (operation == STARTDUMP) {
|
||||
//prepare both buffers to dump
|
||||
// cur_buff->cur_byte = 0;
|
||||
// cur_buff->status = DUMPING;
|
||||
// //send first buffer off to dump
|
||||
// result = dump_page( cur_buff );
|
||||
// if (result != SUCCESS) {
|
||||
// cur_buff->status = PROBLEM;
|
||||
// } else {
|
||||
// cur_buff->status = DUMPED;
|
||||
// //increment page_num so everything is ready for next dump
|
||||
// cur_buff->page_num += cur_buff->reload;
|
||||
// }
|
||||
//now it's ready and just waiting for IN transfer
|
||||
//pretend the last buffer is in USB transfer and
|
||||
//we're waiting to have that dump until the first buffer starts USB transfer
|
||||
|
||||
//do all the same things that would happen between buffers to start things moving
|
||||
//pretend the last buffer is unloading via USB right now
|
||||
|
|
@ -651,6 +641,16 @@ void update_buffers()
|
|||
//don't want to reenter start initialiation again
|
||||
operation = FLASHING;
|
||||
|
||||
//not much else to do, just waiting on payload OUT transfer
|
||||
//current buffer prepared to be sent to usbFunctionWrite
|
||||
cur_buff->status = EMPTY;
|
||||
|
||||
//TODO
|
||||
//perhaps this is where the mapper registers should be initialized as needed
|
||||
//for all buffer writes.
|
||||
//but this will bloat firmware code with each mapper..
|
||||
//so prob best for host to handle this with series of single byte write opcodes
|
||||
|
||||
}
|
||||
|
||||
//this will get entered on first and all successive calls
|
||||
|
|
@ -668,7 +668,7 @@ void update_buffers()
|
|||
cur_buff->cur_byte = 0;
|
||||
cur_buff->status = DUMPING;
|
||||
//send buffer off to dump
|
||||
result = dump_page( cur_buff );
|
||||
result = dump_buff( cur_buff );
|
||||
if (result != SUCCESS) {
|
||||
cur_buff->status = result;
|
||||
} else {
|
||||
|
|
@ -681,6 +681,33 @@ void update_buffers()
|
|||
|
||||
}
|
||||
|
||||
if ( operation == FLASHING ) {
|
||||
//cur_buff will get sent to usbFunctionWrite on next payload OUT transfer
|
||||
//All we need to do here is monitor usbFWr's status via incoming_bytes_remain
|
||||
//which gets set to 254 on wr transfers once gets to zero buffer is filled
|
||||
if ( incoming_bytes_remain == 0 ) {
|
||||
incoming_bytes_remain--; //don't want to re-enter
|
||||
|
||||
//buffer full, send to flash routine
|
||||
last_buff = cur_buff;
|
||||
//but first want to update cur_buff to next buffer so it can
|
||||
//start loading on next OUT transfer
|
||||
cur_buff = get_next_buff( cur_buff, num_buff );
|
||||
cur_buff->status = EMPTY;
|
||||
|
||||
last_buff->status = FLASHING;
|
||||
result = flash_buff( last_buff );
|
||||
if (result != SUCCESS) {
|
||||
last_buff->status = result;
|
||||
} else {
|
||||
last_buff->status = FLASHED;
|
||||
cur_buff->page_num += cur_buff->reload;
|
||||
}
|
||||
//page should be flashed to memory now
|
||||
//the next buffer should be in process of getting filled
|
||||
//once full we'll end up back here again
|
||||
}
|
||||
}
|
||||
|
||||
//to start let's sense dumping operation by buffer status
|
||||
//host updates status of buffer, then we go off and dump as appropriate
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
* Post:page dumped from cart memory to buffer.
|
||||
* Rtn: SUCCESS or ERROR# depending on if there were errors.
|
||||
*/
|
||||
uint8_t dump_page( buffer *buff ) {
|
||||
uint8_t dump_buff( buffer *buff ) {
|
||||
|
||||
uint8_t addrH = buff->page_num; //A15:8 while accessing page
|
||||
//warn uint8_t addrX; //A23:16 while accessing page
|
||||
|
|
|
|||
|
|
@ -11,6 +11,6 @@
|
|||
#include "shared_errors.h"
|
||||
#include "shared_enums.h"
|
||||
|
||||
uint8_t dump_page( buffer *buff ) ;
|
||||
uint8_t dump_buff( buffer *buff ) ;
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1,48 +1,84 @@
|
|||
#include "flash.h"
|
||||
|
||||
|
||||
/* Desc:Programs buffer's data onto cart memory
|
||||
* Pre: Sector/Chip must be erased if required
|
||||
* buffer elements must be updated to designate how to program
|
||||
* Post:page flashed/programmed to designated memory.
|
||||
* Rtn: SUCCESS or ERROR# depending on if there were errors.
|
||||
*/
|
||||
uint8_t flash_page( buffer *buff ) {
|
||||
|
||||
uint8_t addrH = (buff->page_num | 0x80); //or in $8000 to set equiv CPU address
|
||||
uint8_t write_page( uint8_t bank, uint8_t addrH, buffer *buff, write_funcptr wr_func, read_funcptr rd_func )
|
||||
{
|
||||
uint8_t i = buff->cur_byte;
|
||||
uint8_t read;
|
||||
|
||||
//lets start just reading first page of PRG-ROM then get fancy
|
||||
while (buff->cur_byte < buff->last_idx) {
|
||||
do {
|
||||
//write unlock sequence
|
||||
wr_func( 0x55, 0x55, 0xAA );
|
||||
wr_func( 0x2A, 0xAA, 0x55 );
|
||||
wr_func( 0x55, 0x55, 0xA0 );
|
||||
wr_func( addrH, i, buff->data[i] );
|
||||
|
||||
//write unlock sequence first
|
||||
discrete_exp0_prgrom_wr( 0x55, 0x55, 0xAA );
|
||||
discrete_exp0_prgrom_wr( 0x2A, 0xAA, 0x55 );
|
||||
discrete_exp0_prgrom_wr( 0x55, 0x55, 0xA0 );
|
||||
do {
|
||||
usbPoll();
|
||||
read = rd_func( addrH, i );
|
||||
|
||||
//then flash byte
|
||||
discrete_exp0_prgrom_wr( addrH, buff->cur_byte, buff->data[buff->cur_byte] );
|
||||
} while( read != rd_func( addrH, i) );
|
||||
|
||||
//then spin until write finished
|
||||
read = nes_cpu_rd(addrH,buff->cur_byte);
|
||||
while ( read != nes_cpu_rd(addrH,buff->cur_byte) ) {
|
||||
read = nes_cpu_rd(addrH,buff->cur_byte);
|
||||
}
|
||||
|
||||
//byte stable, now verify proper value
|
||||
if ( read == buff->data[buff->cur_byte] ) {
|
||||
buff->cur_byte++;
|
||||
_LED_OFF();
|
||||
} else {//don't increment, retry
|
||||
_LED_OP();
|
||||
_LED_ON();
|
||||
}
|
||||
}
|
||||
//move on to next byte
|
||||
i++;
|
||||
} while ( i != buff->last_idx );
|
||||
|
||||
return SUCCESS;
|
||||
|
||||
|
||||
}
|
||||
|
||||
/* Desc:Flash buffer contents on to cartridge memory
|
||||
* Pre: buffer elements must be updated to designate how/where to flash
|
||||
* buffer's cur_byte must be cleared or set to where to start flashing
|
||||
* mapper registers must be initialized
|
||||
* Post:buffer page flashed/programmed to memory.
|
||||
* Rtn: SUCCESS or ERROR# depending on if there were errors.
|
||||
*/
|
||||
uint8_t flash_buff( buffer *buff ) {
|
||||
|
||||
uint8_t addrH = buff->page_num; //A15:8 while accessing page
|
||||
|
||||
//First need to initialize mapper register bits
|
||||
//Perhaps this only needs to be done on first buffer though..?
|
||||
//Actually think this is best handled from buffer.c in operation == STARTFLASH
|
||||
|
||||
//TODO use mapper to set mapper controlled address bits
|
||||
|
||||
//need to calculate current bank and addrH
|
||||
|
||||
//TODO set unlock addresses based on what works for that mapper and how it's banks are initialized
|
||||
|
||||
//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: //$8000
|
||||
write_page( 0, (0x80 | addrH), buff, discrete_exp0_prgrom_wr, nes_cpu_rd );
|
||||
break;
|
||||
case CHRROM: //$0000
|
||||
write_page( 0, addrH, buff, nes_ppu_wr, nes_ppu_rd );
|
||||
break;
|
||||
case PRGRAM:
|
||||
//addrH |= 0x60; //$6000
|
||||
//buff->cur_byte = nes_cpu_page_wr_poll( buff->data, addrH, buff->id,
|
||||
// buff->last_idx, ~FALSE );
|
||||
break;
|
||||
case SNESROM:
|
||||
case SNESRAM:
|
||||
//warn 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++;
|
||||
// }
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,12 +2,15 @@
|
|||
#define _flash_h
|
||||
|
||||
#include <avr/io.h>
|
||||
#include "usbdrv.h"
|
||||
#include "types.h"
|
||||
#include "logic.h"
|
||||
#include "usb.h"
|
||||
#include "nes.h"
|
||||
#include "shared_dictionaries.h"
|
||||
#include "shared_errors.h"
|
||||
#include "shared_enums.h"
|
||||
|
||||
uint8_t flash_page( buffer *buff ) ;
|
||||
uint8_t flash_buff( buffer *buff ) ;
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1,20 +0,0 @@
|
|||
AVR Memory Usage
|
||||
----------------
|
||||
Device: atmega164a
|
||||
|
||||
Program: 5486 bytes (33.5% Full)
|
||||
(.text + .data + .bootloader)
|
||||
|
||||
Data: 653 bytes (63.8% Full)
|
||||
(.data + .bss + .noinit)
|
||||
|
||||
AVR Memory Usage
|
||||
----------------
|
||||
Device: atmega164a
|
||||
|
||||
Program: 5498 bytes (33.6% Full)
|
||||
(.text + .data + .bootloader)
|
||||
|
||||
Data: 653 bytes (63.8% Full)
|
||||
(.data + .bss + .noinit)
|
||||
|
||||
|
|
@ -37,4 +37,8 @@ typedef struct buffer {
|
|||
uint8_t function; //function "pointer" for flash/dump operation control
|
||||
}buffer;
|
||||
|
||||
//write function pointers
|
||||
typedef void (*write_funcptr) ( uint8_t addrH, uint8_t addrL, uint8_t data );
|
||||
typedef uint8_t (*read_funcptr) ( uint8_t addrH, uint8_t addrL );
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -30,6 +30,9 @@ int allocate_buffers( USBtransfer *transfer, int num_buffers, int buff_size ) {
|
|||
int buff1id = 0;
|
||||
int buff1basebank = 0;
|
||||
int numbanks= 0;
|
||||
int reload = 0;
|
||||
int buff0_firstpage = 0;
|
||||
int buff1_firstpage = 0;
|
||||
|
||||
//want to allocate buffers as makes sense based on num and size
|
||||
//Ideally a buffer will be 256Bytes which equals a page size
|
||||
|
|
@ -38,46 +41,69 @@ int allocate_buffers( USBtransfer *transfer, int num_buffers, int buff_size ) {
|
|||
//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.
|
||||
|
||||
buff0basebank = 0;
|
||||
numbanks= buff_size/RAW_BANK_SIZE;
|
||||
buff1basebank= numbanks; //buff1 starts right after buff0
|
||||
|
||||
if( (num_buffers == 2) && (buff_size == 128)) {
|
||||
//buff0 dumps first half of page, buff1 dumps second half, repeat
|
||||
//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
|
||||
|
||||
//allocate buffer0
|
||||
rv = dictionary_call( 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( 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;
|
||||
}
|
||||
//set reload (value added to page_num after each load/dump to sum of buffers
|
||||
// 2 * 128 = 256 -> reload = 1
|
||||
reload = 0x01;
|
||||
//set first page
|
||||
buff0_firstpage = 0x0000;
|
||||
buff1_firstpage = 0x0000;
|
||||
|
||||
//set reload (value added to page_num after each load/dump to sum of buffers
|
||||
// 2 * 128 = 256 -> reload = 1
|
||||
//set buffer0
|
||||
dictionary_call( transfer, DICT_BUFFER, SET_RELOAD_PAGENUM0, 0x0000, 0x01,
|
||||
USB_IN, NULL, 1);
|
||||
//set buffer1
|
||||
dictionary_call( transfer, DICT_BUFFER, SET_RELOAD_PAGENUM1, 0x0000, 0x01,
|
||||
USB_IN, NULL, 1);
|
||||
} else if( (num_buffers == 2) && (buff_size == 256)) {
|
||||
//buff0 dumps even pages, buff1 dumps odd pages
|
||||
//buffer id not used for addressing both id zero for now..
|
||||
buff0id = 0x00;
|
||||
buff1id = 0x00;
|
||||
|
||||
//set reload (value added to page_num after each load/dump to sum of buffers
|
||||
// 2 * 256 = 512 -> reload = 2
|
||||
reload = 0x02;
|
||||
//set first page of each buffer
|
||||
buff0_firstpage = 0x0000;
|
||||
buff1_firstpage = 0x0001;
|
||||
|
||||
} else {
|
||||
//don't continue
|
||||
sentinel("Not setup to handle this buffer config");
|
||||
}
|
||||
|
||||
|
||||
//allocate buffer0
|
||||
rv = dictionary_call( 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( 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;
|
||||
}
|
||||
|
||||
//set first page and reload (value added to page_num after each load/dump to sum of buffers
|
||||
//set buffer0
|
||||
dictionary_call( transfer, DICT_BUFFER, SET_RELOAD_PAGENUM0, buff0_firstpage, reload,
|
||||
USB_IN, NULL, 1);
|
||||
//set buffer1
|
||||
dictionary_call( transfer, DICT_BUFFER, SET_RELOAD_PAGENUM1, buff1_firstpage, reload,
|
||||
USB_IN, NULL, 1);
|
||||
|
||||
|
||||
return SUCCESS;
|
||||
error:
|
||||
return ~SUCCESS;
|
||||
|
|
@ -128,6 +154,29 @@ int payload_in( USBtransfer *transfer, uint8_t *data, int length )
|
|||
USB_IN, data, length);
|
||||
}
|
||||
|
||||
/* Desc:Payload OUT transfer
|
||||
* Pre: buffers are allocated operation started
|
||||
* Post:payload of length transfered to USB device
|
||||
* Rtn: SUCCESS if no errors
|
||||
*/
|
||||
int payload_out( USBtransfer *transfer, uint8_t *data, int length )
|
||||
{
|
||||
check( length < MAX_VUSB+3, "can't transfer more than %d bytes per transfer", MAX_VUSB+2 );
|
||||
//if over 254 bytes, must stuff first two bytes in setup packet
|
||||
if ( length > MAX_VUSB ) {
|
||||
return dictionary_call( transfer, DICT_BUFFER, BUFF_OUT_PAYLOAD_2B_INSP,
|
||||
//byte0, byte1, bytes3-254
|
||||
data[0], data[1], USB_OUT, &data[2], length-2);
|
||||
} else {
|
||||
return dictionary_call( transfer, DICT_BUFFER, BUFF_PAYLOAD,
|
||||
NILL, NILL, USB_OUT, data, length);
|
||||
}
|
||||
|
||||
error:
|
||||
return ~SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/* Desc:Get buffer elements and print them
|
||||
* Pre: buffers are allocated
|
||||
* Post:
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ int set_mem_n_part( USBtransfer *transfer, int buff_num, int mem_type, int part_
|
|||
int set_map_n_mapvar( USBtransfer *transfer, int buff_num, int mapper, int map_var );
|
||||
int set_buff_operation( USBtransfer *transfer, int operation );
|
||||
int payload_in( USBtransfer *transfer, uint8_t *data, int length );
|
||||
int payload_out( USBtransfer *transfer, uint8_t *data, int length );
|
||||
int get_buff_elements( USBtransfer *transfer, int buff_num );
|
||||
int get_buff_operation( USBtransfer *transfer );
|
||||
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ int detect_file( rom_image *rom )
|
|||
|
||||
//size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
|
||||
rv = fread( header, sizeof(header[0]), (sizeof(header)/sizeof(header[0])), rom->fileptr);
|
||||
check( rv = sizeof(header), "Unable to read NES header");
|
||||
check( rv == sizeof(header), "Unable to read NES header");
|
||||
|
||||
//0-3: Constant $4E $45 $53 $1A ("NES" followed by MS-DOS end-of-file)
|
||||
if ( (header[0]=='N') && (header[1]=='E') && (header[2]=='S') && (header[3]==0x1A) ) {
|
||||
|
|
@ -133,3 +133,22 @@ int append_to_file( rom_image *rom, uint8_t *data, int length )
|
|||
error:
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Desc:Read data from file
|
||||
* Pre: file opened and current position set to desired location
|
||||
* Post:data filled with length amount of data from file
|
||||
* file still open
|
||||
* Rtn: SUCCESS if no errors
|
||||
*/
|
||||
int read_from_file( rom_image *rom, uint8_t *data, int length )
|
||||
{
|
||||
int rv = 0;
|
||||
//size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
|
||||
rv = fread( data, sizeof(data[0]), length, rom->fileptr );
|
||||
|
||||
check( (rv == length), "Error reading from file, %dB read when trying to read %d", rv, length);
|
||||
|
||||
return SUCCESS;
|
||||
error:
|
||||
return -1;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@ int open_rom( rom_image *rom, char *filename );
|
|||
int detect_file( rom_image *rom );
|
||||
int create_file( rom_image *rom, char *filename );
|
||||
int append_to_file( rom_image *rom, uint8_t *data, int length );
|
||||
int read_from_file( rom_image *rom, uint8_t *data, int length );
|
||||
int close_rom( rom_image *rom );
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -0,0 +1,172 @@
|
|||
#include "flash.h"
|
||||
|
||||
/* Desc:
|
||||
* Pre:
|
||||
* Post:
|
||||
* Rtn:
|
||||
*/
|
||||
//should know what mapper the board is by the time we get here
|
||||
//might be hard to tell if all flash is addressable until start writing data though
|
||||
int flash_cart( USBtransfer* transfer, rom_image *rom, cartridge *cart )
|
||||
{
|
||||
//make some checks to ensure rom is compatible with cart
|
||||
|
||||
//first do some checks like ensuring proper areas or sectors are blank
|
||||
|
||||
//erase sectors or chip as needed
|
||||
|
||||
//reset, allocate, and initialize device buffers
|
||||
|
||||
//initialize mapper registers as needed for memory being programmed
|
||||
|
||||
//set device operation to STARTFLASH
|
||||
|
||||
//send payload data
|
||||
|
||||
//run checksums to verify successful flash operation
|
||||
|
||||
int num_buffers = 2;
|
||||
int buff_size = 256;
|
||||
int buff0 = 0;
|
||||
int buff1 = 1;
|
||||
int i;
|
||||
uint8_t data[buff_size];
|
||||
|
||||
|
||||
debug("flashing 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");
|
||||
}
|
||||
|
||||
//start with reset and init
|
||||
io_reset( transfer );
|
||||
nes_init( transfer );
|
||||
//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 flashing
|
||||
//2x 256Byte buffers
|
||||
check(! allocate_buffers( transfer, num_buffers, buff_size ), "Unable to allocate buffers");
|
||||
|
||||
//set mem_type and part_num to designate how to get/write data
|
||||
check(! set_mem_n_part( transfer, buff0, PRGROM, SST_MANF_ID ), "Unable to set mem_type and part");
|
||||
check(! set_mem_n_part( transfer, buff1, PRGROM, SST_MANF_ID ), "Unable to set mem_type and part");
|
||||
//set multiple and add_mult only when flashing
|
||||
//TODO
|
||||
//set mapper, map_var, and function to designate read/write algo
|
||||
|
||||
//just dump visible NROM memory to start
|
||||
check(! set_map_n_mapvar( transfer, buff0, NROM, NILL ), "Unable to set mapper and map_var");
|
||||
check(! set_map_n_mapvar( transfer, buff1, NROM, NILL ), "Unable to set mapper and map_var");
|
||||
|
||||
//tell buffers what function to use for flashing
|
||||
//TODO when start implementing other mappers
|
||||
|
||||
//debugging print out buffer elements
|
||||
get_buff_operation( transfer );
|
||||
get_buff_elements( transfer, buff0 );
|
||||
get_buff_elements( transfer, buff1 );
|
||||
|
||||
debug("\n\nsetting operation STARTFLASH");
|
||||
//inform buffer manager to start dumping operation now that buffers are initialized
|
||||
check(! set_buff_operation( transfer, STARTFLASH ), "Unable to set buffer operation");
|
||||
|
||||
// get_buff_operation( transfer );
|
||||
// get_buff_elements( transfer, buff0 );
|
||||
// get_buff_elements( transfer, buff1 );
|
||||
// //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
|
||||
//
|
||||
// debug("first payload");
|
||||
// check(! read_from_file( rom, data, buff_size ), "Error with file read");
|
||||
// //check(! payload_out( transfer, data, buff_size ), "Error with payload OUT");
|
||||
// payload_out( transfer, data, buff_size );
|
||||
// get_buff_operation( transfer );
|
||||
// get_buff_elements( transfer, buff0 );
|
||||
// get_buff_elements( transfer, buff1 );
|
||||
//
|
||||
// debug("first payload done");
|
||||
//// get_buff_operation( transfer );
|
||||
//// get_buff_elements( transfer, buff0 );
|
||||
//// get_buff_elements( transfer, buff1 );
|
||||
////
|
||||
// debug("second payload");
|
||||
// check(! read_from_file( rom, data, buff_size ), "Error with file read");
|
||||
// check(! payload_out( transfer, data, buff_size ), "Error with payload OUT");
|
||||
|
||||
// get_buff_operation( transfer );
|
||||
// get_buff_elements( transfer, buff0 );
|
||||
// get_buff_elements( transfer, buff1 );
|
||||
|
||||
clock_t tstart, tstop;
|
||||
tstart = clock();
|
||||
|
||||
//now just need to call series of payload IN transfers to retrieve data
|
||||
//for( i=0; i<(512*KByte/buff_size); i++) {
|
||||
for( i=0; i<(32*KByte/buff_size); i++) {
|
||||
//for( i=0; i<(8*KByte/buff_size); i++) {
|
||||
check(! read_from_file( rom, data, buff_size ), "Error with file read");
|
||||
check(! payload_out( transfer, data, buff_size ), "Error with payload OUT");
|
||||
//if ( i % 256 == 0 ) debug("payload in #%d", i);
|
||||
if ( i % 32 == 0 ) debug("payload out #%d", i);
|
||||
}
|
||||
debug("payload done");
|
||||
//need to delay further USB commands until last buffer is flashed
|
||||
//TODO spin while buff1 status == FLASHING
|
||||
//currently this takes about as long as two get elements
|
||||
get_buff_elements( transfer, buff1 );
|
||||
get_buff_elements( transfer, buff1 );
|
||||
get_buff_elements( transfer, buff1 );
|
||||
|
||||
tstop = clock();
|
||||
float timediff = ( (float)(tstop-tstart) / CLOCKS_PER_SEC);
|
||||
printf("total time: %fsec, speed: %fKBps\n", timediff, (512/timediff));
|
||||
//TODO flush file from time to time..?
|
||||
|
||||
|
||||
//tell buffer manager when to stop
|
||||
// or not..? just reset buffers and start next memory or quit
|
||||
//reset buffers and setup to dump CHR-ROM
|
||||
|
||||
check(! reset_buffers( transfer ), "Unable to reset device buffers");
|
||||
check(! allocate_buffers( transfer, num_buffers, buff_size ), "Unable to allocate buffers");
|
||||
check(! set_mem_n_part( transfer, buff0, CHRROM, SST_MANF_ID ), "Unable to set mem_type and part");
|
||||
check(! set_mem_n_part( transfer, buff1, CHRROM, SST_MANF_ID ), "Unable to set mem_type and part");
|
||||
check(! set_map_n_mapvar( transfer, buff0, NROM, NILL ), "Unable to set mapper and map_var");
|
||||
check(! set_map_n_mapvar( transfer, buff1, NROM, NILL ), "Unable to set mapper and map_var");
|
||||
|
||||
debug("\n\nsetting operation STARTFLASH");
|
||||
//inform buffer manager to start dumping operation now that buffers are initialized
|
||||
check(! set_buff_operation( transfer, STARTFLASH ), "Unable to set buffer operation");
|
||||
|
||||
for( i=0; i<(8*KByte/buff_size); i++) {
|
||||
check(! read_from_file( rom, data, buff_size ), "Error with file read");
|
||||
check(! payload_out( transfer, data, buff_size ), "Error with payload OUT");
|
||||
//if ( i % 256 == 0 ) debug("payload in #%d", i);
|
||||
if ( i % 32 == 0 ) debug("payload out #%d", i);
|
||||
}
|
||||
debug("payload done");
|
||||
|
||||
//close file in main
|
||||
|
||||
//reset io at end
|
||||
io_reset( transfer );
|
||||
|
||||
return SUCCESS;
|
||||
error:
|
||||
return ~SUCCESS;
|
||||
}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
#ifndef _flash_h
|
||||
#define _flash_h
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
|
||||
//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 flash_cart( USBtransfer* transfer, rom_image *rom, cartridge *cart );
|
||||
|
||||
|
||||
#endif
|
||||
|
|
@ -20,6 +20,7 @@
|
|||
#include "cartridge.h"
|
||||
#include "file.h"
|
||||
#include "dump.h"
|
||||
#include "flash.h"
|
||||
#include "shared_enums.h"
|
||||
|
||||
|
||||
|
|
@ -274,6 +275,13 @@ int main(int argc, char *argv[])
|
|||
//program file provided at commandline
|
||||
check( !open_rom( rom, p_value ), "Problem opening file %s", p_value);
|
||||
detect_file( rom );
|
||||
|
||||
check( !flash_cart( transfer, rom, cart ), "Error while flashing cart");
|
||||
debug("done flashing, closing");
|
||||
|
||||
check(! close_rom( rom ), "Problem closing file");
|
||||
rom->fileptr = NULL;
|
||||
debug("closed");
|
||||
}
|
||||
|
||||
//if flashing, determine if erasures are necessary and where
|
||||
|
|
|
|||
Loading…
Reference in New Issue