From 133e3feda9223adf1e4758bc32a61e01838b021c Mon Sep 17 00:00:00 2001 From: Vincent Pelletier Date: Sat, 29 Oct 2022 01:31:43 +0000 Subject: [PATCH 01/10] Cart_Reader.ino: New variants of print_Error Tagged with noreturn so the compiler knows about the effect of forceReset=true. Ideally, print_Error should lose its forceReset argument so that: - print_Error never resets - print_FatalError always resets (and hosts the code doing so) so the compiler is more accurately aware of the execution flow. --- Cart_Reader/Cart_Reader.ino | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/Cart_Reader/Cart_Reader.ino b/Cart_Reader/Cart_Reader.ino index 91da0a1..85963bc 100644 --- a/Cart_Reader/Cart_Reader.ino +++ b/Cart_Reader/Cart_Reader.ino @@ -490,7 +490,7 @@ byte sdBuffer[512]; // soft reset Arduino: jumps to 0 // using the watchdog timer would be more elegant but some Mega2560 bootloaders are buggy with it -void (*resetArduino)(void) = 0; +void (*resetArduino)(void) __attribute__ ((noreturn)) = 0; // Progressbar void draw_progressbar(uint32_t processedsize, uint32_t totalsize); @@ -2005,6 +2005,22 @@ void print_Error(byte errorMessage, boolean forceReset) { } } +void print_FatalError(const __FlashStringHelper* errorMessage) __attribute__ ((noreturn)); +void print_FatalError(const __FlashStringHelper* errorMessage) { + print_Error(errorMessage, true); + // Redundant as print_Error already calls it, but makes gcc understand that + // this in fact does not return. + resetArduino(); +} + +void print_FatalError(byte errorMessage) __attribute__ ((noreturn)); +void print_FatalError(byte errorMessage){ + print_Error(errorMessage, true); + // Redundant as print_Error already calls it, but makes gcc understand that + // this in fact does not return. + resetArduino(); +} + void wait() { // Switch status LED off statusLED(false); From 65f7950af4ff2e33c89b38e670c7f294a367bcd2 Mon Sep 17 00:00:00 2001 From: Vincent Pelletier Date: Fri, 28 Oct 2022 23:49:41 +0000 Subject: [PATCH 02/10] NES.ino: Move PRG, CHR and RAM to PROGMEM. Uses 90 bytes of program space. Frees 40 bytes of global ram space. --- Cart_Reader/NES.ino | 90 ++++++++++++++++++++++----------------------- 1 file changed, 45 insertions(+), 45 deletions(-) diff --git a/Cart_Reader/NES.ino b/Cart_Reader/NES.ino index efd4e88..0921926 100644 --- a/Cart_Reader/NES.ino +++ b/Cart_Reader/NES.ino @@ -165,15 +165,15 @@ static const byte PROGMEM mapsize[] = { byte mapcount = (sizeof(mapsize) / sizeof(mapsize[0])) / 7; byte mapselect; -int PRG[] = { 16, 32, 64, 128, 256, 512, 1024, 2048, 4096 }; +const int PRG[] PROGMEM = { 16, 32, 64, 128, 256, 512, 1024, 2048, 4096 }; byte prglo = 0; // Lowest Entry byte prghi = 8; // Highest Entry -int CHR[] = { 0, 8, 16, 32, 64, 128, 256, 512, 1024 }; +const int CHR[] PROGMEM = { 0, 8, 16, 32, 64, 128, 256, 512, 1024 }; byte chrlo = 0; // Lowest Entry byte chrhi = 8; // Highest Entry -byte RAM[] = { 0, 8, 16, 32 }; +const byte RAM[] PROGMEM = { 0, 8, 16, 32 }; byte ramlo = 0; // Lowest Entry byte ramhi = 3; // Highest Entry @@ -1885,7 +1885,7 @@ void setPRGSize() { display_Clear(); print_Msg(F("PRG Size: ")); - println_Msg(PRG[i]); + println_Msg(pgm_read_word(&(PRG[i]))); println_Msg(F("")); #if defined(enable_OLED) print_STR(press_to_change_STR, 1); @@ -1907,7 +1907,7 @@ void setPRGSize() { display_Clear(); print_Msg(F("PRG Size: ")); - println_Msg(PRG[i]); + println_Msg(pgm_read_word(&(PRG[i]))); println_Msg(F("")); #if defined(enable_OLED) print_STR(press_to_change_STR, 1); @@ -1926,7 +1926,7 @@ void setPRGSize() { display_Clear(); print_Msg(F("PRG Size: ")); - println_Msg(PRG[i]); + println_Msg(pgm_read_word(&(PRG[i]))); println_Msg(F("")); #if defined(enable_OLED) print_STR(press_to_change_STR, 1); @@ -1946,7 +1946,7 @@ void setPRGSize() { display.setCursor(0, 56); // Display selection at bottom } print_Msg(F("PRG SIZE ")); - print_Msg(PRG[newprgsize]); + print_Msg(pgm_read_word(&(PRG[newprgsize]))); println_Msg(F("K")); display_Update(); delay(1000); @@ -1961,7 +1961,7 @@ setprg: Serial.print(F("Select PRG Size: ")); Serial.print(i); Serial.print(F(" = ")); - Serial.print(PRG[i + prglo]); + Serial.print(pgm_read_word(&(PRG[i + prglo]))); Serial.println(F("K")); } Serial.print(F("Enter PRG Size: ")); @@ -1976,7 +1976,7 @@ setprg: } } Serial.print(F("PRG Size = ")); - Serial.print(PRG[newprgsize]); + Serial.print(pgm_read_word(&(PRG[newprgsize]))); Serial.println(F("K")); #endif EEPROM_writeAnything(8, newprgsize); @@ -2004,7 +2004,7 @@ void setCHRSize() { display_Clear(); print_Msg(F("CHR Size: ")); - println_Msg(CHR[i]); + println_Msg(pgm_read_word(&(CHR[i]))); println_Msg(F("")); #if defined(enable_OLED) print_STR(press_to_change_STR, 1); @@ -2026,7 +2026,7 @@ void setCHRSize() { display_Clear(); print_Msg(F("CHR Size: ")); - println_Msg(CHR[i]); + println_Msg(pgm_read_word(&(CHR[i]))); println_Msg(F("")); #if defined(enable_OLED) print_STR(press_to_change_STR, 1); @@ -2046,7 +2046,7 @@ void setCHRSize() { display_Clear(); print_Msg(F("CHR Size: ")); - println_Msg(CHR[i]); + println_Msg(pgm_read_word(&(CHR[i]))); println_Msg(F("")); #if defined(enable_OLED) print_STR(press_to_change_STR, 1); @@ -2066,7 +2066,7 @@ void setCHRSize() { display.setCursor(0, 56); // Display selection at bottom } print_Msg(F("CHR SIZE ")); - print_Msg(CHR[newchrsize]); + print_Msg(pgm_read_word(&(CHR[newchrsize]))); println_Msg(F("K")); display_Update(); delay(1000); @@ -2081,7 +2081,7 @@ setchr: Serial.print(F("Select CHR Size: ")); Serial.print(i); Serial.print(F(" = ")); - Serial.print(CHR[i + chrlo]); + Serial.print(pgm_read_word(&(CHR[i + chrlo]))); Serial.println(F("K")); } Serial.print(F("Enter CHR Size: ")); @@ -2096,7 +2096,7 @@ setchr: } } Serial.print(F("CHR Size = ")); - Serial.print(CHR[newchrsize]); + Serial.print(pgm_read_word(&(CHR[newchrsize]))); Serial.println(F("K")); #endif EEPROM_writeAnything(9, newchrsize); @@ -2125,20 +2125,20 @@ void setRAMSize() { display_Clear(); print_Msg(F("RAM Size: ")); if (mapper == 0) - println_Msg(RAM[i] / 4); + println_Msg(pgm_read_byte(&(RAM[i])) / 4); else if (mapper == 16) - println_Msg(RAM[i] * 32); + println_Msg(pgm_read_byte(&(RAM[i])) * 32); else if (mapper == 19) { if (i == 2) println_Msg(F("128")); else - println_Msg(RAM[i]); + println_Msg(pgm_read_byte(&(RAM[i]))); } else if ((mapper == 159) || (mapper == 80)) - println_Msg(RAM[i] * 16); + println_Msg(pgm_read_byte(&(RAM[i])) * 16); else if (mapper == 82) println_Msg(i * 5); else - println_Msg(RAM[i]); + println_Msg(pgm_read_byte(&(RAM[i]))); println_Msg(F("")); #if defined(enable_OLED) print_STR(press_to_change_STR, 1); @@ -2161,20 +2161,20 @@ void setRAMSize() { display_Clear(); print_Msg(F("RAM Size: ")); if (mapper == 0) - println_Msg(RAM[i] / 4); + println_Msg(pgm_read_byte(&(RAM[i])) / 4); else if (mapper == 16) - println_Msg(RAM[i] * 32); + println_Msg(pgm_read_byte(&(RAM[i])) * 32); else if (mapper == 19) { if (i == 2) println_Msg(F("128")); else - println_Msg(RAM[i]); + println_Msg(pgm_read_byte(&(RAM[i]))); } else if ((mapper == 159) || (mapper == 80)) - println_Msg(RAM[i] * 16); + println_Msg(pgm_read_byte(&(RAM[i])) * 16); else if (mapper == 82) println_Msg(i * 5); else - println_Msg(RAM[i]); + println_Msg(pgm_read_byte(&(RAM[i]))); println_Msg(F("")); #if defined(enable_OLED) print_STR(press_to_change_STR, 1); @@ -2195,20 +2195,20 @@ void setRAMSize() { display_Clear(); print_Msg(F("RAM Size: ")); if (mapper == 0) - println_Msg(RAM[i] / 4); + println_Msg(pgm_read_byte(&(RAM[i])) / 4); else if (mapper == 16) - println_Msg(RAM[i] * 32); + println_Msg(pgm_read_byte(&(RAM[i])) * 32); else if (mapper == 19) { if (i == 2) println_Msg(F("128")); else - println_Msg(RAM[i]); + println_Msg(pgm_read_byte(&(RAM[i]))); } else if ((mapper == 159) || (mapper == 80)) - println_Msg(RAM[i] * 16); + println_Msg(pgm_read_byte(&(RAM[i])) * 16); else if (mapper == 82) println_Msg(i * 5); else - println_Msg(RAM[i]); + println_Msg(pgm_read_byte(&(RAM[i]))); println_Msg(F("")); #if defined(enable_OLED) print_STR(press_to_change_STR, 1); @@ -2232,9 +2232,9 @@ void setRAMSize() { int sizeEEP = 0; print_Msg(F("EEPROM SIZE ")); if (mapper == 16) - sizeEEP = RAM[newramsize] * 32; + sizeEEP = pgm_read_byte(&(RAM[newramsize])) * 32; else - sizeEEP = RAM[newramsize] * 16; + sizeEEP = pgm_read_byte(&(RAM[newramsize])) * 16; print_Msg(sizeEEP); println_Msg(F("B")); } else if (mapper == 19) { @@ -2242,12 +2242,12 @@ void setRAMSize() { if (newramsize == 2) println_Msg(F("128B")); else { - print_Msg(RAM[newramsize]); + print_Msg(pgm_read_byte(&(RAM[newramsize]))); println_Msg(F("K")); } } else if (mapper == 80) { print_Msg(F("RAM SIZE ")); - print_Msg(RAM[newramsize] * 16); + print_Msg(pgm_read_byte(&(RAM[newramsize])) * 16); println_Msg(F("B")); } else { print_Msg(F("RAM SIZE ")); @@ -2256,7 +2256,7 @@ void setRAMSize() { else if (mapper == 82) print_Msg(newramsize * 5); else - print_Msg(RAM[newramsize]); + print_Msg(pgm_read_byte(&(RAM[newramsize]))); println_Msg(F("K")); } display_Update(); @@ -2273,23 +2273,23 @@ setram: Serial.print(i); Serial.print(F(" = ")); if (mapper == 0) { - Serial.print(RAM[i] / 4); + Serial.print(pgm_read_byte(&(RAM[i])) / 4); Serial.println(F("K")); } else if ((mapper == 16) || (mapper == 159)) { if (mapper == 16) - Serial.print(RAM[i + ramlo] * 32); + Serial.print(pgm_read_byte(&(RAM[i + ramlo])) * 32); else - Serial.print(RAM[i + ramlo] * 16); + Serial.print(pgm_read_byte(&(RAM[i + ramlo])) * 16); Serial.println(F("B")); } else if (mapper == 19) { if (i == 2) Serial.println(F("128B")); else { - Serial.print(RAM[i + ramlo]); + Serial.print(pgm_read_byte(&(RAM[i + ramlo]))); Serial.println(F("K")); } } else { - Serial.print(RAM[i + ramlo]); + Serial.print(pgm_read_byte(&(RAM[i + ramlo]))); Serial.println(F("K")); } } @@ -2308,9 +2308,9 @@ setram: int sizeEEP = 0; Serial.print(F("EEPROM Size = ")); if (mapper == 16) - sizeEEP = RAM[newramsize] * 32; + sizeEEP = pgm_read_byte(&(RAM[newramsize])) * 32; else - sizeEEP = RAM[newramsize] * 16; + sizeEEP = pgm_read_byte(&(RAM[newramsize])) * 16; Serial.print(sizeEEP); Serial.println(F("B")); Serial.println(F("")); @@ -2319,13 +2319,13 @@ setram: if (newramsize == 2) Serial.println(F("128B")); else { - Serial.print(RAM[newramsize]); + Serial.print(pgm_read_byte(&(RAM[newramsize]))); Serial.println(F("K")); } Serial.println(F("")); } else if (mapper == 80) { Serial.print(F("RAM Size = ")); - Serial.print(RAM[newramsize] * 16); + Serial.print(pgm_read_byte(&(RAM[newramsize])) * 16); Serial.println(F("B")); Serial.println(F("")); } else { @@ -2335,7 +2335,7 @@ setram: else if (mapper == 82) Serial.print(newramsize * 5); else - Serial.print(RAM[newramsize]); + Serial.print(pgm_read_byte(&(RAM[newramsize]))); Serial.println(F("K")); Serial.println(F("")); } From 3bb63d77e370e528078bf8fd7908115768741b54 Mon Sep 17 00:00:00 2001 From: Vincent Pelletier Date: Fri, 28 Oct 2022 23:50:05 +0000 Subject: [PATCH 03/10] COLV.ino: Move COL to PROGMEM Uses 30 bytes of program space Frees 6 bytes of global ram space. --- Cart_Reader/COLV.ino | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/Cart_Reader/COLV.ino b/Cart_Reader/COLV.ino index 070186b..b833c9b 100644 --- a/Cart_Reader/COLV.ino +++ b/Cart_Reader/COLV.ino @@ -34,7 +34,7 @@ // /C000(PH5) - CHIP 2 - SNES /WR // /E000(PH6) - CHIP 3 - SNES /RD -byte COL[] = { 8, 12, 16, 20, 24, 32 }; +const byte COL[] PROGMEM = { 8, 12, 16, 20, 24, 32 }; byte collo = 0; // Lowest Entry byte colhi = 5; // Highest Entry @@ -237,7 +237,7 @@ void setROMSize_COL() { display_Clear(); print_Msg(F("ROM Size: ")); - println_Msg(COL[i]); + println_Msg(pgm_read_byte(&(COL[i]))); println_Msg(F("")); #if defined(enable_OLED) print_STR(press_to_change_STR, 1); @@ -259,7 +259,7 @@ void setROMSize_COL() { // Only update display after input because of slow LCD library display_Clear(); print_Msg(F("ROM Size: ")); - println_Msg(COL[i]); + println_Msg(pgm_read_byte(&(COL[i]))); println_Msg(F("")); #if defined(enable_OLED) print_STR(press_to_change_STR, 1); @@ -279,7 +279,7 @@ void setROMSize_COL() { // Only update display after input because of slow LCD library display_Clear(); print_Msg(F("ROM Size: ")); - println_Msg(COL[i]); + println_Msg(pgm_read_byte(&(COL[i]))); println_Msg(F("")); #if defined(enable_OLED) print_STR(press_to_change_STR, 1); @@ -298,7 +298,7 @@ void setROMSize_COL() { display.setCursor(0, 56); // Display selection at bottom } print_Msg(F("ROM SIZE ")); - print_Msg(COL[newcolsize]); + print_Msg(pgm_read_byte(&(COL[newcolsize]))); println_Msg(F("K")); display_Update(); delay(1000); @@ -312,7 +312,7 @@ setrom: Serial.print(F("Select ROM Size: ")); Serial.print(i); Serial.print(F(" = ")); - Serial.print(COL[i + collo]); + Serial.print(pgm_read_byte(&(COL[i + collo]))); Serial.println(F("K")); } Serial.print(F("Enter ROM Size: ")); @@ -327,7 +327,7 @@ setrom: } } Serial.print(F("ROM Size = ")); - Serial.print(COL[newcolsize]); + Serial.print(pgm_read_byte(&(COL[newcolsize]))); Serial.println(F("K")); #endif EEPROM_writeAnything(8, newcolsize); @@ -347,7 +347,7 @@ void checkStatus_COL() { println_Msg(F("CURRENT SETTINGS")); println_Msg(F("")); print_Msg(F("ROM SIZE: ")); - print_Msg(COL[colsize]); + print_Msg(pgm_read_byte(&(COL[colsize]))); println_Msg(F("K")); println_Msg(F("")); // Prints string out of the common strings array either with or without newline @@ -356,7 +356,7 @@ void checkStatus_COL() { wait(); #else Serial.print(F("CURRENT ROM SIZE: ")); - Serial.print(COL[colsize]); + Serial.print(pgm_read_byte(&(COL[colsize]))); Serial.println(F("K")); Serial.println(F("")); #endif From d4c5f6ec5b9e3cbb8d7a270398ed66f363d84b9c Mon Sep 17 00:00:00 2001 From: Vincent Pelletier Date: Sat, 29 Oct 2022 00:11:33 +0000 Subject: [PATCH 04/10] GBA.ino: Get rid of calcChecksumStr as a global Frees 150 bytes of program space and 5 bytes of global ram space. --- Cart_Reader/GBA.ino | 44 +++++++++++++++++++++++--------------------- 1 file changed, 23 insertions(+), 21 deletions(-) diff --git a/Cart_Reader/GBA.ino b/Cart_Reader/GBA.ino index 2163a01..a824096 100644 --- a/Cart_Reader/GBA.ino +++ b/Cart_Reader/GBA.ino @@ -6,7 +6,6 @@ /****************************************** Variables *****************************************/ -char calcChecksumStr[5]; boolean readType; /****************************************** @@ -569,6 +568,16 @@ void writeByte_GBA(unsigned long myAddress, byte myData) { /****************************************** GBA ROM Functions *****************************************/ +// Compute the checksum of rom header +// "header" must contain at least the rom's first 188 bytes +byte checksumHeader_GBA(const byte *header) { + byte result = 0x00; + for (byte n = 0xA0; n < 0xBD; n++) { + result -= header[n]; + } + return result - 0x19; +} + // Read info out of rom header void getCartInfo_GBA() { char saveTypeStr[14]; @@ -760,22 +769,21 @@ void getCartInfo_GBA() { // Get ROM version romVersion = sdBuffer[0xBC]; - // Get Checksum as string + // Calculate Checksum + byte calcChecksum = checksumHeader_GBA(sdBuffer); + + // Convert checksum from header into string + // (used in compare_checksum_GBA... it should just exchange an integer + // instead) sprintf(checksumStr, "%02X", sdBuffer[0xBD]); - // Calculate Checksum - int calcChecksum = 0x00; - for (int n = 0xA0; n < 0xBD; n++) { - calcChecksum -= sdBuffer[n]; - } - calcChecksum = (calcChecksum - 0x19) & 0xFF; - // Turn into string - sprintf(calcChecksumStr, "%02X", calcChecksum); - // Compare checksum - if (strcmp(calcChecksumStr, checksumStr) != 0) { + if (sdBuffer[0xBD] != calcChecksum) { + char calcChecksumStr[3]; display_Clear(); print_Msg(F("Result: ")); + // Turn into string + sprintf(calcChecksumStr, "%02X", calcChecksum); println_Msg(calcChecksumStr); print_Error(F("Checksum Error"), false); println_Msg(F("")); @@ -912,15 +920,9 @@ boolean compare_checksum_GBA() { myFile.read(sdBuffer, 512); myFile.close(); - // Calculate Checksum - int calcChecksum = 0x00; - for (int n = 0xA0; n < 0xBD; n++) { - calcChecksum -= sdBuffer[n]; - } - calcChecksum = (calcChecksum - 0x19) & 0xFF; - - // Turn into string - sprintf(calcChecksumStr, "%02X", calcChecksum); + // Calculate Checksum and turn into string + char calcChecksumStr[3]; + sprintf(calcChecksumStr, "%02X", checksumHeader_GBA(sdBuffer)); print_Msg(calcChecksumStr); if (strcmp(calcChecksumStr, checksumStr) == 0) { From a6f9e5e99cc7c7ec70e70f82a3e8b338fdd9ba59 Mon Sep 17 00:00:00 2001 From: Vincent Pelletier Date: Sat, 29 Oct 2022 00:12:19 +0000 Subject: [PATCH 05/10] GBA.ino: Get rid of unused global --- Cart_Reader/GBA.ino | 5 ----- 1 file changed, 5 deletions(-) diff --git a/Cart_Reader/GBA.ino b/Cart_Reader/GBA.ino index a824096..0640b4b 100644 --- a/Cart_Reader/GBA.ino +++ b/Cart_Reader/GBA.ino @@ -3,11 +3,6 @@ //****************************************** #ifdef enable_GBX -/****************************************** - Variables - *****************************************/ -boolean readType; - /****************************************** Menu *****************************************/ From 264bfd5ce540ab9d34a739eabc3f6fe2291011e8 Mon Sep 17 00:00:00 2001 From: Vincent Pelletier Date: Sat, 29 Oct 2022 00:14:56 +0000 Subject: [PATCH 06/10] INTV.ino: Move INTV to PROGMEM. Uses 8 bytes of program space. Frees 6 bytes of global ram space. --- Cart_Reader/INTV.ino | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/Cart_Reader/INTV.ino b/Cart_Reader/INTV.ino index f3ce0c5..952b979 100644 --- a/Cart_Reader/INTV.ino +++ b/Cart_Reader/INTV.ino @@ -75,7 +75,7 @@ boolean intvmapfound = false; byte intvmapselect; int intvindex; -byte INTV[] = { 8, 16, 24, 32, 48 }; +const byte INTV[] PROGMEM = { 8, 16, 24, 32, 48 }; byte intvlo = 0; // Lowest Entry byte intvhi = 4; // Highest Entry @@ -645,7 +645,7 @@ void setROMSize_INTV() { // Only update display after input because of slow LCD library display_Clear(); print_Msg(F("ROM Size: ")); - println_Msg(INTV[i]); + println_Msg(pgm_read_byte(&(INTV[i]))); println_Msg(F("")); #if defined(enable_OLED) print_STR(press_to_change_STR, 1); @@ -667,7 +667,7 @@ void setROMSize_INTV() { // Only update display after input because of slow LCD library display_Clear(); print_Msg(F("ROM Size: ")); - println_Msg(INTV[i]); + println_Msg(pgm_read_byte(&(INTV[i]))); println_Msg(F("")); #if defined(enable_OLED) print_STR(press_to_change_STR, 1); @@ -686,7 +686,7 @@ void setROMSize_INTV() { display_Clear(); print_Msg(F("ROM Size: ")); - println_Msg(INTV[i]); + println_Msg(pgm_read_byte(&(INTV[i]))); println_Msg(F("")); #if defined(enable_OLED) print_STR(press_to_change_STR, 1); @@ -705,7 +705,7 @@ void setROMSize_INTV() { display.setCursor(0, 56); // Display selection at bottom } print_Msg(F("ROM SIZE ")); - print_Msg(INTV[newintvsize]); + print_Msg(pgm_read_byte(&(INTV[newintvsize]))); println_Msg(F("K")); display_Update(); delay(1000); @@ -719,7 +719,7 @@ setrom: Serial.print(F("Select ROM Size: ")); Serial.print(i); Serial.print(F(" = ")); - Serial.print(INTV[i + intvlo]); + Serial.print(pgm_read_byte(&(INTV[i + intvlo]))); Serial.println(F("K")); } Serial.print(F("Enter ROM Size: ")); @@ -734,7 +734,7 @@ setrom: } } Serial.print(F("ROM Size = ")); - Serial.print(INTV[newintvsize]); + Serial.print(pgm_read_byte(&(INTV[newintvsize]))); Serial.println(F("K")); #endif EEPROM_writeAnything(8, newintvsize); @@ -761,7 +761,7 @@ void checkStatus_INTV() { print_Msg(F("MAPPER: ")); println_Msg(intvmapper); print_Msg(F("ROM SIZE: ")); - print_Msg(INTV[intvsize]); + print_Msg(pgm_read_byte(&(INTV[intvsize]))); println_Msg(F("K")); display_Update(); wait(); @@ -769,7 +769,7 @@ void checkStatus_INTV() { Serial.print(F("CURRENT MAPPER: ")); Serial.println(intvmapper); Serial.print(F("CURRENT ROM SIZE: ")); - Serial.print(INTV[intvsize]); + Serial.print(pgm_read_byte(&(INTV[intvsize]))); Serial.println(F("K")); Serial.println(F("")); #endif From 64db4ded54495427d91536278ea79fbaaecd0a61 Mon Sep 17 00:00:00 2001 From: Vincent Pelletier Date: Sat, 29 Oct 2022 00:38:06 +0000 Subject: [PATCH 07/10] NES.ino: Convert nointro-disabled global variables into locals Also, remove dead error handling code: sd.exists internally opens the file and returns the produced status, so myFile.open return value should be the same. --- Cart_Reader/NES.ino | 29 +++++++---------------------- 1 file changed, 7 insertions(+), 22 deletions(-) diff --git a/Cart_Reader/NES.ino b/Cart_Reader/NES.ino index 0921926..ed8cf4e 100644 --- a/Cart_Reader/NES.ino +++ b/Cart_Reader/NES.ino @@ -195,16 +195,6 @@ boolean flashfound = false; // NESmaker 39SF040 Flash Cart // Files char fileCount[3]; -#ifndef nointro -FsFile nesFile; -uint32_t prg_crc32; -uint32_t chr_crc32; -char filePRG[] = "PRG.bin"; -char fileCHR[] = "CHR.bin"; -char fileNES[] = "CART.nes"; -char fileBIN[] = "CART.bin"; -#endif - // Cartridge Config byte mapper; byte prgsize; @@ -1226,13 +1216,17 @@ uint32_t atoi32_unsigned(const char* input_string) { } void outputNES() { - display_Clear(); + FsFile nesFile; + const char fileNES[] = "CART.nes"; + const char fileBIN[] = "CART.bin"; char* outputFile; unsigned long crcOffset = 0; uint32_t prg_size_bytes = 1024 * (uint32_t)prg; uint32_t chr_size_bytes = 1024 * (uint32_t)chr; int has_header = 0; + display_Clear(); + unsigned char* nes_header_bytes = getNESHeaderForFileInfo(prg_size_bytes, chr_size_bytes, prg_crc32, chr_crc32); if (nes_header_bytes != NULL) { @@ -1242,7 +1236,7 @@ void outputNES() { LED_RED_ON; LED_GREEN_ON; LED_BLUE_ON; - if (!myFile.open(filePRG, FILE_READ)) { + if (!myFile.open("PRG.bin", FILE_READ)) { LED_GREEN_OFF; LED_BLUE_OFF; @@ -1285,16 +1279,7 @@ void outputNES() { nesFile.write(sdBuffer, n); } myFile.close(); - if (sd.exists(fileCHR)) { - if (!myFile.open(fileCHR, FILE_READ)) { - LED_GREEN_OFF; - LED_BLUE_OFF; - - display_Clear(); - println_Msg(F("CHR FILE FAILED!")); - display_Update(); - print_Error(sd_error_STR, true); - } + if (myFile.open("CHR.bin", FILE_READ)) { while ((n = myFile.read(sdBuffer, sizeof(sdBuffer))) > 0) { nesFile.write(sdBuffer, n); } From 59665bb848002a5009a667475d6d5c1f4b4456e8 Mon Sep 17 00:00:00 2001 From: Vincent Pelletier Date: Sat, 29 Oct 2022 00:55:32 +0000 Subject: [PATCH 08/10] NES.ino: Factorise Create{PRG,CHR,RAM}FileInSD functions Also, gets rid of filesCount global. Frees 390 bytes of program space and 21 bytes of global ram space. --- Cart_Reader/NES.ino | 90 +++++++++++++-------------------------------- 1 file changed, 25 insertions(+), 65 deletions(-) diff --git a/Cart_Reader/NES.ino b/Cart_Reader/NES.ino index ed8cf4e..76f6012 100644 --- a/Cart_Reader/NES.ino +++ b/Cart_Reader/NES.ino @@ -124,6 +124,9 @@ static const byte PROGMEM mapsize[] = { 255, 7, 7, 8, 8, 0, 0, // 110-in-1 multicart (same as 225) [UNLICENSED] }; +const char _file_name_no_number_fmt[] PROGMEM = "%s.%s"; +const char _file_name_with_number_fmt[] PROGMEM = "%s.%02d.%s"; + /****************************************** Defines *****************************************/ @@ -192,9 +195,6 @@ byte bytecheck; byte firstbyte; boolean flashfound = false; // NESmaker 39SF040 Flash Cart -// Files -char fileCount[3]; - // Cartridge Config byte mapper; byte prgsize; @@ -1068,79 +1068,39 @@ void CreateROMFolderInSD() { sd.chdir(folder); } -void CreatePRGFileInSD() { - strcpy(fileName, "PRG"); - strcat(fileName, ".bin"); +FsFile createNewFile(const char *prefix, const char *extension) { + char filename[FILENAME_LENGTH]; + snprintf_P(filename, sizeof(filename), _file_name_no_number_fmt, prefix, extension); for (byte i = 0; i < 100; i++) { - if (!sd.exists(fileName)) { - myFile = sd.open(fileName, O_RDWR | O_CREAT); - break; + if (!sd.exists(filename)) { + return sd.open(fileName, O_RDWR | O_CREAT); } - sprintf(fileCount, "%02d", i); - strcpy(fileName, "PRG."); - strcat(fileName, fileCount); - strcat(fileName, ".bin"); + snprintf_P(filename, sizeof(filename), _file_name_with_number_fmt, prefix, i, extension); } - if (!myFile) { - LED_RED_ON; + // Could not find an available name, recompose the original name and error out. + snprintf_P(filename, sizeof(filename), _file_name_no_number_fmt, prefix, extension); - display_Clear(); - println_Msg(F("PRG FILE FAILED!")); - display_Update(); - print_Error(sd_error_STR, true); + LED_RED_ON; - LED_RED_OFF; - } + display_Clear(); + print_Msg(filename); + println_Msg(F(": no available name")); + display_Update(); + print_FatalError(sd_error_STR); + + LED_RED_OFF; +} + +void CreatePRGFileInSD() { + myFile = createNewFile("PRG", "bin"); } void CreateCHRFileInSD() { - strcpy(fileName, "CHR"); - strcat(fileName, ".bin"); - for (byte i = 0; i < 100; i++) { - if (!sd.exists(fileName)) { - myFile = sd.open(fileName, O_RDWR | O_CREAT); - break; - } - sprintf(fileCount, "%02d", i); - strcpy(fileName, "CHR."); - strcat(fileName, fileCount); - strcat(fileName, ".bin"); - } - if (!myFile) { - LED_RED_ON; - - display_Clear(); - println_Msg(F("CHR FILE FAILED!")); - display_Update(); - print_Error(sd_error_STR, true); - - LED_RED_OFF; - } + myFile = createNewFile("CHR", "bin"); } void CreateRAMFileInSD() { - strcpy(fileName, "RAM"); - strcat(fileName, ".bin"); - for (byte i = 0; i < 100; i++) { - if (!sd.exists(fileName)) { - myFile = sd.open(fileName, O_RDWR | O_CREAT); - break; - } - sprintf(fileCount, "%02d", i); - strcpy(fileName, "RAM."); - strcat(fileName, fileCount); - strcat(fileName, ".bin"); - } - if (!myFile) { - LED_RED_ON; - - display_Clear(); - println_Msg(F("RAM FILE FAILED!")); - display_Update(); - print_Error(sd_error_STR, true); - - LED_RED_OFF; - } + myFile = createNewFile("RAM", "bin"); } #ifndef nointro From cb26782e2244bbcd754d4214e888e6bf7c8092ac Mon Sep 17 00:00:00 2001 From: Vincent Pelletier Date: Sat, 29 Oct 2022 01:08:42 +0000 Subject: [PATCH 09/10] PCE.ino: Get rid of menuOptionspceCart global variable Also, move a few inline string constants into PROGMEM. Uses 64 bytes of program space. Frees 206 bytes of global ram space. --- Cart_Reader/PCE.ino | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/Cart_Reader/PCE.ino b/Cart_Reader/PCE.ino index 81ddec1..20b17f0 100644 --- a/Cart_Reader/PCE.ino +++ b/Cart_Reader/PCE.ino @@ -58,15 +58,13 @@ static const char pceMenuItem3[] PROGMEM = "Turbochip"; static const char *const menuOptionspce[] PROGMEM = { pceMenuItem1, pceMenuItem2, pceMenuItem3, string_reset2 }; // PCE card menu items -static char menuOptionspceCart[7][20] = { - "Read ROM", - "", // Read RAM Bank %d - "", //Write RAM Bank %d - "Reset", - "Inc Bank Number", - "Dec Bank Number", - "" // ROM size now %dK / Force ROM size -}; +static const char menuOptionspceCart_0[] PROGMEM = "Read ROM"; +static const char menuOptionspceCart_1_fmt[] PROGMEM = "Read RAM Bank %d"; +static const char menuOptionspceCart_2_fmt[] PROGMEM = "Write RAM Bank %d"; +static const char menuOptionspceCart_4[] PROGMEM = "Inc Bank Number"; +static const char menuOptionspceCart_5[] PROGMEM = "Dec Bank Number"; +static const char menuOptionspceCart_6_fmt[] PROGMEM = "ROM size now %dK"; +static const char menuOptionspceCart_6[] PROGMEM = "Force ROM size"; // Turbochip menu items static const char pceTCMenuItem1[] PROGMEM = "Read ROM"; @@ -791,14 +789,18 @@ void pceMenu() { unsigned char mainMenu; if (pce_internal_mode == HUCARD || pce_internal_mode == HUCARD_NOSWAP) { - sprintf(menuOptionspceCart[1], "Read RAM Bank %d", tennokoe_bank_index + 1); - sprintf(menuOptionspceCart[2], "Write RAM Bank %d", tennokoe_bank_index + 1); + strcpy_P(menuOptions[0], menuOptionspceCart_0); + sprintf_P(menuOptions[1], menuOptionspceCart_1_fmt, tennokoe_bank_index + 1); + sprintf_P(menuOptions[2], menuOptionspceCart_2_fmt, tennokoe_bank_index + 1); + strcpy_P(menuOptions[3], string_reset2); + strcpy_P(menuOptions[4], menuOptionspceCart_4); + strcpy_P(menuOptions[5], menuOptionspceCart_5); if (pce_force_rom_size > 0) { - sprintf(menuOptionspceCart[6], "ROM size now %dK", pce_force_rom_size); + sprintf_P(menuOptions[6], menuOptionspceCart_6_fmt, pce_force_rom_size); } else { - sprintf(menuOptionspceCart[6], "Force ROM size"); + strcpy_P(menuOptions[6], menuOptionspceCart_6); } - mainMenu = question_box(F("PCE HuCARD menu"), menuOptionspceCart, 7, 0); + mainMenu = question_box(F("PCE HuCARD menu"), menuOptions, 7, 0); // wait for user choice to come back from the question box menu switch (mainMenu) { From 18bd92d100e377a476633c9534e534da91e4ddfd Mon Sep 17 00:00:00 2001 From: Vincent Pelletier Date: Sat, 29 Oct 2022 01:19:04 +0000 Subject: [PATCH 10/10] WSV.ino: Move WVS to PROGMEM Frees 16 bytes of program space and 8 bytes of global ram space. --- Cart_Reader/WSV.ino | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/Cart_Reader/WSV.ino b/Cart_Reader/WSV.ino index 080b19a..65d56b1 100644 --- a/Cart_Reader/WSV.ino +++ b/Cart_Reader/WSV.ino @@ -38,7 +38,7 @@ // /WR - (PH5) // /RD - (PH6) -word WSV[] = { 32, 64, 512 }; +const word WSV[] PROGMEM = { 32, 64, 512 }; byte wsvlo = 0; // Lowest Entry byte wsvhi = 2; // Highest Entry @@ -215,7 +215,7 @@ void readROM_WSV() { dataIn_WSV(); controlIn_WSV(); - romSize = WSV[wsvsize]; + romSize = pgm_read_word(&(WSV[wsvsize])); uint32_t romStart = 0; if (romSize < 64) @@ -254,7 +254,7 @@ void setROMSize_WSV() { display_Clear(); print_Msg(F("ROM Size: ")); - println_Msg(WSV[i]); + println_Msg(pgm_read_word(&(WSV[i]))); println_Msg(F("")); #if defined(enable_OLED) print_STR(press_to_change_STR, 1); @@ -276,7 +276,7 @@ void setROMSize_WSV() { // Only update display after input because of slow LCD library display_Clear(); print_Msg(F("ROM Size: ")); - println_Msg(WSV[i]); + println_Msg(pgm_read_word(&(WSV[i]))); println_Msg(F("")); #if defined(enable_OLED) print_STR(press_to_change_STR, 1); @@ -296,7 +296,7 @@ void setROMSize_WSV() { // Only update display after input because of slow LCD library display_Clear(); print_Msg(F("ROM Size: ")); - println_Msg(WSV[i]); + println_Msg(pgm_read_word(&(WSV[i]))); println_Msg(F("")); #if defined(enable_OLED) print_STR(press_to_change_STR, 1); @@ -315,7 +315,7 @@ void setROMSize_WSV() { display.setCursor(0, 56); // Display selection at bottom } print_Msg(F("ROM SIZE ")); - print_Msg(WSV[newwsvsize]); + print_Msg(pgm_read_word(&(WSV[newwsvsize]))); println_Msg(F("K")); display_Update(); delay(1000); @@ -329,7 +329,7 @@ setrom: Serial.print(F("Select ROM Size: ")); Serial.print(i); Serial.print(F(" = ")); - Serial.print(WSV[i + wsvlo]); + Serial.print(pgm_read_word(&(WSV[i + wsvlo]))); Serial.println(F("K")); } Serial.print(F("Enter ROM Size: ")); @@ -344,7 +344,7 @@ setrom: } } Serial.print(F("ROM Size = ")); - Serial.print(WSV[newwsvsize]); + Serial.print(pgm_read_word(&(WSV[newwsvsize]))); Serial.println(F("K")); #endif EEPROM_writeAnything(8, newwsvsize); @@ -364,13 +364,13 @@ void checkStatus_WSV() { println_Msg(F("CURRENT SETTINGS")); println_Msg(F("")); print_Msg(F("ROM SIZE: ")); - print_Msg(WSV[wsvsize]); + print_Msg(pgm_read_word(&(WSV[wsvsize]))); println_Msg(F("K")); display_Update(); wait(); #else Serial.print(F("CURRENT ROM SIZE: ")); - Serial.print(WSV[wsvsize]); + Serial.print(pgm_read_word(&(WSV[wsvsize]))); Serial.println(F("K")); Serial.println(F("")); #endif