mirror of
https://github.com/sanni/cartreader.git
synced 2024-11-27 15:04:15 +01:00
Selecting [?] now forwards to manual mapper config for NES
This commit is contained in:
parent
b7fa65a3de
commit
18b37c72d8
@ -4,7 +4,7 @@
|
|||||||
This project represents a community-driven effort to provide
|
This project represents a community-driven effort to provide
|
||||||
an easy to build and easy to modify cartridge dumper.
|
an easy to build and easy to modify cartridge dumper.
|
||||||
|
|
||||||
Date: 06.10.2022
|
Date: 07.10.2022
|
||||||
Version: 10.0
|
Version: 10.0
|
||||||
|
|
||||||
SD lib: https://github.com/greiman/SdFat
|
SD lib: https://github.com/greiman/SdFat
|
||||||
@ -737,18 +737,26 @@ byte starting_letter() {
|
|||||||
line--;
|
line--;
|
||||||
selection = 6;
|
selection = 6;
|
||||||
}
|
}
|
||||||
|
else if ((selection == 0) && (line == 0)) {
|
||||||
|
line = 3;
|
||||||
|
selection = 6;
|
||||||
|
}
|
||||||
else if (selection > 0) {
|
else if (selection > 0) {
|
||||||
selection--;
|
selection--;
|
||||||
}
|
}
|
||||||
#if defined(enable_LCD)
|
#if defined(enable_LCD)
|
||||||
display.setDrawColor(0);
|
display.setDrawColor(0);
|
||||||
display.drawLine(0, 10 + (line + 1) * 16, 128, 10 + (line + 1) * 16);
|
display.drawLine(0, 10 + 0 * 16, 128, 10 + 0 * 16);
|
||||||
display.drawLine(0, 10 + line * 16, 128, 10 + line * 16);
|
display.drawLine(0, 10 + 1 * 16, 128, 10 + 1 * 16);
|
||||||
|
display.drawLine(0, 10 + 2 * 16, 128, 10 + 2 * 16);
|
||||||
|
display.drawLine(0, 10 + 3 * 16, 128, 10 + 3 * 16);
|
||||||
display.setDrawColor(1);
|
display.setDrawColor(1);
|
||||||
display.drawLine(4 + selection * 16, 10 + line * 16, 9 + selection * 16, 10 + line * 16);
|
display.drawLine(4 + selection * 16, 10 + line * 16, 9 + selection * 16, 10 + line * 16);
|
||||||
#elif defined(enable_OLED)
|
#elif defined(enable_OLED)
|
||||||
display.drawLine(0, 10 + (line + 1) * 16, 128, 10 + (line + 1) * 16, BLACK);
|
display.drawLine(0, 10 + 0 * 16, 128, 10 + 0 * 16, BLACK);
|
||||||
display.drawLine(0, 10 + line * 16, 128, 10 + line * 16, BLACK);
|
display.drawLine(0, 10 + 1 * 16, 128, 10 + 1 * 16, BLACK);
|
||||||
|
display.drawLine(0, 10 + 2 * 16, 128, 10 + 2 * 16, BLACK);
|
||||||
|
display.drawLine(0, 10 + 3 * 16, 128, 10 + 3 * 16, BLACK);
|
||||||
display.drawLine(selection * 18, 10 + line * 16, 5 + selection * 18, 10 + line * 16, WHITE);
|
display.drawLine(selection * 18, 10 + line * 16, 5 + selection * 18, 10 + line * 16, WHITE);
|
||||||
#endif
|
#endif
|
||||||
display_Update();
|
display_Update();
|
||||||
@ -760,18 +768,26 @@ byte starting_letter() {
|
|||||||
line++;
|
line++;
|
||||||
selection = 0;
|
selection = 0;
|
||||||
}
|
}
|
||||||
|
else if ((selection == 6) && (line == 3)) {
|
||||||
|
line = 0;
|
||||||
|
selection = 0;
|
||||||
|
}
|
||||||
else if (selection < 6) {
|
else if (selection < 6) {
|
||||||
selection++;
|
selection++;
|
||||||
}
|
}
|
||||||
#if defined(enable_LCD)
|
#if defined(enable_LCD)
|
||||||
display.setDrawColor(0);
|
display.setDrawColor(0);
|
||||||
display.drawLine(0, 10 + (line - 1) * 16, 128, 10 + (line - 1) * 16);
|
display.drawLine(0, 10 + 0 * 16, 128, 10 + 0 * 16);
|
||||||
display.drawLine(0, 10 + line * 16, 128, 10 + line * 16);
|
display.drawLine(0, 10 + 1 * 16, 128, 10 + 1 * 16);
|
||||||
|
display.drawLine(0, 10 + 2 * 16, 128, 10 + 2 * 16);
|
||||||
|
display.drawLine(0, 10 + 3 * 16, 128, 10 + 3 * 16);
|
||||||
display.setDrawColor(1);
|
display.setDrawColor(1);
|
||||||
display.drawLine(4 + selection * 16, 10 + line * 16, 9 + selection * 16, 10 + line * 16);
|
display.drawLine(4 + selection * 16, 10 + line * 16, 9 + selection * 16, 10 + line * 16);
|
||||||
#elif defined(enable_OLED)
|
#elif defined(enable_OLED)
|
||||||
display.drawLine(0, 10 + (line - 1) * 16, 128, 10 + (line - 1) * 16, BLACK);
|
display.drawLine(0, 10 + 0 * 16, 128, 10 + 0 * 16, BLACK);
|
||||||
display.drawLine(0, 10 + line * 16, 128, 10 + line * 16, BLACK);
|
display.drawLine(0, 10 + 1 * 16, 128, 10 + 1 * 16, BLACK);
|
||||||
|
display.drawLine(0, 10 + 2 * 16, 128, 10 + 2 * 16, BLACK);
|
||||||
|
display.drawLine(0, 10 + 3 * 16, 128, 10 + 3 * 16, BLACK);
|
||||||
display.drawLine(selection * 18, 10 + line * 16, 5 + selection * 18, 10 + line * 16, WHITE);
|
display.drawLine(selection * 18, 10 + line * 16, 5 + selection * 18, 10 + line * 16, WHITE);
|
||||||
#endif
|
#endif
|
||||||
display_Update();
|
display_Update();
|
||||||
|
@ -197,11 +197,11 @@ int b = 0;
|
|||||||
Menus
|
Menus
|
||||||
*****************************************/
|
*****************************************/
|
||||||
// NES start menu
|
// NES start menu
|
||||||
static const char nesMenuItem1[] PROGMEM = "Change Mapper";
|
static const char nesMenuItem1[] PROGMEM = "Read iNES Rom";
|
||||||
static const char nesMenuItem2[] PROGMEM = "Read iNES Rom";
|
static const char nesMenuItem2[] PROGMEM = "Read PRG/CHR";
|
||||||
static const char nesMenuItem3[] PROGMEM = "Read PRG/CHR";
|
static const char nesMenuItem3[] PROGMEM = "Read Sram";
|
||||||
static const char nesMenuItem4[] PROGMEM = "Read Sram";
|
static const char nesMenuItem4[] PROGMEM = "Write Sram";
|
||||||
static const char nesMenuItem5[] PROGMEM = "Write Sram";
|
static const char nesMenuItem5[] PROGMEM = "Change Mapper";
|
||||||
static const char nesMenuItem6[] PROGMEM = "Flash NESMaker";
|
static const char nesMenuItem6[] PROGMEM = "Flash NESMaker";
|
||||||
static const char nesMenuItem7[] PROGMEM = "Reset";
|
static const char nesMenuItem7[] PROGMEM = "Reset";
|
||||||
static const char* const menuOptionsNES[] PROGMEM = {nesMenuItem1, nesMenuItem2, nesMenuItem3, nesMenuItem4, nesMenuItem5, nesMenuItem6, nesMenuItem7};
|
static const char* const menuOptionsNES[] PROGMEM = {nesMenuItem1, nesMenuItem2, nesMenuItem3, nesMenuItem4, nesMenuItem5, nesMenuItem6, nesMenuItem7};
|
||||||
@ -225,23 +225,8 @@ void nesMenu() {
|
|||||||
|
|
||||||
// wait for user choice to come back from the question box menu
|
// wait for user choice to come back from the question box menu
|
||||||
switch (answer) {
|
switch (answer) {
|
||||||
// Change Mapper
|
|
||||||
case 0:
|
|
||||||
romName[0] = 'C';
|
|
||||||
romName[1] = 'A';
|
|
||||||
romName[2] = 'R';
|
|
||||||
romName[3] = 'T';
|
|
||||||
romName[4] = '\0';
|
|
||||||
setMapper();
|
|
||||||
checkMapperSize();
|
|
||||||
setPRGSize();
|
|
||||||
setCHRSize();
|
|
||||||
setRAMSize();
|
|
||||||
checkStatus_NES();
|
|
||||||
break;
|
|
||||||
|
|
||||||
// Read Rom
|
// Read Rom
|
||||||
case 1:
|
case 0:
|
||||||
#ifndef no-intro
|
#ifndef no-intro
|
||||||
CartStart();
|
CartStart();
|
||||||
readPRG(false);
|
readPRG(false);
|
||||||
@ -270,12 +255,12 @@ void nesMenu() {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
// Read single chip
|
// Read single chip
|
||||||
case 2:
|
case 1:
|
||||||
nesChipMenu();
|
nesChipMenu();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Read RAM
|
// Read RAM
|
||||||
case 3:
|
case 2:
|
||||||
CreateROMFolderInSD();
|
CreateROMFolderInSD();
|
||||||
readRAM();
|
readRAM();
|
||||||
resetROM();
|
resetROM();
|
||||||
@ -286,7 +271,7 @@ void nesMenu() {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
// Write RAM
|
// Write RAM
|
||||||
case 4:
|
case 3:
|
||||||
writeRAM();
|
writeRAM();
|
||||||
resetROM();
|
resetROM();
|
||||||
println_Msg(F(""));
|
println_Msg(F(""));
|
||||||
@ -295,6 +280,21 @@ void nesMenu() {
|
|||||||
wait();
|
wait();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
// Change Mapper
|
||||||
|
case 4:
|
||||||
|
romName[0] = 'C';
|
||||||
|
romName[1] = 'A';
|
||||||
|
romName[2] = 'R';
|
||||||
|
romName[3] = 'T';
|
||||||
|
romName[4] = '\0';
|
||||||
|
setMapper();
|
||||||
|
checkMapperSize();
|
||||||
|
setPRGSize();
|
||||||
|
setCHRSize();
|
||||||
|
setRAMSize();
|
||||||
|
checkStatus_NES();
|
||||||
|
break;
|
||||||
|
|
||||||
// Write FLASH
|
// Write FLASH
|
||||||
case 5:
|
case 5:
|
||||||
if (mapper == 30) {
|
if (mapper == 30) {
|
||||||
@ -431,15 +431,16 @@ uint32_t uppow2(uint32_t n) {
|
|||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
void printPRG() {
|
void printPRG(unsigned long myOffset) {
|
||||||
display_Clear();
|
display_Clear();
|
||||||
println_Msg(F("Printing PRG at 0x8000"));
|
print_Msg(F("Printing PRG at "));
|
||||||
|
println_Msg(myOffset);
|
||||||
|
|
||||||
char myBuffer[3];
|
char myBuffer[3];
|
||||||
|
|
||||||
for (word currLine = 0; currLine < 512; currLine += 16) {
|
for (word currLine = 0; currLine < 512; currLine += 16) {
|
||||||
for (byte currByte = 0; currByte < 16; currByte++) {
|
for (byte currByte = 0; currByte < 16; currByte++) {
|
||||||
itoa (read_prg_byte(0x8000 + currLine + currByte), myBuffer, 16);
|
itoa (read_prg_byte(myOffset + currLine + currByte), myBuffer, 16);
|
||||||
for (word i = 0; i < 2 - strlen(myBuffer); i++) {
|
for (word i = 0; i < 2 - strlen(myBuffer); i++) {
|
||||||
print_Msg(F("0"));
|
print_Msg(F("0"));
|
||||||
}
|
}
|
||||||
@ -494,14 +495,14 @@ boolean getMapping() {
|
|||||||
println_Msg(F("..."));
|
println_Msg(F("..."));
|
||||||
display_Update();
|
display_Update();
|
||||||
|
|
||||||
// Filter out 0xFF checksum
|
// Filter out all 0xFF checksums at 0x8000 and 0xE000
|
||||||
if (strcmp(crcStr, "BD7BC39F") == 0) {
|
if ((strcmp(crcStr, "BD7BC39F") == 0) && (strcmp(crcStrMMC3, "BD7BC39F") == 0)) {
|
||||||
delay(500);
|
delay(200);
|
||||||
println_Msg(F(""));
|
println_Msg(F(""));
|
||||||
println_Msg(F("No data found at 0x8000"));
|
println_Msg(F("No data found."));
|
||||||
println_Msg(F("Using manual selection"));
|
println_Msg(F("Using manual selection"));
|
||||||
display_Update();
|
display_Update();
|
||||||
delay(1000);
|
delay(500);
|
||||||
romName[0] = 'C';
|
romName[0] = 'C';
|
||||||
romName[1] = 'A';
|
romName[1] = 'A';
|
||||||
romName[2] = 'R';
|
romName[2] = 'R';
|
||||||
@ -548,8 +549,8 @@ boolean getMapping() {
|
|||||||
//Skip every 3rd line
|
//Skip every 3rd line
|
||||||
skip_line(&myFile);
|
skip_line(&myFile);
|
||||||
|
|
||||||
//if checksum search successful set mapper and end search
|
//if checksum search was successful set mapper and end search, also filter out 0xFF checksum
|
||||||
if ((strcmp(crc_search, crcStr) == 0) || (strcmp(crc_search, crcStrMMC3) == 0)) {
|
if (((strcmp(crc_search, crcStr) == 0) || (strcmp(crc_search, crcStrMMC3) == 0)) && (strcmp(crc_search, "BD7BC39F") != 0)) {
|
||||||
|
|
||||||
// Rewind to start of entry
|
// Rewind to start of entry
|
||||||
for (byte count_newline = 0; count_newline < 4; count_newline++) {
|
for (byte count_newline = 0; count_newline < 4; count_newline++) {
|
||||||
@ -789,20 +790,22 @@ boolean getMapping() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// File searched until end but nothing found
|
// File searched until end but nothing found
|
||||||
if (strcmp(crc_search, crcStr) != 0) {
|
println_Msg(F(""));
|
||||||
println_Msg(F(""));
|
println_Msg(F("CRC not found in database"));
|
||||||
println_Msg(F("CRC not found in database"));
|
println_Msg(F("Using manual selection"));
|
||||||
println_Msg(F("Using manual selection"));
|
display_Update();
|
||||||
display_Update();
|
delay(1000);
|
||||||
delay(1000);
|
// Print debug
|
||||||
printPRG();
|
printPRG(0x8000);
|
||||||
romName[0] = 'C';
|
printPRG(0xE000);
|
||||||
romName[1] = 'A';
|
|
||||||
romName[2] = 'R';
|
// Change ROM name to CART
|
||||||
romName[3] = 'T';
|
romName[0] = 'C';
|
||||||
romName[4] = '\0';
|
romName[1] = 'A';
|
||||||
return 0;
|
romName[2] = 'R';
|
||||||
}
|
romName[3] = 'T';
|
||||||
|
romName[4] = '\0';
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
println_Msg(F("Database file not found"));
|
println_Msg(F("Database file not found"));
|
||||||
@ -823,270 +826,281 @@ void selectMapping() {
|
|||||||
// Select starting letter
|
// Select starting letter
|
||||||
byte myLetter = starting_letter();
|
byte myLetter = starting_letter();
|
||||||
|
|
||||||
// Open database
|
if (myLetter == 27) {
|
||||||
if (myFile.open("nes.txt", O_READ)) {
|
// Change Mapper
|
||||||
|
setMapper();
|
||||||
|
checkMapperSize();
|
||||||
|
setPRGSize();
|
||||||
|
setCHRSize();
|
||||||
|
setRAMSize();
|
||||||
|
checkStatus_NES();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Open database
|
||||||
|
if (myFile.open("nes.txt", O_READ)) {
|
||||||
|
|
||||||
#ifdef global_log
|
#ifdef global_log
|
||||||
// Disable log to prevent unnecessary logging
|
// Disable log to prevent unnecessary logging
|
||||||
dont_log = true;
|
dont_log = true;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Skip ahead to selected starting letter
|
// Skip ahead to selected starting letter
|
||||||
if ((myLetter > 0) && (myLetter <= 26)) {
|
if ((myLetter > 0) && (myLetter <= 26)) {
|
||||||
|
while (myFile.available()) {
|
||||||
|
// Read current name
|
||||||
|
#if defined(enable_OLED)
|
||||||
|
get_line(gamename, &myFile, 42);
|
||||||
|
#else
|
||||||
|
get_line(gamename, &myFile, 96);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Compare selected letter with first letter of current name until match
|
||||||
|
while (gamename[0] != 64 + myLetter) {
|
||||||
|
skip_line(&myFile);
|
||||||
|
skip_line(&myFile);
|
||||||
|
#if defined(enable_OLED)
|
||||||
|
get_line(gamename, &myFile, 42);
|
||||||
|
#else
|
||||||
|
get_line(gamename, &myFile, 96);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
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()) {
|
while (myFile.available()) {
|
||||||
// Read current name
|
display_Clear();
|
||||||
|
|
||||||
|
// Read game name
|
||||||
#if defined(enable_OLED)
|
#if defined(enable_OLED)
|
||||||
get_line(gamename, &myFile, 42);
|
get_line(gamename, &myFile, 42);
|
||||||
#else
|
#else
|
||||||
get_line(gamename, &myFile, 96);
|
get_line(gamename, &myFile, 96);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Compare selected letter with first letter of current name until match
|
// Read CRC32 checksum
|
||||||
while (gamename[0] != 64 + myLetter) {
|
sprintf(checksumStr, "%c", myFile.read());
|
||||||
skip_line(&myFile);
|
for (byte i = 0; i < 7; i++) {
|
||||||
skip_line(&myFile);
|
sprintf(tempStr2, "%c", myFile.read());
|
||||||
#if defined(enable_OLED)
|
strcat(checksumStr, tempStr2);
|
||||||
get_line(gamename, &myFile, 42);
|
|
||||||
#else
|
|
||||||
get_line(gamename, &myFile, 96);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Rewind one line
|
// Skip over semicolon
|
||||||
for (byte count_newline = 0; count_newline < 2; count_newline++) {
|
myFile.seekSet(myFile.curPosition() + 1);
|
||||||
while (1) {
|
|
||||||
if (myFile.curPosition() == 0) {
|
// Read CRC32 of first 512 bytes
|
||||||
break;
|
sprintf(crc_search, "%c", myFile.read());
|
||||||
}
|
for (byte i = 0; i < 7; i++) {
|
||||||
else if (myFile.peek() == '\n') {
|
sprintf(tempStr2, "%c", myFile.read());
|
||||||
myFile.seekSet(myFile.curPosition() - 1);
|
strcat(crc_search, tempStr2);
|
||||||
break;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
myFile.seekSet(myFile.curPosition() - 1);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if (myFile.curPosition() != 0)
|
|
||||||
myFile.seekSet(myFile.curPosition() + 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Display database
|
// Skip over semicolon
|
||||||
while (myFile.available()) {
|
myFile.seekSet(myFile.curPosition() + 1);
|
||||||
display_Clear();
|
|
||||||
|
|
||||||
// Read game name
|
// Read iNES header
|
||||||
#if defined(enable_OLED)
|
get_line(iNES_STR, &myFile, 33);
|
||||||
get_line(gamename, &myFile, 42);
|
|
||||||
#else
|
|
||||||
get_line(gamename, &myFile, 96);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Read CRC32 checksum
|
// Skip every 3rd line
|
||||||
sprintf(checksumStr, "%c", myFile.read());
|
skip_line(&myFile);
|
||||||
for (byte i = 0; i < 7; i++) {
|
|
||||||
sprintf(tempStr2, "%c", myFile.read());
|
|
||||||
strcat(checksumStr, tempStr2);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Skip over semicolon
|
// Convert "4E4553" to (0x4E, 0x45, 0x53)
|
||||||
myFile.seekSet(myFile.curPosition() + 1);
|
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];
|
||||||
|
}
|
||||||
|
|
||||||
// Read CRC32 of first 512 bytes
|
// Convert iNES garbage to useful info (thx to fceux)
|
||||||
sprintf(crc_search, "%c", myFile.read());
|
mapper = (iNES_HEADER[6] >> 4);
|
||||||
for (byte i = 0; i < 7; i++) {
|
mapper |= (iNES_HEADER[7] & 0xF0);
|
||||||
sprintf(tempStr2, "%c", myFile.read());
|
mapper |= ((iNES_HEADER[8] & 0x0F) << 8);
|
||||||
strcat(crc_search, tempStr2);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Skip over semicolon
|
// PRG size
|
||||||
myFile.seekSet(myFile.curPosition() + 1);
|
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)));
|
||||||
|
|
||||||
// Read iNES header
|
// CHR size
|
||||||
get_line(iNES_STR, &myFile, 33);
|
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)));
|
||||||
|
|
||||||
// Skip every 3rd line
|
// RAM size
|
||||||
skip_line(&myFile);
|
ramsize = ((iNES_HEADER[10] & 0xF0) ? (64 << ((iNES_HEADER[10] & 0xF0) >> 4)) : 0) / 4096; //*4
|
||||||
|
if (ramsize != 0)
|
||||||
|
ramsize = (int(log(ramsize) / log(2)));
|
||||||
|
|
||||||
// Convert "4E4553" to (0x4E, 0x45, 0x53)
|
prg = (int_pow(2, prgsize)) * 16;
|
||||||
byte iNES_BUF[2];
|
if (chrsize == 0)
|
||||||
for (byte j = 0; j < 16; j++) {
|
chr = 0; // 0K
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
println_Msg(gamename);
|
|
||||||
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
|
else
|
||||||
print_Msg(ram * 16);
|
chr = (int_pow(2, chrsize)) * 4;
|
||||||
println_Msg(F("B"));
|
if (ramsize == 0)
|
||||||
}
|
ram = 0; // 0K
|
||||||
else if (mapper == 19) {
|
else if (mapper == 82)
|
||||||
if (ramsize == 2)
|
ram = 5; // 5K
|
||||||
println_Msg(F("128B"));
|
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(gamename);
|
||||||
|
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 {
|
else {
|
||||||
print_Msg(ram);
|
print_Msg(ram);
|
||||||
println_Msg(F("K"));
|
println_Msg(F("K"));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else {
|
|
||||||
print_Msg(ram);
|
|
||||||
println_Msg(F("K"));
|
|
||||||
}
|
|
||||||
#if defined(enable_OLED)
|
#if defined(enable_OLED)
|
||||||
println_Msg(F("Press left to Change"));
|
println_Msg(F("Press left to Change"));
|
||||||
println_Msg(F("and right to Select"));
|
println_Msg(F("and right to Select"));
|
||||||
#elif defined(enable_LCD)
|
#elif defined(enable_LCD)
|
||||||
println_Msg(F("Rotate to Change"));
|
println_Msg(F("Rotate to Change"));
|
||||||
println_Msg(F("Press to Select"));
|
println_Msg(F("Press to Select"));
|
||||||
#elif defined(SERIAL_MONITOR)
|
#elif defined(SERIAL_MONITOR)
|
||||||
println_Msg(F("U/D to Change"));
|
println_Msg(F("U/D to Change"));
|
||||||
println_Msg(F("Space to Select"));
|
println_Msg(F("Space to Select"));
|
||||||
#endif
|
#endif
|
||||||
display_Update();
|
display_Update();
|
||||||
|
|
||||||
int b = 0;
|
int b = 0;
|
||||||
while (1) {
|
while (1) {
|
||||||
// Check button input
|
// Check button input
|
||||||
b = checkButton();
|
b = checkButton();
|
||||||
|
|
||||||
// Next
|
// Next
|
||||||
if (b == 1) {
|
if (b == 1) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Previous
|
// Previous
|
||||||
else if (b == 2) {
|
else if (b == 2) {
|
||||||
for (byte count_newline = 0; count_newline < 7; count_newline++) {
|
for (byte count_newline = 0; count_newline < 7; count_newline++) {
|
||||||
while (1) {
|
while (1) {
|
||||||
if (myFile.curPosition() == 0) {
|
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) {
|
||||||
|
// 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;
|
break;
|
||||||
}
|
}
|
||||||
else if (myFile.peek() == '\n') {
|
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)) && (myLength < 15)) {
|
||||||
myFile.seekSet(myFile.curPosition() - 1);
|
romName[myLength] = char(gamename[i]);
|
||||||
break;
|
myLength++;
|
||||||
}
|
|
||||||
else {
|
|
||||||
myFile.seekSet(myFile.curPosition() - 1);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if (myFile.curPosition() != 0)
|
|
||||||
myFile.seekSet(myFile.curPosition() + 2);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Selection
|
// If name consists out of all japanese characters use CART as name
|
||||||
else if (b == 3) {
|
if (myLength == 0) {
|
||||||
// Get name
|
romName[0] = 'C';
|
||||||
byte myLength = 0;
|
romName[1] = 'A';
|
||||||
for (unsigned int i = 0; i < 20; i++) {
|
romName[2] = 'R';
|
||||||
// Stop at first "(" to remove "(Country)"
|
romName[3] = 'T';
|
||||||
if (char(gamename[i]) == 40) {
|
romName[4] = '\0';
|
||||||
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)) && (myLength < 15)) {
|
|
||||||
romName[myLength] = char(gamename[i]);
|
|
||||||
myLength++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If name consists out of all japanese characters use CART as name
|
// Save Mapper
|
||||||
if (myLength == 0) {
|
EEPROM_writeAnything(7, mapper);
|
||||||
romName[0] = 'C';
|
EEPROM_writeAnything(8, prgsize);
|
||||||
romName[1] = 'A';
|
EEPROM_writeAnything(9, chrsize);
|
||||||
romName[2] = 'R';
|
EEPROM_writeAnything(10, ramsize);
|
||||||
romName[3] = 'T';
|
myFile.close();
|
||||||
romName[4] = '\0';
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save Mapper
|
|
||||||
EEPROM_writeAnything(7, mapper);
|
|
||||||
EEPROM_writeAnything(8, prgsize);
|
|
||||||
EEPROM_writeAnything(9, chrsize);
|
|
||||||
EEPROM_writeAnything(10, ramsize);
|
|
||||||
myFile.close();
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
#ifdef global_log
|
#ifdef global_log
|
||||||
// Enable log again
|
// Enable log again
|
||||||
dont_log = false;
|
dont_log = false;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
print_Error(F("Database file not found"), true);
|
print_Error(F("Database file not found"), true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user