From 2b631600f9847c3894efee17bd4d22880602c530 Mon Sep 17 00:00:00 2001 From: sanni Date: Tue, 30 May 2017 21:00:12 +0200 Subject: [PATCH] V25: Enabled reading of Nintendo Power GB Memory cartridges Not super reliable right now. --- Cart_Reader/Cart_Reader.ino | 12 +-- Cart_Reader/NP.ino | 181 +++++++++++++++++++++++++++++++----- 2 files changed, 163 insertions(+), 30 deletions(-) diff --git a/Cart_Reader/Cart_Reader.ino b/Cart_Reader/Cart_Reader.ino index 7040ff3..0b81d3f 100644 --- a/Cart_Reader/Cart_Reader.ino +++ b/Cart_Reader/Cart_Reader.ino @@ -2,8 +2,8 @@ Cartridge Reader for Arduino Mega2560 Author: sanni - Date: 2017-05-21 - Version: V24E + Date: 2017-05-30 + Version: V25 SD lib: https://github.com/greiman/SdFat LCD lib: https://github.com/adafruit/Adafruit_SSD1306 @@ -34,7 +34,7 @@ YamaArashi - GBA flashrom bank switch command **********************************************************************************/ -char ver[5] = "V24E"; +char ver[5] = "V25"; /****************************************** Define Output @@ -170,7 +170,7 @@ boolean ignoreError; // File browser char fileName[26]; -char filePath[36]; +char filePath[50]; byte currPage; byte lastPage; byte numPages; @@ -407,8 +407,8 @@ void mainMenu() { // create menu with title and 2 options to choose from unsigned char npCart; // Copy menuOptions out of progmem - convertPgm(menuOptionsNP, 1); - npCart = question_box("Select NP Cart", menuOptions, 1, 0); + convertPgm(menuOptionsNP, 2); + npCart = question_box("Select NP Cart", menuOptions, 2, 0); // wait for user choice to come back from the question box menu switch (npCart) diff --git a/Cart_Reader/NP.ino b/Cart_Reader/NP.ino index 4a1b819..a596750 100644 --- a/Cart_Reader/NP.ino +++ b/Cart_Reader/NP.ino @@ -271,6 +271,22 @@ void sfmFlashMenu() { // Write Flash case 1: + // Clear screen + display_Clear(); + + // Print warning + println_Msg(F("Attention")); + println_Msg(F("This will erase your")); + println_Msg(F("NP Cartridge.")); + println_Msg(""); + println_Msg(F("Press Button")); + println_Msg(F("to continue")); + display_Update(); + wait(); + + // Clear screen + display_Clear(); + filePath[0] = '\0'; sd.chdir("/"); // Launch file browser @@ -377,6 +393,19 @@ void sfmFlashMenu() { // Clear screen display_Clear(); + // Print warning + println_Msg(F("Attention")); + println_Msg(F("This will erase your")); + println_Msg(F("NP Cartridge.")); + println_Msg(""); + println_Msg(F("Press Button")); + println_Msg(F("to continue")); + display_Update(); + wait(); + + // Clear screen + display_Clear(); + // Reset to root directory sd.chdir("/"); @@ -1438,8 +1467,8 @@ void write_SFM(int startBank, uint32_t pos) { *****************************************/ // GBM menu items static const char gbmMenuItem1[] PROGMEM = "Read Flash"; -static const char gbmMenuItem2[] PROGMEM = "Write Flash"; -static const char gbmMenuItem3[] PROGMEM = "Read Mapping"; +static const char gbmMenuItem2[] PROGMEM = "Read Mapping"; +static const char gbmMenuItem3[] PROGMEM = "Write Flash"; static const char gbmMenuItem4[] PROGMEM = "Write Mapping"; static const char* const menuOptionsGBM[] PROGMEM = {gbmMenuItem1, gbmMenuItem2, gbmMenuItem3, gbmMenuItem4}; @@ -1447,8 +1476,8 @@ void gbmMenu() { // create menu with title and 4 options to choose from unsigned char mainMenu; // Copy menuOptions out of progmem - convertPgm(menuOptionsGBM, 4); - mainMenu = question_box("GB Memory Menu", menuOptions, 4, 0); + convertPgm(menuOptionsGBM, 2); + mainMenu = question_box("GB Memory Menu", menuOptions, 2, 0); // wait for user choice to come back from the question box menu switch (mainMenu) @@ -1464,23 +1493,8 @@ void gbmMenu() { readFlash_GBM(); break; - // Write Flash + // Read mapping case 1: - filePath[0] = '\0'; - sd.chdir("/"); - // Launch file browser - fileBrowser("Select 1MB file"); - display_Clear(); - sprintf(filePath, "%s/%s", filePath, fileName); - println_Msg(F("Writing rom")); - display_Update(); - - // Write flash - writeFlash_GBM(); - break; - - // Print mapping - case 2: // Clear screen display_Clear(); @@ -1491,11 +1505,53 @@ void gbmMenu() { readMapping_GBM(); break; + // Write Flash + case 2: + // Clear screen + display_Clear(); + + // Print warning + println_Msg(F("Attention")); + println_Msg(F("This will erase your")); + println_Msg(F("NP Cartridge.")); + println_Msg(""); + println_Msg(F("Press Button")); + println_Msg(F("to continue")); + display_Update(); + wait(); + + // Clear screen + display_Clear(); + + filePath[0] = '\0'; + sd.chdir("/"); + // Launch file browser + fileBrowser("Select 1MB file"); + display_Clear(); + sprintf(filePath, "%s/%s", filePath, fileName); + + // Write rom + writeRom_GBM(); + break; + // Write mapping case 3: // Clear screen display_Clear(); + // Print warning + println_Msg(F("Attention")); + println_Msg(F("This will erase your")); + println_Msg(F("NP Cartridge.")); + println_Msg(""); + println_Msg(F("Press Button")); + println_Msg(F("to continue")); + display_Update(); + wait(); + + // Clear screen + display_Clear(); + // Reset to root directory sd.chdir("/"); @@ -1758,9 +1814,11 @@ boolean wakeup_GBM() { // First byte of NP register is always 0x21 while (readByte_GBM(0x0120) != 0x21) { send_GBM(0x09); + __asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t"); timeout++; - if (timeout > 4) { - print_Error(F("Error: Time Out"), true); + if (timeout > 10) { + println_Msg(F("Error: Time Out")); + print_Error(F("Please power cycle"), true); return 0; } } @@ -1888,14 +1946,85 @@ void readFlash_GBM() { } void eraseFlash_GBM() { + // Enable ports 0x0120... + wakeup_GBM(); + // Set WE and WP + enableWrite_GBM(); + + // Unprotect sector 0 + writeByte_GBM(0x2100, 0x01); + send_Flash(0x5555, 0xAA); + send_Flash(0x2AAA, 0x55); + send_Flash(0x5555, 0x60); + send_Flash(0x5555, 0xAA); + send_Flash(0x2AAA, 0x55); + writeByte_GBM(0x2100, 0x0); + send_Flash(0x0000, 0x40); + + // Send erase command + writeByte_GBM(0x2100, 0x01); + send_Flash(0x5555, 0xaa); + send_Flash(0x2AAA, 0x55); + send_Flash(0x5555, 0x80); + send_Flash(0x5555, 0xaa); + send_Flash(0x2AAA, 0x55); + send_Flash(0x5555, 0x10); + + // Wait for erase to complete + while ((readByte_GBM(0) & 0x80) != 0x80) { + } } boolean blankcheckFlash_GBM() { + // Reset flashrom + resetFlash_GBM(); + // Map entire flashrom + //send_GBM(0x04); + // Disable ports 0x0120... + send_GBM(0x08); + // Read rom + word currAddress = 0; + + for (byte currBank = 1; currBank < 64; currBank++) { + // Set rom bank + writeByte_GBM(0x2100, currBank); + + // Switch bank start address + if (currBank > 1) { + currAddress = 0x4000; + } + + for (; currAddress < 0x7FFF; currAddress++) { + if (readByte_GBM(currAddress) != 0xFF) { + return 0; + } + } + } + return 1; } void writeFlash_GBM() { + // Open file on sd card + if (myFile.open(filePath, O_READ)) { + // Get rom size from file + fileSize = myFile.fileSize(); + + for (unsigned long currBuffer = 0; currBuffer < fileSize; currBuffer += 128) { + // Fill SD buffer + myFile.read(sdBuffer, 128); + } + + // Close the file: + myFile.close(); + } + else { + print_Error(F("Can't open file"), false); + } +} + +void writeRom_GBM() { // Enable ports 0x0120... wakeup_GBM(); @@ -1903,10 +2032,14 @@ void writeFlash_GBM() { if (readFlashID_GBM()) { // Reset flashrom to leave flashID area and switch to output resetFlash_GBM(); - // Earse flash + // Erase flash + print_Msg(F("Erasing...")); + display_Update(); eraseFlash_GBM(); if (blankcheckFlash_GBM()) { - + println_Msg(F("Ok")); + display_Update(); + writeFlash_GBM(); } else { print_Error(F("Erase failed"), true);