From 67b54a690b74fc33bc727d92804d9449a70fa310 Mon Sep 17 00:00:00 2001 From: Vincent Pelletier Date: Sun, 23 Oct 2022 15:49:38 +0000 Subject: [PATCH] All: Factorise title generation from cart. Fix out-of-bound access when first byte is not an ascii printable character. Reduces program space use by 480 bytes. --- Cart_Reader/Cart_Reader.ino | 26 ++++++++++++++++++++++++++ Cart_Reader/GB.ino | 16 ++++++++-------- Cart_Reader/GBA.ino | 20 +------------------- Cart_Reader/N64.ino | 30 +++--------------------------- Cart_Reader/SNES.ino | 25 ++++--------------------- 5 files changed, 42 insertions(+), 75 deletions(-) diff --git a/Cart_Reader/Cart_Reader.ino b/Cart_Reader/Cart_Reader.ino index 1c6eb14..d7b38d8 100644 --- a/Cart_Reader/Cart_Reader.ino +++ b/Cart_Reader/Cart_Reader.ino @@ -1884,6 +1884,32 @@ void setColor_RGB(byte r, byte g, byte b) { #endif } +// Extract ASCII printable characters from input, collapsing underscores and spaces. +// Use when extracting titles from cartridges, to build a rom title. +byte buildRomName(char *output, const byte *input, byte length) { + byte input_char; + byte output_len = 0; + for (unsigned int i = 0; i < length; i++) { + input_char = input[i]; + if (isprint(input_char) && input_char != '<' && input_char != '>' && input_char != ':' && input_char != '"' && input_char != '/' && input_char != '\\' && input_char != '|' && input_char != '?' && input_char != '*') { + output[output_len++] = input_char; + } else { + if (output_len == 0 || output[output_len - 1] != '_') { + output[output_len++] = '_'; + } + } + } + while ( + output_len && ( + output[output_len - 1] == '_' || output[output_len - 1] == ' ' + ) + ) { + output_len--; + } + output[output_len] = 0; + return output_len; +} + // Converts a progmem array into a ram array void convertPgm(const char* const pgmOptions[], byte numArrays) { for (int i = 0; i < numArrays; i++) { diff --git a/Cart_Reader/GB.ino b/Cart_Reader/GB.ino index 18a86f6..5f30796 100644 --- a/Cart_Reader/GB.ino +++ b/Cart_Reader/GB.ino @@ -882,12 +882,10 @@ void getCartInfo_GB() { for (int addr = 0x0134; addr <= 0x0143 - x; addr++) { myByte = sdBuffer[addr]; if (isprint(myByte) && myByte != '<' && myByte != '>' && myByte != ':' && myByte != '"' && myByte != '/' && myByte != '\\' && myByte != '|' && myByte != '?' && myByte != '*') { - romName[myLength] = char(myByte); - } else { - if (romName[myLength - 1] == 0x5F) myLength--; - romName[myLength] = 0x5F; + romName[myLength++] = char(myByte); + } else if (myLength == 0 || romName[myLength - 1] != '_') { + romName[myLength++] = '_'; } - myLength++; } // Find Game Serial @@ -904,11 +902,13 @@ void getCartInfo_GB() { } // Strip trailing white space - for (unsigned int i = myLength - 1; i > 0; i--) { - if ((romName[i] != 0x5F) && (romName[i] != 0x20)) break; - romName[i] = 0x00; + while ( + myLength && + (romName[myLength - 1] == '_' || romName[myLength - 1] == ' ') + ) { myLength--; } + romName[myLength] = 0; // M161 (Mani 4 in 1) if (strncmp(romName, "TETRIS SET", 10) == 0 && sdBuffer[0x14D] == 0x3F) { diff --git a/Cart_Reader/GBA.ino b/Cart_Reader/GBA.ino index 27d5b6c..a01ab68 100644 --- a/Cart_Reader/GBA.ino +++ b/Cart_Reader/GBA.ino @@ -755,25 +755,7 @@ void getCartInfo_GBA() { } // Get name - byte myByte = 0; - byte myLength = 0; - for (int addr = 0xA0; addr <= 0xAB; addr++) { - myByte = sdBuffer[addr]; - if (isprint(myByte) && myByte != '<' && myByte != '>' && myByte != ':' && myByte != '"' && myByte != '/' && myByte != '\\' && myByte != '|' && myByte != '?' && myByte != '*') { - romName[myLength] = char(myByte); - } else { - if (romName[myLength - 1] == 0x5F) myLength--; - romName[myLength] = 0x5F; - } - myLength++; - } - - // Strip trailing white space - for (unsigned int i = myLength - 1; i > 0; i--) { - if ((romName[i] != 0x5F) && (romName[i] != 0x20)) break; - romName[i] = 0x00; - myLength--; - } + buildRomName(romName, &sdBuffer[0xA0], 11); // Get ROM version romVersion = sdBuffer[0xBC]; diff --git a/Cart_Reader/N64.ino b/Cart_Reader/N64.ino index 2e44c2f..0efc1fd 100644 --- a/Cart_Reader/N64.ino +++ b/Cart_Reader/N64.ino @@ -2181,33 +2181,9 @@ void idCart() { // Get rom version romVersion = sdBuffer[0x3F]; - // Get name - byte myByte = 0; - byte myLength = 0; - for (unsigned int i = 0; i < 20; i++) { - myByte = sdBuffer[0x20 + i]; - if (isprint(myByte) && myByte != '<' && myByte != '>' && myByte != ':' && myByte != '"' && myByte != '/' && myByte != '\\' && myByte != '|' && myByte != '?' && myByte != '*') { - romName[myLength] = char(myByte); - } else { - if (romName[myLength - 1] == 0x5F) myLength--; - romName[myLength] = 0x5F; - } - myLength++; - } - - // Strip trailing white space - for (unsigned int i = myLength - 1; i > 0; i--) { - if ((romName[i] != 0x5F) && (romName[i] != 0x20)) break; - romName[i] = 0x00; - myLength--; - } - // If name consists out of all japanese characters use cart id - if (myLength == 0) { - romName[0] = sdBuffer[0x3B]; - romName[1] = sdBuffer[0x3C]; - romName[2] = sdBuffer[0x3D]; - romName[3] = sdBuffer[0x3E]; + if (buildRomName(romName, &sdBuffer[0x20], 20) == 0) { + strcpy(romName, cartID); } #ifdef savesummarytotxt @@ -4874,4 +4850,4 @@ unsigned long verifyGameshark_N64() { //****************************************** // End of File -//****************************************** \ No newline at end of file +//****************************************** diff --git a/Cart_Reader/SNES.ino b/Cart_Reader/SNES.ino index 96162d6..95aa756 100644 --- a/Cart_Reader/SNES.ino +++ b/Cart_Reader/SNES.ino @@ -1016,25 +1016,7 @@ boolean checkcart_SNES() { } // Get name - byte myByte = 0; - byte myLength = 0; - for (unsigned int i = 0xFFC0; i < 0xFFD5; i++) { - myByte = snesHeader[i - headerStart]; - if (isprint(myByte) && myByte != '<' && myByte != '>' && myByte != ':' && myByte != '"' && myByte != '/' && myByte != '\\' && myByte != '|' && myByte != '?' && myByte != '*') { - romName[myLength] = char(myByte); - } else { - if (romName[myLength - 1] == 0x5F) myLength--; - romName[myLength] = 0x5F; - } - myLength++; - } - - // Strip trailing white space - for (unsigned int i = myLength - 1; i > 0; i--) { - if ((romName[i] != 0x5F) && (romName[i] != 0x20)) break; - romName[i] = 0x00; - myLength--; - } + byte myLength = buildRomName(romName, &snesHeader[headerStart], 21); // If name consists out of all japanese characters use game code if (myLength == 0) { @@ -1045,9 +1027,10 @@ boolean checkcart_SNES() { romName[3] = 'C'; romName[4] = '-'; for (unsigned int i = 0; i < 4; i++) { + byte myByte; myByte = snesHeader[0xFFB2 + i - headerStart]; - if (((char(myByte) >= 48 && char(myByte) <= 57) || (char(myByte) >= 65 && char(myByte) <= 122)) && myLength < 4) { - romName[myLength + 5] = char(myByte); + if (((myByte >= '0' && myByte <= '9') || (myByte >= 'A' && myByte <= 'z')) && myLength < 4) { + romName[myLength + 5] = myByte; myLength++; } }