mirror of
https://github.com/sanni/cartreader.git
synced 2024-11-14 08:55:06 +01:00
commit
95ba179b74
@ -145,6 +145,11 @@ SdFile myFile;
|
|||||||
#define mode_PCE 13
|
#define mode_PCE 13
|
||||||
#define mode_SV 14
|
#define mode_SV 14
|
||||||
|
|
||||||
|
/******************************************
|
||||||
|
optimization-safe nop delay
|
||||||
|
*****************************************/
|
||||||
|
#define NOP __asm__ __volatile__ ("nop\n\t")
|
||||||
|
|
||||||
/******************************************
|
/******************************************
|
||||||
Variables
|
Variables
|
||||||
*****************************************/
|
*****************************************/
|
||||||
|
@ -449,7 +449,7 @@ void readROM_GB() {
|
|||||||
|
|
||||||
unsigned int calc_checksum_GB (char* fileName, char* folder) {
|
unsigned int calc_checksum_GB (char* fileName, char* folder) {
|
||||||
unsigned int calcChecksum = 0;
|
unsigned int calcChecksum = 0;
|
||||||
int calcFilesize = 0;
|
// int calcFilesize = 0; // unused
|
||||||
unsigned long i = 0;
|
unsigned long i = 0;
|
||||||
int c = 0;
|
int c = 0;
|
||||||
|
|
||||||
@ -458,7 +458,7 @@ unsigned int calc_checksum_GB (char* fileName, char* folder) {
|
|||||||
|
|
||||||
// If file exists
|
// If file exists
|
||||||
if (myFile.open(fileName, O_READ)) {
|
if (myFile.open(fileName, O_READ)) {
|
||||||
calcFilesize = myFile.fileSize() * 8 / 1024 / 1024;
|
//calcFilesize = myFile.fileSize() * 8 / 1024 / 1024; // unused
|
||||||
for (i = 0; i < (myFile.fileSize() / 512); i++) {
|
for (i = 0; i < (myFile.fileSize() / 512); i++) {
|
||||||
myFile.read(sdBuffer, 512);
|
myFile.read(sdBuffer, 512);
|
||||||
for (c = 0; c < 512; c++) {
|
for (c = 0; c < 512; c++) {
|
||||||
@ -959,7 +959,7 @@ void writeFlash_GB(byte MBC) {
|
|||||||
|
|
||||||
// Go back to file beginning
|
// Go back to file beginning
|
||||||
myFile.seekSet(0);
|
myFile.seekSet(0);
|
||||||
unsigned int addr = 0;
|
//unsigned int addr = 0; // unused
|
||||||
writeErrors = 0;
|
writeErrors = 0;
|
||||||
|
|
||||||
// Verify flashrom
|
// Verify flashrom
|
||||||
|
@ -768,8 +768,6 @@ void getCartInfo_GBA() {
|
|||||||
else {
|
else {
|
||||||
char tempStr2[2];
|
char tempStr2[2];
|
||||||
char tempStr[5];
|
char tempStr[5];
|
||||||
char sizeStr[3];
|
|
||||||
char saveStr[2];
|
|
||||||
|
|
||||||
// cart not in list
|
// cart not in list
|
||||||
cartSize = 0;
|
cartSize = 0;
|
||||||
|
@ -68,11 +68,10 @@ static const char N64CartMenuItem5[] PROGMEM = "Reset";
|
|||||||
static const char* const menuOptionsN64Cart[] PROGMEM = {N64CartMenuItem1, N64CartMenuItem2, N64CartMenuItem3, N64CartMenuItem4, N64CartMenuItem5};
|
static const char* const menuOptionsN64Cart[] PROGMEM = {N64CartMenuItem1, N64CartMenuItem2, N64CartMenuItem3, N64CartMenuItem4, N64CartMenuItem5};
|
||||||
|
|
||||||
// N64 CRC32 error menu items
|
// N64 CRC32 error menu items
|
||||||
static const char N64CRCMenuItem1[] PROGMEM = "Recalc CRC";
|
static const char N64CRCMenuItem1[] PROGMEM = "Redump";
|
||||||
static const char N64CRCMenuItem2[] PROGMEM = "Redump";
|
static const char N64CRCMenuItem2[] PROGMEM = "Ignore";
|
||||||
static const char N64CRCMenuItem3[] PROGMEM = "Ignore";
|
static const char N64CRCMenuItem3[] PROGMEM = "Reset";
|
||||||
static const char N64CRCMenuItem4[] PROGMEM = "Reset";
|
static const char* const menuOptionsN64CRC[] PROGMEM = {N64CRCMenuItem1, N64CRCMenuItem2, N64CRCMenuItem3};
|
||||||
static const char* const menuOptionsN64CRC[] PROGMEM = {N64CRCMenuItem1, N64CRCMenuItem2, N64CRCMenuItem3, N64CRCMenuItem4};
|
|
||||||
|
|
||||||
// Rom menu
|
// Rom menu
|
||||||
static const char N64RomItem1[] PROGMEM = "4MB";
|
static const char N64RomItem1[] PROGMEM = "4MB";
|
||||||
@ -528,25 +527,26 @@ static word addrCRC(word address) {
|
|||||||
return address | crc;
|
return address | crc;
|
||||||
}
|
}
|
||||||
|
|
||||||
static byte dataCRC(byte * data) {
|
// unused
|
||||||
byte ret = 0;
|
//static byte dataCRC(byte * data) {
|
||||||
for (byte i = 0; i <= 32; i++) {
|
// byte ret = 0;
|
||||||
for (byte j = 7; j >= 0; j--) {
|
// for (byte i = 0; i <= 32; i++) {
|
||||||
int tmp = 0;
|
// for (byte j = 7; j >= 0; j--) {
|
||||||
if (ret & 0x80) {
|
// int tmp = 0;
|
||||||
tmp = 0x85;
|
// if (ret & 0x80) {
|
||||||
}
|
// tmp = 0x85;
|
||||||
ret <<= 1;
|
// }
|
||||||
if ( i < 32 ) {
|
// ret <<= 1;
|
||||||
if (data[i] & (0x01 << j)) {
|
// if ( i < 32 ) {
|
||||||
ret |= 0x1;
|
// if (data[i] & (0x01 << j)) {
|
||||||
}
|
// ret |= 0x1;
|
||||||
}
|
// }
|
||||||
ret ^= tmp;
|
// }
|
||||||
}
|
// ret ^= tmp;
|
||||||
}
|
// }
|
||||||
return ret;
|
// }
|
||||||
}
|
// return ret;
|
||||||
|
//}
|
||||||
|
|
||||||
/******************************************
|
/******************************************
|
||||||
N64 Controller Protocol Functions
|
N64 Controller Protocol Functions
|
||||||
@ -554,7 +554,6 @@ static byte dataCRC(byte * data) {
|
|||||||
void N64_send(unsigned char *buffer, char length) {
|
void N64_send(unsigned char *buffer, char length) {
|
||||||
// Send these bytes
|
// Send these bytes
|
||||||
char bits;
|
char bits;
|
||||||
bool bit;
|
|
||||||
|
|
||||||
// This routine is very carefully timed by examining the assembly output.
|
// This routine is very carefully timed by examining the assembly output.
|
||||||
// Do not change any statements, it could throw the timings off
|
// Do not change any statements, it could throw the timings off
|
||||||
@ -1136,7 +1135,7 @@ void printCartInfo_N64() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// CRC32 lookup table
|
// CRC32 lookup table // 256 entries
|
||||||
static const uint32_t crc_32_tab[] PROGMEM = { /* CRC polynomial 0xedb88320 */
|
static const uint32_t crc_32_tab[] PROGMEM = { /* CRC polynomial 0xedb88320 */
|
||||||
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
|
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
|
||||||
0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
|
0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
|
||||||
@ -1183,33 +1182,6 @@ static const uint32_t crc_32_tab[] PROGMEM = { /* CRC polynomial 0xedb88320 */
|
|||||||
0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
|
0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
|
||||||
};
|
};
|
||||||
|
|
||||||
// Calculate dumped rom's CRC32
|
|
||||||
inline uint32_t updateCRC32(uint8_t ch, uint32_t crc) {
|
|
||||||
uint32_t idx = ((crc) ^ (ch)) & 0xff;
|
|
||||||
uint32_t tab_value = pgm_read_dword(crc_32_tab + idx);
|
|
||||||
return tab_value ^ ((crc) >> 8);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read rom from sd
|
|
||||||
uint32_t crc32() {
|
|
||||||
if (myFile.open(fileName, O_READ)) {
|
|
||||||
uint32_t oldcrc32 = 0xFFFFFFFF;
|
|
||||||
|
|
||||||
for (unsigned long currByte = 0; currByte < cartSize * 2048; currByte++) {
|
|
||||||
myFile.read(sdBuffer, 512);
|
|
||||||
for (int c = 0; c < 512; c++) {
|
|
||||||
oldcrc32 = updateCRC32(sdBuffer[c], oldcrc32);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Close the file:
|
|
||||||
myFile.close();
|
|
||||||
return ~oldcrc32;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
print_Error(F("File not found"), true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// look-up the calculated crc in the file n64.txt on sd card
|
// look-up the calculated crc in the file n64.txt on sd card
|
||||||
boolean searchCRC(char crcStr[9]) {
|
boolean searchCRC(char crcStr[9]) {
|
||||||
boolean result = 0;
|
boolean result = 0;
|
||||||
@ -1269,8 +1241,6 @@ boolean searchCRC(char crcStr[9]) {
|
|||||||
void getCartInfo_N64() {
|
void getCartInfo_N64() {
|
||||||
char tempStr2[2];
|
char tempStr2[2];
|
||||||
char tempStr[5];
|
char tempStr[5];
|
||||||
char sizeStr[3];
|
|
||||||
char saveStr[2];
|
|
||||||
|
|
||||||
// cart not in list
|
// cart not in list
|
||||||
cartSize = 0;
|
cartSize = 0;
|
||||||
@ -2103,36 +2073,94 @@ readn64rom:
|
|||||||
print_Error(F("SD Error"), true);
|
print_Error(F("SD Error"), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (unsigned long currByte = romBase; currByte < (romBase + (cartSize * 1024 * 1024)); currByte += 512) {
|
// get current time
|
||||||
|
unsigned long startTime = millis();
|
||||||
|
|
||||||
|
byte buffer[1024];
|
||||||
|
|
||||||
|
// run combined dumper + crc32 routine for better performance, as N64 ROMs are quite large for an 8bit micro
|
||||||
|
// currently dumps + checksums a 32MB cart in 170 seconds (down from 347 seconds)
|
||||||
|
uint32_t oldcrc32 = 0xFFFFFFFF;
|
||||||
|
uint32_t tab_value = 0;
|
||||||
|
uint8_t idx = 0;
|
||||||
|
|
||||||
|
for (unsigned long currByte = romBase; currByte < (romBase + (cartSize * 1024 * 1024)); currByte += 1024) {
|
||||||
// Blink led
|
// Blink led
|
||||||
if (currByte % 16384 == 0)
|
if (currByte % 16384 == 0)
|
||||||
PORTB ^= (1 << 4);
|
PORTB ^= (1 << 4);
|
||||||
|
|
||||||
// Set the address for the next 512 bytes
|
// Set the address for the first 512 bytes to dump
|
||||||
setAddress_N64(currByte);
|
setAddress_N64(currByte);
|
||||||
|
// Wait 62.5ns (safety)
|
||||||
|
NOP;
|
||||||
|
|
||||||
for (int c = 0; c < 512; c += 2) {
|
for (int c = 0; c < 512; c += 2) {
|
||||||
// split word
|
// Pull read(PH6) low
|
||||||
word myWord = readWord_N64();
|
PORTH &= ~(1 << 6);
|
||||||
byte loByte = myWord & 0xFF;
|
// Wait ~310ns
|
||||||
byte hiByte = myWord >> 8;
|
NOP; NOP; NOP; NOP; NOP;
|
||||||
|
|
||||||
// write to buffer
|
// data on PINK and PINF is valid now, read into sd card buffer
|
||||||
sdBuffer[c] = hiByte;
|
buffer[c] = PINK; // hiByte
|
||||||
sdBuffer[c + 1] = loByte;
|
buffer[c + 1] = PINF; // loByte
|
||||||
|
|
||||||
|
// Pull read(PH6) high
|
||||||
|
PORTH |= (1 << 6);
|
||||||
|
|
||||||
|
// crc32 update
|
||||||
|
idx = ((oldcrc32) ^ (buffer[c])) & 0xff;
|
||||||
|
tab_value = pgm_read_dword(crc_32_tab + idx);
|
||||||
|
oldcrc32 = tab_value ^ ((oldcrc32) >> 8);
|
||||||
|
idx = ((oldcrc32) ^ (buffer[c + 1])) & 0xff;
|
||||||
|
tab_value = pgm_read_dword(crc_32_tab + idx);
|
||||||
|
oldcrc32 = tab_value ^ ((oldcrc32) >> 8);
|
||||||
}
|
}
|
||||||
myFile.write(sdBuffer, 512);
|
|
||||||
|
// Set the address for the next 512 bytes to dump
|
||||||
|
setAddress_N64(currByte + 512);
|
||||||
|
// Wait 62.5ns (safety)
|
||||||
|
NOP;
|
||||||
|
|
||||||
|
for (int c = 512; c < 1024; c += 2) {
|
||||||
|
// Pull read(PH6) low
|
||||||
|
PORTH &= ~(1 << 6);
|
||||||
|
// Wait ~310ns
|
||||||
|
NOP; NOP; NOP; NOP; NOP;
|
||||||
|
|
||||||
|
// data on PINK and PINF is valid now, read into sd card buffer
|
||||||
|
buffer[c] = PINK; // hiByte
|
||||||
|
buffer[c + 1] = PINF; // loByte
|
||||||
|
|
||||||
|
// Pull read(PH6) high
|
||||||
|
PORTH |= (1 << 6);
|
||||||
|
|
||||||
|
// crc32 update
|
||||||
|
idx = ((oldcrc32) ^ (buffer[c])) & 0xff;
|
||||||
|
tab_value = pgm_read_dword(crc_32_tab + idx);
|
||||||
|
oldcrc32 = tab_value ^ ((oldcrc32) >> 8);
|
||||||
|
idx = ((oldcrc32) ^ (buffer[c + 1])) & 0xff;
|
||||||
|
tab_value = pgm_read_dword(crc_32_tab + idx);
|
||||||
|
oldcrc32 = tab_value ^ ((oldcrc32) >> 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
// write out 1024 bytes to file
|
||||||
|
myFile.write(buffer, 1024);
|
||||||
}
|
}
|
||||||
// Close the file:
|
// Close the file:
|
||||||
myFile.close();
|
myFile.close();
|
||||||
|
|
||||||
if (n64crc) {
|
// print elapsed time
|
||||||
calcn64crc:
|
print_Msg(F("Time elapsed: "));
|
||||||
// Calculate Checksum and convert to string
|
print_Msg((millis() - startTime) / 1000);
|
||||||
println_Msg(F("Calculating CRC.."));
|
println_Msg(F("s"));
|
||||||
display_Update();
|
display_Update();
|
||||||
|
|
||||||
|
if (n64crc) {
|
||||||
|
println_Msg(F("Checking CRC.."));
|
||||||
|
display_Update();
|
||||||
|
// convert checksum to string
|
||||||
char crcStr[9];
|
char crcStr[9];
|
||||||
sprintf(crcStr, "%08lx", crc32());
|
sprintf(crcStr, "%08lx", ~oldcrc32);
|
||||||
// Print checksum
|
// Print checksum
|
||||||
println_Msg(crcStr);
|
println_Msg(crcStr);
|
||||||
display_Update();
|
display_Update();
|
||||||
@ -2145,26 +2173,21 @@ calcn64crc:
|
|||||||
else {
|
else {
|
||||||
// Dump was bad or unknown
|
// Dump was bad or unknown
|
||||||
rgb.setColor(255, 0, 0);
|
rgb.setColor(255, 0, 0);
|
||||||
|
|
||||||
|
// let bad crc show a short while
|
||||||
|
delay(3000);
|
||||||
|
|
||||||
// N64 CRC32 error Menu
|
// N64 CRC32 error Menu
|
||||||
unsigned char CRCMenu;
|
unsigned char CRCMenu;
|
||||||
// Copy menuOptions out of progmem
|
// Copy menuOptions out of progmem
|
||||||
convertPgm(menuOptionsN64CRC, 4);
|
convertPgm(menuOptionsN64CRC, 3);
|
||||||
|
|
||||||
CRCMenu = question_box(F("CRC ERROR "), menuOptions, 4, 1);
|
CRCMenu = question_box(F("CRC ERROR "), menuOptions, 3, 0);
|
||||||
|
|
||||||
// wait for user choice to come back from the question box menu
|
// wait for user choice to come back from the question box menu
|
||||||
switch (CRCMenu)
|
switch (CRCMenu)
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
// Change to last directory
|
|
||||||
sd.chdir(folder);
|
|
||||||
display_Clear();
|
|
||||||
// Calculate CRC again
|
|
||||||
rgb.setColor(0, 0, 0);
|
|
||||||
goto calcn64crc;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 1:
|
|
||||||
// Change to last directory
|
// Change to last directory
|
||||||
sd.chdir(folder);
|
sd.chdir(folder);
|
||||||
// Delete old file
|
// Delete old file
|
||||||
@ -2182,11 +2205,11 @@ calcn64crc:
|
|||||||
goto readn64rom;
|
goto readn64rom;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 2:
|
case 1:
|
||||||
// Return to N64 menu
|
// Return to N64 menu
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 3:
|
case 2:
|
||||||
// Reset
|
// Reset
|
||||||
resetArduino();
|
resetArduino();
|
||||||
break;
|
break;
|
||||||
|
@ -36,7 +36,7 @@ void pin_init_PCE(void);
|
|||||||
void setup_cart_PCE(void);
|
void setup_cart_PCE(void);
|
||||||
void reset_cart_PCE(void);
|
void reset_cart_PCE(void);
|
||||||
uint8_t read_byte_PCE(uint32_t address);
|
uint8_t read_byte_PCE(uint32_t address);
|
||||||
uint8_t write_byte_PCE(uint32_t address, uint8_t data);
|
void write_byte_PCE(uint32_t address, uint8_t data);
|
||||||
uint32_t detect_rom_size_PCE(void);
|
uint32_t detect_rom_size_PCE(void);
|
||||||
void read_bank_PCE(uint32_t address_start, uint32_t address_end, uint32_t *processed_size, uint32_t total_size);
|
void read_bank_PCE(uint32_t address_start, uint32_t address_end, uint32_t *processed_size, uint32_t total_size);
|
||||||
void read_rom_PCE(void);
|
void read_rom_PCE(void);
|
||||||
@ -233,7 +233,6 @@ void set_address_PCE(uint32_t address)
|
|||||||
uint8_t read_byte_PCE(uint32_t address)
|
uint8_t read_byte_PCE(uint32_t address)
|
||||||
{
|
{
|
||||||
uint8_t ret;
|
uint8_t ret;
|
||||||
uint8_t address_byte;
|
|
||||||
|
|
||||||
set_address_PCE(address);
|
set_address_PCE(address);
|
||||||
|
|
||||||
@ -265,11 +264,8 @@ uint8_t read_byte_PCE(uint32_t address)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t write_byte_PCE(uint32_t address, uint8_t data)
|
void write_byte_PCE(uint32_t address, uint8_t data)
|
||||||
{
|
{
|
||||||
uint8_t ret;
|
|
||||||
uint8_t address_byte;
|
|
||||||
|
|
||||||
set_address_PCE(address);
|
set_address_PCE(address);
|
||||||
|
|
||||||
// Arduino running at 16Mhz -> one nop = 62.5ns -> 1000ns total
|
// Arduino running at 16Mhz -> one nop = 62.5ns -> 1000ns total
|
||||||
@ -303,10 +299,6 @@ uint8_t write_byte_PCE(uint32_t address, uint8_t data)
|
|||||||
|
|
||||||
// Enable Internal Pullups
|
// Enable Internal Pullups
|
||||||
PORTC = 0xFF;
|
PORTC = 0xFF;
|
||||||
|
|
||||||
//return read data
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//Confirm the size of ROM - 128Kb, 256Kb, 384Kb, 512Kb, 768Kb or 1024Kb
|
//Confirm the size of ROM - 128Kb, 256Kb, 384Kb, 512Kb, 768Kb or 1024Kb
|
||||||
|
@ -11,8 +11,6 @@
|
|||||||
#define HI 1
|
#define HI 1
|
||||||
#define LO 0
|
#define LO 0
|
||||||
|
|
||||||
// optimization-safe nop delay
|
|
||||||
#define NOP __asm__ __volatile__ ("nop\n\t")
|
|
||||||
/******************************************
|
/******************************************
|
||||||
Variables
|
Variables
|
||||||
*****************************************/
|
*****************************************/
|
||||||
@ -613,8 +611,6 @@ void getCartInfo_SNES() {
|
|||||||
void checkAltConf() {
|
void checkAltConf() {
|
||||||
char tempStr1[2];
|
char tempStr1[2];
|
||||||
char tempStr2[5];
|
char tempStr2[5];
|
||||||
char sizeStr[3];
|
|
||||||
char bankStr[3];
|
|
||||||
|
|
||||||
if (myFile.open("snes.txt", O_READ)) {
|
if (myFile.open("snes.txt", O_READ)) {
|
||||||
while (myFile.available()) {
|
while (myFile.available()) {
|
||||||
|
Loading…
Reference in New Issue
Block a user