mirror of
https://github.com/sanni/cartreader.git
synced 2024-11-23 21:19:16 +01:00
9.4: Add selecting mapping from database list for NES
This commit is contained in:
parent
92f76b324c
commit
511902eb56
@ -372,7 +372,6 @@ void checkStatus_COL()
|
||||
// CART SELECT CODE
|
||||
//******************************************
|
||||
void setCart_COL() {
|
||||
//Search for CRC32 in file
|
||||
char gamename[100];
|
||||
char tempStr2[2];
|
||||
char crc_search[9];
|
||||
@ -380,8 +379,46 @@ void setCart_COL() {
|
||||
//go to root
|
||||
sd.chdir();
|
||||
|
||||
// Select starting letter
|
||||
byte myLetter = starting_letter();
|
||||
|
||||
// Open database
|
||||
if (myFile.open("colv.txt", O_READ)) {
|
||||
// Skip ahead to selected starting letter
|
||||
if ((myLetter > 0) && (myLetter <= 26)) {
|
||||
while (myFile.available()) {
|
||||
// Read current name
|
||||
get_line(gamename, &myFile, 96);
|
||||
|
||||
// Compare selected letter with first letter of current name until match
|
||||
while (gamename[0] != 64 + myLetter) {
|
||||
skip_line(&myFile);
|
||||
skip_line(&myFile);
|
||||
get_line(gamename, &myFile, 96);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// Rewind one line
|
||||
for (byte count_newline = 0; count_newline < 2; count_newline++) {
|
||||
while (1) {
|
||||
if (myFile.curPosition() == 0) {
|
||||
break;
|
||||
}
|
||||
else if (myFile.peek() == '\n') {
|
||||
myFile.seekSet(myFile.curPosition() - 1);
|
||||
break;
|
||||
}
|
||||
else {
|
||||
myFile.seekSet(myFile.curPosition() - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (myFile.curPosition() != 0)
|
||||
myFile.seekSet(myFile.curPosition() + 2);
|
||||
}
|
||||
|
||||
// Display database
|
||||
while (myFile.available()) {
|
||||
display_Clear();
|
||||
|
||||
@ -520,8 +557,7 @@ void setCart_COL() {
|
||||
}
|
||||
}
|
||||
else {
|
||||
println_Msg(F("Database file not found"));
|
||||
return 0;
|
||||
print_Error(F("Database file not found"), true);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -4,8 +4,8 @@
|
||||
This project represents a community-driven effort to provide
|
||||
an easy to build and easy to modify cartridge dumper.
|
||||
|
||||
Date: 03.08.2022
|
||||
Version: 9.3
|
||||
Date: 06.08.2022
|
||||
Version: 9.4
|
||||
|
||||
SD lib: https://github.com/greiman/SdFat
|
||||
OLED lib: https://github.com/adafruit/Adafruit_SSD1306
|
||||
@ -60,7 +60,7 @@
|
||||
|
||||
**********************************************************************************/
|
||||
|
||||
char ver[5] = "9.3";
|
||||
char ver[5] = "9.4";
|
||||
|
||||
//******************************************
|
||||
// !!! CHOOSE HARDWARE VERSION !!!
|
||||
@ -691,6 +691,108 @@ boolean compareCRC(char* database, char* crcString, boolean renamerom, int offse
|
||||
#endif
|
||||
}
|
||||
|
||||
byte starting_letter() {
|
||||
#if (defined(enable_LCD) || defined(enable_OLED))
|
||||
byte selection = 0;
|
||||
byte line = 0;
|
||||
|
||||
display_Clear();
|
||||
#if defined(enable_LCD)
|
||||
println_Msg(F("[#] [A] [B] [C] [D] [E] [F]"));
|
||||
println_Msg(F(""));
|
||||
println_Msg(F("[G] [H] [ I ] [J] [K] [L] [M]"));
|
||||
println_Msg(F(""));
|
||||
println_Msg(F("[N] [O] [P] [Q] [R] [S] [T]"));
|
||||
println_Msg(F(""));
|
||||
println_Msg(F("[U] [V] [W] [X] [Y] [Z] [?]"));
|
||||
#elif defined(enable_OLED)
|
||||
println_Msg(F("# A B C D E F"));
|
||||
println_Msg(F(""));
|
||||
println_Msg(F("G H I J K L M"));
|
||||
println_Msg(F(""));
|
||||
println_Msg(F("N O P Q R S T"));
|
||||
println_Msg(F(""));
|
||||
println_Msg(F("U V W X Y Z ?"));
|
||||
#endif
|
||||
|
||||
// Draw selection line
|
||||
#if defined(enable_LCD)
|
||||
display.setDrawColor(1);
|
||||
display.drawLine(4 + selection * 16, 10 + line * 16, 9 + selection * 16, 10 + line * 16);
|
||||
#elif defined(enable_OLED)
|
||||
display.drawLine(selection * 18, 10 + line * 16, 5 + selection * 18, 10 + line * 16, WHITE);
|
||||
#endif
|
||||
display_Update();
|
||||
|
||||
while (1) {
|
||||
int b = checkButton();
|
||||
if (b == 2) { // Previous
|
||||
if ((selection == 0) && (line > 0)) {
|
||||
line--;
|
||||
selection = 6;
|
||||
}
|
||||
else if (selection > 0) {
|
||||
selection--;
|
||||
}
|
||||
#if defined(enable_LCD)
|
||||
display.setDrawColor(0);
|
||||
display.drawLine(0, 10 + (line + 1) * 16, 128, 10 + (line + 1) * 16);
|
||||
display.drawLine(0, 10 + line * 16, 128, 10 + line * 16);
|
||||
display.setDrawColor(1);
|
||||
display.drawLine(4 + selection * 16, 10 + line * 16, 9 + selection * 16, 10 + line * 16);
|
||||
#elif defined(enable_OLED)
|
||||
display.drawLine(0, 10 + (line + 1) * 16, 128, 10 + (line + 1) * 16, BLACK);
|
||||
display.drawLine(0, 10 + line * 16, 128, 10 + line * 16, BLACK);
|
||||
display.drawLine(selection * 18, 10 + line * 16, 5 + selection * 18, 10 + line * 16, WHITE);
|
||||
#endif
|
||||
display_Update();
|
||||
|
||||
}
|
||||
|
||||
else if (b == 1) { // Next
|
||||
if ((selection == 6) && (line < 3)) {
|
||||
line++;
|
||||
selection = 0;
|
||||
}
|
||||
else if (selection < 6) {
|
||||
selection++;
|
||||
}
|
||||
#if defined(enable_LCD)
|
||||
display.setDrawColor(0);
|
||||
display.drawLine(0, 10 + (line - 1) * 16, 128, 10 + (line - 1) * 16);
|
||||
display.drawLine(0, 10 + line * 16, 128, 10 + line * 16);
|
||||
display.setDrawColor(1);
|
||||
display.drawLine(4 + selection * 16, 10 + line * 16, 9 + selection * 16, 10 + line * 16);
|
||||
#elif defined(enable_OLED)
|
||||
display.drawLine(0, 10 + (line - 1) * 16, 128, 10 + (line - 1) * 16, BLACK);
|
||||
display.drawLine(0, 10 + line * 16, 128, 10 + line * 16, BLACK);
|
||||
display.drawLine(selection * 18, 10 + line * 16, 5 + selection * 18, 10 + line * 16, WHITE);
|
||||
#endif
|
||||
display_Update();
|
||||
}
|
||||
|
||||
else if (b == 3) { // Long Press - Execute
|
||||
display_Clear();
|
||||
println_Msg(F(""));
|
||||
println_Msg(F(""));
|
||||
println_Msg(F(""));
|
||||
println_Msg(F("Please wait..."));
|
||||
display_Update();
|
||||
break;
|
||||
}
|
||||
}
|
||||
return (selection + line * 7);
|
||||
#elif defined(SERIAL_MONITOR)
|
||||
Serial.println(F("Enter first letter: "));
|
||||
while (Serial.available() == 0) {
|
||||
}
|
||||
|
||||
// Read the incoming byte:
|
||||
byte incomingByte = Serial.read();
|
||||
return incomingByte;
|
||||
#endif
|
||||
}
|
||||
|
||||
/******************************************
|
||||
Main menu optimized for rotary encoder
|
||||
*****************************************/
|
||||
@ -759,7 +861,13 @@ void mainMenu() {
|
||||
display_Update();
|
||||
setup_NES();
|
||||
#ifdef no-intro
|
||||
checkStatus_NES(getMapping());
|
||||
if (getMapping() == 0) {
|
||||
selectMapping();
|
||||
checkStatus_NES(0);
|
||||
}
|
||||
else {
|
||||
checkStatus_NES(1);
|
||||
}
|
||||
#else
|
||||
checkStatus_NES(0);
|
||||
#endif
|
||||
@ -1001,7 +1109,13 @@ void consoleMenu() {
|
||||
display_Update();
|
||||
setup_NES();
|
||||
#ifdef no-intro
|
||||
checkStatus_NES(getMapping());
|
||||
if (getMapping() == 0) {
|
||||
selectMapping();
|
||||
checkStatus_NES(0);
|
||||
}
|
||||
else {
|
||||
checkStatus_NES(1);
|
||||
}
|
||||
#else
|
||||
checkStatus_NES(0);
|
||||
#endif
|
||||
|
@ -757,8 +757,10 @@ void checkStatus_INTV()
|
||||
#endif
|
||||
}
|
||||
|
||||
//******************************************
|
||||
// CART SELECT CODE
|
||||
//******************************************
|
||||
void setCart_INTV() {
|
||||
//Search for CRC32 in file
|
||||
char gamename[100];
|
||||
char tempStr2[2];
|
||||
char crc_search[9];
|
||||
@ -766,8 +768,46 @@ void setCart_INTV() {
|
||||
//go to root
|
||||
sd.chdir();
|
||||
|
||||
// Select starting letter
|
||||
byte myLetter = starting_letter();
|
||||
|
||||
// Open database
|
||||
if (myFile.open("intv.txt", O_READ)) {
|
||||
// Skip ahead to selected starting letter
|
||||
if ((myLetter > 0) && (myLetter <= 26)) {
|
||||
while (myFile.available()) {
|
||||
// Read current name
|
||||
get_line(gamename, &myFile, 96);
|
||||
|
||||
// Compare selected letter with first letter of current name until match
|
||||
while (gamename[0] != 64 + myLetter) {
|
||||
skip_line(&myFile);
|
||||
skip_line(&myFile);
|
||||
get_line(gamename, &myFile, 96);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// Rewind one line
|
||||
for (byte count_newline = 0; count_newline < 2; count_newline++) {
|
||||
while (1) {
|
||||
if (myFile.curPosition() == 0) {
|
||||
break;
|
||||
}
|
||||
else if (myFile.peek() == '\n') {
|
||||
myFile.seekSet(myFile.curPosition() - 1);
|
||||
break;
|
||||
}
|
||||
else {
|
||||
myFile.seekSet(myFile.curPosition() - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (myFile.curPosition() != 0)
|
||||
myFile.seekSet(myFile.curPosition() + 2);
|
||||
}
|
||||
|
||||
// Display database
|
||||
while (myFile.available()) {
|
||||
display_Clear();
|
||||
|
||||
@ -916,8 +956,7 @@ void setCart_INTV() {
|
||||
}
|
||||
}
|
||||
else {
|
||||
println_Msg(F("Database file not found"));
|
||||
return 0;
|
||||
print_Error(F("Database file not found"), true);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -603,6 +603,266 @@ boolean getMapping() {
|
||||
}
|
||||
}
|
||||
|
||||
void selectMapping() {
|
||||
char gamename[100];
|
||||
char tempStr2[2];
|
||||
char iNES_STR[33];
|
||||
char crc_search[9];
|
||||
|
||||
//go to root
|
||||
sd.chdir();
|
||||
|
||||
// Select starting letter
|
||||
byte myLetter = starting_letter();
|
||||
|
||||
// Open database
|
||||
if (myFile.open("nes.txt", O_READ)) {
|
||||
// Skip ahead to selected starting letter
|
||||
if ((myLetter > 0) && (myLetter <= 26)) {
|
||||
while (myFile.available()) {
|
||||
// Read current name
|
||||
get_line(gamename, &myFile, 96);
|
||||
|
||||
// Compare selected letter with first letter of current name until match
|
||||
while (gamename[0] != 64 + myLetter) {
|
||||
skip_line(&myFile);
|
||||
skip_line(&myFile);
|
||||
get_line(gamename, &myFile, 96);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// Rewind one line
|
||||
for (byte count_newline = 0; count_newline < 2; count_newline++) {
|
||||
while (1) {
|
||||
if (myFile.curPosition() == 0) {
|
||||
break;
|
||||
}
|
||||
else if (myFile.peek() == '\n') {
|
||||
myFile.seekSet(myFile.curPosition() - 1);
|
||||
break;
|
||||
}
|
||||
else {
|
||||
myFile.seekSet(myFile.curPosition() - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (myFile.curPosition() != 0)
|
||||
myFile.seekSet(myFile.curPosition() + 2);
|
||||
}
|
||||
|
||||
// Display database
|
||||
while (myFile.available()) {
|
||||
display_Clear();
|
||||
|
||||
// Read game name
|
||||
#if defined(enable_OLED)
|
||||
get_line(gamename, &myFile, 42);
|
||||
#else
|
||||
get_line(gamename, &myFile, 96);
|
||||
#endif
|
||||
|
||||
// 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.seekSet(myFile.curPosition() + 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.seekSet(myFile.curPosition() + 1);
|
||||
|
||||
// Read iNES header
|
||||
get_line(iNES_STR, &myFile, 33);
|
||||
|
||||
// Skip every 3rd line
|
||||
skip_line(&myFile);
|
||||
|
||||
// Convert "4E4553" to (0x4E, 0x45, 0x53)
|
||||
byte iNES_BUF[2];
|
||||
for (byte j = 0; j < 16; j++) {
|
||||
sscanf(iNES_STR + j * 2, "%2X", iNES_BUF);
|
||||
iNES_HEADER[j] = iNES_BUF[0];
|
||||
}
|
||||
|
||||
// Convert iNES garbage to useful info (thx to fceux)
|
||||
mapper = (iNES_HEADER[6] >> 4);
|
||||
mapper |= (iNES_HEADER[7] & 0xF0);
|
||||
mapper |= ((iNES_HEADER[8] & 0x0F) << 8);
|
||||
|
||||
// PRG size
|
||||
if ((iNES_HEADER[9] & 0x0F) != 0x0F) {
|
||||
// simple notation
|
||||
prgsize = (iNES_HEADER[4] | ((iNES_HEADER[9] & 0x0F) << 8)); //*16
|
||||
}
|
||||
else {
|
||||
// exponent-multiplier notation
|
||||
prgsize = (((1 << (iNES_HEADER[4] >> 2)) * ((iNES_HEADER[4] & 0b11) * 2 + 1)) >> 14); //*16
|
||||
}
|
||||
if (prgsize != 0)
|
||||
prgsize = (int(log(prgsize) / log(2)));
|
||||
|
||||
// CHR size
|
||||
if ((iNES_HEADER[9] & 0xF0) != 0xF0) {
|
||||
// simple notation
|
||||
chrsize = (uppow2(iNES_HEADER[5] | ((iNES_HEADER[9] & 0xF0) << 4))) * 2; //*4
|
||||
}
|
||||
else {
|
||||
chrsize = (((1 << (iNES_HEADER[5] >> 2)) * ((iNES_HEADER[5] & 0b11) * 2 + 1)) >> 13) * 2; //*4
|
||||
}
|
||||
if (chrsize != 0)
|
||||
chrsize = (int(log(chrsize) / log(2)));
|
||||
|
||||
// RAM size
|
||||
ramsize = ((iNES_HEADER[10] & 0xF0) ? (64 << ((iNES_HEADER[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
|
||||
}
|
||||
|
||||
// Get name
|
||||
byte myLength = 0;
|
||||
for (unsigned int i = 0; i < 20; i++) {
|
||||
// Stop at first "(" to remove "(Country)"
|
||||
if (char(gamename[i]) == 40) {
|
||||
break;
|
||||
}
|
||||
if (((char(gamename[i]) >= 48 && char(gamename[i]) <= 57) || (char(gamename[i]) >= 65 && char(gamename[i]) <= 90) || (char(gamename[i]) >= 97 && char(gamename[i]) <= 122) || (char(gamename[i]) == 32)) && (myLength < 15)) {
|
||||
romName[myLength] = char(gamename[i]);
|
||||
myLength++;
|
||||
}
|
||||
}
|
||||
|
||||
// If name consists out of all japanese characters use CART as name
|
||||
if (myLength == 0) {
|
||||
romName[0] = 'C';
|
||||
romName[1] = 'A';
|
||||
romName[2] = 'R';
|
||||
romName[3] = 'T';
|
||||
}
|
||||
println_Msg(romName);
|
||||
print_Msg(F("MAPPER: "));
|
||||
println_Msg(mapper);
|
||||
print_Msg(F("PRG SIZE: "));
|
||||
print_Msg(prg);
|
||||
println_Msg(F("K"));
|
||||
print_Msg(F("CHR SIZE: "));
|
||||
print_Msg(chr);
|
||||
println_Msg(F("K"));
|
||||
print_Msg(F("RAM SIZE: "));
|
||||
if (mapper == 0) {
|
||||
print_Msg(ram / 4);
|
||||
println_Msg(F("K"));
|
||||
}
|
||||
else if ((mapper == 16) || (mapper == 80) || (mapper == 159)) {
|
||||
if (mapper == 16)
|
||||
print_Msg(ram * 32);
|
||||
else
|
||||
print_Msg(ram * 16);
|
||||
println_Msg(F("B"));
|
||||
}
|
||||
else if (mapper == 19) {
|
||||
if (ramsize == 2)
|
||||
println_Msg(F("128B"));
|
||||
else {
|
||||
print_Msg(ram);
|
||||
println_Msg(F("K"));
|
||||
}
|
||||
}
|
||||
else {
|
||||
print_Msg(ram);
|
||||
println_Msg(F("K"));
|
||||
}
|
||||
println_Msg(F(""));
|
||||
#if defined(enable_OLED)
|
||||
println_Msg(F("Press left to Change"));
|
||||
println_Msg(F("and right to Select"));
|
||||
#elif defined(enable_LCD)
|
||||
println_Msg(F("Rotate to Change"));
|
||||
println_Msg(F("Press to Select"));
|
||||
#elif defined(SERIAL_MONITOR)
|
||||
println_Msg(F("U/D to Change"));
|
||||
println_Msg(F("Space to Select"));
|
||||
#endif
|
||||
display_Update();
|
||||
|
||||
int b = 0;
|
||||
while (1) {
|
||||
// Check button input
|
||||
b = checkButton();
|
||||
|
||||
// Next
|
||||
if (b == 1) {
|
||||
break;
|
||||
}
|
||||
|
||||
// Previous
|
||||
else if (b == 2) {
|
||||
for (byte count_newline = 0; count_newline < 7; count_newline++) {
|
||||
while (1) {
|
||||
if (myFile.curPosition() == 0) {
|
||||
break;
|
||||
}
|
||||
else if (myFile.peek() == '\n') {
|
||||
myFile.seekSet(myFile.curPosition() - 1);
|
||||
break;
|
||||
}
|
||||
else {
|
||||
myFile.seekSet(myFile.curPosition() - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (myFile.curPosition() != 0)
|
||||
myFile.seekSet(myFile.curPosition() + 2);
|
||||
break;
|
||||
}
|
||||
|
||||
// Selection
|
||||
else if (b == 3) {
|
||||
// Save Mapper
|
||||
EEPROM_writeAnything(7, mapper);
|
||||
EEPROM_writeAnything(8, prgsize);
|
||||
EEPROM_writeAnything(9, chrsize);
|
||||
EEPROM_writeAnything(10, ramsize);
|
||||
myFile.close();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
print_Error(F("Database file not found"), true);
|
||||
}
|
||||
}
|
||||
|
||||
void readRom_NES() {
|
||||
// Get name, add extension and convert to char array for sd lib
|
||||
strcpy(fileName, romName);
|
||||
@ -4267,9 +4527,7 @@ void writeFLASH() {
|
||||
sd.chdir(); // root
|
||||
filePath[0] = '\0'; // Reset filePath
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
//******************************************
|
||||
// End of File
|
||||
//******************************************
|
||||
|
Loading…
Reference in New Issue
Block a user