diff options
author | splash5 <[email protected]> | 2023-01-24 16:34:54 +0800 |
---|---|---|
committer | splash5 <[email protected]> | 2023-02-23 12:19:00 +0800 |
commit | 79f2a2b16a82b602338e18a0988abd982dcbf0e2 (patch) | |
tree | dc1efb71b39841b64300c327fee4ef158adb3801 | |
parent | b57470510dc7056882165e45b2e507b82678b54e (diff) | |
download | cartreader-79f2a2b16a82b602338e18a0988abd982dcbf0e2.tar.gz cartreader-79f2a2b16a82b602338e18a0988abd982dcbf0e2.zip |
Add support for Super A'can flash cart
-rw-r--r-- | Cart_Reader/Cart_Reader.ino | 60 | ||||
-rw-r--r-- | Cart_Reader/SUPRACAN.ino | 142 |
2 files changed, 180 insertions, 22 deletions
diff --git a/Cart_Reader/Cart_Reader.ino b/Cart_Reader/Cart_Reader.ino index b57cf1a..891656e 100644 --- a/Cart_Reader/Cart_Reader.ino +++ b/Cart_Reader/Cart_Reader.ino @@ -147,7 +147,7 @@ char ver[5] = "12.3"; //#define enable_WS
// Super A'can
-#define enable_SUPRACAN
+// #define enable_SUPRACAN
//******************************************
// HW CONFIGS
@@ -1007,9 +1007,9 @@ static const char modeItem16[] PROGMEM = "Magnavox Odyssey 2"; static const char modeItem17[] PROGMEM = "Arcadia 2001";
static const char modeItem18[] PROGMEM = "Fairchild Channel F";
static const char modeItem19[] PROGMEM = "Flashrom Programmer";
-static const char modeItem99[] PROGMEM = "Super A'can";
static const char modeItem20[] PROGMEM = "About";
-static const char* const modeOptions[] PROGMEM = { modeItem1, modeItem2, modeItem3, modeItem4, modeItem5, modeItem6, modeItem7, modeItem8, modeItem9, modeItem10, modeItem11, modeItem12, modeItem13, modeItem14, modeItem15, modeItem16, modeItem17, modeItem18, modeItem99, modeItem19, modeItem20 };
+static const char modeItem99[] PROGMEM = "Super A'can";
+static const char* const modeOptions[] PROGMEM = { modeItem1, modeItem2, modeItem3, modeItem4, modeItem5, modeItem6, modeItem7, modeItem8, modeItem9, modeItem10, modeItem11, modeItem12, modeItem13, modeItem14, modeItem15, modeItem16, modeItem17, modeItem18, modeItem19, modeItem20, modeItem99 };
// All included slots
void mainMenu() {
@@ -1032,7 +1032,7 @@ void mainMenu() { num_answers = 7;
} else { // currPage == 3
option_offset = 14;
- num_answers = 6;
+ num_answers = 7;
}
// Copy menuOptions out of progmem
convertPgm(modeOptions + option_offset, num_answers);
@@ -1177,11 +1177,6 @@ void mainMenu() { case 17:
setup_FAIRCHILD();
fairchildMenu();
-
-#ifdef enable_SUPRACAN
- case 99:
- setup_SuprAcan();
- mode = mode_SUPRACAN;
break;
#endif
@@ -1199,6 +1194,12 @@ void mainMenu() { aboutScreen();
break;
+#ifdef enable_SUPRACAN
+ case 20:
+ setup_SuprAcan();
+ break;
+#endif
+
default:
print_MissingModule(); // does not return
}
@@ -1227,8 +1228,9 @@ static const char addonsItem1[] PROGMEM = "70s Consoles"; static const char addonsItem2[] PROGMEM = "80s Consoles";
static const char addonsItem3[] PROGMEM = "Handhelds";
static const char addonsItem4[] PROGMEM = "Flashrom Programmer";
+static const char addonsItem5[] PROGMEM = "90s Consoles";
//static const char addonsItem5[] PROGMEM = "Reset"; (stored in common strings array)
-static const char* const addonsOptions[] PROGMEM = { addonsItem1, addonsItem2, addonsItem3, addonsItem4, string_reset2 };
+static const char* const addonsOptions[] PROGMEM = { addonsItem1, addonsItem2, addonsItem3, addonsItem4, string_reset2, addonsItem5 };
// 70s Consoles submenu
static const char consoles70Item1[] PROGMEM = "Atari 2600";
@@ -1316,8 +1318,8 @@ void addonMenu() { // create menu with title and 5 options to choose from
unsigned char addonsMenu;
// Copy menuOptions out of progmem
- convertPgm(addonsOptions, 5);
- addonsMenu = question_box(F("Type"), menuOptions, 5, 0);
+ convertPgm(addonsOptions, 6);
+ addonsMenu = question_box(F("Type"), menuOptions, 6, 0);
// wait for user choice to come back from the question box menu
switch (addonsMenu) {
@@ -1350,6 +1352,10 @@ void addonMenu() { resetArduino();
break;
+ case 5:
+ consoles90Menu();
+ break;
+
default:
print_MissingModule(); // does not return
}
@@ -1461,6 +1467,31 @@ void consoles80Menu() { }
// Everything that needs an adapter
+void consoles90Menu() {
+ unsigned char consoles90Menu;
+ // Copy menuOptions out of progmem
+ convertPgm(consoles90Options, 2);
+ consoles90Menu = question_box(F("Choose Adapter"), menuOptions, 2, 0);
+
+ // wait for user choice to come back from the question box menu
+ switch (consoles90Menu) {
+#ifdef enable_SUPRACAN
+ case 0:
+ setup_SuprAcan();
+ break;
+#endif
+
+ case 1:
+ resetArduino();
+ break;
+
+ default:
+ print_MissingModule(); // does not return
+ break;
+ }
+}
+
+// Everything that needs an adapter
void handheldMenu() {
// create menu with title and 6 options to choose from
unsigned char handheldsMenu;
@@ -3525,6 +3556,11 @@ void loop() { fairchildMenu();
}
#endif
+#ifdef enable_SUPRACAN
+ else if (mode == mode_SUPRACAN) {
+ suprAcanMenu();
+ }
+#endif
else {
display_Clear();
println_Msg(F("Menu Error"));
diff --git a/Cart_Reader/SUPRACAN.ino b/Cart_Reader/SUPRACAN.ino index 4cc8a8d..9173f5a 100644 --- a/Cart_Reader/SUPRACAN.ino +++ b/Cart_Reader/SUPRACAN.ino @@ -11,8 +11,9 @@ static const char acanMenuItem2[] PROGMEM = "Read Save"; static const char acanMenuItem3[] PROGMEM = "Write Save"; static const char acanMenuItem4[] PROGMEM = "Read UM6650"; static const char acanMenuItem5[] PROGMEM = "Write UM6650"; +static const char acanMenuItem6[] PROGMEM = "Flash..."; -static const char* const menuOptionsAcan[] PROGMEM = {acanMenuItem1, acanMenuItem2, acanMenuItem3, acanMenuItem4, acanMenuItem5, string_reset2}; +static const char* const menuOptionsAcan[] PROGMEM = {acanMenuItem1, acanMenuItem2, acanMenuItem3, acanMenuItem4, acanMenuItem5, string_reset2, acanMenuItem6}; void setup_SuprAcan() { @@ -34,11 +35,33 @@ void setup_SuprAcan() PORTH |= ((1 << 3) | (1 << 5) | (1 << 6)); PORTH &= ~((1 << 0) | (1 << 4)); - // set /CARTIN(PG5) input - DDRG &= ~(1 << 5); // set 6619_124(PE4) input DDRE &= ~(1 << 4); + // detect if flash chip exists + PORTG |= (1 << 5); + DDRG |= (1 << 5); + PORTG |= (1 << 5); + + dataOut_MD(); + writeWord_Acan(0xaaaa, 0xaaaa); + writeWord_Acan(0x5555, 0x5555); + writeWord_Acan(0xaaaa, 0x9090); + + dataIn_MD(); + eepbit[0] = readWord_Acan(0x2); + eepbit[1] = readWord_Acan(0x0); + + dataOut_MD(); + writeWord_Acan(0x0, 0xf0f0); + + dataIn_MD(); + // set /CARTIN(PG5) input + PORTG &= ~(1 << 5); + DDRG &= ~(1 << 5); + + *((uint32_t*)(eepbit + 4)) = getFlashChipSize_Acan(*((uint16_t*)eepbit)); + display_Clear(); initializeClockOffset(); @@ -86,10 +109,13 @@ void setup_SuprAcan() void suprAcanMenu() { - uint8_t mainMenu; + uint8_t mainMenu = 6; + + if (*((uint32_t*)(eepbit + 4)) > 0) + mainMenu = 7; - convertPgm(menuOptionsAcan, 6); - mainMenu = question_box(F("Super A'can Menu"), menuOptions, 6, 0); + convertPgm(menuOptionsAcan, mainMenu); + mainMenu = question_box(F("Super A'can Menu"), menuOptions, mainMenu, 0); switch (mainMenu) { @@ -120,6 +146,11 @@ void suprAcanMenu() verifyUM6650(); break; } + case 6: + { + flashCart_Acan(); + break; + } default: { resetCart_Acan(); @@ -139,7 +170,7 @@ static void readROM_Acan() uint32_t crc32 = 0xffffffff; EEPROM_readAnything(0, foldern); - snprintf(folder, FILEPATH_LENGTH, "ACAN/ROM/%d", foldern); + snprintf(folder, FILEPATH_LENGTH, "/ACAN/ROM/%d", foldern); display_Clear(); print_STR(saving_to_STR, 0); @@ -187,7 +218,7 @@ static void readSRAM_Acan() { // create a new folder for storing rom file EEPROM_readAnything(0, foldern); - snprintf(folder, FILEPATH_LENGTH, "ACAN/SAVE/%d", foldern); + snprintf(folder, FILEPATH_LENGTH, "/ACAN/SAVE/%d", foldern); display_Clear(); print_STR(saving_to_STR, 0); @@ -220,7 +251,7 @@ static void readSRAM_Acan() static void writeSRAM_Acan() { filePath[0] = 0; - sd.chdir("/"); + sd.chdir(); fileBrowser(F("Select a file")); snprintf(filePath, FILEPATH_LENGTH, "%s/%s", filePath, fileName); @@ -297,7 +328,7 @@ static void readUM6650() { // create a new folder for storing rom file EEPROM_readAnything(0, foldern); - snprintf(folder, sizeof(folder), "ACAN/UM6650/%d", foldern); + snprintf(folder, sizeof(folder), "/ACAN/UM6650/%d", foldern); display_Clear(); print_STR(saving_to_STR, 0); @@ -404,6 +435,84 @@ static void writeUM6650() print_STR(done_STR, 1); } +static void flashCart_Acan() +{ + uint32_t *flash_size = (uint32_t*)(eepbit + 4); + + filePath[0] = 0; + sd.chdir(); + fileBrowser(F("Select a file")); + snprintf(filePath, FILEPATH_LENGTH, "%s/%s", filePath, fileName); + + display_Clear(); + + if (!myFile.open(filePath, O_READ)) + { + print_Error(F("File doesn't exist")); + return; + } + + print_Msg(F("Writing ")); + print_Msg(filePath + 1); + println_Msg(F("...")); + display_Update(); + + uint32_t i, j, k, file_length = myFile.fileSize(); + uint16_t data; + + DDRG |= (1 << 5); + PORTG |= (1 << 5); + + draw_progressbar(0, file_length); + + for (i = 0; i < file_length; i += *flash_size) + { + // erase chip + dataOut_MD(); + writeWord_Acan(i + 0xaaaa, 0xaaaa); + writeWord_Acan(i + 0x5555, 0x5555); + writeWord_Acan(i + 0xaaaa, 0x8080); + writeWord_Acan(i + 0xaaaa, 0xaaaa); + writeWord_Acan(i + 0x5555, 0x5555); + writeWord_Acan(i + 0xaaaa, 0x1010); + + dataIn_MD(); + while (readWord_Acan(i) != 0xffff); + + for (j = 0; j < *flash_size; j += 512) + { + myFile.read(sdBuffer, 512); + + for (k = 0; k < 512; k += 2) + { + data = *((uint16_t*)(sdBuffer + k)); + + dataOut_MD(); + writeWord_Acan(i + 0xaaaa, 0xaaaa); + writeWord_Acan(i + 0x5555, 0x5555); + writeWord_Acan(i + 0xaaaa, 0xa0a0); + writeWord_Acan(i + j + k, data); + + dataIn_MD(); + while (readWord_Acan(i + j + k) != data); + } + + draw_progressbar(i + j + k, file_length); + + if ((j & 0xfff) == 0) + blinkLED(); + } + } + + PORTG &= ~(1 << 5); + DDRG &= ~(1 << 5); + + myFile.close(); + + print_STR(done_STR, 1); + display_Update(); +} + static uint32_t checkRomSize_Acan() { uint32_t addr = 0; @@ -559,4 +668,17 @@ static uint16_t readWord_Acan(uint32_t addr) return data; } +static uint32_t getFlashChipSize_Acan(uint16_t chip_id) +{ + // 0x0458 (8M), 0x01ab (4M), 0x01d8 (16M) + switch (chip_id) + { + case 0x01ab: return 524288; + case 0x0458: return 1048576; + case 0x01d8: return 2097152; + } + + return 0; +} + #endif |