Add support for Super A'can flash cart

This commit is contained in:
splash5 2023-01-24 16:34:54 +08:00
parent b57470510d
commit 79f2a2b16a
2 changed files with 180 additions and 22 deletions

View File

@ -147,7 +147,7 @@ char ver[5] = "12.3";
//#define enable_WS //#define enable_WS
// Super A'can // Super A'can
#define enable_SUPRACAN // #define enable_SUPRACAN
//****************************************** //******************************************
// HW CONFIGS // HW CONFIGS
@ -1007,9 +1007,9 @@ static const char modeItem16[] PROGMEM = "Magnavox Odyssey 2";
static const char modeItem17[] PROGMEM = "Arcadia 2001"; static const char modeItem17[] PROGMEM = "Arcadia 2001";
static const char modeItem18[] PROGMEM = "Fairchild Channel F"; static const char modeItem18[] PROGMEM = "Fairchild Channel F";
static const char modeItem19[] PROGMEM = "Flashrom Programmer"; static const char modeItem19[] PROGMEM = "Flashrom Programmer";
static const char modeItem99[] PROGMEM = "Super A'can";
static const char modeItem20[] PROGMEM = "About"; 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 // All included slots
void mainMenu() { void mainMenu() {
@ -1032,7 +1032,7 @@ void mainMenu() {
num_answers = 7; num_answers = 7;
} else { // currPage == 3 } else { // currPage == 3
option_offset = 14; option_offset = 14;
num_answers = 6; num_answers = 7;
} }
// Copy menuOptions out of progmem // Copy menuOptions out of progmem
convertPgm(modeOptions + option_offset, num_answers); convertPgm(modeOptions + option_offset, num_answers);
@ -1177,11 +1177,6 @@ void mainMenu() {
case 17: case 17:
setup_FAIRCHILD(); setup_FAIRCHILD();
fairchildMenu(); fairchildMenu();
#ifdef enable_SUPRACAN
case 99:
setup_SuprAcan();
mode = mode_SUPRACAN;
break; break;
#endif #endif
@ -1199,6 +1194,12 @@ void mainMenu() {
aboutScreen(); aboutScreen();
break; break;
#ifdef enable_SUPRACAN
case 20:
setup_SuprAcan();
break;
#endif
default: default:
print_MissingModule(); // does not return 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 addonsItem2[] PROGMEM = "80s Consoles";
static const char addonsItem3[] PROGMEM = "Handhelds"; static const char addonsItem3[] PROGMEM = "Handhelds";
static const char addonsItem4[] PROGMEM = "Flashrom Programmer"; 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 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 // 70s Consoles submenu
static const char consoles70Item1[] PROGMEM = "Atari 2600"; static const char consoles70Item1[] PROGMEM = "Atari 2600";
@ -1316,8 +1318,8 @@ void addonMenu() {
// create menu with title and 5 options to choose from // create menu with title and 5 options to choose from
unsigned char addonsMenu; unsigned char addonsMenu;
// Copy menuOptions out of progmem // Copy menuOptions out of progmem
convertPgm(addonsOptions, 5); convertPgm(addonsOptions, 6);
addonsMenu = question_box(F("Type"), menuOptions, 5, 0); addonsMenu = question_box(F("Type"), menuOptions, 6, 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 (addonsMenu) { switch (addonsMenu) {
@ -1350,6 +1352,10 @@ void addonMenu() {
resetArduino(); resetArduino();
break; break;
case 5:
consoles90Menu();
break;
default: default:
print_MissingModule(); // does not return print_MissingModule(); // does not return
} }
@ -1460,6 +1466,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 // Everything that needs an adapter
void handheldMenu() { void handheldMenu() {
// create menu with title and 6 options to choose from // create menu with title and 6 options to choose from
@ -3524,6 +3555,11 @@ void loop() {
else if (mode == mode_FAIRCHILD) { else if (mode == mode_FAIRCHILD) {
fairchildMenu(); fairchildMenu();
} }
#endif
#ifdef enable_SUPRACAN
else if (mode == mode_SUPRACAN) {
suprAcanMenu();
}
#endif #endif
else { else {
display_Clear(); display_Clear();

View File

@ -11,8 +11,9 @@ static const char acanMenuItem2[] PROGMEM = "Read Save";
static const char acanMenuItem3[] PROGMEM = "Write Save"; static const char acanMenuItem3[] PROGMEM = "Write Save";
static const char acanMenuItem4[] PROGMEM = "Read UM6650"; static const char acanMenuItem4[] PROGMEM = "Read UM6650";
static const char acanMenuItem5[] PROGMEM = "Write 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() void setup_SuprAcan()
{ {
@ -34,11 +35,33 @@ void setup_SuprAcan()
PORTH |= ((1 << 3) | (1 << 5) | (1 << 6)); PORTH |= ((1 << 3) | (1 << 5) | (1 << 6));
PORTH &= ~((1 << 0) | (1 << 4)); PORTH &= ~((1 << 0) | (1 << 4));
// set /CARTIN(PG5) input
DDRG &= ~(1 << 5);
// set 6619_124(PE4) input // set 6619_124(PE4) input
DDRE &= ~(1 << 4); 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(); display_Clear();
initializeClockOffset(); initializeClockOffset();
@ -86,10 +109,13 @@ void setup_SuprAcan()
void suprAcanMenu() void suprAcanMenu()
{ {
uint8_t mainMenu; uint8_t mainMenu = 6;
convertPgm(menuOptionsAcan, 6); if (*((uint32_t*)(eepbit + 4)) > 0)
mainMenu = question_box(F("Super A'can Menu"), menuOptions, 6, 0); mainMenu = 7;
convertPgm(menuOptionsAcan, mainMenu);
mainMenu = question_box(F("Super A'can Menu"), menuOptions, mainMenu, 0);
switch (mainMenu) switch (mainMenu)
{ {
@ -120,6 +146,11 @@ void suprAcanMenu()
verifyUM6650(); verifyUM6650();
break; break;
} }
case 6:
{
flashCart_Acan();
break;
}
default: default:
{ {
resetCart_Acan(); resetCart_Acan();
@ -139,7 +170,7 @@ static void readROM_Acan()
uint32_t crc32 = 0xffffffff; uint32_t crc32 = 0xffffffff;
EEPROM_readAnything(0, foldern); EEPROM_readAnything(0, foldern);
snprintf(folder, FILEPATH_LENGTH, "ACAN/ROM/%d", foldern); snprintf(folder, FILEPATH_LENGTH, "/ACAN/ROM/%d", foldern);
display_Clear(); display_Clear();
print_STR(saving_to_STR, 0); print_STR(saving_to_STR, 0);
@ -187,7 +218,7 @@ static void readSRAM_Acan()
{ {
// create a new folder for storing rom file // create a new folder for storing rom file
EEPROM_readAnything(0, foldern); EEPROM_readAnything(0, foldern);
snprintf(folder, FILEPATH_LENGTH, "ACAN/SAVE/%d", foldern); snprintf(folder, FILEPATH_LENGTH, "/ACAN/SAVE/%d", foldern);
display_Clear(); display_Clear();
print_STR(saving_to_STR, 0); print_STR(saving_to_STR, 0);
@ -220,7 +251,7 @@ static void readSRAM_Acan()
static void writeSRAM_Acan() static void writeSRAM_Acan()
{ {
filePath[0] = 0; filePath[0] = 0;
sd.chdir("/"); sd.chdir();
fileBrowser(F("Select a file")); fileBrowser(F("Select a file"));
snprintf(filePath, FILEPATH_LENGTH, "%s/%s", filePath, fileName); snprintf(filePath, FILEPATH_LENGTH, "%s/%s", filePath, fileName);
@ -297,7 +328,7 @@ static void readUM6650()
{ {
// create a new folder for storing rom file // create a new folder for storing rom file
EEPROM_readAnything(0, foldern); EEPROM_readAnything(0, foldern);
snprintf(folder, sizeof(folder), "ACAN/UM6650/%d", foldern); snprintf(folder, sizeof(folder), "/ACAN/UM6650/%d", foldern);
display_Clear(); display_Clear();
print_STR(saving_to_STR, 0); print_STR(saving_to_STR, 0);
@ -404,6 +435,84 @@ static void writeUM6650()
print_STR(done_STR, 1); 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() static uint32_t checkRomSize_Acan()
{ {
uint32_t addr = 0; uint32_t addr = 0;
@ -559,4 +668,17 @@ static uint16_t readWord_Acan(uint32_t addr)
return data; 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 #endif