mirror of
https://github.com/sanni/cartreader.git
synced 2024-12-30 15:01:53 +01:00
1631 lines
44 KiB
C++
1631 lines
44 KiB
C++
//******************************************
|
|
// CP System III Module
|
|
// Cartridge
|
|
// 32/64/128 Mbits SIMM
|
|
// Tested with HW5
|
|
// https://github.com/herzmx/CPS3-OSCR-Adapter
|
|
//******************************************
|
|
#if (defined(ENABLE_CPS3) && defined(ENABLE_FLASH8) && defined(ENABLE_FLASH16))
|
|
/******************************************
|
|
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
|