Merge pull request #36 from ramapcsx2/n64_speedup

n64_speedup
This commit is contained in:
sanni 2019-08-29 07:09:27 +02:00 committed by GitHub
commit 95ba179b74
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 115 additions and 101 deletions

View File

@ -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
*****************************************/ *****************************************/

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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

View File

@ -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()) {