From 06d5f28d0cd2ad53b14cd773d31e8b29c24f1ba6 Mon Sep 17 00:00:00 2001 From: smesgr9000 Date: Sun, 28 Apr 2024 13:35:21 +0200 Subject: [PATCH] port NES fast forward selection to other systems --- Cart_Reader/2600.ino | 73 +++---------- Cart_Reader/7800.ino | 85 ++++----------- Cart_Reader/C64.ino | 85 ++++----------- Cart_Reader/COLV.ino | 178 ++++++++++++------------------ Cart_Reader/Cart_Reader.ino | 102 +++++++++++++++++ Cart_Reader/INTV.ino | 212 +++++++++++++++--------------------- Cart_Reader/NES.ino | 201 ++++++++++++---------------------- Cart_Reader/WSV.ino | 160 ++++++++++----------------- 8 files changed, 441 insertions(+), 655 deletions(-) diff --git a/Cart_Reader/2600.ino b/Cart_Reader/2600.ino index 831640e..88c2896 100644 --- a/Cart_Reader/2600.ino +++ b/Cart_Reader/2600.ino @@ -792,12 +792,18 @@ setmapper: //****************************************** // CART SELECT CODE //****************************************** +void readDataLine_2600(FsFile& database, byte* gameMapper) { + // Read mapper with three ascii character and subtract 48 to convert to decimal + (*gameMapper) = ((database.read() - 48) * 100) + ((database.read() - 48) * 10) + (database.read() - 48); + + // Skip rest of line + database.seekCur(2); +} void setCart_2600() { //go to root sd.chdir(); - char gamename[100]; byte gameMapper; byte gameSize; @@ -808,64 +814,13 @@ void setCart_2600() { if (myFile.open("2600.txt", O_READ)) { seek_first_letter_in_database(myFile, myLetter); - // Display database - while (myFile.available()) { - display_Clear(); - - get_line(gamename, &myFile, sizeof(gamename)); - - // Read mapper with three ascii character and subtract 48 to convert to decimal - gameMapper = ((myFile.read() - 48) * 100) + ((myFile.read() - 48) * 10) + (myFile.read() - 48); - - // Skip rest of line - myFile.seekCur(2); - - skip_line(&myFile); - - println_Msg(F("Select your cartridge")); - println_Msg(FS(FSTRING_EMPTY)); - println_Msg(gamename); - -#if defined(ENABLE_OLED) - print_STR(press_to_change_STR, 1); - print_STR(right_to_select_STR, 1); -#elif defined(ENABLE_LCD) - print_STR(rotate_to_change_STR, 1); - print_STR(press_to_select_STR, 1); -#elif defined(SERIAL_MONITOR) - println_Msg(F("U/D to Change")); - println_Msg(F("Space to Select")); -#endif - display_Update(); - - uint8_t b = 0; - while (1) { - // Check button input - b = checkButton(); - - // Next - if (b == 1) { - break; - } - - // Previous - else if (b == 2) { - rewind_line(myFile, 6); - break; - } - - // Selection - else if (b == 3) { - EEPROM_writeAnything(7, gameMapper); - for (int i = 0; i < a2600mapcount; i++) { - a2600index = i * 2; - if (gameMapper == pgm_read_byte(a2600mapsize + a2600index)) { - a2600size = pgm_read_byte(a2600mapsize + a2600index + 1); - EEPROM_writeAnything(8, a2600size); - break; - } - } - myFile.close(); + if(checkCartSelection(myFile, &readDataLine_2600, &gameMapper)) { + EEPROM_writeAnything(7, gameMapper); + for (int i = 0; i < a2600mapcount; i++) { + a2600index = i * 2; + if (gameMapper == pgm_read_byte(a2600mapsize + a2600index)) { + a2600size = pgm_read_byte(a2600mapsize + a2600index + 1); + EEPROM_writeAnything(8, a2600size); break; } } diff --git a/Cart_Reader/7800.ino b/Cart_Reader/7800.ino index 383eb5f..e439e8e 100644 --- a/Cart_Reader/7800.ino +++ b/Cart_Reader/7800.ino @@ -781,14 +781,30 @@ setmapper: //****************************************** // CART SELECT CODE //****************************************** +struct database_entry_7800 { + byte gameMapper; + byte gameSize; +}; + +void readDataLine_7800(FsFile& database, struct database_entry_7800* entry) { + // Read mapper + entry->gameMapper = database.read() - 48; + + // Skip over semicolon + database.seekCur(1); + + // Read rom size + entry->gameSize = database.read() - 48; + + // Skip rest of line + database.seekCur(2); +} void setCart_7800() { //go to root sd.chdir(); - char gamename[100]; - byte gameMapper; - byte gameSize; + struct database_entry_7800 entry; // Select starting letter byte myLetter = starting_letter(); @@ -797,66 +813,9 @@ void setCart_7800() { if (myFile.open("7800.txt", O_READ)) { seek_first_letter_in_database(myFile, myLetter); - // Display database - while (myFile.available()) { - display_Clear(); - - get_line(gamename, &myFile, sizeof(gamename)); - - // Read mapper - gameMapper = myFile.read() - 48; - - // Skip over semicolon - myFile.seekCur(1); - - // Read rom size - gameSize = myFile.read() - 48; - - // Skip rest of line - myFile.seekCur(2); - - skip_line(&myFile); - - println_Msg(F("Select your cartridge")); - println_Msg(FS(FSTRING_EMPTY)); - println_Msg(gamename); - -#if defined(ENABLE_OLED) - print_STR(press_to_change_STR, 1); - print_STR(right_to_select_STR, 1); -#elif defined(ENABLE_LCD) - print_STR(rotate_to_change_STR, 1); - print_STR(press_to_select_STR, 1); -#elif defined(SERIAL_MONITOR) - println_Msg(F("U/D to Change")); - println_Msg(F("Space to Select")); -#endif - display_Update(); - - uint8_t b = 0; - while (1) { - // Check button input - b = checkButton(); - - // Next - if (b == 1) { - break; - } - - // Previous - else if (b == 2) { - rewind_line(myFile, 6); - break; - } - - // Selection - else if (b == 3) { - EEPROM_writeAnything(7, gameMapper); - EEPROM_writeAnything(8, gameSize); - myFile.close(); - break; - } - } + if(checkCartSelection(myFile, &readDataLine_7800, &entry)) { + EEPROM_writeAnything(7, entry.gameMapper); + EEPROM_writeAnything(8, entry.gameSize); } } else { print_FatalError(F("Database file not found")); diff --git a/Cart_Reader/C64.ino b/Cart_Reader/C64.ino index 1d01454..8988505 100644 --- a/Cart_Reader/C64.ino +++ b/Cart_Reader/C64.ino @@ -1029,13 +1029,30 @@ void printMapper_C64(byte c64maplabel) { //****************************************** // CART SELECT CODE //****************************************** +struct database_entry_C64 { + byte gameMapper; + byte gameSize; +}; + +void readDataLine_C64(FsFile& database, struct database_entry_C64* entry) { + // Read mapper with two ascii character and subtract 48 to convert to decimal + entry->gameMapper = ((database.read() - 48) * 10) + (database.read() - 48); + + // Skip over semicolon + database.seekCur(1); + + // Read size and subtract 48 to convert to decimal + entry->gameSize = database.read() - 48; + + // Skip rest of line + database.seekCur(2); +} + void setCart_C64() { //go to root sd.chdir(); - char gamename[100]; - byte gameMapper; - byte gameSize; + struct database_entry_C64 entry; // Select starting letter byte myLetter = starting_letter(); @@ -1044,65 +1061,9 @@ void setCart_C64() { if (myFile.open("c64cart.txt", O_READ)) { seek_first_letter_in_database(myFile, myLetter); - // Display database - while (myFile.available()) { - display_Clear(); - - get_line(gamename, &myFile, sizeof(gamename)); - - // Read mapper with two ascii character and subtract 48 to convert to decimal - gameMapper = ((myFile.read() - 48) * 10) + (myFile.read() - 48); - - // Skip over semicolon - myFile.seekCur(1); - - // Read size and subtract 48 to convert to decimal - gameSize = myFile.read() - 48; - - // Skip rest of line - myFile.seekCur(2); - - skip_line(&myFile); - - println_Msg(F("Select your cartridge")); - println_Msg(FS(FSTRING_EMPTY)); - println_Msg(gamename); - -#if defined(ENABLE_OLED) - print_STR(press_to_change_STR, 1); - print_STR(right_to_select_STR, 1); -#elif defined(ENABLE_LCD) - print_STR(rotate_to_change_STR, 1); - print_STR(press_to_select_STR, 1); -#elif defined(SERIAL_MONITOR) - println_Msg(F("U/D to Change")); - println_Msg(F("Space to Select")); -#endif - display_Update(); - - uint8_t b = 0; - while (1) { - // Check button input - b = checkButton(); - - // Next - if (b == 1) { - break; - } - - // Previous - else if (b == 2) { - rewind_line(myFile, 6); - break; - } - // Selection - else if (b == 3) { - EEPROM_writeAnything(7, gameMapper); - EEPROM_writeAnything(8, gameSize); - myFile.close(); - break; - } - } + if(checkCartSelection(myFile, &readDataLine_C64, &entry)) { + EEPROM_writeAnything(7, entry.gameMapper); + EEPROM_writeAnything(8, entry.gameSize); } } else { print_FatalError(F("Database file not found")); diff --git a/Cart_Reader/COLV.ino b/Cart_Reader/COLV.ino index 01f7197..a7972f6 100644 --- a/Cart_Reader/COLV.ino +++ b/Cart_Reader/COLV.ino @@ -364,14 +364,54 @@ void checkStatus_COL() { //****************************************** // CART SELECT CODE //****************************************** -void setCart_COL() { - char gamename[100]; - char tempStr2[2]; +struct database_entry_COL { char crc_search[9]; + byte gameSize; +}; +void readDataLine_COL(FsFile& database, struct database_entry_COL* entry) { + char tempStr2[2]; + + // Read CRC32 checksum + sprintf(checksumStr, "%c", database.read()); + for (byte i = 0; i < 7; i++) { + sprintf(tempStr2, "%c", database.read()); + strcat(checksumStr, tempStr2); + } + + // Skip over semicolon + database.seekCur(1); + + // Read CRC32 of first 512 bytes + sprintf(entry->crc_search, "%c", database.read()); + for (byte i = 0; i < 7; i++) { + sprintf(tempStr2, "%c", database.read()); + strcat(entry->crc_search, tempStr2); + } + + // Skip over semicolon + database.seekCur(1); + + // Read rom size + // Read the next ascii character and subtract 48 to convert to decimal + entry->gameSize = ((database.read() - 48) * 10) + (database.read() - 48); + + // Skip rest of line + database.seekCur(2); +} + +void printDataLine_COL(struct database_entry_COL* entry) { + print_Msg(F("Size: ")); + print_Msg(entry->gameSize); + println_Msg(F("KB")); +} + +void setCart_COL() { //go to root sd.chdir(); + struct database_entry_COL entry; + // Select starting letter byte myLetter = starting_letter(); @@ -379,122 +419,38 @@ void setCart_COL() { if (myFile.open("colv.txt", O_READ)) { seek_first_letter_in_database(myFile, myLetter); - // Display database - while (myFile.available()) { - display_Clear(); + if(checkCartSelection(myFile, &readDataLine_COL, &entry, &printDataLine_COL)) { + //byte COL[] = {8, 12, 16, 20, 24, 32}; + switch (entry.gameSize) { + case 8: + colsize = 0; + break; - // Read game name - get_line(gamename, &myFile, 96); + case 12: + colsize = 1; + break; - // Read CRC32 checksum - sprintf(checksumStr, "%c", myFile.read()); - for (byte i = 0; i < 7; i++) { - sprintf(tempStr2, "%c", myFile.read()); - strcat(checksumStr, tempStr2); - } + case 16: + colsize = 2; + break; - // Skip over semicolon - myFile.seekCur(1); + case 20: + colsize = 3; + break; - // Read CRC32 of first 512 bytes - sprintf(crc_search, "%c", myFile.read()); - for (byte i = 0; i < 7; i++) { - sprintf(tempStr2, "%c", myFile.read()); - strcat(crc_search, tempStr2); - } + case 24: + colsize = 4; + break; - // Skip over semicolon - myFile.seekCur(1); + case 32: + colsize = 5; + break; - // Read rom size - // Read the next ascii character and subtract 48 to convert to decimal - cartSize = myFile.read() - 48; - - // Remove leading 0 for single digit cart sizes - if (cartSize != 0) { - cartSize = cartSize * 10 + myFile.read() - 48; - } else { - cartSize = myFile.read() - 48; - } - - // Skip rest of line - myFile.seekCur(2); - - // Skip every 3rd line - skip_line(&myFile); - - println_Msg(F("Select your cartridge")); - println_Msg(FS(FSTRING_EMPTY)); - println_Msg(gamename); - print_Msg(F("Size: ")); - print_Msg(cartSize); - println_Msg(F("KB")); - println_Msg(FS(FSTRING_EMPTY)); -#if defined(ENABLE_OLED) - print_STR(press_to_change_STR, 1); - print_STR(right_to_select_STR, 1); -#elif defined(ENABLE_LCD) - print_STR(rotate_to_change_STR, 1); - print_STR(press_to_select_STR, 1); -#elif defined(SERIAL_MONITOR) - println_Msg(F("U/D to Change")); - println_Msg(F("Space to Select")); -#endif - display_Update(); - - uint8_t b = 0; - while (1) { - // Check button input - b = checkButton(); - - // Next - if (b == 1) { + default: + colsize = 0; break; } - - // Previous - else if (b == 2) { - rewind_line(myFile, 6); - break; - } - - // Selection - else if (b == 3) { - //byte COL[] = {8, 12, 16, 20, 24, 32}; - switch (cartSize) { - case 8: - colsize = 0; - break; - - case 12: - colsize = 1; - break; - - case 16: - colsize = 2; - break; - - case 20: - colsize = 3; - break; - - case 24: - colsize = 4; - break; - - case 32: - colsize = 5; - break; - - default: - colsize = 0; - break; - } - EEPROM_writeAnything(8, colsize); - myFile.close(); - break; - } - } + EEPROM_writeAnything(8, colsize); } } else { print_FatalError(F("Database file not found")); diff --git a/Cart_Reader/Cart_Reader.ino b/Cart_Reader/Cart_Reader.ino index 4c62851..bcb659e 100644 --- a/Cart_Reader/Cart_Reader.ino +++ b/Cart_Reader/Cart_Reader.ino @@ -707,6 +707,108 @@ void seek_first_letter_in_database(FsFile& database, byte myLetter) { #endif } +// navigate through the database file using OSSC input buttons. Requires function pointer readData for reading device specific data line from database +// printDataLine - optional callback for printing device specific data informations about the currently browsed game +// setRomName - callback function to set rom name if game is selected +// returns true if a game was selected, false otherwise +boolean checkCartSelection(FsFile& database, void (*readData)(FsFile&, void*), void* data, void (*printDataLine)(void*) = NULL, void (setRomName)(const char* input) = NULL) { + char gamename[128]; + uint8_t fastScrolling = 1; + + // Display database + while (database.available()) { +#ifdef ENABLE_GLOBAL_LOG + // Disable log to prevent unnecessary logging + dont_log = true; +#endif + display_Clear(); + + get_line(gamename, &database, sizeof(gamename)); + + readData(database, data); + + skip_line(&database); + + println_Msg(F("Select your cartridge")); + println_Msg(FS(FSTRING_EMPTY)); + println_Msg(gamename); + + if(printDataLine) { + printDataLine(data); + } + println_Msg(FS(FSTRING_EMPTY)); +#if defined(ENABLE_OLED) + print_STR(press_to_change_STR, 0); + if (fastScrolling > 1) + println_Msg(F(" (fast)")); + else + println_Msg(""); + print_STR(right_to_select_STR, 1); +#elif defined(ENABLE_LCD) + print_STR(rotate_to_change_STR, 0); + if (fastScrolling > 1) + println_Msg(F(" (fast)")); + else + println_Msg(""); + print_STR(press_to_select_STR, 1); +#elif defined(SERIAL_MONITOR) + println_Msg(F("U/D to Change")); + println_Msg(F("Space to Select")); +#endif + display_Update(); + +#ifdef ENABLE_GLOBAL_LOG + // Enable log again + dont_log = false; +#endif + uint8_t b = 0; + while (1) { + // Check button input + b = checkButton(); + + // Next + if (b == 1) { + // 1: Next record + if (fastScrolling > 1) { + for (uint8_t skipped = 0; skipped < fastScrolling * 3; skipped++) { + skip_line(&database); + } + } + break; + } + + // Previous + else if (b == 2) { + // 2: Previous record + if (fastScrolling > 1) + rewind_line(database, fastScrolling * 3 + 3); + else + rewind_line(database, 6); + break; + } + + // Selection + else if (b == 3) { + if(setRomName) { + setRomName(gamename); + } + database.close(); + return true; + } + + else if (b == 4) { + // 4: Toggle Fast Scrolling + if (fastScrolling == 1) + fastScrolling = 30; + else + fastScrolling = 1; + continue; + } + } + } + return false; +} + void starting_letter__subDraw(byte selection, byte line) { display.setDrawColor(0); for (uint8_t i = 0; i < 4; i++) display.drawLine(0, 10 + i * 16, 128, 10 + i * 16); diff --git a/Cart_Reader/INTV.ino b/Cart_Reader/INTV.ino index 6d1f763..d07f76f 100644 --- a/Cart_Reader/INTV.ino +++ b/Cart_Reader/INTV.ino @@ -757,14 +757,69 @@ void checkStatus_INTV() { //****************************************** // CART SELECT CODE //****************************************** -void setCart_INTV() { - char gamename[100]; - char tempStr2[2]; +struct database_entry_INTV { char crc_search[9]; + byte gameMapper; + byte gameSize; +}; +void readDataLine_INTV(FsFile& database, struct database_entry_INTV* entry) { + char tempStr2[2]; + + // Read CRC32 checksum + sprintf(checksumStr, "%c", database.read()); + for (byte i = 0; i < 7; i++) { + sprintf(tempStr2, "%c", database.read()); + strcat(checksumStr, tempStr2); + } + + // Skip over semicolon + database.seekCur(1); + + // Read CRC32 of first 512 bytes + sprintf(entry->crc_search, "%c", database.read()); + for (byte i = 0; i < 7; i++) { + sprintf(tempStr2, "%c", database.read()); + strcat(entry->crc_search, tempStr2); + } + + // Skip over semicolon + database.seekCur(1); + + // Read mapper + entry->gameMapper = database.read() - 48; + + // Skip over semicolon + database.seekCur(1); + + // Read rom size + // Read the next ascii character and subtract 48 to convert to decimal + entry->gameSize = ((database.read() - 48) * 10) + (database.read() - 48); + + // Skip over semicolon + database.seekCur(1); + + // Read SRAM size + byte sramSize __attribute__((unused)) = database.read() - 48; + + // Skip rest of line + database.seekCur(2); +} + +void printDataLine_INTV(struct database_entry_INTV* entry) { + print_Msg(F("Size: ")); + print_Msg(entry->gameSize); + println_Msg(F("KB")); + print_Msg(F("Mapper: ")); + println_Msg(entry->gameMapper); +} + +void setCart_INTV() { //go to root sd.chdir(); + struct database_entry_INTV entry; + // Select starting letter byte myLetter = starting_letter(); @@ -772,136 +827,39 @@ void setCart_INTV() { if (myFile.open("intv.txt", O_READ)) { seek_first_letter_in_database(myFile, myLetter); - // Display database - while (myFile.available()) { - display_Clear(); - - // Read game name - get_line(gamename, &myFile, 96); - - // Read CRC32 checksum - sprintf(checksumStr, "%c", myFile.read()); - for (byte i = 0; i < 7; i++) { - sprintf(tempStr2, "%c", myFile.read()); - strcat(checksumStr, tempStr2); - } - - // Skip over semicolon - myFile.seekCur(1); - - // Read CRC32 of first 512 bytes - sprintf(crc_search, "%c", myFile.read()); - for (byte i = 0; i < 7; i++) { - sprintf(tempStr2, "%c", myFile.read()); - strcat(crc_search, tempStr2); - } - - // Skip over semicolon - myFile.seekCur(1); - - // Read mapper - intvmapper = myFile.read() - 48; - - // Skip over semicolon - myFile.seekCur(1); - - // Read rom size - // Read the next ascii character and subtract 48 to convert to decimal - cartSize = myFile.read() - 48; - - // Remove leading 0 for single digit cart sizes - if (cartSize != 0) { - cartSize = cartSize * 10 + myFile.read() - 48; - } else { - cartSize = myFile.read() - 48; - } - - // Skip over semicolon - myFile.seekCur(1); - - // Read SRAM size - byte sramSize __attribute__((unused)) = myFile.read() - 48; - - // Skip rest of line - myFile.seekCur(2); - - // Skip every 3rd line - skip_line(&myFile); - - println_Msg(F("Select your cartridge")); - println_Msg(FS(FSTRING_EMPTY)); - println_Msg(gamename); - print_Msg(F("Size: ")); - print_Msg(cartSize); - println_Msg(F("KB")); - print_Msg(F("Mapper: ")); - println_Msg(intvmapper); -#if defined(ENABLE_OLED) - print_STR(press_to_change_STR, 1); - print_STR(right_to_select_STR, 1); -#elif defined(ENABLE_LCD) - print_STR(rotate_to_change_STR, 1); - print_STR(press_to_select_STR, 1); -#elif defined(SERIAL_MONITOR) - println_Msg(F("U/D to Change")); - println_Msg(F("Space to Select")); -#endif - display_Update(); - - uint8_t b = 0; - while (1) { - // Check button input - b = checkButton(); - - // Next - if (b == 1) { + if(checkCartSelection(myFile, &readDataLine_INTV, &entry, &printDataLine_INTV)) { + //byte INTV[] = {8, 12, 16, 24, 32, 48}; + switch (entry.gameSize) { + case 8: + intvsize = 0; break; - } - // Previous - else if (b == 2) { - rewind_line(myFile, 6); + case 12: + intvsize = 1; break; - } - // Selection - else if (b == 3) { - //byte INTV[] = {8, 12, 16, 24, 32, 48}; - switch (cartSize) { - case 8: - intvsize = 0; - break; - - case 12: - intvsize = 1; - break; - - case 16: - intvsize = 2; - break; - - case 24: - intvsize = 3; - break; - - case 32: - intvsize = 4; - break; - - case 48: - intvsize = 5; - break; - - default: - intvsize = 0; - break; - } - EEPROM_writeAnything(7, intvmapper); - EEPROM_writeAnything(8, intvsize); - myFile.close(); + case 16: + intvsize = 2; + break; + + case 24: + intvsize = 3; + break; + + case 32: + intvsize = 4; + break; + + case 48: + intvsize = 5; + break; + + default: + intvsize = 0; break; - } } + EEPROM_writeAnything(7, entry.gameMapper); + EEPROM_writeAnything(8, intvsize); } } else { print_FatalError(F("Database file not found")); diff --git a/Cart_Reader/NES.ino b/Cart_Reader/NES.ino index c39a60e..c77c9fd 100644 --- a/Cart_Reader/NES.ino +++ b/Cart_Reader/NES.ino @@ -514,6 +514,69 @@ void setRomnameFromString(const char* input) { } } +void printDataLine_NES(struct database_entry* entry) { + uint8_t iNES[16]; + uint8_t* output; + char* input; + + input = entry->iNES_str; + output = iNES; + for (uint8_t i = 0; i < sizeof(iNES); i++) { + unsigned int buf; + + sscanf(input, "%2X", &buf); + *(output++) = buf; + input += 2; + } + + mapper = (iNES[6] >> 4) | (iNES[7] & 0xF0) | (iNES[8] & 0x0F); + + if ((iNES[9] & 0x0F) != 0x0F) { + // simple notation + prgsize = (iNES[4] | ((iNES[9] & 0x0F) << 8)); //*16 + } else { + // exponent-multiplier notation + prgsize = (((1 << (iNES[4] >> 2)) * ((iNES[4] & 0b11) * 2 + 1)) >> 14); //*16 + } + if (prgsize != 0) + prgsize = (int(log(prgsize) / log(2))); + + if ((iNES[9] & 0xF0) != 0xF0) { + // simple notation + chrsize = (uppow2(iNES[5] | ((iNES[9] & 0xF0) << 4))) * 2; //*4 + } else { + // exponent-multiplier notation + chrsize = (((1 << (iNES[5] >> 2)) * ((iNES[5] & 0b11) * 2 + 1)) >> 13) * 2; //*4 + } + if (chrsize != 0) + chrsize = (int(log(chrsize) / log(2))); + + ramsize = ((iNES[10] & 0xF0) ? (64 << ((iNES[10] & 0xF0) >> 4)) : 0) / 4096; //*4 + if (ramsize != 0) + ramsize = (int(log(ramsize) / log(2))); + + prg = (int_pow(2, prgsize)) * 16; + if (chrsize == 0) + chr = 0; // 0K + else + chr = (int_pow(2, chrsize)) * 4; + if (ramsize == 0) + ram = 0; // 0K + else if (mapper == 82) + ram = 5; // 5K + else + ram = (int_pow(2, ramsize)) * 4; + + // Mapper Variants + // Identify variant for use across multiple functions + if (mapper == 4) { // Check for MMC6/MMC3 + checkMMC6(); + if (mmc6) + ram = 1; // 1K + } + printNESSettings(); +} + void getMapping() { FsFile database; uint32_t oldcrc32 = 0xFFFFFFFF; @@ -590,143 +653,15 @@ void getMapping() { } } if (browseDatabase) { - uint8_t fastScrolling = 1; + struct database_entry entry; - // Display database - while (database.available()) { -#ifdef ENABLE_GLOBAL_LOG - // Disable log to prevent unnecessary logging - dont_log = true; -#endif - - uint8_t iNES[16]; - uint8_t* output; - char* input; - - struct database_entry entry; - display_Clear(); - readDatabaseEntry(database, &entry); - - input = entry.iNES_str; - output = iNES; - for (uint8_t i = 0; i < sizeof(iNES); i++) { - unsigned int buf; - - sscanf(input, "%2X", &buf); - *(output++) = buf; - input += 2; - } - - mapper = (iNES[6] >> 4) | (iNES[7] & 0xF0) | (iNES[8] & 0x0F); - - if ((iNES[9] & 0x0F) != 0x0F) { - // simple notation - prgsize = (iNES[4] | ((iNES[9] & 0x0F) << 8)); //*16 - } else { - // exponent-multiplier notation - prgsize = (((1 << (iNES[4] >> 2)) * ((iNES[4] & 0b11) * 2 + 1)) >> 14); //*16 - } - if (prgsize != 0) - prgsize = (int(log(prgsize) / log(2))); - - if ((iNES[9] & 0xF0) != 0xF0) { - // simple notation - chrsize = (uppow2(iNES[5] | ((iNES[9] & 0xF0) << 4))) * 2; //*4 - } else { - // exponent-multiplier notation - chrsize = (((1 << (iNES[5] >> 2)) * ((iNES[5] & 0b11) * 2 + 1)) >> 13) * 2; //*4 - } - if (chrsize != 0) - chrsize = (int(log(chrsize) / log(2))); - - ramsize = ((iNES[10] & 0xF0) ? (64 << ((iNES[10] & 0xF0) >> 4)) : 0) / 4096; //*4 - if (ramsize != 0) - ramsize = (int(log(ramsize) / log(2))); - - prg = (int_pow(2, prgsize)) * 16; - if (chrsize == 0) - chr = 0; // 0K - else - chr = (int_pow(2, chrsize)) * 4; - if (ramsize == 0) - ram = 0; // 0K - else if (mapper == 82) - ram = 5; // 5K - else - ram = (int_pow(2, ramsize)) * 4; - - // Mapper Variants - // Identify variant for use across multiple functions - if (mapper == 4) { // Check for MMC6/MMC3 - checkMMC6(); - if (mmc6) - ram = 1; // 1K - } - - println_Msg(entry.filename); - printNESSettings(); -#if defined(ENABLE_OLED) - print_STR(press_to_change_STR, 0); - if (fastScrolling > 1) - println_Msg(F(" (fast)")); - else - println_Msg(""); - print_STR(right_to_select_STR, 1); -#elif defined(ENABLE_LCD) - print_STR(rotate_to_change_STR, 0); - if (fastScrolling > 1) - println_Msg(F(" (fast)")); - else - println_Msg(""); - print_STR(press_to_select_STR, 1); -#elif defined(SERIAL_MONITOR) - println_Msg(F("U/D to Change")); - println_Msg(F("Space to Select")); -#endif - display_Update(); - -#ifdef ENABLE_GLOBAL_LOG - // Enable log again - dont_log = false; -#endif - uint8_t b = 0; - do { - b = checkButton(); - } while (b == 0); - - if (b == 1) { - // 1: Next record - if (fastScrolling > 1) { - for (uint8_t skipped = 0; skipped < fastScrolling * 3; skipped++) { - skip_line(&database); - } - } - continue; - } - if (b == 2) { - // 2: Previous record - if (fastScrolling > 1) - rewind_line(database, fastScrolling * 3 + 3); - else - rewind_line(database, 6); - continue; - } - if (b == 4) { - // 4: Toggle Fast Scrolling - if (fastScrolling == 1) - fastScrolling = 30; - else - fastScrolling = 1; - continue; - } + if(checkCartSelection(database, &readDataLine_NES, &entry, &printDataLine_NES, &setRomnameFromString)) { // anything else: select current record - setRomnameFromString(entry.filename); // Save Mapper EEPROM_writeAnything(7, mapper); EEPROM_writeAnything(8, prgsize); EEPROM_writeAnything(9, chrsize); EEPROM_writeAnything(10, ramsize); - break; } } database.close(); @@ -734,8 +669,12 @@ void getMapping() { static void readDatabaseEntry(FsFile& database, struct database_entry* entry) { get_line(entry->filename, &database, sizeof(entry->filename)); - get_line(entry->crc_str, &database, sizeof(entry->crc_str)); + readDataLine_NES(database, entry); skip_line(&database); +} + +void readDataLine_NES(FsFile& database, struct database_entry* entry) { + get_line(entry->crc_str, &database, sizeof(entry->crc_str)); entry->crc_str[8] = 0; entry->crc512_str = &entry->crc_str[8 + 1]; diff --git a/Cart_Reader/WSV.ino b/Cart_Reader/WSV.ino index db75c2b..29ea1fb 100644 --- a/Cart_Reader/WSV.ino +++ b/Cart_Reader/WSV.ino @@ -378,14 +378,57 @@ void checkStatus_WSV() { //****************************************** // CART SELECT CODE //****************************************** -void setCart_WSV() { - char gamename[100]; - char tempStr2[2]; +struct database_entry_WSV { char crc_search[9]; + byte gameSize; +}; +void readDataLine_WSV(FsFile& database, struct database_entry_WSV* entry) { + char tempStr2[2]; + + // Read CRC32 checksum + sprintf(checksumStr, "%c", database.read()); + for (byte i = 0; i < 7; i++) { + sprintf(tempStr2, "%c", database.read()); + strcat(checksumStr, tempStr2); + } + + // Skip over semicolon + database.seekCur(1); + + // Read CRC32 of first 512 bytes + sprintf(entry->crc_search, "%c", database.read()); + for (byte i = 0; i < 7; i++) { + sprintf(tempStr2, "%c", database.read()); + strcat(entry->crc_search, tempStr2); + } + + // Skip over semicolon + database.seekCur(1); + + // Read rom size + // Read the next ascii character and subtract 48 to convert to decimal + entry->gameSize = ((database.read() - 48) * 10) + (database.read() - 48); + + // Skip rest of line + database.seekCur(2); +} + +void printDataLine_WSV(struct database_entry_WSV* entry) { + print_Msg(F("Size: ")); + if (entry->gameSize == 51) + print_Msg(F("512")); + else + print_Msg(entry->gameSize); + println_Msg(F("KB")); +} + +void setCart_WSV() { //go to root sd.chdir(); + struct database_entry_WSV entry; + // Select starting letter byte myLetter = starting_letter(); @@ -393,109 +436,22 @@ void setCart_WSV() { if (myFile.open("wsv.txt", O_READ)) { seek_first_letter_in_database(myFile, myLetter); - // Display database - while (myFile.available()) { - display_Clear(); + if(checkCartSelection(myFile, &readDataLine_WSV, &entry, &printDataLine_WSV)) { + //word WSV[] = {32,64,512}; + switch (entry.gameSize) { + case 32: + wsvsize = 0; + break; - // Read game name - get_line(gamename, &myFile, 96); + case 64: + wsvsize = 1; + break; - // Read CRC32 checksum - sprintf(checksumStr, "%c", myFile.read()); - for (byte i = 0; i < 7; i++) { - sprintf(tempStr2, "%c", myFile.read()); - strcat(checksumStr, tempStr2); - } - - // Skip over semicolon - myFile.seekCur(1); - - // Read CRC32 of first 512 bytes - sprintf(crc_search, "%c", myFile.read()); - for (byte i = 0; i < 7; i++) { - sprintf(tempStr2, "%c", myFile.read()); - strcat(crc_search, tempStr2); - } - - // Skip over semicolon - myFile.seekCur(1); - - // Read rom size - // Read the next ascii character and subtract 48 to convert to decimal - cartSize = myFile.read() - 48; - - // Remove leading 0 for single digit cart sizes - if (cartSize != 0) { - cartSize = cartSize * 10 + myFile.read() - 48; - } else { - cartSize = myFile.read() - 48; - } - - // Skip rest of line - myFile.seekCur(2); - - // Skip every 3rd line - skip_line(&myFile); - - println_Msg(F("Select your cartridge")); - println_Msg(FS(FSTRING_EMPTY)); - println_Msg(gamename); - print_Msg(F("Size: ")); - if (cartSize == 51) - print_Msg(F("512")); - else - print_Msg(cartSize); - println_Msg(F("KB")); - println_Msg(FS(FSTRING_EMPTY)); -#if defined(ENABLE_OLED) - print_STR(press_to_change_STR, 1); - print_STR(right_to_select_STR, 1); -#elif defined(ENABLE_LCD) - print_STR(rotate_to_change_STR, 1); - print_STR(press_to_select_STR, 1); -#elif defined(SERIAL_MONITOR) - println_Msg(F("U/D to Change")); - println_Msg(F("Space to Select")); -#endif - display_Update(); - - uint8_t b = 0; - while (1) { - // Check button input - b = checkButton(); - - // Next - if (b == 1) { + case 51: + wsvsize = 2; break; } - - // Previous - else if (b == 2) { - rewind_line(myFile, 6); - break; - } - - // Selection - else if (b == 3) { - //word WSV[] = {32,64,512}; - switch (cartSize) { - case 32: - wsvsize = 0; - break; - - case 64: - wsvsize = 1; - break; - - case 51: - wsvsize = 2; - break; - } - EEPROM_writeAnything(8, wsvsize); - myFile.close(); - break; - } - } + EEPROM_writeAnything(8, wsvsize); } } else { print_FatalError(F("Database file not found"));