diff --git a/Cart_Reader/Cart_Reader.ino b/Cart_Reader/Cart_Reader.ino index d357c5ef..afa6acff 100644 --- a/Cart_Reader/Cart_Reader.ino +++ b/Cart_Reader/Cart_Reader.ino @@ -460,7 +460,7 @@ uint32_t calculateCRC(char* fileName, char* folder, unsigned long offset) { /****************************************** CRC Functions for Atari, Fairchild, Ody2, Arc, etc. modules *****************************************/ -#if (defined(ENABLE_ODY2) || defined(ENABLE_ARC) || defined(ENABLE_FAIRCHILD) || defined(ENABLE_MSX) || defined(ENABLE_POKE) || defined(ENABLE_2600) || defined(ENABLE_7800) || defined(ENABLE_C64) || defined(ENABLE_VECTREX) || defined(ENABLE_NES) || defined(ENABLE_LYNX) || defined(ENABLE_ATARI8) || defined(ENABLE_BALLY) || defined(ENABLE_LEAP) || defined(ENABLE_LJ) || defined(ENABLE_LJPRO) || defined(ENABLE_PV1000) || defined(ENABLE_PYUUTA) || defined(ENABLE_RCA) || defined(ENABLE_TI99) || defined(ENABLE_TRS80) || defined(ENABLE_VIC20) || defined(ENABLE_VSMILE)) +#if (defined(ENABLE_ODY2) || defined(ENABLE_ARC) || defined(ENABLE_FAIRCHILD) || defined(ENABLE_MSX) || defined(ENABLE_POKE) || defined(ENABLE_2600) || defined(ENABLE_7800) || defined(ENABLE_C64) || defined(ENABLE_VECTREX) || defined(ENABLE_NES) || defined(ENABLE_LYNX) || defined(ENABLE_ATARI8) || defined(ENABLE_BALLY) || defined(ENABLE_LEAP) || defined(ENABLE_LJ) || defined(ENABLE_LJPRO) || defined(ENABLE_PV1000) || defined(ENABLE_PYUUTA) || defined(ENABLE_RCA) || defined(ENABLE_TI99) || defined(ENABLE_TRS80) || defined(ENABLE_VIC20) || defined(ENABLE_VSMILE) || defined(ENABLE_CPS3)) void printCRC(char* checkFile, uint32_t* crcCopy, unsigned long offset) { uint32_t crc = calculateCRC(checkFile, folder, offset); @@ -1122,8 +1122,9 @@ constexpr char modeItem38[] PROGMEM = "Tomy Pyuuta"; constexpr char modeItem39[] PROGMEM = "TRS-80"; constexpr char modeItem40[] PROGMEM = "Vtech V.Smile (3V)"; constexpr char modeItem41[] PROGMEM = "Flashrom Programmer"; -constexpr char modeItem42[] PROGMEM = "Self Test (3V)"; -constexpr char modeItem43[] PROGMEM = "About"; +constexpr char modeItem42[] PROGMEM = "CP System III"; +constexpr char modeItem43[] PROGMEM = "Self Test (3V)"; +constexpr char modeItem44[] PROGMEM = "About"; static const char* const modeOptions[] PROGMEM = { #ifdef ENABLE_GBX @@ -1249,10 +1250,13 @@ static const char* const modeOptions[] PROGMEM = { #ifdef ENABLE_FLASH8 modeItem41, #endif -#ifdef ENABLE_SELFTEST +#ifdef ENABLE_CPS3 modeItem42, #endif - modeItem43, FSTRING_RESET +#ifdef ENABLE_SELFTEST + modeItem43, +#endif + modeItem44, FSTRING_RESET }; @@ -1570,6 +1574,11 @@ void mainMenu() { break; #endif +#ifdef ENABLE_CPS3 + case SYSTEM_MENU_CPS3: + return cpsMenu(); +#endif + #ifdef ENABLE_SELFTEST case SYSTEM_MENU_SELFTEST: return selfTest(); @@ -3832,6 +3841,11 @@ void loop() { #endif #ifdef ENABLE_VSMILE case CORE_VSMILE: return vsmileMenu(); +#endif +#ifdef ENABLE_CPS3 + case CORE_CPS3_CART: return flashromCPS_Cartridge(); + case CORE_CPS3_128SIMM: return flashromCPS_SIMM2x8(); + case CORE_CPS3_64SIMM: return flashromCPS_SIMM4x8(); #endif case CORE_MAX: return resetArduino(); } diff --git a/Cart_Reader/Config.h b/Cart_Reader/Config.h index f46d5f67..9706af96 100644 --- a/Cart_Reader/Config.h +++ b/Cart_Reader/Config.h @@ -390,6 +390,13 @@ /****/ +/* [ CP System III ------------------------------------------------ ] +*/ + +#define ENABLE_CPS3 + +/****/ + /*==== FIRMWARE OPTIONS ===========================================*/ /* [ Config File -------------------------------------------------- ] diff --git a/Cart_Reader/FLASH.ino b/Cart_Reader/FLASH.ino index e2d5e64d..b0ad5fa6 100644 --- a/Cart_Reader/FLASH.ino +++ b/Cart_Reader/FLASH.ino @@ -16,6 +16,7 @@ unsigned long blank; unsigned long sectorSize; uint16_t bufferSize; byte mapping = 0; +boolean byteCtrl = 0; /****************************************** Menu @@ -238,7 +239,7 @@ void flashromMenu8() { writeFlash29LV640(); else if (flashid == 0x017E) writeFlash29GL(sectorSize, bufferSize); - else if ((flashid == 0x0458) || (flashid == 0x0158) || (flashid == 0x01AB)) + else if ((flashid == 0x0458) || (flashid == 0x0158) || (flashid == 0x01AB) || (flashid == 0x0422) || (flashid == 0x0423)) writeFlash29F800(); else if (flashid == 0x0) // Manual flash config, pick most common type writeFlash29LV640(); @@ -576,7 +577,7 @@ idtheflash: flashSize = 2097152; flashromType = 1; } else if (flashid == 0x04AD) { - println_Msg(F("AM29F016D detected")); + println_Msg(F("MBM29F016A detected")); flashSize = 2097152; flashromType = 1; } else if (flashid == 0x04D4) { @@ -595,6 +596,14 @@ idtheflash: println_Msg(F("AM29F400AB detected")); flashSize = 131072 * 4; flashromType = 2; + } else if (flashid == 0x0423) { + println_Msg(F("MBM29F400TC detected")); + flashSize = 131072 * 4; + flashromType = 2; + } else if (flashid == 0x0422) { + println_Msg(F("MBM29F400BC detected")); + flashSize = 131072 * 4; + flashromType = 2; } else if (flashid == 0x0158) { println_Msg(F("AM29F800BB detected")); flashSize = 1048576; @@ -1207,8 +1216,13 @@ byte readByte_Flash(unsigned long myAddress) { "nop\n\t" "nop\n\t"); - // Setting OE(PH1) OE_SNS(PH3) LOW - PORTH &= ~((1 << 1) | (1 << 3)); + if (byteCtrl) { + // Setting OE(PH1) LOW + PORTH &= ~(1 << 1); + } else { + // Setting OE(PH1) OE_SNS(PH3) LOW + PORTH &= ~((1 << 1) | (1 << 3)); + } __asm__("nop\n\t" "nop\n\t" @@ -1220,8 +1234,13 @@ byte readByte_Flash(unsigned long myAddress) { // Read byte tempByte = PINC; - // Setting OE(PH1) OE_SNS(PH3) HIGH - PORTH |= (1 << 1) | (1 << 3); + if (byteCtrl) { + // Setting OE(PH1) HIGH + PORTH |= (1 << 1); + } else { + // Setting OE(PH1) OE_SNS(PH3) HIGH + PORTH |= (1 << 1) | (1 << 3); + } __asm__("nop\n\t" "nop\n\t" "nop\n\t" @@ -1507,8 +1526,13 @@ int busyCheck29F032(uint32_t addr, byte c) { // Set data pins to input dataIn8(); - // Setting OE(PH1) OE_SNS(PH3) CE(PH6)LOW - PORTH &= ~((1 << 1) | (1 << 3) | (1 << 6)); + if (byteCtrl) { + // Setting OE(PH1) CE(PH6)LOW + PORTH &= ~((1 << 1) | (1 << 6)); + } else { + // Setting OE(PH1) OE_SNS(PH3) CE(PH6)LOW + PORTH &= ~((1 << 1) | (1 << 3) | (1 << 6)); + } // Setting WE(PH4) WE_SNES(PH5) HIGH PORTH |= (1 << 4) | (1 << 5); @@ -1537,8 +1561,13 @@ int busyCheck29F032(uint32_t addr, byte c) { // Set data pins to output dataOut(); - // Setting OE(PH1) OE_SNS(PH3) HIGH - PORTH |= (1 << 1) | (1 << 3); + if (byteCtrl) { + // Setting OE(PH1) HIGH + PORTH |= (1 << 1); + } else { + // Setting OE(PH1) OE_SNS(PH3) HIGH + PORTH |= (1 << 1) | (1 << 3); + } return ret; } /****************************************** @@ -2425,11 +2454,11 @@ void printFlash16(int numBytes) { byte right_byte = (currWord >> 8) & 0xFF; - sprintf(buf, "%.2x", left_byte); + sprintf(buf, "%.2X", left_byte); // Now print the significant bits print_Msg(buf); - sprintf(buf, "%.2x", right_byte); + sprintf(buf, "%.2X", right_byte); // Now print the significant bits print_Msg(buf); } diff --git a/Cart_Reader/FLASH_CPS3.ino b/Cart_Reader/FLASH_CPS3.ino new file mode 100644 index 00000000..38f30f5a --- /dev/null +++ b/Cart_Reader/FLASH_CPS3.ino @@ -0,0 +1,1630 @@ +//****************************************** +// CP System III Module +// Cartridge +// 32/64/128 Mbits SIMM +// Tested with HW5 +// https://github.com/herzmx/CPS3-OSCR-Adapter +//****************************************** +#ifdef ENABLE_CPS3 +/****************************************** + Variables + *****************************************/ +uint32_t cartRegion = 0; +uint32_t cartCD = 0; +uint32_t cartCDPatch = 0; +uint32_t multiCart = 0; +uint32_t multiCartPatch1 = 0; +uint32_t multiCartPatch2 = 0; +uint32_t cartRegionOffset = 0; +uint32_t cartnocdOffset = 0; +uint16_t flashids[8]; + +/****************************************** + Menu + *****************************************/ +// CPS3 start menu options +static const char cpsMenuItem1[] PROGMEM = "CPS3 cartridge"; +static const char cpsMenuItem2[] PROGMEM = "32/128 Mbits SIMM"; +static const char cpsMenuItem3[] PROGMEM = "64 Mbits SIMM"; +static const char cpsMenuItem4[] PROGMEM = "32/128 MBytes SIMM"; +static const char cpsMenuItem5[] PROGMEM = "64 MBytes SIMM"; +static const char* const menuOptionsCPS[] PROGMEM = { cpsMenuItem1, cpsMenuItem2, cpsMenuItem3, cpsMenuItem4, cpsMenuItem5, FSTRING_RESET }; + +// Cartridge region options +static const char cpsCartRegion0[] PROGMEM = "No Patch"; +static const char cpsCartRegion1[] PROGMEM = "JAP"; +static const char cpsCartRegion2[] PROGMEM = "ASIA"; +static const char cpsCartRegion3[] PROGMEM = "EUR"; +static const char cpsCartRegion4[] PROGMEM = "USA"; +static const char cpsCartRegion5[] PROGMEM = "HISPANIC"; +static const char cpsCartRegion6[] PROGMEM = "BRAZIL"; +static const char cpsCartRegion7[] PROGMEM = "OCEANIA"; +static const char cpsCartRegion8[] PROGMEM = "ASIA NCD"; +static const char* const menuOptionsCartRegion[] PROGMEM = { cpsCartRegion0, cpsCartRegion1, cpsCartRegion2, cpsCartRegion3, cpsCartRegion4, cpsCartRegion5, cpsCartRegion6, cpsCartRegion7, cpsCartRegion8, FSTRING_RESET }; + +// Cartridge cd options +static const char cpsCDItem1[] PROGMEM = "CD"; +static const char cpsCDItem2[] PROGMEM = "NOCD"; +static const char* const menuOptionsCartCD[] PROGMEM = { cpsCartRegion0, cpsCDItem1, cpsCDItem2, FSTRING_RESET }; + +// CPS3 start menu +void cpsMenu() { + // create menu with title and 6 options to choose from + unsigned char cpsType; + convertPgm(menuOptionsCPS, 6); + cpsType = question_box(FS(FSTRING_SELECT_CART_TYPE), menuOptions, 6, 0); + + // wait for user choice to come back from the question box menu + switch (cpsType) { + case 0: + display_Clear(); + display_Update(); + mode = CORE_CPS3_CART; + setup_CPS3(); + id_Flash8(); + wait(); + break; + case 1: + display_Clear(); + display_Update(); + mode = CORE_CPS3_128SIMM; + setup_CPS3(); + id_SIMM2x8(); + wait(); + break; + case 2: + display_Clear(); + display_Update(); + mode = CORE_CPS3_64SIMM; + setup_CPS3(); + id_SIMM4x8(); + wait(); + break; + case 3: + display_Clear(); + display_Update(); + mode = CORE_CPS3_01SIMM; + setup_CPS3(); + break; + case 4: + display_Clear(); + display_Update(); + mode = CORE_CPS3_512SIMM; + setup_CPS3(); + break; + case 5: + resetArduino(); + break; + default: + print_MissingModule(); // does not return + } +} + +// CPS3 Cartridge menu +void flashromCPS_Cartridge() { + // create menu with title and 7 options to choose from + unsigned char mainMenu; + // Copy menuOptions out of progmem + convertPgm(menuOptionsFLASH8, 7); + mainMenu = question_box(F("CPS3 Cartdrige Writer"), menuOptions, 7, 0); + + // wait for user choice to come back from the question box menu + switch (mainMenu) { + case 0: + display_Clear(); + println_Msg(F("Blankcheck")); + display_Update(); + time = millis(); + resetFlash8(); + blankcheck_Flash(); + break; + + case 1: + if (flashromType != 0) { + display_Clear(); + println_Msg(F("Warning: This will erase")); + println_Msg(F("your CPS3 Cartdrige BIOS")); + print_STR(press_button_STR, 1); + display_Update(); + wait(); + rgbLed(black_color); + println_Msg(FS(FSTRING_EMPTY)); + println_Msg(F("Please wait...")); + display_Update(); + time = millis(); + + switch (flashromType) { + case 1: eraseFlash29F032(); break; + case 2: eraseFlash29F1610(); break; + case 3: eraseFlash28FXXX(); break; + } + + println_Msg(F("CPS3 Cartdrige BIOS erased")); + display_Update(); + resetFlash8(); + } else { + readOnlyMode(); + } + break; + + case 2: + time = millis(); + resetFlash8(); + readCartridge(); + break; + + case 3: + if (flashromType != 0) { + // Set cartridge region + filePath[0] = '\0'; + sd.chdir("/"); + fileBrowser(FS(FSTRING_SELECT_FILE)); + // Calculate CRC32 of BIOS + display_Clear(); + println_Msg("Looking BIOS patch"); + println_Msg(FS(FSTRING_EMPTY)); + println_Msg(F("Please wait...")); + display_Update(); + char crcStr[9]; + sprintf(crcStr, "%08lX", calculateCRC(fileName, filePath, 0)); + setCartridgePatchData(crcStr); + display_Clear(); + time = millis(); + + switch (flashromType) { + case 1: + break; + case 2: + if ((flashid == 0x0458) || (flashid == 0x0158) || (flashid == 0x01AB) || (flashid == 0x0422) || (flashid == 0x0423)) + writeCartridge(); + else if (flashid == 0x0) // Manual flash config, pick most common type + writeFlash29LV640(); + break; + case 3: + break; + } + + delay(100); + + // Reset twice just to be sure + resetFlash8(); + resetFlash8(); + + verifyCartridge(); + } else { + readOnlyMode(); + } + break; + + case 4: + time = 0; + display_Clear(); + resetFlash8(); + println_Msg(F("ID Flashrom")); + switch (flashromType) { + case 0: break; + case 1: idFlash29F032(); break; + case 2: idFlash29F1610(); break; + case 3: idFlash28FXXX(); break; + } + println_Msg(FS(FSTRING_EMPTY)); + printFlash(40); + println_Msg(FS(FSTRING_EMPTY)); + display_Update(); + resetFlash8(); + break; + + case 5: + time = 0; + display_Clear(); + println_Msg(F("Print first 70Bytes")); + display_Update(); + resetFlash8(); + printFlash(70); + break; + + case 6: + time = 0; + display_Clear(); + display_Update(); + resetFlash8(); + resetArduino(); + break; + } + if (time != 0) { + print_Msg(F("Operation took : ")); + print_Msg((millis() - time) / 1000, DEC); + println_Msg(F("s")); + display_Update(); + } + // Prints string out of the common strings array either with or without newline + print_STR(press_button_STR, 0); + display_Update(); + wait(); +} + +// CPS3 Cartridge region patch menu +void cpsCartRegionMenu() { + cartRegion = pageMenu(F("Cartridge Region Patch"), menuOptionsCartRegion, 10); + if (cartRegion < 9) { + display_Clear(); + display_Update(); + } else { + time = 0; + display_Clear(); + display_Update(); + resetFlash8(); + resetArduino(); + } +} + +// CPS3 Cartridge CD patch menu +void cpsCartCDMenu() { + // Copy menuOptions out of progmem + convertPgm(menuOptionsCartCD, 4); + cartCD = question_box(F("Cartridge CD Patch"), menuOptions, 4, 0); + + // wait for user choice to come back from the question box menu + if (cartCD < 3) { + display_Clear(); + display_Update(); + } else { + time = 0; + display_Clear(); + display_Update(); + resetFlash8(); + resetArduino(); + } +} + +// CPS3 32/128 SIMM menu +void flashromCPS_SIMM2x8() { + // create menu with title and 7 options to choose from + unsigned char mainMenu; + // Copy menuOptions out of progmem + convertPgm(menuOptionsFLASH8, 7); + mainMenu = question_box(F("CPS3 SIMM Writer 2x8bit"), menuOptions, 7, 0); + + // wait for user choice to come back from the question box menu + switch (mainMenu) { + case 0: + display_Clear(); + println_Msg(F("Blankcheck")); + display_Update(); + time = millis(); + resetSIMM2x8(); + blankcheckSIMM2x8(); + break; + + case 1: + if (flashromType != 0) { + display_Clear(); + println_Msg(F("Warning: This will erase")); + println_Msg(F("your CPS3 SIMM 2x8bit")); + print_STR(press_button_STR, 1); + display_Update(); + wait(); + rgbLed(black_color); + println_Msg(FS(FSTRING_EMPTY)); + println_Msg(F("Please wait...")); + display_Update(); + time = millis(); + + switch (flashromType) { + case 1: eraseSIMM2x8(); break; + case 2: break; + case 3: break; + } + + println_Msg(F("CPS3 SIMM 2x8bit erased")); + display_Update(); + resetSIMM2x8(); + } else { + readOnlyMode(); + } + break; + + case 2: + time = millis(); + resetSIMM2x8(); + readSIMM2x8B(); + break; + + case 3: + if (flashromType != 0) { + // Set cartridge region + filePath[0] = '\0'; + sd.chdir("/"); + fileBrowser(FS(FSTRING_SELECT_FILE)); + display_Clear(); + time = millis(); + + switch (flashromType) { + case 1: + if (flashid == 0x04AD) + writeSIMM2x8(); + break; + case 2: + break; + case 3: + break; + } + + delay(100); + + // Reset twice just to be sure + resetSIMM2x8(); + resetSIMM2x8(); + + verifySIMM2x8(); + } else { + readOnlyMode(); + } + break; + + case 4: + time = 0; + display_Clear(); + resetFlash8(); + println_Msg(F("ID Flashrom")); + switch (flashromType) { + case 0: break; + case 1: idFlash2x8(0x0); break; + case 2: break; + case 3: break; + } + println_Msg(FS(FSTRING_EMPTY)); + printFlash16(40); + println_Msg(FS(FSTRING_EMPTY)); + display_Update(); + resetSIMM2x8(); + break; + + case 5: + time = 0; + display_Clear(); + println_Msg(F("Print first 70Bytes")); + display_Update(); + resetSIMM2x8(); + printFlash16(70); + break; + + case 6: + time = 0; + display_Clear(); + display_Update(); + resetSIMM2x8(); + resetArduino(); + break; + } + if (time != 0) { + print_Msg(F("Operation took : ")); + print_Msg((millis() - time) / 1000, DEC); + println_Msg(F("s")); + display_Update(); + } + // Prints string out of the common strings array either with or without newline + print_STR(press_button_STR, 0); + display_Update(); + wait(); +} + +// CPS3 32/128 SIMM menu +void flashromCPS_SIMM4x8() { + // create menu with title and 7 options to choose from + unsigned char mainMenu; + // Copy menuOptions out of progmem + convertPgm(menuOptionsFLASH8, 7); + mainMenu = question_box(F("CPS3 SIMM Writer 4x8bit"), menuOptions, 7, 0); + + // wait for user choice to come back from the question box menu + switch (mainMenu) { + case 0: + display_Clear(); + println_Msg(F("Blankcheck")); + display_Update(); + time = millis(); + resetSIMM4x8(); + blankcheckSIMM4x8(); + break; + + case 1: + if (flashromType != 0) { + display_Clear(); + println_Msg(F("Warning: This will erase")); + println_Msg(F("your CPS3 SIMM 4x8bit")); + print_STR(press_button_STR, 1); + display_Update(); + wait(); + rgbLed(black_color); + println_Msg(FS(FSTRING_EMPTY)); + println_Msg(F("Please wait...")); + display_Update(); + time = millis(); + + switch (flashromType) { + case 1: eraseSIMM4x8(); break; + case 2: break; + case 3: break; + } + + println_Msg(F("CPS3 SIMM 4x8bit erased")); + display_Update(); + resetSIMM4x8(); + } else { + readOnlyMode(); + } + break; + + case 2: + time = millis(); + resetSIMM4x8(); + readSIMM4x8(); + break; + + case 3: + if (flashromType != 0) { + // Set cartridge region + filePath[0] = '\0'; + sd.chdir("/"); + fileBrowser(FS(FSTRING_SELECT_FILE)); + display_Clear(); + time = millis(); + + switch (flashromType) { + case 1: + if (flashid == 0x04AD) + writeSIMM4x8(); + break; + case 2: + break; + case 3: + break; + } + + delay(100); + + // Reset twice just to be sure + resetSIMM4x8(); + resetSIMM4x8(); + + verifySIMM4x8(); + } else { + readOnlyMode(); + } + break; + + case 4: + time = 0; + display_Clear(); + resetFlash8(); + println_Msg(F("ID Flashrom")); + switch (flashromType) { + case 0: break; + case 1: + enable64MSB(); + idFlash2x8(0x0); + enable64LSB(); + idFlash2x8(0x1); + break; + case 2: break; + case 3: break; + } + println_Msg(FS(FSTRING_EMPTY)); + printSIMM4x8(40); + println_Msg(FS(FSTRING_EMPTY)); + display_Update(); + resetSIMM4x8(); + break; + + case 5: + time = 0; + display_Clear(); + println_Msg(F("Print first 70Bytes")); + display_Update(); + resetSIMM4x8(); + enable64MSB(); + printSIMM4x8(70); + break; + + case 6: + time = 0; + display_Clear(); + display_Update(); + resetSIMM4x8(); + resetArduino(); + break; + } + if (time != 0) { + print_Msg(F("Operation took : ")); + print_Msg((millis() - time) / 1000, DEC); + println_Msg(F("s")); + display_Update(); + } + // Prints string out of the common strings array either with or without newline + print_STR(press_button_STR, 0); + display_Update(); + wait(); +} + +/****************************************** + Setup + *****************************************/ +void setup_CPS3() { + // Set Address Pins to Output + //A0-A7 + DDRF = 0xFF; + //A8-A15 + DDRK = 0xFF; + //A16-A23 + DDRL = 0xFF; + //A24(PJ0), A25(PJ1) + DDRJ |= (1 << 0) | (1 << 1); + + // Set Control Pins to Output + // RST(PH0) OE(PH1) BYTE(PH3) WE(PH4) CKIO_CPU(PH5) CE/CER_CST(PH6) + DDRH |= (1 << 0) | (1 << 1) | (1 << 3) | (1 << 4) | (1 << 5) | (1 << 6); + // CE64LSB(PE3) CE128(PE4) + DDRE |= (1 << 3) | (1 << 4); + // RST_CPUC(PG1) CE64MSB(PG5) + DDRG |= (1 << 1) | (1 << 5); + + // Set Data Pins (D0-D15) to Input + DDRC = 0x00; + DDRA = 0x00; + // Disable Internal Pullups + PORTC = 0x00; + PORTA = 0x00; + + // Setting RST(PH0) OE(PH1) WE(PH4) CKIO_CPU(PH5) HIGH + PORTH |= (1 << 0) | (1 << 1) | (1 << 4) | (1 << 5); + // Setting CE64LSB(PE3) CE128(PE4) HIGH + PORTE |= (1 << 3) | (1 << 4); + // Setting CE64MSB(PG5) HIGH + PORTG |= (1 << 5); + // Setting CE_CART/CER_CST(PH6) HIGH + PORTH |= (1 << 6); + // Setting BYTE(PH3) LOW + PORTH &= ~(1 << 3); + // Setting RST_CPUC(PG1) LOW + PORTG &= ~(1 << 1); + + if (mode == CORE_CPS3_128SIMM || mode == CORE_CPS3_01SIMM) { + // Setting CE128(PE4) LOW + PORTE &= ~(1 << 4); + } else if (mode == CORE_CPS3_CART) { + // Setting CE_CART/CER_CST(PH6) LOW + PORTH &= ~(1 << 6); + } + + byteCtrl = 1; +} + +/****************************************** + Low level functions + *****************************************/ +void enable64MSB() { + // Setting CE64LSB(PE3) HIGH + PORTE |= (1 << 3); + // Setting CE64MSB(PG5) LOW + PORTG &= ~(1 << 5); + // Wait till output is stable + NOP; + NOP; +} + +void enable64LSB() { + // Setting CE64MSB(PG5) HIGH + PORTG |= (1 << 5); + // Setting CE64LSB(PE3) LOW + PORTE &= ~(1 << 3); + // Wait till output is stable + NOP; + NOP; +} + +/****************************************** + helper functions +*****************************************/ +uint32_t char2int(char hex) { + uint32_t byte = 0; + // transform hex character to the 4bit equivalent number, using the ascii table indexes + if (hex >= '0' && hex <= '9') + byte = hex - 48; + else if (hex >= 'A' && hex <= 'F') + byte = hex - 55; + return byte; +} + +/****************************************** + Command functions +*****************************************/ +void writeByteCommand_Flash2x8(uint32_t bank, byte command) { + writeWord_Flash((bank << 21) | 0x555, 0xaaaa); + writeWord_Flash((bank << 21) | 0x2aa, 0x5555); + writeWord_Flash((bank << 21) | 0x555, command << 8 | command); +} + +/****************************************** + Cartridge functions +*****************************************/ +void readCartridge() { + // Reset to root directory + sd.chdir("/"); + + createFolderAndOpenFile("CPS3", "Cartridge", "29f400", "u2"); + + //Initialize progress bar + uint32_t processedProgressBar = 0; + uint32_t totalProgressBar = flashSize; + draw_progressbar(0, totalProgressBar); + + for (unsigned long currByte = 0; currByte < flashSize; currByte += 512) { + for (int c = 0; c < 512; c++) { + sdBuffer[c] = readByte_Flash(currByte + c); + } + myFile.write(sdBuffer, 512); + // Update progress bar + processedProgressBar += 512; + draw_progressbar(processedProgressBar, totalProgressBar); + // Blink led + if (currByte % 25600 == 0) + blinkLED(); + } + + // Close the file: + myFile.close(); + // Compare dump CRC with db values + compareCRC("cps3.txt", 0, 1, 0); + println_Msg(F("Finished reading")); + display_Update(); +} + +void writeCartridge() { + if (openFlashFile()) { + // Set data pins to output + dataOut(); + + // Initialize progress bar + uint32_t processedProgressBar = 0; + uint32_t totalProgressBar = (uint32_t)fileSize; + draw_progressbar(0, totalProgressBar); + + // Fill sdBuffer + for (unsigned long currByte = 0; currByte < fileSize; currByte += 512) { + myFile.read(sdBuffer, 512); + // Blink led + if (currByte % 2048 == 0) + blinkLED(); + + for (int c = 0; c < 512; c++) { + // Write command sequence + writeByteCommandShift_Flash(0xa0); + + // Write patch to avoid region menu in multi + if ((currByte + c) == 0x405F && cartRegion > 0 && multiCart == 1) { + writeByte_Flash(currByte + c, multiCartPatch1 & 0xFF); + busyCheck29F032(currByte + c, multiCartPatch1 & 0xFF); + continue; + } + if ((currByte + c) == 0x20746 && cartRegion > 0 && multiCart == 1) { + writeByte_Flash(currByte + c, multiCartPatch2 & 0xFF); + busyCheck29F032(currByte + c, multiCartPatch2 & 0xFF); + continue; + } + // Write cartridge region + if ((currByte + c) == cartRegionOffset && cartRegion > 0) { + writeByte_Flash(currByte + c, cartRegion & 0xFF); + busyCheck29F032(currByte + c, cartRegion & 0xFF); + continue; + } + // Write cartridge cd + if ((currByte + c) == cartnocdOffset && cartCD > 0) { + writeByte_Flash(currByte + c, cartCDPatch & 0xFF); + busyCheck29F032(currByte + c, cartCDPatch & 0xFF); + continue; + } + // Write current byte + writeByte_Flash(currByte + c, sdBuffer[c]); + busyCheck29F032(currByte + c, sdBuffer[c]); + } + // update progress bar + processedProgressBar += 512; + draw_progressbar(processedProgressBar, totalProgressBar); + } + + // Set data pins to input again + dataIn8(); + + // Close the file: + myFile.close(); + } +} + +void verifyCartridge() { + if (openVerifyFlashFile()) { + blank = 0; + + //Initialize progress bar + uint32_t processedProgressBar = 0; + uint32_t totalProgressBar = fileSize; + draw_progressbar(0, totalProgressBar); + + for (unsigned long currByte = 0; currByte < fileSize; currByte += 512) { + //fill sdBuffer + myFile.read(sdBuffer, 512); + for (int c = 0; c < 512; c++) { + // Verify patch to avoid region menu + if ((currByte + c) == 0x405F && cartRegion > 0 && multiCart == 1 && readByte_Flash(currByte + c) == multiCartPatch1 & 0xFF) { + continue; + } else if ((currByte + c) == 0x20746 && cartRegion > 0 && multiCart == 1 && readByte_Flash(currByte + c) == multiCartPatch2 & 0xFF) { + continue; + // Verify cartridge region + } else if ((currByte + c) == cartRegionOffset && cartRegion > 0 && readByte_Flash(currByte + c) == cartRegion & 0xFF) { + continue; + // Verify cartridge cd + } else if ((currByte + c) == cartnocdOffset && cartCD > 0 && readByte_Flash(currByte + c) == cartCDPatch & 0xFF) { + continue; + } else if (readByte_Flash(currByte + c) != sdBuffer[c]) { + blank++; + } + } + // Update progress bar + processedProgressBar += 512; + draw_progressbar(processedProgressBar, totalProgressBar); + // Blink led + if (currByte % 25600 == 0) + blinkLED(); + } + if (blank == 0) { + println_Msg(F("Cart BIOS verified OK")); + display_Update(); + } else { + print_STR(error_STR, 0); + print_Msg(blank); + print_STR(_bytes_STR, 1); + print_Error(did_not_verify_STR); + } + // Close the file: + myFile.close(); + } +} + +void setCartridgePatchData(char crcStr[9]) { + // Init vars + cartRegionOffset = 0; + //Search for CRC32 in file + char crc_search[9]; + char tmpDWord[9]; + //go to root + sd.chdir("/"); + if (myFile.open("cps3.txt", O_READ)) { + while (myFile.available()) { + // Skip first line with name + skip_line(&myFile); + // Read the CRC32 from database + for (byte i = 0; i < 8; i++) { + crc_search[i] = char(myFile.read()); + } + crc_search[8] = '\0'; + //if checksum search successful, set patch data + if (strcmp(crc_search, crcStr) == 0) { + // Skip the , in the file + myFile.seekCur(1); + // Read region offset + cartRegionOffset = char2int(myFile.read()) << 16 | char2int(myFile.read()) << 12 | char2int(myFile.read()) << 8 | char2int(myFile.read()) << 4 | char2int(myFile.read()); + // Skip the , in the file + myFile.seekCur(1); + if (cartRegionOffset != 0) { + // Ask for cart region change + cpsCartRegionMenu(); + if (cartRegion != 0) { + uint8_t skipRegions = 8 - cartRegion; + cartRegion -= 1; + myFile.seekCur(cartRegion * 2); + cartRegion = (char2int(myFile.read())) << 4 | char2int(myFile.read()); + myFile.seekCur(skipRegions * 2); + } else { + myFile.seekCur(16); + } + } else { + myFile.seekCur(16); + } + // Skip the , in the file + myFile.seekCur(1); + cartnocdOffset = char2int(myFile.read()) << 16 | char2int(myFile.read()) << 12 | char2int(myFile.read()) << 8 | char2int(myFile.read()) << 4 | char2int(myFile.read()); + // Skip the , in the file + myFile.seekCur(1); + if (cartnocdOffset != 0) { + // Ask for cart cd change + cpsCartCDMenu(); + cartCDPatch = char2int(myFile.read()) << 4 | char2int(myFile.read()); + if (cartCD == 1) { + cartCDPatch = char2int(myFile.read()) << 4 | char2int(myFile.read()); + } else { + // Skip the byte + myFile.seekCur(2); + } + } else { + myFile.seekCur(4); + } + // Skip the , in the file + myFile.seekCur(1); + // Read multi cart dat from database + multiCart = char2int(myFile.read()); + // Read multi cart patches + if (multiCart == 1) { + multiCartPatch1 = char2int(myFile.read()) << 4 | char2int(myFile.read()); + multiCartPatch2 = char2int(myFile.read()) << 4 | char2int(myFile.read()); + } + break; + } + // If no match go to next entry + else { + // skip rest of line + myFile.seekCur(42); + // skip third empty line + skip_line(&myFile); + } + } + myFile.close(); + } +} + +/****************************************** + 2x8bit SIMM functions +*****************************************/ +void id_SIMM2x8() { + idFlash2x8(0x0); + idFlash2x8(0x1); + idFlash2x8(0x2); + idFlash2x8(0x3); + resetSIMM2x8(); + uint8_t ngFlash = 0; + uint8_t okFlash = 0; + + if (flashids[6] == flashids[7]) { + flashid = flashids[7]; + sprintf(flashid_str, "%04X", flashid); + okFlash = 2; + for (byte i = 0; i < 6; i++) { + if (flashid == flashids[i]) + okFlash += 1; + else + ngFlash += 1; + } + } + // Print start screen + display_Clear(); + display_Update(); + println_Msg(F("SIMM Writer 2x8bit")); + println_Msg(""); + println_Msg(""); + print_Msg(F("Flash ID: ")); + println_Msg(flashid_str); + if (flashid == 0x04AD && okFlash == 2 && ngFlash == 6) { + println_Msg(F("32 Mbit Fujitsu SIMM detected")); + flashSize = 0x400000; + flashromType = 1; + } else if (flashid == 0x04AD && okFlash == 8) { + println_Msg(F("128 Mbit Fujitsu SIMM detected")); + flashSize = 0x1000000; + flashromType = 1; + } else if (flashid == 0x04AD && okFlash > 2) { + println_Msg(F("?? Mbit Fujitsu SIMM detected")); + println_Msg(F("With some bad flash")); + flashSize = 0x1000000; + flashromType = 0; + } else { + // ID not found + flashSize = 0x1000000; + flashromType = 0; + display_Clear(); + println_Msg(F("SIMM Writer 2x8bit")); + println_Msg(""); + print_Msg(F("ID Type 1: ")); + println_Msg(vendorID); + print_Msg(F("ID Type 2: ")); + println_Msg(flashid_str); + println_Msg(""); + println_Msg(F("UNKNOWN FLASHROM")); + println_Msg(""); + // Prints string out of the common strings array either with or without newline + print_Error(press_button_STR); + display_Update(); + wait(); + // print first 40 bytes of flash + display_Clear(); + println_Msg(F("First 40 bytes:")); + println_Msg(FS(FSTRING_EMPTY)); + printFlash16(40); + resetSIMM2x8(); + } + println_Msg(FS(FSTRING_EMPTY)); + // Prints string out of the common strings array either with or without newline + print_STR(press_button_STR, 1); + display_Update(); + resetSIMM2x8(); +} + +void resetSIMM2x8() { + resetFlash2x8(0x3); + resetFlash2x8(0x2); + resetFlash2x8(0x1); + resetFlash2x8(0x0); +} + +void blankcheckSIMM2x8() { + + //Initialize progress bar + uint32_t processedProgressBar = 0; + uint32_t totalProgressBar = flashSize; + draw_progressbar(0, totalProgressBar); + + blank = 1; + word d = 0; + unsigned long simmAddress = 0; + for (unsigned long currBuffer = 0; currBuffer < flashSize / 2; currBuffer += 256) { + // Fill buffer + for (int c = 0; c < 256; c++) { + simmAddress = currBuffer + c; + word currWord = readWord_Flash(simmAddress); + // Read byte right + sdBuffer[d + 1] = ((currWord >> 8) & 0xFF); + // Read byte left + sdBuffer[d] = (currWord & 0xFF); + d += 2; + } + // Check if all bytes are 0xFF + d = 0; + for (unsigned long currByte = 0; currByte < 256; currByte++) { + if (sdBuffer[d] != 0xFF || sdBuffer[d + 1] != 0xFF) { + currByte = 256; + currBuffer = flashSize / 2; + blank = 0; + } + d += 2; + } + d = 0; + // Update progress bar + processedProgressBar += 512; + draw_progressbar(processedProgressBar, totalProgressBar); + // Blink led + if (currBuffer % 25600 == 0) + blinkLED(); + } + if (blank) { + println_Msg(F("SIMM is empty")); + display_Update(); + } else { + println_Msg(FS(FSTRING_EMPTY)); + print_Error(F("Error: Not blank")); + } +} + +// From readFlash +void readSIMM2x8() { + // Reset to root directory + sd.chdir("/"); + + createFolderAndOpenFile("CPS3", "SIMM", "128M", "bin"); + + //Initialize progress bar + uint32_t processedProgressBar = 0; + uint32_t totalProgressBar = flashSize; + draw_progressbar(0, totalProgressBar); + + word d = 0; + unsigned long simmAddress = 0; + char tmpWord[5]; + char tmpDWord[9]; + for (unsigned long currByte = 0; currByte < flashSize / 2; currByte += 256) { + for (word c = 0; c < 256; c++) { + simmAddress = currByte + c; + word currWord = readWord_Flash(simmAddress); + // Split word into two bytes + // Right + sdBuffer[d + 1] = ((currWord >> 8) & 0xFF); + // Left + sdBuffer[d] = (currWord & 0xFF); + d += 2; + } + myFile.write(sdBuffer, 512); + d = 0; + // Update progress bar + processedProgressBar += 512; + draw_progressbar(processedProgressBar, totalProgressBar); + // Blink led + if (currByte % 25600 == 0) + blinkLED(); + } + + // Close the file: + myFile.close(); + println_Msg(F("Finished reading")); + display_Update(); +} + +// From readFlash16 +void readSIMM2x8B() { + // Reset to root directory + sd.chdir("/"); + + createFolderAndOpenFile("CPS3", "SIMM", "128M", "bin"); + //Initialize progress bar + uint32_t processedProgressBar = 0; + uint32_t totalProgressBar = flashSize; + draw_progressbar(0, totalProgressBar); + + word d = 0; + unsigned long simmAddress = 0; + for (unsigned long currByte = 0; currByte < flashSize / 2; currByte += 256) { + for (word c = 0; c < 256; c++) { + simmAddress = currByte + c; + + word currWord = readWord_Flash(simmAddress); + // Split word into two bytes + // Right + sdBuffer[d + 1] = ((currWord >> 8) & 0xFF); + // Left + sdBuffer[d] = (currWord & 0xFF); + d += 2; + } + myFile.write(sdBuffer, 512); + d = 0; + // Update progress bar + processedProgressBar += 512; + draw_progressbar(processedProgressBar, totalProgressBar); + // Blink led + if (currByte % 25600 == 0) + blinkLED(); + } + + // Close the file: + myFile.close(); + println_Msg(F("Finished reading.")); + display_Update(); +} + +void eraseSIMM2x8() { + eraseFlash2x8(0x3); + eraseFlash2x8(0x2); + eraseFlash2x8(0x1); + eraseFlash2x8(0x0); +} + +// From writeFlash29F032 +void writeSIMM2x8() { + if (openFlashFile()) { + // Set data pins to output + dataOut16(); + + //Initialize progress bar + uint32_t processedProgressBar = 0; + uint32_t totalProgressBar = (uint32_t)fileSize; + draw_progressbar(0, totalProgressBar); + + // Fill sdBuffer LSB + unsigned long simmAddress = 0; + for (unsigned long currByte = 0; currByte < fileSize / 2; currByte += 256) { + myFile.read(sdBuffer, 512); + // Blink led + if (currByte % 4096 == 0) + blinkLED(); + + noInterrupts(); + for (int c = 0; c < 256; c++) { + simmAddress = currByte + c; + word myWord = ((sdBuffer[(c * 2) + 1] & 0xFF) << 8) | (sdBuffer[c * 2] & 0xFF); + // Skip if data exist in flash + dataIn16(); + word wordFlash = readWord_Flash(simmAddress); + dataOut16(); + if (wordFlash == myWord || myWord == 0xFFFF) { + continue; + } + // Write command sequence + writeByteCommand_Flash2x8(simmAddress >> 21, 0xa0); + // Write current word + writeWord_Flash(simmAddress, myWord); + busyCheck2x8(simmAddress, myWord); + } + interrupts(); + // update progress bar + processedProgressBar += 512; + draw_progressbar(processedProgressBar, totalProgressBar); + } + + // Set data pins to input again + dataIn16(); + + // Close the file: + myFile.close(); + } +} + +// From verifyFlash16 +void verifySIMM2x8() { + if (openVerifyFlashFile()) { + blank = 0; + word d = 0; + unsigned long simmAddress = 0; + //Initialize progress bar + uint32_t processedProgressBar = 0; + uint32_t totalProgressBar = fileSize; + draw_progressbar(0, totalProgressBar); + for (unsigned long currByte = 0; currByte < fileSize / 2; currByte += 256) { + //fill sdBuffer + myFile.read(sdBuffer, 512); + for (int c = 0; c < 256; c++) { + // Set address + simmAddress = currByte + c; + word currWord = ((sdBuffer[d + 1] << 8) | sdBuffer[d]); + if (readWord_Flash(simmAddress) != currWord) { + blank++; + } + d += 2; + } + d = 0; + // Update progress bar + if (currByte % 256 == 0) { + processedProgressBar += 512; + draw_progressbar(processedProgressBar, totalProgressBar); + } + // Blink led + if (currByte % 25600 == 0) + blinkLED(); + } + if (blank == 0) { + println_Msg(F("SIMM verified OK")); + display_Update(); + } else { + print_STR(error_STR, 0); + print_Msg(blank); + print_STR(_bytes_STR, 1); + print_Error(did_not_verify_STR); + } + // Close the file: + myFile.close(); + } +} + +/****************************************** + 4x8bit SIMM functions +*****************************************/ +void id_SIMM4x8() { + enable64MSB(); + idFlash2x8(0x0); + enable64LSB(); + idFlash2x8(0x1); + resetSIMM4x8(); + uint8_t ngFlash = 0; + uint8_t okFlash = 0; + + flashid = flashids[7]; + sprintf(flashid_str, "%04X", flashid); + for (byte i = 4; i < 8; i++) { + if (flashid == flashids[i]) + okFlash += 1; + else + ngFlash += 1; + } + + // Print start screen + display_Clear(); + display_Update(); + println_Msg(F("SIMM Writer 4x8bit")); + println_Msg(""); + println_Msg(""); + print_Msg(F("Flash ID: ")); + println_Msg(flashid_str); + if (flashid == 0x04AD && okFlash == 4) { + println_Msg(F("64 Mbit Fujitsu SIMM detected")); + flashSize = 0x800000; + flashromType = 1; + } else if (flashid == 0x04AD && okFlash < 4) { + println_Msg(F("Fujitsu SIMM detected")); + println_Msg(F("With some bad flash")); + flashSize = 0x800000; + flashromType = 0; + } else { + // ID not found + display_Clear(); + println_Msg(F("SIMM Writer 4x8bit")); + println_Msg(""); + print_Msg(F("ID Type 1: ")); + println_Msg(vendorID); + print_Msg(F("ID Type 2: ")); + println_Msg(flashid_str); + println_Msg(""); + println_Msg(F("UNKNOWN FLASHROM")); + println_Msg(""); + // Prints string out of the common strings array either with or without newline + print_Error(press_button_STR); + display_Update(); + wait(); + // print first 40 bytes of flash + display_Clear(); + println_Msg(F("First 40 bytes:")); + println_Msg(FS(FSTRING_EMPTY)); + printFlash16(40); + resetSIMM4x8(); + } + println_Msg(FS(FSTRING_EMPTY)); + // Prints string out of the common strings array either with or without newline + print_STR(press_button_STR, 1); + display_Update(); + resetSIMM4x8(); +} + +void resetSIMM4x8() { + enable64MSB(); + resetFlash2x8(0x0); + enable64LSB(); + resetFlash2x8(0x0); +} + +void blankcheckSIMM4x8() { + + //Initialize progress bar + uint32_t processedProgressBar = 0; + uint32_t totalProgressBar = flashSize; + draw_progressbar(0, totalProgressBar); + + blank = 1; + word d = 0; + for (unsigned long currBuffer = 0; currBuffer < flashSize / 4; currBuffer += 128) { + // Fill buffer + for (int c = 0; c < 128; c++) { + enable64MSB(); + word currWord = readWord_Flash(currBuffer + c); + // Read byte right + sdBuffer[d + 1] = ((currWord >> 8) & 0xFF); + // Read byte left + sdBuffer[d] = (currWord & 0xFF); + enable64LSB(); + currWord = readWord_Flash(currBuffer + c); + // Read byte right + sdBuffer[d + 3] = ((currWord >> 8) & 0xFF); + // Read byte left + sdBuffer[d + 2] = (currWord & 0xFF); + d += 4; + } + // Check if all bytes are 0xFF + d = 0; + for (unsigned long currByte = 0; currByte < 128; currByte++) { + if (sdBuffer[d] != 0xFF || sdBuffer[d + 1] != 0xFF || sdBuffer[d + 2] != 0xFF || sdBuffer[d + 3] != 0xFF) { + currByte = 128; + currBuffer = flashSize / 4; + blank = 0; + } + d += 4; + } + d = 0; + // Update progress bar + processedProgressBar += 512; + draw_progressbar(processedProgressBar, totalProgressBar); + // Blink led + if (currBuffer % 25600 == 0) + blinkLED(); + } + if (blank) { + println_Msg(F("SIMM is empty")); + display_Update(); + } else { + println_Msg(FS(FSTRING_EMPTY)); + print_Error(F("Error: Not blank")); + } +} + +void eraseSIMM4x8() { + enable64MSB(); + eraseFlash2x8(0x0); + enable64LSB(); + eraseFlash2x8(0x0); +} + +// From readFlash16 +void readSIMM4x8() { + // Reset to root directory + sd.chdir("/"); + + createFolderAndOpenFile("CPS3", "SIMM", "64M", "bin"); + //Initialize progress bar + uint32_t processedProgressBar = 0; + uint32_t totalProgressBar = flashSize; + draw_progressbar(0, totalProgressBar); + + word d = 0; + for (unsigned long currByte = 0; currByte < flashSize / 4; currByte += 128) { + for (word c = 0; c < 128; c++) { + enable64MSB(); + word currWord = readWord_Flash(currByte + c); + // Split word into two bytes + // Right + sdBuffer[d + 1] = ((currWord >> 8) & 0xFF); + // Left + sdBuffer[d] = (currWord & 0xFF); + + enable64LSB(); + currWord = readWord_Flash(currByte + c); + // Split word into two bytes + // Right + sdBuffer[d + 3] = ((currWord >> 8) & 0xFF); + // Left + sdBuffer[d + 2] = (currWord & 0xFF); + d += 4; + } + myFile.write(sdBuffer, 512); + d = 0; + // Update progress bar + processedProgressBar += 512; + draw_progressbar(processedProgressBar, totalProgressBar); + // Blink led + if (currByte % 12800 == 0) + blinkLED(); + } + + // Close the file: + myFile.close(); + println_Msg(F("Finished reading.")); + display_Update(); +} + +void writeSIMM4x8() { + if (openFlashFile()) { + // Set data pins to output + dataOut16(); + + //Initialize progress bar + uint32_t processedProgressBar = 0; + uint32_t totalProgressBar = (uint32_t)fileSize; + draw_progressbar(0, totalProgressBar); + + // Fill sdBuffer + for (unsigned long currByte = 0; currByte < fileSize / 4; currByte += 128) { + myFile.read(sdBuffer, 512); + // Blink led + if (currByte % 2048 == 0) + blinkLED(); + + noInterrupts(); + for (int c = 0; c < 128; c++) { + // 0600 0EA0 + enable64MSB(); + // 0006 + word myWord = ((sdBuffer[(c * 4) + 1] & 0xFF) << 8) | (sdBuffer[(c * 4)] & 0xFF); + // Write command sequence + writeByteCommand_Flash2x8(0x0, 0xa0); + // Write current word + writeWord_Flash(currByte + c, myWord); + busyCheck2x8(currByte + c, myWord); + + enable64LSB(); + // A00E + myWord = ((sdBuffer[(c * 4) + 3] & 0xFF) << 8) | (sdBuffer[(c * 4) + 2] & 0xFF); + // Write command sequence + writeByteCommand_Flash2x8(0x0, 0xa0); + // Write current word + writeWord_Flash(currByte + c, myWord); + busyCheck2x8(currByte + c, myWord); + } + interrupts(); + // update progress bar + processedProgressBar += 512; + draw_progressbar(processedProgressBar, totalProgressBar); + } + + // Set data pins to input again + dataIn16(); + + // Close the file: + myFile.close(); + } +} + +void verifySIMM4x8() { + if (openVerifyFlashFile()) { + blank = 0; + word d = 0; + //Initialize progress bar + uint32_t processedProgressBar = 0; + uint32_t totalProgressBar = fileSize; + draw_progressbar(0, totalProgressBar); + + for (unsigned long currByte = 0; currByte < fileSize / 4; currByte += 128) { + //fill sdBuffer + myFile.read(sdBuffer, 512); + for (int c = 0; c < 128; c++) { + enable64MSB(); + word currWord = ((sdBuffer[d + 1] << 8) | sdBuffer[d]); + if (readWord_Flash(currByte + c) != currWord) { + blank++; + } + enable64LSB(); + currWord = ((sdBuffer[d + 3] << 8) | sdBuffer[d + 2]); + if (readWord_Flash(currByte + c) != currWord) { + blank++; + } + d += 4; + } + d = 0; + // Update progress bar + if (currByte % 128 == 0) { + processedProgressBar += 512; + draw_progressbar(processedProgressBar, totalProgressBar); + } + // Blink led + if (currByte % 25600 == 0) + blinkLED(); + } + + if (blank == 0) { + println_Msg(F("SIMM verified OK")); + display_Update(); + } else { + print_STR(error_STR, 0); + print_Msg(blank); + print_STR(_bytes_STR, 1); + print_Error(did_not_verify_STR); + } + // Close the file: + myFile.close(); + } +} + +void printSIMM4x8(int numBytes) { + /* + right_byte = short_val & 0xFF; + left_byte = ( short_val >> 8 ) & 0xFF + short_val = ( ( left_byte & 0xFF ) << 8 ) | ( right_byte & 0xFF ); + */ + + char buf[3]; + + for (int currByte = 0; currByte < numBytes / 4; currByte += 4) { + // 2 dwords per line + for (int c = 0; c < 2; c++) { + enable64MSB(); + word currWord = readWord_Flash(currByte + c); + + // Split word into two bytes + byte left_byte = currWord & 0xFF; + byte right_byte = (currWord >> 8) & 0xFF; + + sprintf(buf, "%.2X", left_byte); + // Now print the significant bits + print_Msg(buf); + + sprintf(buf, "%.2X", right_byte); + // Now print the significant bits + print_Msg(buf); + enable64LSB(); + currWord = readWord_Flash(currByte + c); + + // Split word into two bytes + left_byte = currWord & 0xFF; + right_byte = (currWord >> 8) & 0xFF; + + sprintf(buf, "%.2X", left_byte); + // Now print the significant bits + print_Msg(buf); + + sprintf(buf, "%.2X", right_byte); + // Now print the significant bits + print_Msg(buf); + } + println_Msg(""); + } + display_Update(); +} + +/****************************************** + SIMM 2x8bit flashrom functions +*****************************************/ + +void resetFlash2x8(uint32_t bank) { + // Set data pins to output + dataOut16(); + + // Reset command sequence + writeByteCommand_Flash2x8(bank, 0xf0); + + // Set data pins to input again + dataIn16(); + + delay(500); +} + +void idFlash2x8(uint32_t bank) { + // Set data pins to output + dataOut16(); + + // ID command sequence + writeByteCommand_Flash2x8(bank, 0x90); + + // Set data pins to input again + dataIn16(); + + // Read the two id bytes into a string + flashids[(bank * 2)] = (readWord_Flash((bank << 21) | 0) >> 8) << 8; + flashids[(bank * 2)] |= readWord_Flash((bank << 21) | 1) >> 8; + //sprintf(flashid_str, "%04X", flashid); + + // Read the two id bytes into a string + flashids[(bank * 2) + 1] = (readWord_Flash((bank << 21) | 0) & 0xFF) << 8; + flashids[(bank * 2) + 1] |= readWord_Flash((bank << 21) | 1) & 0xFF; + //sprintf(flashid_str2, "%04X", flashid2); +} + +// From eraseFlash29F032 +void eraseFlash2x8(uint32_t bank) { + // Set data pins to output + dataOut16(); + + // Erase command sequence + writeByteCommand_Flash2x8(bank, 0x80); + writeByteCommand_Flash2x8(bank, 0x10); + + // Set data pins to input again + dataIn16(); + + // Read the status register + word statusReg = readWord_Flash((bank << 21) | 0); + + // After a completed erase D7 and D15 will output 1 + while ((statusReg & 0x8080) != 0x8080) { + // Blink led + blinkLED(); + delay(100); + // Update Status + statusReg = readWord_Flash((bank << 21) | 0); + } +} + +// From busyCheck29F032 +int busyCheck2x8(uint32_t addr, word c) { + int ret = 0; + // Set data pins to input + dataIn16(); + + // Setting OE(PH1) LOW + PORTH &= ~(1 << 1); + // Setting WE(PH4) HIGH + PORTH |= (1 << 4); + NOP; + NOP; + + //When the Embedded Program algorithm is complete, the device outputs the datum programmed to D7 and D15 + for (;;) { + word d = readWord_Flash(addr); + if ((d & 0x8080) == (c & 0x8080)) { + break; + } + if ((d & 0x2020) == 0x2020) { + // From the datasheet: + // DQ 5 will indicate if the program or erase time has exceeded the specified limits (internal pulse count). + // Under these conditions DQ 5 will produce a “1”. + // This is a failure condition which indicates that the program or erase cycle was not successfully completed. + // Note : DQ 7 is rechecked even if DQ 5 = “1” because DQ 7 may change simultaneously with DQ 5 . + d = readWord_Flash(addr); + if ((d & 0x8080) == (c & 0x8080)) { + break; + } else { + ret = 1; + break; + } + } + } + + // Set data pins to output + dataOut16(); + + // Setting OE(PH1) HIGH + PORTH |= (1 << 1); + NOP; + NOP; + return ret; +} + +#endif diff --git a/Cart_Reader/OSCR.h b/Cart_Reader/OSCR.h index bbd2ebad..df27263f 100644 --- a/Cart_Reader/OSCR.h +++ b/Cart_Reader/OSCR.h @@ -268,6 +268,13 @@ enum CORES: uint8_t { # endif # ifdef ENABLE_VSMILE CORE_VSMILE, +# endif +# ifdef ENABLE_CPS3 + CORE_CPS3_CART, + CORE_CPS3_64SIMM, + CORE_CPS3_128SIMM, + CORE_CPS3_512SIMM, + CORE_CPS3_01SIMM, # endif CORE_MAX // Always last }; @@ -396,6 +403,9 @@ enum SYSTEM_MENU: uint8_t { # if defined(ENABLE_FLASH8) SYSTEM_MENU_FLASH, # endif +# if defined(ENABLE_CPS3) + SYSTEM_MENU_CPS3, +# endif # if defined(ENABLE_SELFTEST) SYSTEM_MENU_SELFTEST, # endif @@ -471,4 +481,4 @@ extern long configGetLong(const __FlashStringHelper* key, int onFail = 0); #include "ClockedSerial.h" -#endif /* OSCR_H_ */ \ No newline at end of file +#endif /* OSCR_H_ */ diff --git a/sd/cps3.txt b/sd/cps3.txt new file mode 100644 index 00000000..e22f2a2f --- /dev/null +++ b/sd/cps3.txt @@ -0,0 +1,92 @@ +Warzard (Japan).u2 +F8E2F0C6,1FEDB,868584838281808F,0000,0000,0,0000 + +Red Earth (Europe).u2 +02E0F336,1FEDB,868584838281808F,0000,0000,0,0000 + +Red Earth (Asia, NO CD).u2 +7A4F0851,00000,868584838281808F,0000,0000,0,0000 + +Street Fighter III New Generation (Japan).u2 +74205250,1FECB,B4B7B6B1B0B3B2BD,1FECC,D2D3,0,0000 + +Street Fighter III New Generation (Asia).u2 +CBD28DE7,1FECB,B4B7B6B1B0B3B2BD,1FECC,D2D3,0,0000 + +Street Fighter III New Generation (Europe).u2 +27699DDC,1FECB,B4B7B6B1B0B3B2BD,1FECC,D2D3,0,0000 + +Street Fighter III New Generation (USA).u2 +FB172A8E,1FECB,B4B7B6B1B0B3B2BD,1FECC,D2D3,0,0000 + +Street Fighter III New Generation (Hispanic).u2 +D2B3CD48,1FECB,B4B7B6B1B0B3B2BD,1FECC,D2D3,0,0000 + +Street Fighter III New Generation (Asia, NO CD, Set 1).u2 +CA2B715F,1FECB,B4B7B6B1B0B3B2BD,1FECC,D2D3,0,0000 + +Street Fighter III New Generation (Asia, NO CD, Set 2).u2 +73E32463,1FECB,B4B7B6B1B0B3B2BD,1FECC,D2D3,0,0000 + +Street Fighter III 2nd Impact Giant Attack (Japan).u2 +FAEA0A3E,1FECB,A9AAABACADAEAFA0,1FECC,BCBD,0,0000 + +Street Fighter III 2nd Impact Giant Attack (USA) +75DD72E0,1FECB,A9AAABACADAEAFA0,1FECC,BCBD,0,0000 + +Street Fighter III 2nd Impact Giant Attack (Hispanic).u2 +5C799526,1FECB,A9AAABACADAEAFA0,1FECC,BCBD,0,0000 + +Street Fighter III 2nd Impact Giant Attack (Asia, NO CD).u2 +FD297C0D,1FECB,A9AAABACADAEAFA0,1FECC,BCBD,0,0000 + +JoJo no Kimyou na Bouken (Japan).u2 +02778F60,1FECB,0C0F0E09080B0A05,1FECC,B4B5,0,0000 + +JoJo's Venture (Asia).u2 +789AA72A,1FECB,0C0F0E09080B0A05,1FECC,B4B5,0,0000 + +JoJo's Venture (Asia, NO CD).u2 +05B4F953,1FECB,0C0F0E09080B0A05,1FECC,B4B5,0,0000 + +JoJo's Venture (Europe).u2 +513E40EC,1FECB,0C0F0E09080B0A05,1FECC,B4B5,0,0000 + +JoJo's Venture (USA).u2 +8D40F7BE,1FECB,0C0F0E09080B0A05,1FECC,B4B5,0,0000 + +Street Fighter III 3rd Strike Fight for the Future (Japan).u2 +63F23D1F,1FECB,6063626564676669,1FECC,3031,0,0000 + +Street Fighter III 3rd Strike Fight for the Future (Japan, NO CD).u2 +1EDC6366,1FECB,6063626564676669,1FECC,3031,0,0000 + +Street Fighter III 3rd Strike Fight for the Future (Europe).u2 +30BBF293,1FECB,6063626564676669,1FECC,3031,0,0000 + +Street Fighter III 3rd Strike Fight for the Future (USA).u2 +ECC545C1,1FECB,6063626564676669,1FECC,3031,0,0000 + +JoJo no Kimyou na Bouken Mirai e no Isan (Japan).u2 +3085478C,1FECB,2B28292E2F2C2D22,1FECC,6B6A,0,0000 + +JoJo no Kimyou na Bouken Mirai e no Isan (Japan, NO CD).u2 +4DAB19F5,1FECB,2B28292E2F2C2D22,1FECC,6B6A,0,0000 + +JoJo's Bizarre Adventure (Europe).u2 +63CC8800,1FECB,2B28292E2F2C2D22,1FECC,6B6A,0,0000 + +JoJo's Bizarre Adventure (Europe, NO CD).u2 +1EE2D679,1FECB,2B28292E2F2C2D22,1FECC,6B6A,0,0000 + +UltraBIOS for custom SH2 AUTOSELECT v1.0 CD.u2 +4D938388,20733,B1B2B3B4B5B6B7B8,1FECC,BCBD,1,1FC5 + +UltraBIOS for custom SH2 AUTOSELECT v1.0 NOCD.u2 +30BDDDF1,20733,B1B2B3B4B5B6B7B8,1FECC,BCBD,1,1FC5 + +UltraBIOS for standard SH2 AUTOSELECT v1.0 CD.u2 +89DD398B,20733,0102030405060708,1FECC,0001,1,3089 + +UltraBIOS for standard SH2 AUTOSELECT v1.0 CD.u2 +F4F367F2,20733,0102030405060708,1FECC,0001,1,3089