V25: Enabled reading of Nintendo Power GB Memory cartridges

Not super reliable right now.
This commit is contained in:
sanni 2017-05-30 21:00:12 +02:00 committed by GitHub
parent fcd4400f83
commit 2b631600f9
2 changed files with 163 additions and 30 deletions

View File

@ -2,8 +2,8 @@
Cartridge Reader for Arduino Mega2560 Cartridge Reader for Arduino Mega2560
Author: sanni Author: sanni
Date: 2017-05-21 Date: 2017-05-30
Version: V24E Version: V25
SD lib: https://github.com/greiman/SdFat SD lib: https://github.com/greiman/SdFat
LCD lib: https://github.com/adafruit/Adafruit_SSD1306 LCD lib: https://github.com/adafruit/Adafruit_SSD1306
@ -34,7 +34,7 @@
YamaArashi - GBA flashrom bank switch command YamaArashi - GBA flashrom bank switch command
**********************************************************************************/ **********************************************************************************/
char ver[5] = "V24E"; char ver[5] = "V25";
/****************************************** /******************************************
Define Output Define Output
@ -170,7 +170,7 @@ boolean ignoreError;
// File browser // File browser
char fileName[26]; char fileName[26];
char filePath[36]; char filePath[50];
byte currPage; byte currPage;
byte lastPage; byte lastPage;
byte numPages; byte numPages;
@ -407,8 +407,8 @@ void mainMenu() {
// create menu with title and 2 options to choose from // create menu with title and 2 options to choose from
unsigned char npCart; unsigned char npCart;
// Copy menuOptions out of progmem // Copy menuOptions out of progmem
convertPgm(menuOptionsNP, 1); convertPgm(menuOptionsNP, 2);
npCart = question_box("Select NP Cart", menuOptions, 1, 0); npCart = question_box("Select NP Cart", menuOptions, 2, 0);
// 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 (npCart) switch (npCart)

View File

@ -271,6 +271,22 @@ void sfmFlashMenu() {
// Write Flash // Write Flash
case 1: 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'; filePath[0] = '\0';
sd.chdir("/"); sd.chdir("/");
// Launch file browser // Launch file browser
@ -377,6 +393,19 @@ void sfmFlashMenu() {
// Clear screen // Clear screen
display_Clear(); 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 // Reset to root directory
sd.chdir("/"); sd.chdir("/");
@ -1438,8 +1467,8 @@ void write_SFM(int startBank, uint32_t pos) {
*****************************************/ *****************************************/
// GBM menu items // GBM menu items
static const char gbmMenuItem1[] PROGMEM = "Read Flash"; static const char gbmMenuItem1[] PROGMEM = "Read Flash";
static const char gbmMenuItem2[] PROGMEM = "Write Flash"; static const char gbmMenuItem2[] PROGMEM = "Read Mapping";
static const char gbmMenuItem3[] PROGMEM = "Read Mapping"; static const char gbmMenuItem3[] PROGMEM = "Write Flash";
static const char gbmMenuItem4[] PROGMEM = "Write Mapping"; static const char gbmMenuItem4[] PROGMEM = "Write Mapping";
static const char* const menuOptionsGBM[] PROGMEM = {gbmMenuItem1, gbmMenuItem2, gbmMenuItem3, gbmMenuItem4}; 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 // create menu with title and 4 options to choose from
unsigned char mainMenu; unsigned char mainMenu;
// Copy menuOptions out of progmem // Copy menuOptions out of progmem
convertPgm(menuOptionsGBM, 4); convertPgm(menuOptionsGBM, 2);
mainMenu = question_box("GB Memory Menu", menuOptions, 4, 0); mainMenu = question_box("GB Memory Menu", menuOptions, 2, 0);
// 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 (mainMenu) switch (mainMenu)
@ -1464,23 +1493,8 @@ void gbmMenu() {
readFlash_GBM(); readFlash_GBM();
break; break;
// Write Flash // Read mapping
case 1: 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 // Clear screen
display_Clear(); display_Clear();
@ -1491,11 +1505,53 @@ void gbmMenu() {
readMapping_GBM(); readMapping_GBM();
break; 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 // Write mapping
case 3: case 3:
// Clear screen // Clear screen
display_Clear(); 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 // Reset to root directory
sd.chdir("/"); sd.chdir("/");
@ -1758,9 +1814,11 @@ boolean wakeup_GBM() {
// First byte of NP register is always 0x21 // First byte of NP register is always 0x21
while (readByte_GBM(0x0120) != 0x21) { while (readByte_GBM(0x0120) != 0x21) {
send_GBM(0x09); 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++; timeout++;
if (timeout > 4) { if (timeout > 10) {
print_Error(F("Error: Time Out"), true); println_Msg(F("Error: Time Out"));
print_Error(F("Please power cycle"), true);
return 0; return 0;
} }
} }
@ -1888,14 +1946,85 @@ void readFlash_GBM() {
} }
void eraseFlash_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() { 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() { 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... // Enable ports 0x0120...
wakeup_GBM(); wakeup_GBM();
@ -1903,10 +2032,14 @@ void writeFlash_GBM() {
if (readFlashID_GBM()) { if (readFlashID_GBM()) {
// Reset flashrom to leave flashID area and switch to output // Reset flashrom to leave flashID area and switch to output
resetFlash_GBM(); resetFlash_GBM();
// Earse flash // Erase flash
print_Msg(F("Erasing..."));
display_Update();
eraseFlash_GBM(); eraseFlash_GBM();
if (blankcheckFlash_GBM()) { if (blankcheckFlash_GBM()) {
println_Msg(F("Ok"));
display_Update();
writeFlash_GBM();
} }
else { else {
print_Error(F("Erase failed"), true); print_Error(F("Erase failed"), true);