port NES fast forward selection to other systems

This commit is contained in:
smesgr9000 2024-04-28 13:35:21 +02:00
parent 38f3ebdc8d
commit 06d5f28d0c
8 changed files with 441 additions and 655 deletions

View File

@ -792,12 +792,18 @@ setmapper:
//****************************************** //******************************************
// CART SELECT CODE // 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() { void setCart_2600() {
//go to root //go to root
sd.chdir(); sd.chdir();
char gamename[100];
byte gameMapper; byte gameMapper;
byte gameSize; byte gameSize;
@ -808,64 +814,13 @@ void setCart_2600() {
if (myFile.open("2600.txt", O_READ)) { if (myFile.open("2600.txt", O_READ)) {
seek_first_letter_in_database(myFile, myLetter); seek_first_letter_in_database(myFile, myLetter);
// Display database if(checkCartSelection(myFile, &readDataLine_2600, &gameMapper)) {
while (myFile.available()) { EEPROM_writeAnything(7, gameMapper);
display_Clear(); for (int i = 0; i < a2600mapcount; i++) {
a2600index = i * 2;
get_line(gamename, &myFile, sizeof(gamename)); if (gameMapper == pgm_read_byte(a2600mapsize + a2600index)) {
a2600size = pgm_read_byte(a2600mapsize + a2600index + 1);
// Read mapper with three ascii character and subtract 48 to convert to decimal EEPROM_writeAnything(8, a2600size);
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();
break; break;
} }
} }

View File

@ -781,14 +781,30 @@ setmapper:
//****************************************** //******************************************
// CART SELECT CODE // 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() { void setCart_7800() {
//go to root //go to root
sd.chdir(); sd.chdir();
char gamename[100]; struct database_entry_7800 entry;
byte gameMapper;
byte gameSize;
// Select starting letter // Select starting letter
byte myLetter = starting_letter(); byte myLetter = starting_letter();
@ -797,66 +813,9 @@ void setCart_7800() {
if (myFile.open("7800.txt", O_READ)) { if (myFile.open("7800.txt", O_READ)) {
seek_first_letter_in_database(myFile, myLetter); seek_first_letter_in_database(myFile, myLetter);
// Display database if(checkCartSelection(myFile, &readDataLine_7800, &entry)) {
while (myFile.available()) { EEPROM_writeAnything(7, entry.gameMapper);
display_Clear(); EEPROM_writeAnything(8, entry.gameSize);
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;
}
}
} }
} else { } else {
print_FatalError(F("Database file not found")); print_FatalError(F("Database file not found"));

View File

@ -1029,13 +1029,30 @@ void printMapper_C64(byte c64maplabel) {
//****************************************** //******************************************
// CART SELECT CODE // 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() { void setCart_C64() {
//go to root //go to root
sd.chdir(); sd.chdir();
char gamename[100]; struct database_entry_C64 entry;
byte gameMapper;
byte gameSize;
// Select starting letter // Select starting letter
byte myLetter = starting_letter(); byte myLetter = starting_letter();
@ -1044,65 +1061,9 @@ void setCart_C64() {
if (myFile.open("c64cart.txt", O_READ)) { if (myFile.open("c64cart.txt", O_READ)) {
seek_first_letter_in_database(myFile, myLetter); seek_first_letter_in_database(myFile, myLetter);
// Display database if(checkCartSelection(myFile, &readDataLine_C64, &entry)) {
while (myFile.available()) { EEPROM_writeAnything(7, entry.gameMapper);
display_Clear(); EEPROM_writeAnything(8, entry.gameSize);
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;
}
}
} }
} else { } else {
print_FatalError(F("Database file not found")); print_FatalError(F("Database file not found"));

View File

@ -364,14 +364,54 @@ void checkStatus_COL() {
//****************************************** //******************************************
// CART SELECT CODE // CART SELECT CODE
//****************************************** //******************************************
void setCart_COL() { struct database_entry_COL {
char gamename[100];
char tempStr2[2];
char crc_search[9]; 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 //go to root
sd.chdir(); sd.chdir();
struct database_entry_COL entry;
// Select starting letter // Select starting letter
byte myLetter = starting_letter(); byte myLetter = starting_letter();
@ -379,122 +419,38 @@ void setCart_COL() {
if (myFile.open("colv.txt", O_READ)) { if (myFile.open("colv.txt", O_READ)) {
seek_first_letter_in_database(myFile, myLetter); seek_first_letter_in_database(myFile, myLetter);
// Display database if(checkCartSelection(myFile, &readDataLine_COL, &entry, &printDataLine_COL)) {
while (myFile.available()) { //byte COL[] = {8, 12, 16, 20, 24, 32};
display_Clear(); switch (entry.gameSize) {
case 8:
colsize = 0;
break;
// Read game name case 12:
get_line(gamename, &myFile, 96); colsize = 1;
break;
// Read CRC32 checksum case 16:
sprintf(checksumStr, "%c", myFile.read()); colsize = 2;
for (byte i = 0; i < 7; i++) { break;
sprintf(tempStr2, "%c", myFile.read());
strcat(checksumStr, tempStr2);
}
// Skip over semicolon case 20:
myFile.seekCur(1); colsize = 3;
break;
// Read CRC32 of first 512 bytes case 24:
sprintf(crc_search, "%c", myFile.read()); colsize = 4;
for (byte i = 0; i < 7; i++) { break;
sprintf(tempStr2, "%c", myFile.read());
strcat(crc_search, tempStr2);
}
// Skip over semicolon case 32:
myFile.seekCur(1); colsize = 5;
break;
// Read rom size default:
// Read the next ascii character and subtract 48 to convert to decimal colsize = 0;
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) {
break; break;
} }
EEPROM_writeAnything(8, colsize);
// 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;
}
}
} }
} else { } else {
print_FatalError(F("Database file not found")); print_FatalError(F("Database file not found"));

View File

@ -707,6 +707,108 @@ void seek_first_letter_in_database(FsFile& database, byte myLetter) {
#endif #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) { void starting_letter__subDraw(byte selection, byte line) {
display.setDrawColor(0); display.setDrawColor(0);
for (uint8_t i = 0; i < 4; i++) display.drawLine(0, 10 + i * 16, 128, 10 + i * 16); for (uint8_t i = 0; i < 4; i++) display.drawLine(0, 10 + i * 16, 128, 10 + i * 16);

View File

@ -757,14 +757,69 @@ void checkStatus_INTV() {
//****************************************** //******************************************
// CART SELECT CODE // CART SELECT CODE
//****************************************** //******************************************
void setCart_INTV() { struct database_entry_INTV {
char gamename[100];
char tempStr2[2];
char crc_search[9]; 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 //go to root
sd.chdir(); sd.chdir();
struct database_entry_INTV entry;
// Select starting letter // Select starting letter
byte myLetter = starting_letter(); byte myLetter = starting_letter();
@ -772,136 +827,39 @@ void setCart_INTV() {
if (myFile.open("intv.txt", O_READ)) { if (myFile.open("intv.txt", O_READ)) {
seek_first_letter_in_database(myFile, myLetter); seek_first_letter_in_database(myFile, myLetter);
// Display database if(checkCartSelection(myFile, &readDataLine_INTV, &entry, &printDataLine_INTV)) {
while (myFile.available()) { //byte INTV[] = {8, 12, 16, 24, 32, 48};
display_Clear(); switch (entry.gameSize) {
case 8:
// Read game name intvsize = 0;
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) {
break; break;
}
// Previous case 12:
else if (b == 2) { intvsize = 1;
rewind_line(myFile, 6);
break; break;
}
// Selection case 16:
else if (b == 3) { intvsize = 2;
//byte INTV[] = {8, 12, 16, 24, 32, 48}; break;
switch (cartSize) {
case 8: case 24:
intvsize = 0; intvsize = 3;
break; break;
case 12: case 32:
intvsize = 1; intvsize = 4;
break; break;
case 16: case 48:
intvsize = 2; intvsize = 5;
break; break;
case 24: default:
intvsize = 3; intvsize = 0;
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();
break; break;
}
} }
EEPROM_writeAnything(7, entry.gameMapper);
EEPROM_writeAnything(8, intvsize);
} }
} else { } else {
print_FatalError(F("Database file not found")); print_FatalError(F("Database file not found"));

View File

@ -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() { void getMapping() {
FsFile database; FsFile database;
uint32_t oldcrc32 = 0xFFFFFFFF; uint32_t oldcrc32 = 0xFFFFFFFF;
@ -590,143 +653,15 @@ void getMapping() {
} }
} }
if (browseDatabase) { if (browseDatabase) {
uint8_t fastScrolling = 1; struct database_entry entry;
// Display database if(checkCartSelection(database, &readDataLine_NES, &entry, &printDataLine_NES, &setRomnameFromString)) {
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;
}
// anything else: select current record // anything else: select current record
setRomnameFromString(entry.filename);
// Save Mapper // Save Mapper
EEPROM_writeAnything(7, mapper); EEPROM_writeAnything(7, mapper);
EEPROM_writeAnything(8, prgsize); EEPROM_writeAnything(8, prgsize);
EEPROM_writeAnything(9, chrsize); EEPROM_writeAnything(9, chrsize);
EEPROM_writeAnything(10, ramsize); EEPROM_writeAnything(10, ramsize);
break;
} }
} }
database.close(); database.close();
@ -734,8 +669,12 @@ void getMapping() {
static void readDatabaseEntry(FsFile& database, struct database_entry* entry) { static void readDatabaseEntry(FsFile& database, struct database_entry* entry) {
get_line(entry->filename, &database, sizeof(entry->filename)); 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); 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->crc_str[8] = 0;
entry->crc512_str = &entry->crc_str[8 + 1]; entry->crc512_str = &entry->crc_str[8 + 1];

View File

@ -378,14 +378,57 @@ void checkStatus_WSV() {
//****************************************** //******************************************
// CART SELECT CODE // CART SELECT CODE
//****************************************** //******************************************
void setCart_WSV() { struct database_entry_WSV {
char gamename[100];
char tempStr2[2];
char crc_search[9]; 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 //go to root
sd.chdir(); sd.chdir();
struct database_entry_WSV entry;
// Select starting letter // Select starting letter
byte myLetter = starting_letter(); byte myLetter = starting_letter();
@ -393,109 +436,22 @@ void setCart_WSV() {
if (myFile.open("wsv.txt", O_READ)) { if (myFile.open("wsv.txt", O_READ)) {
seek_first_letter_in_database(myFile, myLetter); seek_first_letter_in_database(myFile, myLetter);
// Display database if(checkCartSelection(myFile, &readDataLine_WSV, &entry, &printDataLine_WSV)) {
while (myFile.available()) { //word WSV[] = {32,64,512};
display_Clear(); switch (entry.gameSize) {
case 32:
wsvsize = 0;
break;
// Read game name case 64:
get_line(gamename, &myFile, 96); wsvsize = 1;
break;
// Read CRC32 checksum case 51:
sprintf(checksumStr, "%c", myFile.read()); wsvsize = 2;
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) {
break; break;
} }
EEPROM_writeAnything(8, wsvsize);
// 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;
}
}
} }
} else { } else {
print_FatalError(F("Database file not found")); print_FatalError(F("Database file not found"));