Move to Arduino IDE 2.0.0 (different auto formatting, no code changes)

This commit is contained in:
sanni 2022-10-13 09:49:03 +02:00
parent 6ddb206a63
commit 4badfff458
21 changed files with 4167 additions and 4106 deletions

View File

@ -34,9 +34,9 @@
// /C000(PH5) - CHIP 2 - SNES /WR
// /E000(PH6) - CHIP 3 - SNES /RD
byte COL[] = {8, 12, 16, 20, 24, 32};
byte collo = 0; // Lowest Entry
byte colhi = 5; // Highest Entry
byte COL[] = { 8, 12, 16, 20, 24, 32 };
byte collo = 0; // Lowest Entry
byte colhi = 5; // Highest Entry
byte colsize;
byte newcolsize;
@ -52,10 +52,9 @@ static const char colMenuItem1[] PROGMEM = "Select Cart";
static const char colMenuItem2[] PROGMEM = "Read ROM";
static const char colMenuItem3[] PROGMEM = "Set Size";
static const char colMenuItem4[] PROGMEM = "Reset";
static const char* const menuOptionsCOL[] PROGMEM = {colMenuItem1, colMenuItem2, colMenuItem3, colMenuItem4};
static const char* const menuOptionsCOL[] PROGMEM = { colMenuItem1, colMenuItem2, colMenuItem3, colMenuItem4 };
void setup_COL()
{
void setup_COL() {
// Set Address Pins to Output
// Colecovision uses A0-A14 [A15-A23 UNUSED]
//A0-A7
@ -67,10 +66,10 @@ void setup_COL()
// Set Control Pins to Output
// ---(PH0) ---(PH1) /8000(PH3) /A000(PH4) /C000(PH5) /E000(PH6)
DDRH |= (1 << 0) | (1 << 1) | (1 << 3) | (1 << 4) | (1 << 5) | (1 << 6);
DDRH |= (1 << 0) | (1 << 1) | (1 << 3) | (1 << 4) | (1 << 5) | (1 << 6);
// Set TIME(PJ0) to Output (UNUSED)
DDRJ |= (1 << 0);
DDRJ |= (1 << 0);
// Set Pins (D0-D7) to Input
DDRC = 0x00;
@ -84,8 +83,8 @@ void setup_COL()
// Set Unused Pins HIGH
PORTA = 0xFF;
PORTL = 0xFF; // A16-A23
PORTJ |= (1 << 0); // TIME(PJ0)
PORTL = 0xFF; // A16-A23
PORTJ |= (1 << 0); // TIME(PJ0)
checkStatus_COL();
strcpy(romName, "COLECO");
@ -93,13 +92,11 @@ void setup_COL()
mode = mode_COL;
}
void colMenu()
{
void colMenu() {
convertPgm(menuOptionsCOL, 4);
uint8_t mainMenu = question_box(F("COLECOVISION MENU"), menuOptions, 4, 0);
switch (mainMenu)
{
switch (mainMenu) {
case 0:
// Select Cart
setCart_COL();
@ -134,31 +131,29 @@ void colMenu()
// /C000(PH5) - CHIP 2
// /E000(PH6) - CHIP 3
uint8_t readData_COL(uint32_t addr)
{
uint8_t readData_COL(uint32_t addr) {
// SELECT ROM CHIP - PULL /CE LOW
uint8_t chipdecode = ((addr >> 13) & 0x3);
if (chipdecode == 3) // CHIP 3
PORTH &= ~(1 << 6); // /E000 LOW (ENABLE)
else if (chipdecode == 2) // CHIP 2
PORTH &= ~(1 << 5); // /C000 LOW (ENABLE)
else if (chipdecode == 1) // CHIP 1
PORTH &= ~(1 << 4); // /A000 LOW (ENABLE)
else // CHIP 0
PORTH &= ~(1 << 3); // /8000 LOW (ENABLE)
if (chipdecode == 3) // CHIP 3
PORTH &= ~(1 << 6); // /E000 LOW (ENABLE)
else if (chipdecode == 2) // CHIP 2
PORTH &= ~(1 << 5); // /C000 LOW (ENABLE)
else if (chipdecode == 1) // CHIP 1
PORTH &= ~(1 << 4); // /A000 LOW (ENABLE)
else // CHIP 0
PORTH &= ~(1 << 3); // /8000 LOW (ENABLE)
PORTF = addr & 0xFF; // A0-A7
PORTK = (addr >> 8) & 0xFF; // A8-A15
PORTF = addr & 0xFF; // A0-A7
PORTK = (addr >> 8) & 0xFF; // A8-A15
// LATCH ADDRESS - PULL /CE HIGH
PORTH |= (1 << 3) | (1 << 4) | (1 << 5) | (1 << 6); // ALL /CE HIGH (DISABLE)
PORTH |= (1 << 3) | (1 << 4) | (1 << 5) | (1 << 6); // ALL /CE HIGH (DISABLE)
uint8_t ret = PINC;
return ret;
}
void readSegment_COL(uint32_t startaddr, uint32_t endaddr)
{
void readSegment_COL(uint32_t startaddr, uint32_t endaddr) {
for (uint32_t addr = startaddr; addr < endaddr; addr += 512) {
for (int w = 0; w < 512; w++) {
uint8_t temp = readData_COL(addr + w);
@ -168,8 +163,7 @@ void readSegment_COL(uint32_t startaddr, uint32_t endaddr)
}
}
void readROM_COL()
{
void readROM_COL() {
strcpy(fileName, romName);
strcat(fileName, ".col");
@ -197,17 +191,17 @@ void readROM_COL()
// RESET ALL CS PINS HIGH (DISABLE)
PORTH |= (1 << 3) | (1 << 4) | (1 << 5) | (1 << 6);
readSegment_COL(0x8000, 0xA000); // 8K
readSegment_COL(0x8000, 0xA000); // 8K
if (colsize > 0) {
readSegment_COL(0xA000, 0xB000); // +4K = 12K
readSegment_COL(0xA000, 0xB000); // +4K = 12K
if (colsize > 1) {
readSegment_COL(0xB000, 0xC000); // +4K = 16K
readSegment_COL(0xB000, 0xC000); // +4K = 16K
if (colsize > 2) {
readSegment_COL(0xC000, 0xD000); // +4K = 20K
readSegment_COL(0xC000, 0xD000); // +4K = 20K
if (colsize > 3) {
readSegment_COL(0xD000, 0xE000); // +4K = 24K
readSegment_COL(0xD000, 0xE000); // +4K = 24K
if (colsize > 4) {
readSegment_COL(0xE000, 0x10000); // +8K = 32K
readSegment_COL(0xE000, 0x10000); // +8K = 32K
}
}
}
@ -231,8 +225,7 @@ void readROM_COL()
// ROM SIZE
//******************************************
void setROMSize_COL()
{
void setROMSize_COL() {
#if (defined(enable_OLED) || defined(enable_LCD))
display_Clear();
if (collo == colhi)
@ -256,7 +249,7 @@ void setROMSize_COL()
while (1) {
b = checkButton();
if (b == 2) { // Previous (doubleclick)
if (b == 2) { // Previous (doubleclick)
if (i == collo)
i = colhi;
else
@ -276,7 +269,7 @@ void setROMSize_COL()
#endif
display_Update();
}
if (b == 1) { // Next (press)
if (b == 1) { // Next (press)
if (i == colhi)
i = collo;
else
@ -296,12 +289,12 @@ void setROMSize_COL()
#endif
display_Update();
}
if (b == 3) { // Long Press - Execute (hold)
if (b == 3) { // Long Press - Execute (hold)
newcolsize = i;
break;
}
}
display.setCursor(0, 56); // Display selection at bottom
display.setCursor(0, 56); // Display selection at bottom
}
print_Msg(F("ROM SIZE "));
print_Msg(COL[newcolsize]);
@ -340,8 +333,7 @@ setrom:
colsize = newcolsize;
}
void checkStatus_COL()
{
void checkStatus_COL() {
EEPROM_readAnything(8, colsize);
if (colsize > 5) {
colsize = 0;
@ -404,12 +396,10 @@ void setCart_COL() {
while (1) {
if (myFile.curPosition() == 0) {
break;
}
else if (myFile.peek() == '\n') {
} else if (myFile.peek() == '\n') {
myFile.seekSet(myFile.curPosition() - 1);
break;
}
else {
} else {
myFile.seekSet(myFile.curPosition() - 1);
}
}
@ -451,9 +441,8 @@ void setCart_COL() {
// Remove leading 0 for single digit cart sizes
if (cartSize != 0) {
cartSize = cartSize * 10 + myFile.read() - 48;
}
else {
cartSize = cartSize * 10 + myFile.read() - 48;
} else {
cartSize = myFile.read() - 48;
}
@ -498,12 +487,10 @@ void setCart_COL() {
while (1) {
if (myFile.curPosition() == 0) {
break;
}
else if (myFile.peek() == '\n') {
} else if (myFile.peek() == '\n') {
myFile.seekSet(myFile.curPosition() - 1);
break;
}
else {
} else {
myFile.seekSet(myFile.curPosition() - 1);
}
}
@ -551,8 +538,7 @@ void setCart_COL() {
}
}
}
}
else {
} else {
print_Error(F("Database file not found"), true);
}
}

File diff suppressed because it is too large Load Diff

View File

@ -28,7 +28,7 @@ static const char flash8MenuItem4[] PROGMEM = "Write";
static const char flash8MenuItem5[] PROGMEM = "ID";
static const char flash8MenuItem6[] PROGMEM = "Print";
static const char flash8MenuItem7[] PROGMEM = "Reset";
static const char* const menuOptionsFLASH8[] PROGMEM = {flash8MenuItem1, flash8MenuItem2, flash8MenuItem3, flash8MenuItem4, flash8MenuItem5, flash8MenuItem6, flash8MenuItem7};
static const char* const menuOptionsFLASH8[] PROGMEM = { flash8MenuItem1, flash8MenuItem2, flash8MenuItem3, flash8MenuItem4, flash8MenuItem5, flash8MenuItem6, flash8MenuItem7 };
#ifdef enable_FLASH16
// Flash start menu
@ -36,7 +36,7 @@ static const char flashMenuItem1[] PROGMEM = "8bit Flash adapter";
static const char flashMenuItem2[] PROGMEM = "Eprom adapter";
static const char flashMenuItem3[] PROGMEM = "MX26L6420 adapter";
static const char flashMenuItem4[] PROGMEM = "Reset";
static const char* const menuOptionsFlash[] PROGMEM = {flashMenuItem1, flashMenuItem2, flashMenuItem3, flashMenuItem4};
static const char* const menuOptionsFlash[] PROGMEM = { flashMenuItem1, flashMenuItem2, flashMenuItem3, flashMenuItem4 };
// 16bit Flash menu items
static const char flash16MenuItem1[] PROGMEM = "Blankcheck";
@ -46,7 +46,7 @@ static const char flash16MenuItem4[] PROGMEM = "Write";
static const char flash16MenuItem5[] PROGMEM = "ID";
static const char flash16MenuItem6[] PROGMEM = "Print";
static const char flash16MenuItem7[] PROGMEM = "Reset";
static const char* const menuOptionsFLASH16[] PROGMEM = {flash16MenuItem1, flash16MenuItem2, flash16MenuItem3, flash16MenuItem4, flash16MenuItem5, flash16MenuItem6, flash16MenuItem7};
static const char* const menuOptionsFLASH16[] PROGMEM = { flash16MenuItem1, flash16MenuItem2, flash16MenuItem3, flash16MenuItem4, flash16MenuItem5, flash16MenuItem6, flash16MenuItem7 };
// Eprom menu items
static const char epromMenuItem1[] PROGMEM = "Blankcheck";
@ -55,7 +55,7 @@ static const char epromMenuItem3[] PROGMEM = "Write";
static const char epromMenuItem4[] PROGMEM = "Verify";
static const char epromMenuItem5[] PROGMEM = "Print";
static const char epromMenuItem6[] PROGMEM = "Reset";
static const char* const menuOptionsEprom[] PROGMEM = {epromMenuItem1, epromMenuItem2, epromMenuItem3, epromMenuItem4, epromMenuItem5, epromMenuItem6};
static const char* const menuOptionsEprom[] PROGMEM = { epromMenuItem1, epromMenuItem2, epromMenuItem3, epromMenuItem4, epromMenuItem5, epromMenuItem6 };
void flashMenu() {
// create menu with title and 3 options to choose from
@ -65,8 +65,7 @@ void flashMenu() {
flashSlot = question_box(F("Select adapter PCB"), menuOptions, 4, 0);
// wait for user choice to come back from the question box menu
switch (flashSlot)
{
switch (flashSlot) {
case 0:
display_Clear();
display_Update();
@ -74,14 +73,14 @@ void flashMenu() {
setup_Flash8();
id_Flash8();
wait();
mode = mode_FLASH8;
mode = mode_FLASH8;
break;
case 1:
display_Clear();
display_Update();
setup_Eprom();
mode = mode_EPROM;
mode = mode_EPROM;
break;
case 2:
@ -90,7 +89,7 @@ void flashMenu() {
setup_Flash16();
id_Flash16();
wait();
mode = mode_FLASH16;
mode = mode_FLASH16;
break;
case 3:
@ -108,8 +107,7 @@ void flashromMenu8() {
mainMenu = question_box(F("Flashrom Writer 8"), menuOptions, 7, 0);
// wait for user choice to come back from the question box menu
switch (mainMenu)
{
switch (mainMenu) {
case 0:
display_Clear();
println_Msg(F("Blankcheck"));
@ -159,16 +157,12 @@ void flashromMenu8() {
writeFlash29F1601();
else if ((strcmp(flashid, "C2F1") == 0) || (strcmp(flashid, "C2F9") == 0))
writeFlash29F1610();
else if ((strcmp(flashid, "C2C4") == 0) || (strcmp(flashid, "C249") == 0) ||
(strcmp(flashid, "C2A7") == 0) || (strcmp(flashid, "C2A8") == 0) ||
(strcmp(flashid, "C2C9") == 0) || (strcmp(flashid, "C2CB") == 0))
else if ((strcmp(flashid, "C2C4") == 0) || (strcmp(flashid, "C249") == 0) || (strcmp(flashid, "C2A7") == 0) || (strcmp(flashid, "C2A8") == 0) || (strcmp(flashid, "C2C9") == 0) || (strcmp(flashid, "C2CB") == 0))
writeFlash29LV640();
else if (strcmp(flashid, "017E") == 0) {
// sector size, write buffer size
writeFlash29GL(sectorSize, bufferSize);
}
else if ((strcmp(flashid, "0458") == 0) || (strcmp(flashid, "0158") == 0) ||
(strcmp(flashid, "01AB") == 0))
} else if ((strcmp(flashid, "0458") == 0) || (strcmp(flashid, "0158") == 0) || (strcmp(flashid, "01AB") == 0))
writeFlash29F800();
break;
@ -242,8 +236,7 @@ void flashromMenu16() {
mainMenu = question_box(F("Flashrom Writer 16"), menuOptions, 7, 0);
// wait for user choice to come back from the question box menu
switch (mainMenu)
{
switch (mainMenu) {
case 0:
display_Clear();
println_Msg(F("Blankcheck"));
@ -279,11 +272,9 @@ void flashromMenu16() {
time = millis();
if (strcmp(flashid, "C2F3") == 0) {
writeFlash16_29F1601();
}
else if ((strcmp(flashid, "C2C4") == 0) || (strcmp(flashid, "C249") == 0) || (strcmp(flashid, "C2A7") == 0) || (strcmp(flashid, "C2A8") == 0) || (strcmp(flashid, "C2C9") == 0) || (strcmp(flashid, "C2CB") == 0) || (strcmp(flashid, "C2FC") == 0)) {
} else if ((strcmp(flashid, "C2C4") == 0) || (strcmp(flashid, "C249") == 0) || (strcmp(flashid, "C2A7") == 0) || (strcmp(flashid, "C2A8") == 0) || (strcmp(flashid, "C2C9") == 0) || (strcmp(flashid, "C2CB") == 0) || (strcmp(flashid, "C2FC") == 0)) {
writeFlash16_29LV640();
}
else {
} else {
writeFlash16();
}
delay(100);
@ -338,8 +329,7 @@ void epromMenu() {
mainMenu = question_box(F("Eprom Writer"), menuOptions, 6, 0);
// wait for user choice to come back from the question box menu
switch (mainMenu)
{
switch (mainMenu) {
case 0:
display_Clear();
println_Msg(F("Blankcheck"));
@ -419,87 +409,71 @@ idtheflash:
println_Msg(F("MX29F1610 detected"));
flashSize = 2097152;
flashromType = 2;
}
else if (strcmp(flashid, "C2F3") == 0) {
} else if (strcmp(flashid, "C2F3") == 0) {
println_Msg(F("MX29F1601 detected"));
flashSize = 2097152;
flashromType = 2;
}
else if (strcmp(flashid, "C2F9") == 0) {
} else if (strcmp(flashid, "C2F9") == 0) {
println_Msg(F("MX29L3211 detected"));
println_Msg(F("ATTENTION 3.3V"));
flashSize = 4194304;
flashromType = 2;
}
else if ((strcmp(flashid, "C2C4") == 0) || (strcmp(flashid, "C249") == 0)) {
} else if ((strcmp(flashid, "C2C4") == 0) || (strcmp(flashid, "C249") == 0)) {
println_Msg(F("MX29LV160 detected"));
println_Msg(F("ATTENTION 3.3V"));
flashSize = 2097152;
flashromType = 2;
}
else if ((strcmp(flashid, "C2A7") == 0) || (strcmp(flashid, "C2A8") == 0)) {
} else if ((strcmp(flashid, "C2A7") == 0) || (strcmp(flashid, "C2A8") == 0)) {
println_Msg(F("MX29LV320 detected"));
println_Msg(F("ATTENTION 3.3V"));
flashSize = 4194304;
flashromType = 2;
}
else if ((strcmp(flashid, "C2C9") == 0) || (strcmp(flashid, "C2CB") == 0)) {
} else if ((strcmp(flashid, "C2C9") == 0) || (strcmp(flashid, "C2CB") == 0)) {
println_Msg(F("MX29LV640 detected"));
println_Msg(F("ATTENTION 3.3V"));
flashSize = 8388608;
flashromType = 2;
}
else if (strcmp(flashid, "0141") == 0) {
} else if (strcmp(flashid, "0141") == 0) {
println_Msg(F("AM29F032B detected"));
flashSize = 4194304;
flashromType = 1;
}
else if (strcmp(flashid, "01AD") == 0) {
} else if (strcmp(flashid, "01AD") == 0) {
println_Msg(F("AM29F016B detected"));
flashSize = 2097152;
flashromType = 1;
}
else if (strcmp(flashid, "20AD") == 0) {
} else if (strcmp(flashid, "20AD") == 0) {
println_Msg(F("AM29F016D detected"));
flashSize = 2097152;
flashromType = 1;
}
else if (strcmp(flashid, "04AD") == 0) {
} else if (strcmp(flashid, "04AD") == 0) {
println_Msg(F("AM29F016D detected"));
flashSize = 2097152;
flashromType = 1;
}
else if (strcmp(flashid, "04D4") == 0) {
} else if (strcmp(flashid, "04D4") == 0) {
println_Msg(F("MBM29F033C detected"));
flashSize = 4194304;
flashromType = 1;
}
else if (strcmp(flashid, "04D5") == 0) {
} else if (strcmp(flashid, "04D5") == 0) {
println_Msg(F("MBM29F080C detected"));
flashSize = 1048576;
flashromType = 1;
}
else if (strcmp(flashid, "0458") == 0) {
} else if (strcmp(flashid, "0458") == 0) {
println_Msg(F("MBM29F800BA detected"));
flashSize = 1048576;
flashromType = 2;
}
else if (strcmp(flashid, "01AB") == 0) {
} else if (strcmp(flashid, "01AB") == 0) {
println_Msg(F("AM29F400AB detected"));
flashSize = 131072 * 4;
flashromType = 2;
}
else if (strcmp(flashid, "0158") == 0) {
} else if (strcmp(flashid, "0158") == 0) {
println_Msg(F("AM29F800BB detected"));
flashSize = 1048576;
flashromType = 2;
}
else if (strcmp(flashid, "01A3") == 0) {
} else if (strcmp(flashid, "01A3") == 0) {
println_Msg(F("AM29LV033C detected"));
flashSize = 131072 * 32;
flashromType = 1;
}
else if (strcmp(flashid, "017E") == 0) {
} else if (strcmp(flashid, "017E") == 0) {
// S29GL032M
if (readByte_Flash(28) == 0x1A) {
println_Msg(F("S29GL032M detected"));
@ -523,8 +497,7 @@ idtheflash:
}
println_Msg(F("ATTENTION 3.3V"));
flashromType = 2;
}
else if (strcmp(flashid, "B088") == 0) {
} else if (strcmp(flashid, "B088") == 0) {
// LH28F016SUT
println_Msg(F("LH28F016SUT detected"));
println_Msg(F("ATTENTION 3/5 setting"));
@ -532,10 +505,7 @@ idtheflash:
sectorSize = 65536;
bufferSize = 256;
flashromType = 3;
}
else if ((strcmp(flashid, "8916") == 0) ||
(strcmp(flashid, "8917") == 0) ||
(strcmp(flashid, "8918") == 0)) {
} else if ((strcmp(flashid, "8916") == 0) || (strcmp(flashid, "8917") == 0) || (strcmp(flashid, "8918") == 0)) {
// E28FXXXJ3A
print_Msg(F("E28F"));
@ -558,15 +528,13 @@ idtheflash:
sectorSize = 131072;
bufferSize = 32;
flashromType = 3;
}
else if (secondID == 1) {
} else if (secondID == 1) {
// Read ID a second time using a different command (type 1 flashrom)
resetFlash8();
idFlash29F032();
secondID = 2;
goto idtheflash;
}
else if (secondID == 2) {
} else if (secondID == 2) {
// Backup first ID read-out
strncpy(vendorID, flashid, 5);
@ -575,8 +543,7 @@ idtheflash:
idFlash29F1610();
secondID = 0;
goto idtheflash;
}
else {
} else {
// ID not found
display_Clear();
println_Msg(F("Flashrom Writer 8bit"));
@ -624,43 +591,36 @@ void id_Flash16() {
println_Msg("");
flashSize = 2097152;
flashromType = 2;
}
else if (strcmp(flashid, "C2F3") == 0) {
} else if (strcmp(flashid, "C2F3") == 0) {
println_Msg(F("MX29F1601 detected"));
flashSize = 2097152;
flashromType = 2;
}
else if (strcmp(flashid, "C2F9") == 0) {
} else if (strcmp(flashid, "C2F9") == 0) {
println_Msg(F("MX29L3211 detected"));
println_Msg(F("ATTENTION 3.3V"));
flashSize = 4194304;
flashromType = 2;
}
else if ((strcmp(flashid, "C2C4") == 0) || (strcmp(flashid, "C249") == 0)) {
} else if ((strcmp(flashid, "C2C4") == 0) || (strcmp(flashid, "C249") == 0)) {
println_Msg(F("MX29LV160 detected"));
println_Msg(F("ATTENTION 3.3V"));
flashSize = 2097152;
flashromType = 2;
}
else if ((strcmp(flashid, "C2A7") == 0) || (strcmp(flashid, "C2A8") == 0)) {
} else if ((strcmp(flashid, "C2A7") == 0) || (strcmp(flashid, "C2A8") == 0)) {
println_Msg(F("MX29LV320 detected"));
println_Msg(F("ATTENTION 3.3V"));
flashSize = 4194304;
flashromType = 2;
}
else if ((strcmp(flashid, "C2C9") == 0) || (strcmp(flashid, "C2CB") == 0)) {
} else if ((strcmp(flashid, "C2C9") == 0) || (strcmp(flashid, "C2CB") == 0)) {
println_Msg(F("MX29LV640 detected"));
println_Msg(F("ATTENTION 3.3V"));
flashSize = 8388608;
flashromType = 2;
}
else if (strcmp(flashid, "C2FC") == 0) {
} else if (strcmp(flashid, "C2FC") == 0) {
println_Msg(F("MX26L6420 detected"));
println_Msg(F("ATTENTION 3.3V"));
flashSize = 8388608;
flashromType = 2;
}
else {
} else {
print_Error(F("Unknown flashrom"), true);
println_Msg("");
}
@ -683,7 +643,7 @@ void setup_Flash8() {
DDRL = 0xFF;
// Set Control Pins to Output RST(PH0) OE(PH1) OE_SNS(PH3) WE(PH4) WE_SNS(PH5) CE(PH6)
DDRH |= (1 << 0) | (1 << 1) | (1 << 3) | (1 << 4) | (1 << 5) | (1 << 6);
DDRH |= (1 << 0) | (1 << 1) | (1 << 3) | (1 << 4) | (1 << 5) | (1 << 6);
// Setting RST(PH0) OE(PH1) OE_SNS(PH3) WE(PH4) WE_SNS(PH5) HIGH
PORTH |= (1 << 0) | (1 << 1) | (1 << 3) | (1 << 4) | (1 << 5);
// Setting CE(PH6) LOW
@ -819,10 +779,9 @@ void writeByte_Flash(unsigned long myAddress, byte myData) {
if (!(((myAddress >> 16) & 0xFF) & 0x40)) {
// if PL6 is 0 set PL7 to 1
PORTL |= (1 << 7);
}
else if (((myAddress >> 16) & 0xFF) & 0x40) {
} else if (((myAddress >> 16) & 0xFF) & 0x40) {
// if PL6 is 1 set PL7 to 0
PORTL &= ~ (1 << 7);
PORTL &= ~(1 << 7);
}
// Switch SNES BA6(PL6) to HIGH to disable SRAM
PORTL |= (1 << 6);
@ -833,19 +792,34 @@ void writeByte_Flash(unsigned long myAddress, byte myData) {
// Arduino running at 16Mhz -> one nop = 62.5ns
// Wait till output is stable
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");
__asm__("nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t");
// Switch WE(PH4) WE_SNS(PH5) to LOW
PORTH &= ~((1 << 4) | (1 << 5));
// Leave WE low for at least 60ns
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");
__asm__("nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t");
// Switch WE(PH4) WE_SNS(PH5) to HIGH
PORTH |= (1 << 4) | (1 << 5);
// Leave WE high for at least 50ns
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");
__asm__("nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t");
}
byte readByte_Flash(unsigned long myAddress) {
@ -889,29 +863,43 @@ byte readByte_Flash(unsigned long myAddress) {
if (!(((myAddress >> 16) & 0xFF) & 0x40)) {
// if PL6 is 0 set PL7 to 1
PORTL |= (1 << 7);
}
else if (((myAddress >> 16) & 0xFF) & 0x40) {
} else if (((myAddress >> 16) & 0xFF) & 0x40) {
// if PL6 is 1 set PL7 to 0
PORTL &= ~ (1 << 7);
PORTL &= ~(1 << 7);
}
// Switch SNES BA6(PL6) to HIGH to disable SRAM
PORTL |= (1 << 6);
}
// Arduino running at 16Mhz -> one nop = 62.5ns
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");
__asm__("nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t");
// Setting OE(PH1) OE_SNS(PH3) LOW
PORTH &= ~((1 << 1) | (1 << 3));
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");
__asm__("nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t");
// Read
byte tempByte = PINC;
// Setting OE(PH1) OE_SNS(PH3) HIGH
PORTH |= (1 << 1) | (1 << 3);
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");
__asm__("nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t");
return tempByte;
}
@ -932,13 +920,23 @@ void writeWord_Flash(unsigned long myAddress, word myData) {
PORTH &= ~(1 << 4);
// Leave WE low for at least 60ns
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");
__asm__("nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t");
// Switch WE(PH4) to HIGH
PORTH |= (1 << 4);
// Leave WE high for at least 50ns
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");
__asm__("nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t");
}
word readWord_Flash(unsigned long myAddress) {
@ -952,16 +950,26 @@ word readWord_Flash(unsigned long myAddress) {
// Setting OE(PH1) LOW
PORTH &= ~(1 << 1);
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");
__asm__("nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t");
// Read
word tempWord = ( ( PINA & 0xFF ) << 8 ) | ( PINC & 0xFF );
word tempWord = ((PINA & 0xFF) << 8) | (PINC & 0xFF);
__asm__("nop\n\t");
// Setting OE(PH1) HIGH
PORTH |= (1 << 1);
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");
__asm__("nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t");
return tempWord;
}
@ -1104,8 +1112,7 @@ void writeFlash29F032() {
// Close the file:
myFile.close();
}
else {
} else {
println_Msg(F("Can't open file"));
display_Update();
}
@ -1119,7 +1126,7 @@ int busyCheck29F032(uint32_t addr, byte c) {
// 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);
PORTH |= (1 << 4) | (1 << 5);
//When the Embedded Program algorithm is complete, the device outputs the datum programmed to D7
for (;;) {
@ -1217,8 +1224,7 @@ void writeFlash29F1610() {
// Close the file:
myFile.close();
}
else {
} else {
println_Msg(F("Can't open file on SD"));
display_Update();
}
@ -1277,8 +1283,7 @@ void writeFlash29F1601() {
// Close the file:
myFile.close();
}
else {
} else {
println_Msg(F("Can't open file on SD"));
display_Update();
}
@ -1406,8 +1411,7 @@ void writeFlash29LV640() {
dataIn8();
// Close the file:
myFile.close();
}
else {
} else {
println_Msg(F("Can't open file on SD"));
display_Update();
}
@ -1474,8 +1478,7 @@ void writeFlash29GL(unsigned long sectorSize, byte bufferSize) {
dataIn8();
// Close the file:
myFile.close();
}
else {
} else {
println_Msg(F("Can't open file on SD"));
display_Update();
}
@ -1524,8 +1527,7 @@ void writeFlash29F800() {
// Close the file:
myFile.close();
}
else {
} else {
println_Msg(F("Can't open file on SD"));
display_Update();
}
@ -1562,14 +1564,14 @@ uint8_t statusFlash28FXXX() {
void eraseFlash28FXXX() {
// only can erase block by block
for (uint32_t ba = 0; ba < flashSize; ba += sectorSize)
{
for (uint32_t ba = 0; ba < flashSize; ba += sectorSize) {
dataOut();
writeByte_Flash(ba, 0x20);
writeByte_Flash(ba, 0xd0);
dataIn8();
while ((readByte_Flash(ba) & 0x80) == 0x00);
while ((readByte_Flash(ba) & 0x80) == 0x00)
;
// blink LED
blinkLED();
@ -1586,15 +1588,12 @@ void writeFlash28FXXX() {
if (myFile.open(filePath, O_READ)) {
if ((strcmp(flashid, "B088") == 0))
writeFlashLH28F0XX();
else if ((strcmp(flashid, "8916") == 0) ||
(strcmp(flashid, "8917") == 0) ||
(strcmp(flashid, "8918") == 0)) {
else if ((strcmp(flashid, "8916") == 0) || (strcmp(flashid, "8917") == 0) || (strcmp(flashid, "8918") == 0)) {
writeFlashE28FXXXJ3A();
}
myFile.close();
}
else {
} else {
println_Msg(F("Can't open file on SD"));
display_Update();
}
@ -1627,7 +1626,8 @@ void writeFlashE28FXXXJ3A() {
// waiting for buffer available
dataIn8();
while ((readByte_Flash(block_addr) & 0x80) == 0x00);
while ((readByte_Flash(block_addr) & 0x80) == 0x00)
;
dataOut();
// set write byte count
@ -1642,7 +1642,8 @@ void writeFlashE28FXXXJ3A() {
// waiting for finishing
dataIn8();
while ((readByte_Flash(block_addr) & 0x80) == 0x00);
while ((readByte_Flash(block_addr) & 0x80) == 0x00)
;
}
}
@ -1667,20 +1668,21 @@ void writeFlashLH28F0XX() {
// sequence load to page
dataOut();
writeByte_Flash(0x0, 0xe0);
writeByte_Flash(0x0, bufferSize - 1); // BCL
writeByte_Flash(0x0, 0x00); // BCH should be 0x00
writeByte_Flash(0x0, bufferSize - 1); // BCL
writeByte_Flash(0x0, 0x00); // BCH should be 0x00
for (uint32_t d = 0; d < bufferSize; d++)
writeByte_Flash(d, sdBuffer[c + d]);
// start flashing page
writeByte_Flash(0x0, 0x0c);
writeByte_Flash(0x0, bufferSize - 1); // BCL
writeByte_Flash(currByte + c, 0x00); // BCH should be 0x00
writeByte_Flash(0x0, bufferSize - 1); // BCL
writeByte_Flash(currByte + c, 0x00); // BCH should be 0x00
// waiting for finishing
dataIn8();
while ((readByte_Flash(currByte + c) & 0x80) == 0x00);
while ((readByte_Flash(currByte + c) & 0x80) == 0x00)
;
}
}
@ -1705,8 +1707,7 @@ void blankcheck_Flash() {
if (blank) {
println_Msg(F("Flashrom is empty"));
display_Update();
}
else {
} else {
print_Error(F("Error: Not blank"), false);
}
}
@ -1735,8 +1736,7 @@ void verifyFlash() {
if (blank == 0) {
println_Msg(F("Flashrom verified OK"));
display_Update();
}
else {
} else {
print_Msg(F("Error: "));
print_Msg(blank);
println_Msg(F(" bytes "));
@ -1744,8 +1744,7 @@ void verifyFlash() {
}
// Close the file:
myFile.close();
}
else {
} else {
println_Msg(F("Can't open file on SD"));
display_Update();
}
@ -1793,7 +1792,7 @@ void printFlash(int numBytes) {
for (int currByte = 0; currByte < numBytes; currByte += 10) {
for (int c = 0; c < 10; c++) {
itoa (readByte_Flash(currByte + c), myBuffer, 16);
itoa(readByte_Flash(currByte + c), myBuffer, 16);
for (int i = 0; i < 2 - strlen(myBuffer); i++) {
print_Msg(F("0"));
}
@ -1869,7 +1868,7 @@ void writeFlash16() {
// Write one full page at a time
for (byte c = 0; c < 64; c++) {
word currWord = ( ( sdBuffer[d + 1] & 0xFF ) << 8 ) | ( sdBuffer[d] & 0xFF );
word currWord = ((sdBuffer[d + 1] & 0xFF) << 8) | (sdBuffer[d] & 0xFF);
writeWord_Flash(currByte + c, currWord);
d += 2;
}
@ -1884,8 +1883,7 @@ void writeFlash16() {
// Close the file:
myFile.close();
}
else {
} else {
println_Msg(F("Can't open file on SD."));
display_Update();
}
@ -1928,7 +1926,7 @@ void writeFlash16_29F1601() {
// Write one full page at a time
for (byte c = 0; c < 64; c++) {
word currWord = ( ( sdBuffer[d + 1] & 0xFF ) << 8 ) | ( sdBuffer[d] & 0xFF );
word currWord = ((sdBuffer[d + 1] & 0xFF) << 8) | (sdBuffer[d] & 0xFF);
writeWord_Flash(currByte + c, currWord);
if (c == 63) {
@ -1948,8 +1946,7 @@ void writeFlash16_29F1601() {
// Close the file:
myFile.close();
}
else {
} else {
println_Msg(F("Can't open file on SD."));
display_Update();
}
@ -2021,8 +2018,7 @@ void blankcheck16() {
if (blank) {
println_Msg(F("Flashrom is empty."));
display_Update();
}
else {
} else {
print_Error(F("Error: Not blank"), false);
}
}
@ -2057,8 +2053,7 @@ void verifyFlash16() {
if (blank == 0) {
println_Msg(F("Flashrom verified OK"));
display_Update();
}
else {
} else {
println_Msg(F("Verification ERROR!"));
print_Msg(blank);
print_Error(F("B did not verify."), false);
@ -2066,8 +2061,7 @@ void verifyFlash16() {
}
// Close the file:
myFile.close();
}
else {
} else {
println_Msg(F("Can't open file on SD."));
display_Update();
}
@ -2097,7 +2091,8 @@ void readFlash16() {
if (!myFile.open(fileName, O_RDWR | O_CREAT)) {
println_Msg(F("Can't create file on SD."));
display_Update();
while (1);
while (1)
;
}
word d = 0;
for (unsigned long currByte = 0; currByte < flashSize / 2; currByte += 256) {
@ -2105,7 +2100,7 @@ void readFlash16() {
word currWord = readWord_Flash(currByte + c);
// Split word into two bytes
// Right
sdBuffer[d + 1] = (( currWord >> 8 ) & 0xFF);
sdBuffer[d + 1] = ((currWord >> 8) & 0xFF);
// Left
sdBuffer[d] = (currWord & 0xFF);
d += 2;
@ -2136,17 +2131,17 @@ void printFlash16(int numBytes) {
// Split word into two bytes
byte left_byte = currWord & 0xFF;
byte right_byte = ( currWord >> 8 ) & 0xFF;
byte right_byte = (currWord >> 8) & 0xFF;
sprintf (buf, "%x", left_byte);
sprintf(buf, "%x", left_byte);
for (int i = 0; i < 2 - strlen(buf); i++) {
print_Msg(F("0"));
}
// Now print the significant bits
print_Msg(buf);
sprintf (buf, "%x", right_byte);
sprintf(buf, "%x", right_byte);
for (int i = 0; i < 2 - strlen(buf); i++) {
print_Msg(F("0"));
}
@ -2225,7 +2220,7 @@ void writeFlash16_29LV640() {
writeWord_Flash(0x5555, 0xa0);
// Write current word
word myWord = ( ( sdBuffer[d + 1] & 0xFF ) << 8 ) | ( sdBuffer[d] & 0xFF );
word myWord = ((sdBuffer[d + 1] & 0xFF) << 8) | (sdBuffer[d] & 0xFF);
writeWord_Flash(currWord + c, myWord);
d += 2;
// Check if write is complete
@ -2238,8 +2233,7 @@ void writeFlash16_29LV640() {
// Close the file:
myFile.close();
}
else {
} else {
println_Msg(F("Can't open file on SD."));
display_Update();
}
@ -2291,7 +2285,10 @@ word writeWord_Eprom(unsigned long myAddress, word myData) {
DDRA = 0x00;
// Arduino running at 16Mhz -> one nop = 62.5ns
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t");
__asm__("nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t");
// Setting CE(PH6) LOW
PORTH &= ~(1 << 6);
@ -2300,15 +2297,20 @@ word writeWord_Eprom(unsigned long myAddress, word myData) {
delayMicroseconds(3);
// Read
word tempWord = ( ( PINA & 0xFF ) << 8 ) | ( PINC & 0xFF );
word tempWord = ((PINA & 0xFF) << 8) | (PINC & 0xFF);
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t");
__asm__("nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t");
// Setting CE(PH6) HIGH
PORTH |= (1 << 6);
// Delay 130ns for Chip Enable High to Output Hi-Z
__asm__("nop\n\t""nop\n\t""nop\n\t");
__asm__("nop\n\t"
"nop\n\t"
"nop\n\t");
return tempWord;
}
@ -2329,10 +2331,15 @@ word readWord_Eprom(unsigned long myAddress) {
PORTH &= ~(1 << 6);
// Delay for 100ns for Address Valid/Chip Enable Low to Output Valid
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");
__asm__("nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t");
// Read
word tempWord = ( ( PINA & 0xFF ) << 8 ) | ( PINC & 0xFF );
word tempWord = ((PINA & 0xFF) << 8) | (PINC & 0xFF);
// Setting CE(PH6) HIGH
PORTH |= (1 << 6);
@ -2354,8 +2361,7 @@ void blankcheck_Eprom() {
if (blank) {
println_Msg(F("Flashrom is empty."));
display_Update();
}
else {
} else {
print_Error(F("Error: Not blank"), false);
}
}
@ -2384,7 +2390,8 @@ void read_Eprom() {
if (!myFile.open(fileName, O_RDWR | O_CREAT)) {
println_Msg(F("Can't create file on SD."));
display_Update();
while (1);
while (1)
;
}
word d = 0;
for (unsigned long currWord = 0; currWord < flashSize / 2; currWord += 256) {
@ -2392,7 +2399,7 @@ void read_Eprom() {
word myWord = readWord_Eprom(currWord + c);
// Split word into two bytes
// Right
sdBuffer[d + 1] = ((myWord >> 8 ) & 0xFF);
sdBuffer[d + 1] = ((myWord >> 8) & 0xFF);
// Left
sdBuffer[d] = (myWord & 0xFF);
d += 2;
@ -2437,7 +2444,7 @@ void write_Eprom() {
// Work through SD buffer
for (int c = 0; c < 256; c++) {
word checkWord;
word myWord = ( ( sdBuffer[d + 1] & 0xFF ) << 8 ) | ( sdBuffer[d] & 0xFF );
word myWord = ((sdBuffer[d + 1] & 0xFF) << 8) | (sdBuffer[d] & 0xFF);
// Error counter
byte n = 0;
@ -2457,15 +2464,13 @@ void write_Eprom() {
print_Error(F("Press button to reset"), true);
}
n++;
}
while (checkWord != myWord);
} while (checkWord != myWord);
d += 2;
}
}
// Close the file:
myFile.close();
}
else {
} else {
println_Msg(F("Can't open file on SD."));
display_Update();
}
@ -2501,8 +2506,7 @@ void verify_Eprom() {
if (blank == 0) {
println_Msg(F("Eprom verified OK"));
display_Update();
}
else {
} else {
println_Msg(F("Verification ERROR!"));
print_Msg(blank);
print_Error(F(" words did not verify."), false);
@ -2510,8 +2514,7 @@ void verify_Eprom() {
}
// Close the file:
myFile.close();
}
else {
} else {
println_Msg(F("Can't open file on SD."));
display_Update();
}
@ -2527,17 +2530,17 @@ void print_Eprom(int numBytes) {
// Split word into two bytes
byte left_byte = currWord & 0xFF;
byte right_byte = ( currWord >> 8 ) & 0xFF;
byte right_byte = (currWord >> 8) & 0xFF;
sprintf (buf, "%x", left_byte);
sprintf(buf, "%x", left_byte);
for (int i = 0; i < 2 - strlen(buf); i++) {
print_Msg(F("0"));
}
// Now print the significant bits
print_Msg(buf);
sprintf (buf, "%x", right_byte);
sprintf(buf, "%x", right_byte);
for (int i = 0; i < 2 - strlen(buf); i++) {
print_Msg(F("0"));
}

View File

@ -20,14 +20,14 @@ static const char gbxMenuItem2[] PROGMEM = "GB Advance (3V)";
static const char gbxMenuItem3[] PROGMEM = "Flash GBC Cart";
static const char gbxMenuItem4[] PROGMEM = "NPower GB Memory";
static const char gbxMenuItem5[] PROGMEM = "Reset";
static const char* const menuOptionsGBx[] PROGMEM = {gbxMenuItem1, gbxMenuItem2, gbxMenuItem3, gbxMenuItem4, gbxMenuItem5};
static const char* const menuOptionsGBx[] PROGMEM = { gbxMenuItem1, gbxMenuItem2, gbxMenuItem3, gbxMenuItem4, gbxMenuItem5 };
// GB menu items
static const char GBMenuItem1[] PROGMEM = "Read ROM";
static const char GBMenuItem2[] PROGMEM = "Read Save";
static const char GBMenuItem3[] PROGMEM = "Write Save";
static const char GBMenuItem4[] PROGMEM = "Reset";
static const char* const menuOptionsGB[] PROGMEM = {GBMenuItem1, GBMenuItem2, GBMenuItem3, GBMenuItem4};
static const char* const menuOptionsGB[] PROGMEM = { GBMenuItem1, GBMenuItem2, GBMenuItem3, GBMenuItem4 };
// GB Flash items
static const char GBFlashItem1[] PROGMEM = "29F Cart (MBC3)";
@ -37,7 +37,7 @@ static const char GBFlashItem4[] PROGMEM = "CFI Cart";
static const char GBFlashItem5[] PROGMEM = "CFI Cart and Save";
static const char GBFlashItem6[] PROGMEM = "GB Smart";
static const char GBFlashItem7[] PROGMEM = "Reset";
static const char* const menuOptionsGBFlash[] PROGMEM = {GBFlashItem1, GBFlashItem2, GBFlashItem3, GBFlashItem4, GBFlashItem5, GBFlashItem6, GBFlashItem7};
static const char* const menuOptionsGBFlash[] PROGMEM = { GBFlashItem1, GBFlashItem2, GBFlashItem3, GBFlashItem4, GBFlashItem5, GBFlashItem6, GBFlashItem7 };
// Start menu for both GB and GBA
void gbxMenu() {
@ -48,20 +48,19 @@ void gbxMenu() {
gbType = question_box(F("Select Game Boy"), menuOptions, 5, 0);
// wait for user choice to come back from the question box menu
switch (gbType)
{
switch (gbType) {
case 0:
display_Clear();
display_Update();
setup_GB();
mode = mode_GB;
mode = mode_GB;
break;
case 1:
display_Clear();
display_Update();
setup_GBA();
mode = mode_GBA;
mode = mode_GBA;
break;
case 2:
@ -72,14 +71,13 @@ void gbxMenu() {
gbFlash = question_box(F("Select type"), menuOptions, 7, 0);
// wait for user choice to come back from the question box menu
switch (gbFlash)
{
switch (gbFlash) {
case 0:
//Flash MBC3
display_Clear();
display_Update();
setup_GB();
mode = mode_GB;
mode = mode_GB;
// Change working dir to root
sd.chdir("/");
@ -97,7 +95,7 @@ void gbxMenu() {
display_Clear();
display_Update();
setup_GB();
mode = mode_GB;
mode = mode_GB;
// Change working dir to root
sd.chdir("/");
@ -115,7 +113,7 @@ void gbxMenu() {
display_Clear();
display_Update();
setup_GB();
mode = mode_GB;
mode = mode_GB;
//Flash first bank with erase
// Change working dir to root
@ -156,7 +154,7 @@ void gbxMenu() {
display_Clear();
display_Update();
setup_GB();
mode = mode_GB;
mode = mode_GB;
// Change working dir to root
sd.chdir("/");
@ -183,7 +181,7 @@ void gbxMenu() {
display_Clear();
display_Update();
setup_GB();
mode = mode_GB;
mode = mode_GB;
// Change working dir to root
sd.chdir("/");
@ -231,8 +229,7 @@ void gbxMenu() {
if (wrErrors == 0) {
println_Msg(F("Verified OK"));
display_Update();
}
else {
} else {
print_Msg(F("Error: "));
print_Msg(wrErrors);
println_Msg(F(" bytes "));
@ -245,8 +242,7 @@ void gbxMenu() {
if (!saveFound) {
println_Msg(F("Error: No save found."));
}
}
else {
} else {
print_Error(F("Cart has no Sram"), false);
}
// Reset
@ -273,7 +269,7 @@ void gbxMenu() {
display_Clear();
display_Update();
setup_GBM();
mode = mode_GBM;
mode = mode_GBM;
break;
case 4:
@ -290,8 +286,7 @@ void gbMenu() {
mainMenu = question_box(F("GB Cart Reader"), menuOptions, 4, 0);
// wait for user choice to come back from the question box menu
switch (mainMenu)
{
switch (mainMenu) {
case 0:
display_Clear();
// Change working dir to root
@ -313,8 +308,7 @@ void gbMenu() {
readSRAMFLASH_MBC6_GB();
else
readSRAM_GB();
}
else {
} else {
print_Error(F("No save or unsupported type"), false);
}
println_Msg(F(""));
@ -331,24 +325,21 @@ void gbMenu() {
if (romType == 32) {
writeSRAMFLASH_MBC6_GB();
}
else {
} else {
writeSRAM_GB();
unsigned long wrErrors;
wrErrors = verifySRAM_GB();
if (wrErrors == 0) {
println_Msg(F("Verified OK"));
display_Update();
}
else {
} else {
print_Msg(F("Error: "));
print_Msg(wrErrors);
println_Msg(F(" bytes "));
print_Error(F("did not verify."), false);
}
}
}
else {
} else {
print_Error(F("No save or unsupported type"), false);
}
println_Msg(F(""));
@ -498,19 +489,15 @@ void showCartInfo_GB() {
case 0:
if (romType == 6) {
print_Msg(F("512 Byte"));
}
else if (romType == 0x22) {
} else if (romType == 0x22) {
if (strncmp(cartID, "KCEJ", 4) == 0) {
print_Msg(F("512 Byte"));
}
else {
} else {
print_Msg(F("256 Byte"));
}
}
else if (romType == 0xFD) {
} else if (romType == 0xFD) {
print_Msg(F("32 Byte"));
}
else {
} else {
print_Msg(F("None"));
}
break;
@ -550,8 +537,7 @@ void showCartInfo_GB() {
println_Msg(F("Press Button..."));
display_Update();
wait();
}
else {
} else {
print_Error(F("GAMEPAK ERROR"), true);
}
}
@ -568,12 +554,18 @@ byte readByte_GB(word myAddress) {
// Enable pullups
PORTC = 0xFF;
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t");
__asm__("nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t");
// Switch RD(PH6) to LOW
PORTH &= ~(1 << 6);
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t");
__asm__("nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t");
// Read
byte tempByte = PINC;
@ -581,7 +573,10 @@ byte readByte_GB(word myAddress) {
// Switch and RD(PH6) to HIGH
PORTH |= (1 << 6);
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t");
__asm__("nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t");
return tempByte;
}
@ -596,18 +591,27 @@ void writeByte_GB(int myAddress, byte myData) {
DDRC = 0xFF;
// Wait till output is stable
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t");
__asm__("nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t");
// Pull WR(PH5) low
PORTH &= ~(1 << 5);
// Leave WR low for at least 60ns
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t");
__asm__("nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t");
// Pull WR(PH5) HIGH
PORTH |= (1 << 5);
// Leave WR high for at least 50ns
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t");
__asm__("nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t");
// Switch data pins to input
DDRC = 0x00;
@ -624,29 +628,37 @@ byte readByteSRAM_GB(word myAddress) {
// Enable pullups
PORTC = 0xFF;
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t");
__asm__("nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t");
// Pull CS(PH3) CLK(PH1)(for FRAM MOD) LOW
PORTH &= ~((1 << 3) | (1 << 1));
// Pull RD(PH6) LOW
PORTH &= ~(1 << 6);
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t");
__asm__("nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t");
// Read
byte tempByte = PINC;
// Pull RD(PH6) HIGH
PORTH |= (1 << 6);
PORTH |= (1 << 6);
if (romType == 252) {
// Pull CS(PH3) HIGH
PORTH |= (1 << 3);
}
else {
} else {
// Pull CS(PH3) CLK(PH1)(for FRAM MOD) HIGH
PORTH |= (1 << 3) | (1 << 1);
}
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t");
__asm__("nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t");
return tempByte;
}
@ -661,7 +673,10 @@ void writeByteSRAM_GB(int myAddress, byte myData) {
// Switch data pins to output
DDRC = 0xFF;
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t");
__asm__("nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t");
if (romType == 252 || romType == 253) {
// Pull CS(PH3) LOW
@ -670,8 +685,7 @@ void writeByteSRAM_GB(int myAddress, byte myData) {
PORTH |= (1 << 1);
// Pull WR(PH5) low
PORTH &= ~(1 << 5);
}
else {
} else {
// Pull CS(PH3) CLK(PH1)(for FRAM MOD) LOW
PORTH &= ~((1 << 3) | (1 << 1));
// Pull WR(PH5) low
@ -679,7 +693,10 @@ void writeByteSRAM_GB(int myAddress, byte myData) {
}
// Leave WR low for at least 60ns
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t");
__asm__("nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t");
if (romType == 252 || romType == 253) {
// Pull WR(PH5) HIGH
@ -688,8 +705,7 @@ void writeByteSRAM_GB(int myAddress, byte myData) {
PORTH |= (1 << 3);
// Pull CLK(PH1) LOW (for GB CAM)
PORTH &= ~(1 << 1);
}
else {
} else {
// Pull WR(PH5) HIGH
PORTH |= (1 << 5);
// Pull CS(PH3) CLK(PH1)(for FRAM MOD) HIGH
@ -697,7 +713,10 @@ void writeByteSRAM_GB(int myAddress, byte myData) {
}
// Leave WR high for at least 50ns
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t");
__asm__("nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t");
// Switch data pins to input
DDRC = 0x00;
@ -829,8 +848,7 @@ void getCartInfo_GB() {
}
if (sramSize == 1) {
lastByte = 0xA7FF;
}
else if (sramSize > 1) {
} else if (sramSize > 1) {
lastByte = 0xBFFF;
}
@ -890,21 +908,13 @@ void getCartInfo_GB() {
// MMM01 (Mani 4 in 1)
if (
(strncmp(romName, "BOUKENJIMA2 SET", 15) == 0) && (sdBuffer[0x14D] == 0) ||
(strncmp(romName, "BUBBLEBOBBLE SET", 16) == 0) && (sdBuffer[0x14D] == 0xC6) ||
(strncmp(romName, "GANBARUGA SET", 13) == 0) && (sdBuffer[0x14D] == 0x90) ||
(strncmp(romName, "RTYPE 2 SET", 11) == 0) && (sdBuffer[0x14D] == 0x32)) {
(strncmp(romName, "BOUKENJIMA2 SET", 15) == 0) && (sdBuffer[0x14D] == 0) || (strncmp(romName, "BUBBLEBOBBLE SET", 16) == 0) && (sdBuffer[0x14D] == 0xC6) || (strncmp(romName, "GANBARUGA SET", 13) == 0) && (sdBuffer[0x14D] == 0x90) || (strncmp(romName, "RTYPE 2 SET", 11) == 0) && (sdBuffer[0x14D] == 0x32)) {
romType = 0x0B;
}
// MBC1M
if (
(strncmp(romName, "MOMOCOL", 7) == 0) && (sdBuffer[0x14D] == 0x28) ||
(strncmp(romName, "BOMCOL", 6) == 0) && (sdBuffer[0x14D] == 0x86) ||
(strncmp(romName, "GENCOL", 6) == 0) && (sdBuffer[0x14D] == 0x8A) ||
(strncmp(romName, "SUPERCHINESE 123", 16) == 0) && (sdBuffer[0x14D] == 0xE4) ||
(strncmp(romName, "MORTALKOMBATI&II", 16) == 0) && (sdBuffer[0x14D] == 0xB9) ||
(strncmp(romName, "MORTALKOMBAT DUO", 16) == 0) && (sdBuffer[0x14D] == 0xA7)) {
(strncmp(romName, "MOMOCOL", 7) == 0) && (sdBuffer[0x14D] == 0x28) || (strncmp(romName, "BOMCOL", 6) == 0) && (sdBuffer[0x14D] == 0x86) || (strncmp(romName, "GENCOL", 6) == 0) && (sdBuffer[0x14D] == 0x8A) || (strncmp(romName, "SUPERCHINESE 123", 16) == 0) && (sdBuffer[0x14D] == 0xE4) || (strncmp(romName, "MORTALKOMBATI&II", 16) == 0) && (sdBuffer[0x14D] == 0xB9) || (strncmp(romName, "MORTALKOMBAT DUO", 16) == 0) && (sdBuffer[0x14D] == 0xA7)) {
romType += 0x100;
}
@ -948,7 +958,7 @@ void readROM_GB() {
//Initialize progress bar
uint32_t processedProgressBar = 0;
uint32_t totalProgressBar = (uint32_t)(romBanks) * 16384;
uint32_t totalProgressBar = (uint32_t)(romBanks)*16384;
draw_progressbar(0, totalProgressBar);
// M161 banks are double size and start with 0
@ -1028,13 +1038,11 @@ void readROM_GB() {
// for every 4Mbits ROM, restart from 0x0000
romAddress = 0x0000;
currBank++;
}
else {
} else {
writeByte_GB(0x6000, 0);
writeByte_GB(0x2000, (currBank & 0x1f));
}
}
else {
} else {
if ((romType >= 0x19 && romType <= 0x1E) && (currBank == 0 || currBank == 256)) {
writeByte_GB(0x3000, (currBank >> 8) & 0xFF);
}
@ -1065,7 +1073,7 @@ void readROM_GB() {
}
// Calculate checksum
unsigned int calc_checksum_GB (char* fileName, char* folder) {
unsigned int calc_checksum_GB(char* fileName, char* folder) {
unsigned int calcChecksum = 0;
// int calcFilesize = 0; // unused
unsigned long i = 0;
@ -1115,8 +1123,7 @@ void compare_checksums_GB() {
print_Msg(calcsumStr);
if (strcmp(calcsumStr, checksumStr) == 0) {
println_Msg(F(" -> OK"));
}
else {
} else {
print_Msg(F(" != "));
println_Msg(checksumStr);
print_Error(F("Invalid Checksum"), false);
@ -1188,8 +1195,7 @@ void readSRAM_GB() {
print_Msg(folder);
println_Msg(F("/"));
display_Update();
}
else {
} else {
print_Error(F("Cart has no SRAM"), false);
}
}
@ -1232,12 +1238,10 @@ void writeSRAM_GB() {
println_Msg(F("SRAM writing finished"));
display_Update();
}
else {
} else {
print_Error(F("File doesnt exist"), false);
}
}
else {
} else {
print_Error(F("Cart has no SRAM"), false);
}
}
@ -1256,8 +1260,8 @@ unsigned long verifySRAM_GB() {
// Check SRAM size
if (lastByte > 0) {
if (romType <= 4) { // MBC1
writeByte_GB(0x6000, 1); // Set RAM Mode
if (romType <= 4) { // MBC1
writeByte_GB(0x6000, 1); // Set RAM Mode
}
// Initialise MBC
@ -1284,8 +1288,7 @@ unsigned long verifySRAM_GB() {
// Close the file:
myFile.close();
return writeErrors;
}
else {
} else {
print_Error(F("Can't open file"), true);
}
}
@ -1464,8 +1467,7 @@ void writeSRAMFLASH_MBC6_GB() {
print_Error(F("Error erasing FLASH sector."), true);
}
}
}
else {
} else {
writeByte_GB(0x2800, 0x08);
writeByte_GB(0x3800, 0x08);
writeByte_GB(0x2000, currBank);
@ -1521,8 +1523,7 @@ void writeSRAMFLASH_MBC6_GB() {
myFile.close();
println_Msg(F("Save writing finished"));
display_Update();
}
else {
} else {
print_Error(F("File doesnt exist"), false);
}
}
@ -1606,36 +1607,31 @@ void writeFlash29F_GB(byte MBC, boolean flashErase) {
print_Msg(romBanks);
println_Msg(F("/256"));
display_Update();
}
else if (strcmp(flashid, "0141") == 0) {
} else if (strcmp(flashid, "0141") == 0) {
println_Msg(F("AM29F032B"));
print_Msg(F("Banks: "));
print_Msg(romBanks);
println_Msg(F("/256"));
display_Update();
}
else if (strcmp(flashid, "01AD") == 0) {
} else if (strcmp(flashid, "01AD") == 0) {
println_Msg(F("AM29F016B"));
print_Msg(F("Banks: "));
print_Msg(romBanks);
println_Msg(F("/128"));
display_Update();
}
else if (strcmp(flashid, "04AD") == 0) {
} else if (strcmp(flashid, "04AD") == 0) {
println_Msg(F("AM29F016D"));
print_Msg(F("Banks: "));
print_Msg(romBanks);
println_Msg(F("/128"));
display_Update();
}
else if (strcmp(flashid, "01D5") == 0) {
} else if (strcmp(flashid, "01D5") == 0) {
println_Msg(F("AM29F080B"));
print_Msg(F("Banks: "));
print_Msg(romBanks);
println_Msg(F("/64"));
display_Update();
}
else {
} else {
print_Msg(F("Flash ID: "));
println_Msg(flashid);
display_Update();
@ -1703,7 +1699,7 @@ void writeFlash29F_GB(byte MBC, boolean flashErase) {
//Initialize progress bar
uint32_t processedProgressBar = 0;
uint32_t totalProgressBar = (uint32_t)(romBanks) * 16384;
uint32_t totalProgressBar = (uint32_t)(romBanks)*16384;
draw_progressbar(0, totalProgressBar);
for (int currBank = 0; currBank < romBanks; currBank++) {
@ -1753,7 +1749,7 @@ void writeFlash29F_GB(byte MBC, boolean flashErase) {
// Write flash
//Initialize progress bar
uint32_t processedProgressBar = 0;
uint32_t totalProgressBar = (uint32_t)(romBanks) * 16384;
uint32_t totalProgressBar = (uint32_t)(romBanks)*16384;
draw_progressbar(0, totalProgressBar);
for (int currBank = 0; currBank < romBanks; currBank++) {
@ -1805,13 +1801,12 @@ void writeFlash29F_GB(byte MBC, boolean flashErase) {
// Read number of banks and switch banks
for (word bank = 1; bank < romBanks; bank++) {
if (romType >= 5) { // MBC2 and above
writeByte_GB(0x2100, bank); // Set ROM bank
}
else { // MBC1
writeByte_GB(0x6000, 0); // Set ROM Mode
writeByte_GB(0x4000, bank >> 5); // Set bits 5 & 6 (01100000) of ROM bank
writeByte_GB(0x2000, bank & 0x1F); // Set bits 0 & 4 (00011111) of ROM bank
if (romType >= 5) { // MBC2 and above
writeByte_GB(0x2100, bank); // Set ROM bank
} else { // MBC1
writeByte_GB(0x6000, 0); // Set ROM Mode
writeByte_GB(0x4000, bank >> 5); // Set bits 5 & 6 (01100000) of ROM bank
writeByte_GB(0x2000, bank & 0x1F); // Set bits 0 & 4 (00011111) of ROM bank
}
if (bank > 1) {
@ -1839,15 +1834,13 @@ void writeFlash29F_GB(byte MBC, boolean flashErase) {
if (writeErrors == 0) {
println_Msg(F("OK"));
display_Update();
}
else {
} else {
println_Msg(F("Error"));
print_Msg(writeErrors);
println_Msg(F(" bytes "));
print_Error(F("did not verify."), true);
}
}
else {
} else {
println_Msg(F("Can't open file"));
display_Update();
}
@ -1890,15 +1883,15 @@ byte writeByteCompensated(int address, byte data) {
void startCFIMode(boolean x16Mode) {
if (x16Mode) {
writeByte_GB(0x555, 0xf0); //x16 mode reset command
writeByte_GB(0x555, 0xf0); //x16 mode reset command
delay(500);
writeByte_GB(0x555, 0xf0); //Double reset to get out of possible Autoselect + CFI mode
writeByte_GB(0x555, 0xf0); //Double reset to get out of possible Autoselect + CFI mode
delay(500);
writeByte_GB(0x55, 0x98); //x16 CFI Query command
} else {
writeByte_GB(0xAAA, 0xf0); //x8 mode reset command
writeByte_GB(0xAAA, 0xf0); //x8 mode reset command
delay(100);
writeByte_GB(0xAAA, 0xf0); //Double reset to get out of possible Autoselect + CFI mode
writeByte_GB(0xAAA, 0xf0); //Double reset to get out of possible Autoselect + CFI mode
delay(100);
writeByte_GB(0xAA, 0x98); //x8 CFI Query command
}
@ -1910,42 +1903,42 @@ void startCFIMode(boolean x16Mode) {
void identifyCFI_GB() {
// Reset flash
display_Clear();
writeByte_GB(0x6000, 0); // Set ROM Mode
writeByte_GB(0x2000, 0); // Set Bank to 0
writeByte_GB(0x6000, 0); // Set ROM Mode
writeByte_GB(0x2000, 0); // Set Bank to 0
writeByte_GB(0x3000, 0);
startCFIMode(false); // Trying x8 mode first
startCFIMode(false); // Trying x8 mode first
display_Clear();
// Try x8 mode first
char cfiQRYx8[7];
char cfiQRYx16[7];
sprintf(cfiQRYx8, "%02X%02X%02X", readByte_GB(0x20), readByte_GB(0x22), readByte_GB(0x24));
sprintf(cfiQRYx16, "%02X%02X%02X", readByte_GB(0x10), readByte_GB(0x11), readByte_GB(0x12)); // some devices use x8-style CFI Query command even though they are in x16 command mode
if (strcmp(cfiQRYx8, "515259") == 0) { // QRY in x8 mode
sprintf(cfiQRYx16, "%02X%02X%02X", readByte_GB(0x10), readByte_GB(0x11), readByte_GB(0x12)); // some devices use x8-style CFI Query command even though they are in x16 command mode
if (strcmp(cfiQRYx8, "515259") == 0) { // QRY in x8 mode
println_Msg(F("Normal CFI x8 Mode"));
flashX16Mode = false;
flashSwitchLastBits = false;
} else if (strcmp(cfiQRYx8, "52515A") == 0) { // QRY in x8 mode with switched last bit
} else if (strcmp(cfiQRYx8, "52515A") == 0) { // QRY in x8 mode with switched last bit
println_Msg(F("Switched CFI x8 Mode"));
flashX16Mode = false;
flashSwitchLastBits = true;
} else if (strcmp(cfiQRYx16, "515259") == 0) { // QRY in x16 mode
} else if (strcmp(cfiQRYx16, "515259") == 0) { // QRY in x16 mode
println_Msg(F("Normal CFI x16 Mode"));
flashX16Mode = true;
flashSwitchLastBits = false;
} else if (strcmp(cfiQRYx16, "52515A") == 0) { // QRY in x16 mode with switched last bit
} else if (strcmp(cfiQRYx16, "52515A") == 0) { // QRY in x16 mode with switched last bit
println_Msg(F("Switched CFI x16 Mode"));
flashX16Mode = true;
flashSwitchLastBits = true;
} else {
startCFIMode(true); // Try x16 mode next
startCFIMode(true); // Try x16 mode next
sprintf(cfiQRYx16, "%02X%02X%02X", readByte_GB(0x10), readByte_GB(0x11), readByte_GB(0x12));
if (strcmp(cfiQRYx16, "515259") == 0) { // QRY in x16 mode
if (strcmp(cfiQRYx16, "515259") == 0) { // QRY in x16 mode
println_Msg(F("Normal CFI x16 Mode"));
flashX16Mode = true;
flashSwitchLastBits = false;
} else if (strcmp(cfiQRYx16, "52515A") == 0) { // QRY in x16 mode with switched last bit
} else if (strcmp(cfiQRYx16, "52515A") == 0) { // QRY in x16 mode with switched last bit
println_Msg(F("Switched CFI x16 Mode"));
flashX16Mode = true;
flashSwitchLastBits = true;
@ -1956,7 +1949,7 @@ void identifyCFI_GB() {
return;
}
}
flashBanks = 1 << (readByteCompensated(0x4E) - 14); // - flashX16Mode);
flashBanks = 1 << (readByteCompensated(0x4E) - 14); // - flashX16Mode);
// Reset flash
writeByteCompensated(0xAAA, 0xf0);
@ -2134,12 +2127,12 @@ bool writeCFI_GB() {
while ((PINC & 0x80) != (sdBuffer[currByte] & 0x80)) {
i++;
if (i > 500) {
if (currAddr < 0x4000) { // This happens when trying to flash an MBC5 as if it was an MBC3. Retry to flash as MBC5, starting from last successfull byte.
if (currAddr < 0x4000) { // This happens when trying to flash an MBC5 as if it was an MBC3. Retry to flash as MBC5, starting from last successfull byte.
currByte--;
currAddr += 0x4000;
endAddr = 0x7FFF;
break;
} else { // If a timeout happens while trying to flash MBC5-style, flashing failed.
} else { // If a timeout happens while trying to flash MBC5-style, flashing failed.
return false;
}
}
@ -2147,8 +2140,7 @@ bool writeCFI_GB() {
// Switch CS(PH3) and OE/RD(PH6) to HIGH
PORTH |= (1 << 3) | (1 << 6);
__asm__("nop\n\tnop\n\tnop\n\t"); // Waste a few CPU cycles to remove write errors
__asm__("nop\n\tnop\n\tnop\n\t"); // Waste a few CPU cycles to remove write errors
}
currAddr += 512;
}
@ -2168,13 +2160,12 @@ bool writeCFI_GB() {
// Read number of banks and switch banks
for (word bank = 1; bank < romBanks; bank++) {
if (romType >= 5) { // MBC2 and above
writeByte_GB(0x2100, bank); // Set ROM bank
}
else { // MBC1
writeByte_GB(0x6000, 0); // Set ROM Mode
writeByte_GB(0x4000, bank >> 5); // Set bits 5 & 6 (01100000) of ROM bank
writeByte_GB(0x2000, bank & 0x1F); // Set bits 0 & 4 (00011111) of ROM bank
if (romType >= 5) { // MBC2 and above
writeByte_GB(0x2100, bank); // Set ROM bank
} else { // MBC1
writeByte_GB(0x6000, 0); // Set ROM Mode
writeByte_GB(0x4000, bank >> 5); // Set bits 5 & 6 (01100000) of ROM bank
writeByte_GB(0x2000, bank & 0x1F); // Set bits 0 & 4 (00011111) of ROM bank
}
if (bank > 1) {
@ -2202,15 +2193,13 @@ bool writeCFI_GB() {
if (writeErrors == 0) {
println_Msg(F("OK"));
display_Update();
}
else {
} else {
print_Msg(F("Error: "));
print_Msg(writeErrors);
println_Msg(F(" bytes "));
print_Error(F("did not verify."), false);
}
}
else {
} else {
println_Msg(F("Can't open file"));
display_Update();
}

File diff suppressed because it is too large Load Diff

View File

@ -14,7 +14,7 @@ static const char gbmMenuItem4[] PROGMEM = "Blankcheck";
static const char gbmMenuItem5[] PROGMEM = "Write Flash";
static const char gbmMenuItem6[] PROGMEM = "Read Mapping";
static const char gbmMenuItem7[] PROGMEM = "Write Mapping";
static const char* const menuOptionsGBM[] PROGMEM = {gbmMenuItem1, gbmMenuItem2, gbmMenuItem3, gbmMenuItem4, gbmMenuItem5, gbmMenuItem6, gbmMenuItem7};
static const char* const menuOptionsGBM[] PROGMEM = { gbmMenuItem1, gbmMenuItem2, gbmMenuItem3, gbmMenuItem4, gbmMenuItem5, gbmMenuItem6, gbmMenuItem7 };
void gbmMenu() {
// create menu with title and 7 options to choose from
@ -24,8 +24,7 @@ void gbmMenu() {
mainMenu = question_box(F("GB Memory Menu"), menuOptions, 7, 0);
// wait for user choice to come back from the question box menu
switch (mainMenu)
{
switch (mainMenu) {
// Read Flash ID
case 0:
// Clear screen
@ -87,8 +86,7 @@ void gbmMenu() {
if (blankcheckFlash_GBM()) {
println_Msg(F("OK"));
display_Update();
}
else {
} else {
println_Msg(F("ERROR"));
display_Update();
}
@ -163,8 +161,7 @@ void gbmMenu() {
if (blankcheckMapping_GBM()) {
println_Msg(F("OK"));
display_Update();
}
else {
} else {
print_Error(F("Erasing failed"), false);
break;
}
@ -211,7 +208,26 @@ void setup_GBM() {
while (readByte_GBM(0x120) != 0x21) {
// Enable ports 0x120h (F2)
send_GBM(0x09);
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");
__asm__("nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t");
timeout++;
if (timeout > 10) {
println_Msg(F("Error: Time Out"));
@ -230,13 +246,19 @@ byte readByte_GBM(word myAddress) {
PORTF = myAddress & 0xFF;
PORTK = (myAddress >> 8) & 0xFF;
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t");
__asm__("nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t");
// Switch CS(PH3) and RD(PH6) to LOW
PORTH &= ~(1 << 3);
PORTH &= ~(1 << 6);
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t");
__asm__("nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t");
// Read
byte tempByte = PINC;
@ -260,13 +282,19 @@ void writeByte_GBM(word myAddress, byte myData) {
PORTH &= ~(1 << 3);
PORTH &= ~(1 << 5);
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t");
__asm__("nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t");
// Pull CS(PH3) and write(PH5) high
PORTH |= (1 << 5);
PORTH |= (1 << 3);
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t");
__asm__("nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t");
// Set data pins to Input (or read errors??!)
DDRC = 0x0;
@ -306,8 +334,7 @@ void readROM_GBM(word numBanks) {
// Open file on sd card
if (!myFile.open(fileName, O_RDWR | O_CREAT)) {
print_Error(F("Can't create file on SD"), true);
}
else {
} else {
// Read rom
word currAddress = 0;
@ -472,8 +499,7 @@ boolean readFlashID_GBM() {
display_Update();
resetFlash_GBM();
return 1;
}
else {
} else {
print_Msg(F("Flash ID: "));
println_Msg(flashid);
print_Error(F("Unknown Flash ID"), true);
@ -652,8 +678,7 @@ void writeFlash_GBM() {
// Close the file:
myFile.close();
println_Msg(F("Done"));
}
else {
} else {
print_Error(F("Can't open file"), false);
}
}
@ -692,8 +717,7 @@ void readMapping_GBM() {
// Open file on sd card
if (!myFile.open(fileName, O_RDWR | O_CREAT)) {
print_Error(F("Can't create file on SD"), true);
}
else {
} else {
for (byte currByte = 0; currByte < 128; currByte++) {
sdBuffer[currByte] = readByte_GBM(currByte);
}
@ -868,8 +892,7 @@ void writeMapping_GBM() {
// Close the file:
myFile.close();
println_Msg(F("Done"));
}
else {
} else {
print_Error(F("Can't open file"), false);
}
}

View File

@ -3,7 +3,7 @@
// Supports 32M cart with LH28F016SUT flash
//******************************************
#ifdef enable_GBX
#define GB_SMART_GAMES_PER_PAGE 6
#define GB_SMART_GAMES_PER_PAGE 6
/******************************************
Menu
@ -12,19 +12,19 @@
static const char gbSmartMenuItem1[] PROGMEM = "Game Menu";
static const char gbSmartMenuItem2[] PROGMEM = "Flash Menu";
static const char gbSmartMenuItem3[] PROGMEM = "Reset";
static const char* const menuOptionsGBSmart[] PROGMEM = {gbSmartMenuItem1, gbSmartMenuItem2, gbSmartMenuItem3};
static const char* const menuOptionsGBSmart[] PROGMEM = { gbSmartMenuItem1, gbSmartMenuItem2, gbSmartMenuItem3 };
static const char gbSmartFlashMenuItem1[] PROGMEM = "Read Flash";
static const char gbSmartFlashMenuItem2[] PROGMEM = "Write Flash";
static const char gbSmartFlashMenuItem3[] PROGMEM = "Back";
static const char* const menuOptionsGBSmartFlash[] PROGMEM = {gbSmartFlashMenuItem1, gbSmartFlashMenuItem2, gbSmartFlashMenuItem3};
static const char* const menuOptionsGBSmartFlash[] PROGMEM = { gbSmartFlashMenuItem1, gbSmartFlashMenuItem2, gbSmartFlashMenuItem3 };
static const char gbSmartGameMenuItem1[] PROGMEM = "Read Game";
static const char gbSmartGameMenuItem2[] PROGMEM = "Read SRAM";
static const char gbSmartGameMenuItem3[] PROGMEM = "Write SRAM";
static const char gbSmartGameMenuItem4[] PROGMEM = "Switch Game";
static const char gbSmartGameMenuItem5[] PROGMEM = "Reset";
static const char* const menuOptionsGBSmartGame[] PROGMEM = {gbSmartGameMenuItem1, gbSmartGameMenuItem2, gbSmartGameMenuItem3, gbSmartGameMenuItem4, gbSmartGameMenuItem5};
static const char* const menuOptionsGBSmartGame[] PROGMEM = { gbSmartGameMenuItem1, gbSmartGameMenuItem2, gbSmartGameMenuItem3, gbSmartGameMenuItem4, gbSmartGameMenuItem5 };
typedef struct
{
@ -80,8 +80,7 @@ boolean compare_checksum_GBS() {
println_Msg(F("Checksum matches"));
display_Update();
return 1;
}
else {
} else {
print_Msg(F("Result: "));
println_Msg(calcsumStr);
print_Error(F("Checksum Error"), false);
@ -93,12 +92,18 @@ byte readByte_GBS(word myAddress) {
PORTF = myAddress & 0xFF;
PORTK = (myAddress >> 8) & 0xFF;
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t");
__asm__("nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t");
// Switch CS(PH3) and RD(PH6) to LOW
PORTH &= ~((1 << 3) | (1 << 6));
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t");
__asm__("nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t");
// Read
byte tempByte = PINC;
@ -106,13 +111,15 @@ byte readByte_GBS(word myAddress) {
// Switch CS(PH3) and RD(PH6) to HIGH
PORTH |= (1 << 3) | (1 << 6);
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t");
__asm__("nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t");
return tempByte;
}
void setup_GBSmart()
{
void setup_GBSmart() {
// take from setup_GB
// Set RST(PH0) to Input
DDRH &= ~(1 << 0);
@ -150,8 +157,7 @@ void setup_GBSmart()
display_Update();
}
void gbSmartMenu()
{
void gbSmartMenu() {
uint8_t mainMenu;
// Copy menuOptions out of progmem
@ -159,8 +165,7 @@ void gbSmartMenu()
mainMenu = question_box(F("GB Smart"), menuOptions, 3, 0);
// wait for user choice to come back from the question box menu
switch (mainMenu)
{
switch (mainMenu) {
case 0:
{
gbSmartGameMenu();
@ -173,22 +178,20 @@ void gbSmartMenu()
}
default:
{
asm volatile (" jmp 0");
asm volatile(" jmp 0");
break;
}
}
}
void gbSmartGameOptions()
{
void gbSmartGameOptions() {
uint8_t gameSubMenu;
convertPgm(menuOptionsGBSmartGame, 5);
gameSubMenu = question_box(F("GB Smart Game Menu"), menuOptions, 5, 0);
switch (gameSubMenu)
{
case 0: // Read Game
switch (gameSubMenu) {
case 0: // Read Game
{
display_Clear();
sd.chdir("/");
@ -196,26 +199,23 @@ void gbSmartGameOptions()
compare_checksum_GBS();
break;
}
case 1: // Read SRAM
case 1: // Read SRAM
{
display_Clear();
sd.chdir("/");
readSRAM_GB();
break;
}
case 2: // Write SRAM
case 2: // Write SRAM
{
display_Clear();
sd.chdir("/");
writeSRAM_GB();
uint32_t wrErrors = verifySRAM_GB();
if (wrErrors == 0)
{
if (wrErrors == 0) {
println_Msg(F("Verified OK"));
display_Update();
}
else
{
} else {
print_Msg(F("Error: "));
print_Msg(wrErrors);
println_Msg(F(" bytes"));
@ -223,7 +223,7 @@ void gbSmartGameOptions()
}
break;
}
case 3: // Switch Game
case 3: // Switch Game
{
gameMenuStartBank = 0x02;
gbSmartGameMenu();
@ -231,13 +231,12 @@ void gbSmartGameOptions()
}
default:
{
asm volatile (" jmp 0");
asm volatile(" jmp 0");
break;
}
}
if (gameSubMenu != 3)
{
if (gameSubMenu != 3) {
println_Msg(F(""));
println_Msg(F("Press Button..."));
display_Update();
@ -245,8 +244,7 @@ void gbSmartGameOptions()
}
}
void gbSmartGameMenu()
{
void gbSmartGameMenu() {
uint8_t gameSubMenu = 0;
gb_smart_load_more_games:
if (gameMenuStartBank > 0xfe)
@ -254,8 +252,7 @@ gb_smart_load_more_games:
gbSmartGetGames();
if (hasMenu)
{
if (hasMenu) {
char menuOptionsGBSmartGames[7][20];
int i = 0;
for (; i < numGames; i++)
@ -266,9 +263,7 @@ gb_smart_load_more_games:
if (gameSubMenu >= i)
goto gb_smart_load_more_games;
}
else
{
} else {
gameSubMenu = 0;
}
@ -283,15 +278,13 @@ gb_smart_load_more_games:
mode = mode_GB_GBSmart_Game;
}
void gbSmartFlashMenu()
{
void gbSmartFlashMenu() {
uint8_t flashSubMenu;
convertPgm(menuOptionsGBSmartFlash, 3);
flashSubMenu = question_box(F("GB Smart Flash Menu"), menuOptions, 3, 0);
switch (flashSubMenu)
{
switch (flashSubMenu) {
case 0:
{
// read flash
@ -343,9 +336,8 @@ void gbSmartFlashMenu()
wait();
}
void gbSmartGetGames()
{
static const byte menu_title[] = {0x47, 0x42, 0x31, 0x36, 0x4d};
void gbSmartGetGames() {
static const byte menu_title[] = { 0x47, 0x42, 0x31, 0x36, 0x4d };
// reset remap setting
gbSmartRemapStartBank(0x00, gbSmartRomSizeGB, gbSmartSramSizeGB);
@ -356,19 +348,15 @@ void gbSmartGetGames()
// check if contain menu
hasMenu = true;
dataIn();
for (i = 0; i < 5; i++)
{
if (readByte_GBS(0x0134 + i) != menu_title[i])
{
for (i = 0; i < 5; i++) {
if (readByte_GBS(0x0134 + i) != menu_title[i]) {
hasMenu = false;
break;
}
}
if (hasMenu)
{
for (i = gameMenuStartBank, numGames = 0; i < gbSmartBanks && numGames < GB_SMART_GAMES_PER_PAGE; )
{
if (hasMenu) {
for (i = gameMenuStartBank, numGames = 0; i < gbSmartBanks && numGames < GB_SMART_GAMES_PER_PAGE;) {
myLength = 0;
// switch bank
@ -377,21 +365,17 @@ void gbSmartGetGames()
dataIn();
// read signature
for (uint8_t j = 0x00; j < 0x30; j++)
{
if (readByte_GBS(0x4104 + j) != signature[j])
{
for (uint8_t j = 0x00; j < 0x30; j++) {
if (readByte_GBS(0x4104 + j) != signature[j]) {
i += 0x02;
goto gb_smart_get_game_loop_end;
}
}
for (uint8_t j = 0; j < 15; j++)
{
for (uint8_t j = 0; j < 15; j++) {
myByte = readByte_GBS(0x4134 + j);
if (((char(myByte) >= 0x30 && char(myByte) <= 0x39) ||
(char(myByte) >= 0x41 && char(myByte) <= 0x7a)))
if (((char(myByte) >= 0x30 && char(myByte) <= 0x39) || (char(myByte) >= 0x41 && char(myByte) <= 0x7a)))
gbSmartGames[numGames].title[myLength++] = char(myByte);
}
@ -408,16 +392,12 @@ gb_smart_get_game_loop_end:;
}
gameMenuStartBank = i;
}
else
{
} else {
dataIn();
for (uint8_t j = 0; j < 15; j++)
{
for (uint8_t j = 0; j < 15; j++) {
myByte = readByte_GBS(0x0134 + j);
if (((char(myByte) >= 0x30 && char(myByte) <= 0x39) ||
(char(myByte) >= 0x41 && char(myByte) <= 0x7a)))
if (((char(myByte) >= 0x30 && char(myByte) <= 0x39) || (char(myByte) >= 0x41 && char(myByte) <= 0x7a)))
gbSmartGames[0].title[myLength++] = char(myByte);
}
@ -432,8 +412,7 @@ gb_smart_get_game_loop_end:;
}
}
void gbSmartReadFlash()
{
void gbSmartReadFlash() {
print_Msg(F("Saving as GB/GBS/"));
print_Msg(fileName);
println_Msg(F("..."));
@ -451,8 +430,7 @@ void gbSmartReadFlash()
// dump fixed bank 0x00
dataIn();
for (uint16_t addr = 0x0000; addr <= 0x3fff; addr += 512)
{
for (uint16_t addr = 0x0000; addr <= 0x3fff; addr += 512) {
for (uint16_t c = 0; c < 512; c++)
sdBuffer[c] = readByte_GBS(addr + c);
@ -460,14 +438,12 @@ void gbSmartReadFlash()
}
// read rest banks
for (uint16_t bank = 0x01; bank < gbSmartBanks; bank++)
{
for (uint16_t bank = 0x01; bank < gbSmartBanks; bank++) {
dataOut();
writeByte_GB(0x2100, bank);
dataIn();
for (uint16_t addr = 0x4000; addr <= 0x7fff; addr += 512)
{
for (uint16_t addr = 0x4000; addr <= 0x7fff; addr += 512) {
for (uint16_t c = 0; c < 512; c++)
sdBuffer[c] = readByte_GBS(addr + c);
@ -484,10 +460,8 @@ void gbSmartReadFlash()
display_Update();
}
void gbSmartWriteFlash()
{
for (int bank = 0x00; bank < gbSmartBanks; bank += gbSmartBanksPerFlashChip)
{
void gbSmartWriteFlash() {
for (int bank = 0x00; bank < gbSmartBanks; bank += gbSmartBanksPerFlashChip) {
display_Clear();
print_Msg(F("Erasing..."));
@ -517,13 +491,10 @@ void gbSmartWriteFlash()
display_Update();
writeErrors = gbSmartVerifyFlash();
if (writeErrors == 0)
{
if (writeErrors == 0) {
println_Msg(F("OK"));
display_Update();
}
else
{
} else {
print_Msg(F("Error: "));
print_Msg(writeErrors);
println_Msg(F(" bytes "));
@ -531,8 +502,7 @@ void gbSmartWriteFlash()
}
}
void gbSmartWriteFlash(uint32_t start_bank)
{
void gbSmartWriteFlash(uint32_t start_bank) {
if (!myFile.open(filePath, O_READ))
print_Error(F("Can't open file on SD"), true);
@ -550,8 +520,7 @@ void gbSmartWriteFlash(uint32_t start_bank)
gbSmartWriteFlashFromMyFile(0x0000);
// handle rest banks on 0x4000
for (uint8_t bank = 0x01; bank < gbSmartBanksPerFlashChip; bank++)
{
for (uint8_t bank = 0x01; bank < gbSmartBanksPerFlashChip; bank++) {
dataOut();
writeByte_GB(0x2100, bank);
@ -562,17 +531,15 @@ void gbSmartWriteFlash(uint32_t start_bank)
println_Msg("");
}
void gbSmartWriteFlashFromMyFile(uint32_t addr)
{
for (uint16_t i = 0; i < 16384; i += 256)
{
void gbSmartWriteFlashFromMyFile(uint32_t addr) {
for (uint16_t i = 0; i < 16384; i += 256) {
myFile.read(sdBuffer, 256);
// sequence load to page
dataOut();
gbSmartWriteFlashByte(addr, 0xe0);
gbSmartWriteFlashByte(addr, 0xff);
gbSmartWriteFlashByte(addr, 0x00); // BCH should be 0x00
gbSmartWriteFlashByte(addr, 0x00); // BCH should be 0x00
// fill page buffer
for (int d = 0; d < 256; d++)
@ -585,53 +552,45 @@ void gbSmartWriteFlashFromMyFile(uint32_t addr)
// waiting for finishing
dataIn();
while ((readByte_GBS(addr + i) & 0x80) == 0x00);
while ((readByte_GBS(addr + i) & 0x80) == 0x00)
;
}
// blink LED
blinkLED();
}
uint32_t gbSmartVerifyFlash()
{
uint32_t gbSmartVerifyFlash() {
uint32_t verified = 0;
if (!myFile.open(filePath, O_READ))
{
if (!myFile.open(filePath, O_READ)) {
verified = 0xffffffff;
print_Error(F("Can't open file on SD"), false);
}
else
{
} else {
// remaps mmc to full access
gbSmartRemapStartBank(0x00, gbSmartRomSizeGB, gbSmartSramSizeGB);
// verify bank 0x00
dataIn();
for (uint16_t addr = 0x0000; addr <= 0x3fff; addr += 512)
{
for (uint16_t addr = 0x0000; addr <= 0x3fff; addr += 512) {
myFile.read(sdBuffer, 512);
for (uint16_t c = 0; c < 512; c++)
{
for (uint16_t c = 0; c < 512; c++) {
if (readByte_GBS(addr + c) != sdBuffer[c])
verified++;
}
}
// verify rest banks
for (uint16_t bank = 0x01; bank < gbSmartBanks; bank++)
{
for (uint16_t bank = 0x01; bank < gbSmartBanks; bank++) {
dataOut();
writeByte_GB(0x2100, bank);
dataIn();
for (uint16_t addr = 0x4000; addr <= 0x7fff; addr += 512)
{
for (uint16_t addr = 0x4000; addr <= 0x7fff; addr += 512) {
myFile.read(sdBuffer, 512);
for (uint16_t c = 0; c < 512; c++)
{
for (uint16_t c = 0; c < 512; c++) {
if (readByte_GBS(addr + c) != sdBuffer[c])
verified++;
}
@ -647,27 +606,23 @@ uint32_t gbSmartVerifyFlash()
return verified;
}
byte gbSmartBlankCheckingFlash(uint8_t flash_start_bank)
{
byte gbSmartBlankCheckingFlash(uint8_t flash_start_bank) {
gbSmartRemapStartBank(flash_start_bank, gbSmartFlashSizeGB, gbSmartSramSizeGB);
// check first bank
dataIn();
for (uint16_t addr = 0x0000; addr <= 0x3fff; addr++)
{
for (uint16_t addr = 0x0000; addr <= 0x3fff; addr++) {
if (readByte_GBS(addr) != 0xff)
return 0;
}
// check rest banks
for (uint16_t bank = 0x01; bank < gbSmartBanksPerFlashChip; bank++)
{
for (uint16_t bank = 0x01; bank < gbSmartBanksPerFlashChip; bank++) {
dataOut();
writeByte_GB(0x2100, bank);
dataIn();
for (uint16_t addr = 0x4000; addr <= 0x7fff; addr++)
{
for (uint16_t addr = 0x4000; addr <= 0x7fff; addr++) {
if (readByte_GBS(addr) != 0xff)
return 0;
}
@ -676,16 +631,14 @@ byte gbSmartBlankCheckingFlash(uint8_t flash_start_bank)
return 1;
}
void gbSmartResetFlash(uint8_t flash_start_bank)
{
void gbSmartResetFlash(uint8_t flash_start_bank) {
gbSmartRemapStartBank(flash_start_bank, gbSmartFlashSizeGB, gbSmartSramSizeGB);
dataOut();
gbSmartWriteFlashByte(0x0, 0xff);
}
void gbSmartEraseFlash(uint8_t flash_start_bank)
{
void gbSmartEraseFlash(uint8_t flash_start_bank) {
gbSmartRemapStartBank(flash_start_bank, gbSmartFlashSizeGB, gbSmartSramSizeGB);
// handling first flash block
@ -694,14 +647,14 @@ void gbSmartEraseFlash(uint8_t flash_start_bank)
gbSmartWriteFlashByte(0x0000, 0xd0);
dataIn();
while ((readByte_GBS(0x0000) & 0x80) == 0x00);
while ((readByte_GBS(0x0000) & 0x80) == 0x00)
;
// blink LED
blinkLED();
// rest of flash block
for (uint32_t ba = gbSmartBanksPerFlashBlock; ba < gbSmartBanksPerFlashChip; ba += gbSmartBanksPerFlashBlock)
{
for (uint32_t ba = gbSmartBanksPerFlashBlock; ba < gbSmartBanksPerFlashChip; ba += gbSmartBanksPerFlashBlock) {
dataOut();
writeByte_GB(0x2100, ba);
@ -709,15 +662,15 @@ void gbSmartEraseFlash(uint8_t flash_start_bank)
gbSmartWriteFlashByte(0x4000, 0xd0);
dataIn();
while ((readByte_GBS(0x4000) & 0x80) == 0x00);
while ((readByte_GBS(0x4000) & 0x80) == 0x00)
;
// blink LED
blinkLED();
}
}
void gbSmartWriteFlashByte(uint32_t myAddress, uint8_t myData)
{
void gbSmartWriteFlashByte(uint32_t myAddress, uint8_t myData) {
PORTF = myAddress & 0xff;
PORTK = (myAddress >> 8) & 0xff;
PORTC = myData;
@ -739,8 +692,7 @@ void gbSmartWriteFlashByte(uint32_t myAddress, uint8_t myData)
}
// rom_start_bank = 0x00 means back to original state
void gbSmartRemapStartBank(uint8_t rom_start_bank, uint8_t rom_size, uint8_t sram_size)
{
void gbSmartRemapStartBank(uint8_t rom_start_bank, uint8_t rom_size, uint8_t sram_size) {
rom_start_bank &= 0xfe;
dataOut();
@ -751,8 +703,7 @@ void gbSmartRemapStartBank(uint8_t rom_start_bank, uint8_t rom_size, uint8_t sra
writeByte_GB(0x1000, 0x98);
writeByte_GB(0x2000, rom_start_bank);
if (rom_start_bank > 1)
{
if (rom_start_bank > 1) {
// start set new base bank
writeByte_GB(0x1000, 0xa5);
@ -773,35 +724,25 @@ void gbSmartRemapStartBank(uint8_t rom_start_bank, uint8_t rom_size, uint8_t sra
// Use for setting correct rom and sram size
// Code logic is take from SmartCard32M V1.3 menu code,
// see 0x2db2 to 0x2e51 (0xa0 bytes)
uint8_t gbSmartGetResizeParam(uint8_t rom_size, uint8_t sram_size)
{
if (rom_size < 0x0f)
{
uint8_t gbSmartGetResizeParam(uint8_t rom_size, uint8_t sram_size) {
if (rom_size < 0x0f) {
rom_size &= 0x07;
rom_size ^= 0x07;
}
else
{
} else {
rom_size = 0x01;
}
if (sram_size > 0)
{
if (sram_size > 1)
{
if (sram_size > 0) {
if (sram_size > 1) {
sram_size--;
sram_size ^= 0x03;
sram_size <<= 4;
sram_size &= 0x30;
} else {
sram_size = 0x20; // 2KiB treat as 8KiB
}
else
{
sram_size = 0x20; // 2KiB treat as 8KiB
}
}
else
{
sram_size = 0x30; // no sram
} else {
sram_size = 0x30; // no sram
}
return (sram_size | rom_size);

View File

@ -57,27 +57,27 @@
// Cart Configurations
// Format = {mapper,romlo,romhi,ramsize}
static const byte PROGMEM intvmapsize [] = {
0, 0, 2, 0, // default mattel up to 32K (8K/16K/24K/32K)
1, 1, 3, 0, // demo cart 16K, championship tennis 32K, wsml baseball 48K
2, 1, 3, 0, // up to 48K (16K/32K/48K)
3, 4, 4, 0, // tower of doom 48K
4, 0, 1, 1, // uscf chess 16K + RAM 1K
5, 2, 3, 0, // congo bongo/defender/pac-man 24K, dig dug 32K
6, 1, 1, 0, // centipede 16K
7, 1, 1, 0, // imagic carts 16K
8, 1, 1, 0, // mte-201 test cart 16K
9, 3, 3, 2, // triple challenge 32K + RAM 2K
static const byte PROGMEM intvmapsize[] = {
0, 0, 2, 0, // default mattel up to 32K (8K/16K/24K/32K)
1, 1, 3, 0, // demo cart 16K, championship tennis 32K, wsml baseball 48K
2, 1, 3, 0, // up to 48K (16K/32K/48K)
3, 4, 4, 0, // tower of doom 48K
4, 0, 1, 1, // uscf chess 16K + RAM 1K
5, 2, 3, 0, // congo bongo/defender/pac-man 24K, dig dug 32K
6, 1, 1, 0, // centipede 16K
7, 1, 1, 0, // imagic carts 16K
8, 1, 1, 0, // mte-201 test cart 16K
9, 3, 3, 2, // triple challenge 32K + RAM 2K
};
byte intvmapcount = 10; // (sizeof(mapsize)/sizeof(mapsize[0])) / 4;
byte intvmapcount = 10; // (sizeof(mapsize)/sizeof(mapsize[0])) / 4;
boolean intvmapfound = false;
byte intvmapselect;
int intvindex;
byte INTV[] = {8, 16, 24, 32, 48};
byte intvlo = 0; // Lowest Entry
byte intvhi = 4; // Highest Entry
byte INTV[] = { 8, 16, 24, 32, 48 };
byte intvlo = 0; // Lowest Entry
byte intvhi = 4; // Highest Entry
byte intvmapper;
byte newintvmapper;
@ -96,10 +96,9 @@ static const char intvMenuItem1[] PROGMEM = "Select Cart";
static const char intvMenuItem2[] PROGMEM = "Read ROM";
static const char intvMenuItem3[] PROGMEM = "Set Mapper + Size";
static const char intvMenuItem4[] PROGMEM = "Reset";
static const char* const menuOptionsINTV[] PROGMEM = {intvMenuItem1, intvMenuItem2, intvMenuItem3, intvMenuItem4};
static const char* const menuOptionsINTV[] PROGMEM = { intvMenuItem1, intvMenuItem2, intvMenuItem3, intvMenuItem4 };
void setup_INTV()
{
void setup_INTV() {
// Set Address Pins to Output (UNUSED)
//A0-A7
DDRF = 0xFF;
@ -113,7 +112,7 @@ void setup_INTV()
DDRH |= (1 << 0) | (1 << 1) | (1 << 3) | (1 << 4) | (1 << 5) | (1 << 6);
// Set TIME(PJ0) to Output (UNUSED)
DDRJ |= (1 << 0);
DDRJ |= (1 << 0);
// Set Pins (DB0-DB15) to Input
DDRC = 0x00;
@ -124,10 +123,10 @@ void setup_INTV()
PORTH |= (1 << 0) | (1 << 1) | (1 << 3) | (1 << 4) | (1 << 5) | (1 << 6);
// Set Unused Pins HIGH
PORTF = 0xFF; // A0-A7
PORTK = 0xFF; // A8-A15
PORTL = 0xFF; // A16-A23
PORTJ |= (1 << 0); // TIME(PJ0)
PORTF = 0xFF; // A0-A7
PORTK = 0xFF; // A8-A15
PORTL = 0xFF; // A16-A23
PORTJ |= (1 << 0); // TIME(PJ0)
checkStatus_INTV();
strcpy(romName, "INTV");
@ -135,13 +134,11 @@ void setup_INTV()
mode = mode_INTV;
}
void intvMenu()
{
void intvMenu() {
convertPgm(menuOptionsINTV, 4);
uint8_t mainMenu = question_box(F("INTELLIVISION MENU"), menuOptions, 4, 0);
switch (mainMenu)
{
switch (mainMenu) {
case 0:
// Select Cart
setCart_INTV();
@ -185,8 +182,7 @@ void intvMenu()
// DIRECT ADDRESSING MODE READ SEQUENCE: BAR-NACT-ADAR-NACT-DTB-NACT
// NO ACTION (NACT) - 0/0/0
void NACT_INT()
{
void NACT_INT() {
// Switch BC1(PH4) + BC2(PH5) + BDIR(PH6) to LOW
PORTH &= ~(1 << 4) & ~(1 << 5) & ~(1 << 6);
// DB0..DB15 INPUT
@ -195,8 +191,7 @@ void NACT_INT()
}
// SET ADDRESS - BUS TO ADDR (BAR) - 1/0/0
void BAR_INT()
{
void BAR_INT() {
// Switch BDIR(PH6) to HIGH
PORTH |= (1 << 6);
// Switch BC1(PH4) + BC2(PH5) to LOW
@ -207,8 +202,7 @@ void BAR_INT()
}
// READ DATA - DATA TO BUS (DTB) - 0/1/1
void DTB_INT()
{
void DTB_INT() {
// Switch BDIR(PH6) to LOW
PORTH &= ~(1 << 6);
// Switch BC1(PH4) + BC2(PH5) to HIGH
@ -219,8 +213,7 @@ void DTB_INT()
}
// ADDRESS DATA TO ADDRESS REGISTER (ADAR) - 0/1/0
void ADAR_INT()
{
void ADAR_INT() {
// Switch BC2(PH5) + BDIR(PH6) to LOW
PORTH &= ~(1 << 5) & ~(1 << 6);
// Switch BC1(PH4) to HIGH
@ -231,8 +224,7 @@ void ADAR_INT()
// DATA SHOULD BE STABLE ACROSS BOTH
// DATA WRITE (DW) - 1/1/0
void DW_INT()
{
void DW_INT() {
// Switch BC1(PH4) + BDIR(PH6) to HIGH
PORTH |= (1 << 4) | (1 << 6);
// Switch BC2(PH5) to LOW
@ -240,8 +232,7 @@ void DW_INT()
}
// DATA WRITE STROBE (DWS) - 1/0/1
void DWS_INT()
{
void DWS_INT() {
// Switch BC2(PH5) + BDIR(PH6) to HIGH
PORTH |= (1 << 5) | (1 << 6);
// Switch BC1(PH4) to LOW
@ -252,25 +243,40 @@ void DWS_INT()
// READ CODE
//******************************************
uint16_t readData_INTV(uint32_t addr)
{
uint16_t readData_INTV(uint32_t addr) {
PORTC = addr & 0xFF;
PORTA = (addr >> 8) & 0xFF;
BAR_INT();
// Wait for bus
// 5 x 62.5ns = 312.5ns
NOP; NOP; NOP; NOP; NOP;
NOP;
NOP;
NOP;
NOP;
NOP;
NACT_INT();
NOP; NOP; NOP; NOP; NOP;
NOP;
NOP;
NOP;
NOP;
NOP;
DTB_INT();
NOP; NOP; NOP; NOP; NOP;
NOP;
NOP;
NOP;
NOP;
NOP;
uint16_t ret = (((PINA & 0xFF) << 8) | (PINC & 0xFF));
NACT_INT();
NOP; NOP; NOP; NOP; NOP;
NOP;
NOP;
NOP;
NOP;
NOP;
return ret;
}
@ -287,8 +293,7 @@ uint16_t readData_INTV(uint32_t addr)
// 8: 0x50-0x60,0x70-0x80, // mte-201 test cart 16K
// 9: 0x50-0x70,0x90-0xB0,[0xC0-0xC8,0xD0-0xD8] // triple challenge 32K + RAM 2K [0xC0 + 0xD0 segments are not needed]
void readSegment_INTV(uint32_t startaddr, uint32_t endaddr)
{
void readSegment_INTV(uint32_t startaddr, uint32_t endaddr) {
for (uint32_t addr = startaddr; addr < endaddr; addr += 256) {
for (uint16_t w = 0; w < 256; w++) {
uint16_t temp = readData_INTV(addr + w);
@ -300,8 +305,7 @@ void readSegment_INTV(uint32_t startaddr, uint32_t endaddr)
}
// MODIFIED READ ROUTINE FOR ALL 10 MAPPERS
void readROM_INTV()
{
void readROM_INTV() {
strcpy(fileName, romName);
strcat(fileName, ".int");
@ -326,88 +330,88 @@ void readROM_INTV()
EEPROM_writeAnything(0, foldern);
switch (intvmapper) {
case 0: //default mattel up to 32K (8K/16K/24K/32K)
readSegment_INTV(0x5000, 0x6000); // 8K
case 0: //default mattel up to 32K (8K/16K/24K/32K)
readSegment_INTV(0x5000, 0x6000); // 8K
if (intvsize > 0) {
readSegment_INTV(0x6000, 0x7000); // +8K = 16K
readSegment_INTV(0x6000, 0x7000); // +8K = 16K
if (intvsize > 1) {
readSegment_INTV(0xD000, 0xE000); // +8K = 24K
readSegment_INTV(0xD000, 0xE000); // +8K = 24K
if (intvsize > 2)
readSegment_INTV(0xF000, 0x10000); // +8K = 32K
readSegment_INTV(0xF000, 0x10000); // +8K = 32K
}
}
break;
case 1: // demo cart/championship tennis/wsml baseball
readSegment_INTV(0x5000, 0x7000); // 16K Demo Cart
case 1: // demo cart/championship tennis/wsml baseball
readSegment_INTV(0x5000, 0x7000); // 16K Demo Cart
if (intvsize > 1) {
readSegment_INTV(0xD000, 0xE000); // +8K = 24K [NONE]
readSegment_INTV(0xD000, 0xE000); // +8K = 24K [NONE]
if (intvsize > 2) {
readSegment_INTV(0xE000, 0xF000); // +8K = 32K Championship Tennis
readSegment_INTV(0xE000, 0xF000); // +8K = 32K Championship Tennis
if (intvsize > 3) {
readSegment_INTV(0xF000, 0x10000); // +8K = 40K WSML Baseball [MISSING 8K ECS BANK]
readSegment_INTV(0xF000, 0x10000); // +8K = 40K WSML Baseball [MISSING 8K ECS BANK]
// ecs bank switch
ecsBank(0xFFFF, 0x1); // switch ecs page 1 to 0xF000
readSegment_INTV(0xF000, 0x10000); // + 8K = 48K WSML Baseball
ecsBank(0xFFFF, 0x0); // reset ecs page 0 to 0xF000
ecsBank(0xFFFF, 0x1); // switch ecs page 1 to 0xF000
readSegment_INTV(0xF000, 0x10000); // + 8K = 48K WSML Baseball
ecsBank(0xFFFF, 0x0); // reset ecs page 0 to 0xF000
}
}
}
break;
case 2: // up to 48K (16K/32K/48K)
readSegment_INTV(0x5000, 0x7000); // 16K
case 2: // up to 48K (16K/32K/48K)
readSegment_INTV(0x5000, 0x7000); // 16K
if (intvsize > 1) {
readSegment_INTV(0x9000, 0xA000); // +8K = 24K [NONE]
readSegment_INTV(0x9000, 0xA000); // +8K = 24K [NONE]
if (intvsize > 2) {
readSegment_INTV(0xA000, 0xB000); // +8K = 32K
readSegment_INTV(0xA000, 0xB000); // +8K = 32K
if (intvsize > 3) {
readSegment_INTV(0xB000, 0xC000); // +8K = 40K
readSegment_INTV(0xD000, 0xE000); // +8K = 48K
readSegment_INTV(0xB000, 0xC000); // +8K = 40K
readSegment_INTV(0xD000, 0xE000); // +8K = 48K
}
}
}
break;
case 3: // tower of doom 48K
readSegment_INTV(0x5000, 0x7000); // 16K
readSegment_INTV(0x9000, 0xB000); // +16K = 32K
readSegment_INTV(0xD000, 0xE000); // +8K = 40K
readSegment_INTV(0xF000, 0x10000); // +8K = 48K
case 3: // tower of doom 48K
readSegment_INTV(0x5000, 0x7000); // 16K
readSegment_INTV(0x9000, 0xB000); // +16K = 32K
readSegment_INTV(0xD000, 0xE000); // +8K = 40K
readSegment_INTV(0xF000, 0x10000); // +8K = 48K
break;
case 4: // chess 16K
PORTH &= ~(1 << 3); // /MSYNC to LOW
readSegment_INTV(0x5000, 0x6000); // 8K
PORTH |= (1 << 3); // /MSYNC to HIGH
readSegment_INTV(0x6000, 0x7000); // 8K
case 4: // chess 16K
PORTH &= ~(1 << 3); // /MSYNC to LOW
readSegment_INTV(0x5000, 0x6000); // 8K
PORTH |= (1 << 3); // /MSYNC to HIGH
readSegment_INTV(0x6000, 0x7000); // 8K
break;
case 5:// congo bongo/defender/pac-man/dig dug
readSegment_INTV(0x5000, 0x7000); // 16K
readSegment_INTV(0x7000, 0x8000); // +8K = 24K Congo Bongo/Defender/Pac-Man
case 5: // congo bongo/defender/pac-man/dig dug
readSegment_INTV(0x5000, 0x7000); // 16K
readSegment_INTV(0x7000, 0x8000); // +8K = 24K Congo Bongo/Defender/Pac-Man
if (intvsize > 2) {
readSegment_INTV(0x9000, 0xA000); // +8K = 32K Dig Dug
readSegment_INTV(0x9000, 0xA000); // +8K = 32K Dig Dug
//readSegment_INTV(0xA000,0xC000); // +16K = 48K [UNUSED]
}
break;
case 6: // centipede 16K
readSegment_INTV(0x6000, 0x8000); // 16K
case 6: // centipede 16K
readSegment_INTV(0x6000, 0x8000); // 16K
break;
case 7: // imagic carts 16K
readSegment_INTV(0x4800, 0x6800); // 16K
case 7: // imagic carts 16K
readSegment_INTV(0x4800, 0x6800); // 16K
break;
case 8: //mte-201 test cart 16K
readSegment_INTV(0x5000, 0x6000); // 8K
readSegment_INTV(0x7000, 0x8000); // +8K = 16K
case 8: //mte-201 test cart 16K
readSegment_INTV(0x5000, 0x6000); // 8K
readSegment_INTV(0x7000, 0x8000); // +8K = 16K
break;
case 9: // triple challenge 32K [KNOWN ROM 44K BAD!]
readSegment_INTV(0x5000, 0x7000); // 16K
readSegment_INTV(0x9000, 0xB000); // +16K = 32K
case 9: // triple challenge 32K [KNOWN ROM 44K BAD!]
readSegment_INTV(0x5000, 0x7000); // 16K
readSegment_INTV(0x9000, 0xB000); // +16K = 32K
// 0xC000 + 0xD000 SEGMENTS ARE NOT NEEDED (PER INTVNUT POST)
// readSegment_INTV(0xC000,0xC800); // +4K = 36K
// readSegment_INTV(0xD000,0xE000); // +8K = 44K
@ -429,7 +433,7 @@ void readROM_INTV()
// x = rom location ($x000 - $xFFF)
// y = page (up to 16 - WSML Baseball only uses 0/1)
void ecsBank(uint32_t addr, uint8_t bank) {
uint16_t ecsdata = (addr & 0xF000) + 0x0A50 + bank; // $xA5y
uint16_t ecsdata = (addr & 0xF000) + 0x0A50 + bank; // $xA5y
// Data OUT
DDRA = 0xFF;
@ -440,47 +444,62 @@ void ecsBank(uint32_t addr, uint8_t bank) {
PORTC = addr & 0xFF;
BAR_INT();
NOP; NOP; NOP; NOP; NOP;
NOP;
NOP;
NOP;
NOP;
NOP;
NACT_INT();
NOP;
// Data OUT
DDRA = 0xFF;
DDRC = 0xFF;
PORTA = (ecsdata >> 8) & 0xFF; // $xA
PORTC = ecsdata & 0xFF; // $5y
PORTA = (ecsdata >> 8) & 0xFF; // $xA
PORTC = ecsdata & 0xFF; // $5y
DW_INT();
NOP; NOP; NOP; NOP; NOP;
NOP;
NOP;
NOP;
NOP;
NOP;
DWS_INT();
NOP; NOP; NOP; NOP; NOP;
NOP;
NOP;
NOP;
NOP;
NOP;
NACT_INT();
NOP; NOP; NOP; NOP; NOP;
NOP;
NOP;
NOP;
NOP;
NOP;
}
//******************************************
// MAPPER CODE
//******************************************
void setMapper_INTV()
{
void setMapper_INTV() {
#if (defined(enable_OLED) || defined(enable_LCD))
int b = 0;
int i = 0;
// Check Button Status
#if defined(enable_OLED)
buttonVal1 = (PIND & (1 << 7)); // PD7
buttonVal1 = (PIND & (1 << 7)); // PD7
#elif defined(enable_LCD)
boolean buttonVal1 = (PING & (1 << 2)); // PG2
boolean buttonVal1 = (PING & (1 << 2)); // PG2
#endif
if (buttonVal1 == LOW) { // Button Pressed
while (1) { // Scroll Mapper List
if (buttonVal1 == LOW) { // Button Pressed
while (1) { // Scroll Mapper List
#if defined(enable_OLED)
buttonVal1 = (PIND & (1 << 7)); // PD7
buttonVal1 = (PIND & (1 << 7)); // PD7
#elif defined(enable_LCD)
boolean buttonVal1 = (PING & (1 << 2)); // PG2
boolean buttonVal1 = (PING & (1 << 2)); // PG2
#endif
if (buttonVal1 == HIGH) { // Button Released
if (buttonVal1 == HIGH) { // Button Released
// Correct Overshoot
if (i == 0)
i = intvmapcount - 1;
@ -520,7 +539,7 @@ void setMapper_INTV()
while (1) {
b = checkButton();
if (b == 2) { // Previous Mapper (doubleclick)
if (b == 2) { // Previous Mapper (doubleclick)
if (i == 0)
i = intvmapcount - 1;
else
@ -542,7 +561,7 @@ void setMapper_INTV()
#endif
display_Update();
}
if (b == 1) { // Next Mapper (press)
if (b == 1) { // Next Mapper (press)
if (i == (intvmapcount - 1))
i = 0;
else
@ -564,7 +583,7 @@ void setMapper_INTV()
#endif
display_Update();
}
if (b == 3) { // Long Press - Execute (hold)
if (b == 3) { // Long Press - Execute (hold)
newintvmapper = intvmapselect;
break;
}
@ -613,8 +632,7 @@ void checkMapperSize_INTV() {
}
}
void setROMSize_INTV()
{
void setROMSize_INTV() {
#if (defined(enable_OLED) || defined(enable_LCD))
display_Clear();
if (intvlo == intvhi)
@ -639,7 +657,7 @@ void setROMSize_INTV()
while (1) {
b = checkButton();
if (b == 2) { // Previous (doubleclick)
if (b == 2) { // Previous (doubleclick)
if (i == intvlo)
i = intvhi;
else
@ -659,7 +677,7 @@ void setROMSize_INTV()
#endif
display_Update();
}
if (b == 1) { // Next (press)
if (b == 1) { // Next (press)
if (i == intvhi)
i = intvlo;
else
@ -678,12 +696,12 @@ void setROMSize_INTV()
#endif
display_Update();
}
if (b == 3) { // Long Press - Execute (hold)
if (b == 3) { // Long Press - Execute (hold)
newintvsize = i;
break;
}
}
display.setCursor(0, 56); // Display selection at bottom
display.setCursor(0, 56); // Display selection at bottom
}
print_Msg(F("ROM SIZE "));
print_Msg(INTV[newintvsize]);
@ -722,8 +740,7 @@ setrom:
intvsize = newintvsize;
}
void checkStatus_INTV()
{
void checkStatus_INTV() {
EEPROM_readAnything(7, intvmapper);
EEPROM_readAnything(8, intvsize);
if (intvmapper > 9) {
@ -793,12 +810,10 @@ void setCart_INTV() {
while (1) {
if (myFile.curPosition() == 0) {
break;
}
else if (myFile.peek() == '\n') {
} else if (myFile.peek() == '\n') {
myFile.seekSet(myFile.curPosition() - 1);
break;
}
else {
} else {
myFile.seekSet(myFile.curPosition() - 1);
}
}
@ -846,9 +861,8 @@ void setCart_INTV() {
// Remove leading 0 for single digit cart sizes
if (cartSize != 0) {
cartSize = cartSize * 10 + myFile.read() - 48;
}
else {
cartSize = cartSize * 10 + myFile.read() - 48;
} else {
cartSize = myFile.read() - 48;
}
@ -900,12 +914,10 @@ void setCart_INTV() {
while (1) {
if (myFile.curPosition() == 0) {
break;
}
else if (myFile.peek() == '\n') {
} else if (myFile.peek() == '\n') {
myFile.seekSet(myFile.curPosition() - 1);
break;
}
else {
} else {
myFile.seekSet(myFile.curPosition() - 1);
}
}
@ -950,8 +962,7 @@ void setCart_INTV() {
}
}
}
}
else {
} else {
print_Error(F("Database file not found"), true);
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -6,13 +6,13 @@
static const char ngpMenuItem1[] PROGMEM = "Read Rom";
static const char ngpMenuItem2[] PROGMEM = "Read chip info";
static const char ngpMenuItemReset[] PROGMEM = "Reset";
static const char* const menuOptionsNGP[] PROGMEM = {ngpMenuItem1, ngpMenuItem2, ngpMenuItemReset};
static const char* const menuOptionsNGP[] PROGMEM = { ngpMenuItem1, ngpMenuItem2, ngpMenuItemReset };
static const char ngpRomItem1[] PROGMEM = "4 Mbits / 512 KB";
static const char ngpRomItem2[] PROGMEM = "8 Mbits / 1 MB";
static const char ngpRomItem3[] PROGMEM = "16 Mbits / 2 MB";
static const char ngpRomItem4[] PROGMEM = "32 Mbits / 4 MB";
static const char* const ngpRomOptions[] PROGMEM = {ngpRomItem1, ngpRomItem2, ngpRomItem3, ngpRomItem4};
static const char* const ngpRomOptions[] PROGMEM = { ngpRomItem1, ngpRomItem2, ngpRomItem3, ngpRomItem4 };
char ngpRomVersion[3];
uint8_t ngpSystemType;
@ -79,7 +79,7 @@ void ngpMenu() {
}
bool getCartInfo_NGP() {
uint8_t *tmp;
uint8_t* tmp;
// enter autoselect mode
dataOut();
@ -99,13 +99,13 @@ bool getCartInfo_NGP() {
switch (romSize) {
case 0xffff: return false; break; // detection error (no cart inserted or hw problem)
case 0x98ab: cartSize = 524288; break; // 4 Mbits - Toshiba
case 0x204c: cartSize = 524288; break; // 4 Mbits - STMicroelectronics ?
case 0x982c: cartSize = 1048576; break; // 8 Mbits - Toshiba
case 0xec2c: cartSize = 1048576; break; // 8 Mbits - Samsung
case 0x982f: cartSize = 2097152; break; // 16 Mbits - Toshiba
case 0xec2f: cartSize = 2097152; break; // 16 Mbits - Samsung
case 0xffff: return false; break; // detection error (no cart inserted or hw problem)
case 0x98ab: cartSize = 524288; break; // 4 Mbits - Toshiba
case 0x204c: cartSize = 524288; break; // 4 Mbits - STMicroelectronics ?
case 0x982c: cartSize = 1048576; break; // 8 Mbits - Toshiba
case 0xec2c: cartSize = 1048576; break; // 8 Mbits - Samsung
case 0x982f: cartSize = 2097152; break; // 16 Mbits - Toshiba
case 0xec2f: cartSize = 2097152; break; // 16 Mbits - Samsung
}
// reset to read mode
@ -123,7 +123,7 @@ bool getCartInfo_NGP() {
snprintf(cartID, 5, "%02X%02X", readByte_NGP(0x21), readByte_NGP(0x20));
// force rom size to 32 Mbits for few titles
if (strcmp(cartID, "0060") == 0 || strcmp(cartID, "0061") == 0 || strcmp(cartID, "0069") == 0 )
if (strcmp(cartID, "0060") == 0 || strcmp(cartID, "0061") == 0 || strcmp(cartID, "0069") == 0)
cartSize = 4194304;
// get app version
@ -164,8 +164,7 @@ void printCartInfo_NGP() {
print_Msg(F("ROM Size: "));
if (cartSize == 0) {
println_Msg(F("Unknown"));
}
else {
} else {
print_Msg((cartSize >> 17));
println_Msg(F(" Mbits"));
}
@ -175,7 +174,7 @@ void printCartInfo_NGP() {
wait();
}
void readROM_NGP(char *outPathBuf, size_t bufferSize) {
void readROM_NGP(char* outPathBuf, size_t bufferSize) {
// Set cartsize manually if chip ID is unknown
if (cartSize == 0) {
unsigned char ngpRomMenu;
@ -300,8 +299,7 @@ void scanChip_NGP() {
myFile.println("Warning: this cart is 32Mbits. Only the first 16Mbits chip will be scanned.");
myFile.println("");
addrMax = 2097152;
}
else
} else
addrMax = cartSize;
myFile.println("Sector | Start address | Status");
@ -309,7 +307,7 @@ void scanChip_NGP() {
// browse sectors
for (uint32_t addr = 0; addr < addrMax; addr += 0x1000) {
if ( (addr % 0x10000 == 0) || (addr == addrMax - 0x8000) || (addr == addrMax - 0x6000) || (addr == addrMax - 0x4000)) {
if ((addr % 0x10000 == 0) || (addr == addrMax - 0x8000) || (addr == addrMax - 0x6000) || (addr == addrMax - 0x4000)) {
myFile.print("#" + String(sectorID) + " | 0x" + String(addr, HEX) + " | ");
@ -344,7 +342,8 @@ void writeByte_NGP(uint32_t addr, uint8_t data) {
PORTH |= data;
PORTH |= (1 << 5);
NOP; NOP;
NOP;
NOP;
}
uint8_t readByte_NGP(uint32_t addr) {
@ -361,7 +360,9 @@ uint8_t readByte_NGP(uint32_t addr) {
PORTH &= ~data;
PORTH &= ~(1 << 6);
NOP; NOP; NOP;
NOP;
NOP;
NOP;
data = PINC;

View File

@ -42,7 +42,7 @@ void read_rom_PCE(void);
/******************************************
Variables
*****************************************/
uint8_t pce_internal_mode; //0 - HuCARD, 1 - TurboChip
uint8_t pce_internal_mode; //0 - HuCARD, 1 - TurboChip
uint16_t pce_force_rom_size = 0;
uint8_t tennokoe_bank_index = 0;
@ -55,7 +55,7 @@ static const char pceMenuItem1[] PROGMEM = "HuCARD (swapped)";
static const char pceMenuItem2[] PROGMEM = "HuCARD(not swapped)";
static const char pceMenuItem3[] PROGMEM = "Turbochip";
static const char pceMenuItem4[] PROGMEM = "Reset";
static const char* const menuOptionspce[] PROGMEM = {pceMenuItem1, pceMenuItem2, pceMenuItem3, pceMenuItem4};
static const char *const menuOptionspce[] PROGMEM = { pceMenuItem1, pceMenuItem2, pceMenuItem3, pceMenuItem4 };
// PCE card menu items
static const char pceCartMenuItem1[] = "Read ROM";
@ -70,7 +70,7 @@ static char menuOptionspceCart[7][20];
// Turbochip menu items
static const char pceTCMenuItem1[] PROGMEM = "Read ROM";
static const char pceTCMenuItem2[] PROGMEM = "Reset";
static const char* const menuOptionspceTC[] PROGMEM = {pceTCMenuItem1, pceTCMenuItem2};
static const char *const menuOptionspceTC[] PROGMEM = { pceTCMenuItem1, pceTCMenuItem2 };
// PCE start menu
void pcsMenu(void) {
@ -81,8 +81,7 @@ void pcsMenu(void) {
pceDev = question_box(F("Select device"), menuOptions, 3, 0);
// wait for user choice to come back from the question box menu
switch (pceDev)
{
switch (pceDev) {
case 0:
//Hucard
display_Clear();
@ -116,8 +115,7 @@ void pcsMenu(void) {
}
}
void pin_read_write_PCE(void)
{
void pin_read_write_PCE(void) {
// Set Address Pins to Output
//A0-A7
DDRF = 0xFF;
@ -153,8 +151,7 @@ void pin_read_write_PCE(void)
reset_cart_PCE();
}
void pin_init_PCE(void)
{
void pin_init_PCE(void) {
//Set Address Pins to input and pull up
DDRF = 0x00;
@ -175,61 +172,67 @@ void pin_init_PCE(void)
DDRC = 0x00;
// Enable Internal Pullups
PORTC = 0xFF;
}
void setup_cart_PCE(void)
{
void setup_cart_PCE(void) {
// Set cicrstPin(PG1) to Output
DDRG |= (1 << 1);
// Output a high to disable CIC
PORTG |= (1 << 1);
pin_init_PCE();
}
void reset_cart_PCE(void)
{
void reset_cart_PCE(void) {
//Set RESET as Low
PORTH &= ~(1 << 0);
delay(200);
//Set RESET as High
PORTH |= (1 << 0);
delay(200);
}
void set_address_PCE(uint32_t address)
{
void set_address_PCE(uint32_t address) {
//Set address
PORTF = address & 0xFF;
PORTK = (address >> 8) & 0xFF;
PORTL = (PORTL & 0xF0) | ((address >> 16) & 0x0F);
}
void set_cs_rd_low_PCE ()
{
void set_cs_rd_low_PCE() {
// Set CS(PL4) and RD(PH3) as LOW
PORTL &= ~(1 << 4);
PORTH &= ~(1 << 3);
}
uint8_t read_byte_PCE(uint32_t address)
{
uint8_t read_byte_PCE(uint32_t address) {
uint8_t ret;
set_address_PCE(address);
// Arduino running at 16Mhz -> one nop = 62.5ns -> 1000ns total
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");
__asm__("nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t");
//read byte
ret = PINC;
//Swap bit order for PC Engine HuCARD
if (pce_internal_mode == HUCARD)
{
if (pce_internal_mode == HUCARD) {
ret = ((ret & 0x01) << 7) | ((ret & 0x02) << 5) | ((ret & 0x04) << 3) | ((ret & 0x08) << 1) | ((ret & 0x10) >> 1) | ((ret & 0x20) >> 3) | ((ret & 0x40) >> 5) | ((ret & 0x80) >> 7);
}
@ -237,12 +240,12 @@ uint8_t read_byte_PCE(uint32_t address)
return ret;
}
void data_output_PCE () {
void data_output_PCE() {
// Set Data Pins (D0-D7) to Output
DDRC = 0xFF;
}
void data_input_PCE () {
void data_input_PCE() {
// Set Data Pins (D0-D7) to Input
DDRC = 0x00;
// Enable Internal Pullups
@ -251,17 +254,30 @@ void data_input_PCE () {
set_cs_rd_low_PCE();
}
void write_byte_PCE(uint32_t address, uint8_t data)
{
void write_byte_PCE(uint32_t address, uint8_t data) {
//PORTH |= (1 << 3); // RD HIGH
set_address_PCE(address);
// Arduino running at 16Mhz -> one nop = 62.5ns -> 1000ns total
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");
__asm__("nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t");
//Swap bit order for PC Engine HuCARD
if (pce_internal_mode == HUCARD)
{
if (pce_internal_mode == HUCARD) {
data = ((data & 0x01) << 7) | ((data & 0x02) << 5) | ((data & 0x04) << 3) | ((data & 0x08) << 1) | ((data & 0x10) >> 1) | ((data & 0x20) >> 3) | ((data & 0x40) >> 5) | ((data & 0x80) >> 7);
}
@ -273,7 +289,22 @@ void write_byte_PCE(uint32_t address, uint8_t data)
PORTH &= ~(1 << 5);
// Arduino running at 16Mhz -> one nop = 62.5ns -> 1000ns total
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");
__asm__("nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t");
// Set CS(PL4) and WR(PH5) as HIGH
PORTL |= (1 << 4);
@ -281,8 +312,7 @@ void write_byte_PCE(uint32_t address, uint8_t data)
}
//Confirm the size of ROM - 128Kb, 256Kb, 384Kb, 512Kb, 768Kb or 1024Kb
uint32_t detect_rom_size_PCE(void)
{
uint32_t detect_rom_size_PCE(void) {
uint32_t rom_size;
uint8_t read_byte;
uint8_t current_byte;
@ -299,8 +329,7 @@ uint32_t detect_rom_size_PCE(void)
//Confirm where mirror address start from(128KB, 256KB, 512KB, 768, or 1024KB)
for (current_byte = 0; current_byte < DETECTION_SIZE; current_byte++) {
if ((current_byte != detect_128) && (current_byte != detect_256) && (current_byte != detect_512) && (current_byte != detect_768))
{
if ((current_byte != detect_128) && (current_byte != detect_256) && (current_byte != detect_512) && (current_byte != detect_768)) {
//If none matched, it is 1024KB
break;
}
@ -309,38 +338,30 @@ uint32_t detect_rom_size_PCE(void)
read_byte = read_byte_PCE(current_byte);
//128KB detection
if (current_byte == detect_128)
{
if (read_byte_PCE(current_byte + 128UL * 1024UL) == read_byte)
{
if (current_byte == detect_128) {
if (read_byte_PCE(current_byte + 128UL * 1024UL) == read_byte) {
detect_128++;
}
}
//256KB detection
if (current_byte == detect_256)
{
if (read_byte_PCE(current_byte + 256UL * 1024UL) == read_byte)
{
if (current_byte == detect_256) {
if (read_byte_PCE(current_byte + 256UL * 1024UL) == read_byte) {
detect_256++;
}
}
//512KB detection
if (current_byte == detect_512)
{
if (read_byte_PCE(current_byte + 512UL * 1024UL) == read_byte)
{
if (current_byte == detect_512) {
if (read_byte_PCE(current_byte + 512UL * 1024UL) == read_byte) {
detect_512++;
}
}
//768KB detection
read_byte = read_byte_PCE(current_byte + 512UL * 1024UL);
if (current_byte == detect_768)
{
if (read_byte_PCE(current_byte + 768UL * 1024UL) == read_byte)
{
if (current_byte == detect_768) {
if (read_byte_PCE(current_byte + 768UL * 1024UL) == read_byte) {
detect_768++;
}
}
@ -351,43 +372,29 @@ uint32_t detect_rom_size_PCE(void)
//println_Msg(fileName);
//ROM size detection by result
if (detect_128 == DETECTION_SIZE)
{
if (detect_128 == DETECTION_SIZE) {
rom_size = 128;
}
else if (detect_256 == DETECTION_SIZE)
{
if (detect_512 == DETECTION_SIZE)
{
} else if (detect_256 == DETECTION_SIZE) {
if (detect_512 == DETECTION_SIZE) {
rom_size = 256;
}
else
{
} else {
//rom_size = 1024;
//Another confirmation for 384KB because 384KB hucard has data in 0x0--0x40000 and 0x80000--0xA0000(0x40000 is mirror of 0x00000)
rom_size = 384;
}
}
else if (detect_512 == DETECTION_SIZE)
{
} else if (detect_512 == DETECTION_SIZE) {
rom_size = 512;
}
else if (detect_768 == DETECTION_SIZE)
{
} else if (detect_768 == DETECTION_SIZE) {
rom_size = 768;
}
else
{
} else {
rom_size = 1024;
}
//If rom size is more than or equal to 512KB, detect Street fighter II'
if (rom_size >= 512)
{
if (rom_size >= 512) {
//Look for "NEC HE "
if (read_byte_PCE(0x7FFF9) == 'N' && read_byte_PCE(0x7FFFA) == 'E' && read_byte_PCE(0x7FFFB) == 'C'
&& read_byte_PCE(0x7FFFC) == ' ' && read_byte_PCE(0x7FFFD) == 'H' && read_byte_PCE(0x7FFFE) == 'E')
{
if (read_byte_PCE(0x7FFF9) == 'N' && read_byte_PCE(0x7FFFA) == 'E' && read_byte_PCE(0x7FFFB) == 'C'
&& read_byte_PCE(0x7FFFC) == ' ' && read_byte_PCE(0x7FFFD) == 'H' && read_byte_PCE(0x7FFFE) == 'E') {
rom_size = 2560;
}
}
@ -396,8 +403,7 @@ uint32_t detect_rom_size_PCE(void)
}
/* Must be address_start and address_end should be 512 byte aligned */
void read_bank_PCE_ROM(uint32_t address_start, uint32_t address_end, uint32_t *processed_size, uint32_t total_size, uint32_t *crcp)
{
void read_bank_PCE_ROM(uint32_t address_start, uint32_t address_end, uint32_t *processed_size, uint32_t total_size, uint32_t *crcp) {
uint32_t currByte;
uint16_t c;
@ -414,29 +420,26 @@ void read_bank_PCE_ROM(uint32_t address_start, uint32_t address_end, uint32_t *p
}
}
void read_bank_PCE_RAM(uint32_t address_start, int block_index)
{
void read_bank_PCE_RAM(uint32_t address_start, int block_index) {
uint32_t start = address_start + block_index * 512;
for (uint16_t c = 0; c < 512; c++) {
sdBuffer[c] = read_byte_PCE(start + c);
}
}
uint32_t calculate_crc32(int n, unsigned char c[], uint32_t r)
{
uint32_t calculate_crc32(int n, unsigned char c[], uint32_t r) {
int i, j;
for (i = 0; i < n; i++) {
r ^= c[i];
for (j = 0; j < 8; j++)
if (r & 1) r = (r >> 1) ^ 0xEDB88320UL;
else r >>= 1;
else r >>= 1;
}
return r;
}
void crc_search(char *file_p, char *folder_p, uint32_t rom_size, uint32_t crc)
{
void crc_search(char *file_p, char *folder_p, uint32_t rom_size, uint32_t crc) {
FsFile rom, script;
uint32_t r, processedsize;
char gamename[100];
@ -445,16 +448,14 @@ void crc_search(char *file_p, char *folder_p, uint32_t rom_size, uint32_t crc)
flag = CHKSUM_SKIP;
//Open list file. If no list file found, just skip
sd.chdir("/"); //Set read directry to root
if (script.open("pce.txt", O_READ))
{
sd.chdir("/"); //Set read directry to root
if (script.open("pce.txt", O_READ)) {
//Calculate CRC of ROM file
sd.chdir(folder_p);
if (rom.open(file_p, O_READ))
{
if (rom.open(file_p, O_READ)) {
//Initialize flag as error
flag = CHKSUM_ERROR;
crc = crc ^ 0xFFFFFFFFUL; //Finish CRC calculation and progress bar
crc = crc ^ 0xFFFFFFFFUL; //Finish CRC calculation and progress bar
//Display calculated CRC
sprintf(crc_file, "%08lX", crc);
@ -463,11 +464,10 @@ void crc_search(char *file_p, char *folder_p, uint32_t rom_size, uint32_t crc)
//Read 2 lines (game name and CRC)
get_line(gamename, &script, 96);
get_line(crc_search, &script, 9);
skip_line(&script); //Skip every 3rd line
skip_line(&script); //Skip every 3rd line
//if checksum search successful, rename the file and end search
if (strcmp(crc_search, crc_file) == 0)
{
if (strcmp(crc_search, crc_file) == 0) {
print_Msg(F("Chksum OK "));
println_Msg(crc_file);
print_Msg(F("Saved to "));
@ -486,15 +486,12 @@ void crc_search(char *file_p, char *folder_p, uint32_t rom_size, uint32_t crc)
}
if (flag == CHKSUM_SKIP)
{
if (flag == CHKSUM_SKIP) {
print_Msg(F("Saved to "));
print_Msg(folder_p);
print_Msg(F("/"));
print_Msg(file_p);
}
else if (flag == CHKSUM_ERROR)
{
} else if (flag == CHKSUM_ERROR) {
print_Msg(F("Chksum Error "));
println_Msg(crc_file);
print_Msg(F("Saved to "));
@ -504,27 +501,23 @@ void crc_search(char *file_p, char *folder_p, uint32_t rom_size, uint32_t crc)
}
script.close();
}
void unlock_tennokoe_bank_RAM()
{
write_byte_PCE(0x0D0000, 0x68); //Unlock RAM sequence 1 Bank 68
write_byte_PCE(0x0F0000, 0x00); //Unlock RAM sequence 2 Bank 78
write_byte_PCE(0x0F0000, 0x73); //Unlock RAM sequence 3 Bank 78
write_byte_PCE(0x0F0000, 0x73); //Unlock RAM sequence 4 Bank 78
write_byte_PCE(0x0F0000, 0x73); //Unlock RAM sequence 5 Bank 78
void unlock_tennokoe_bank_RAM() {
write_byte_PCE(0x0D0000, 0x68); //Unlock RAM sequence 1 Bank 68
write_byte_PCE(0x0F0000, 0x00); //Unlock RAM sequence 2 Bank 78
write_byte_PCE(0x0F0000, 0x73); //Unlock RAM sequence 3 Bank 78
write_byte_PCE(0x0F0000, 0x73); //Unlock RAM sequence 4 Bank 78
write_byte_PCE(0x0F0000, 0x73); //Unlock RAM sequence 5 Bank 78
}
void lock_tennokoe_bank_RAM()
{
write_byte_PCE(0x0D0000, 0x68); //Lock RAM sequence 1 Bank 68
write_byte_PCE(0x0F0001, 0x00); //Lock RAM sequence 2 Bank 78
write_byte_PCE(0x0C0001, 0x60); //Lock RAM sequence 3 Bank 60
void lock_tennokoe_bank_RAM() {
write_byte_PCE(0x0D0000, 0x68); //Lock RAM sequence 1 Bank 68
write_byte_PCE(0x0F0001, 0x00); //Lock RAM sequence 2 Bank 78
write_byte_PCE(0x0C0001, 0x60); //Lock RAM sequence 3 Bank 60
}
void read_tennokoe_bank_PCE(int bank_index)
{
void read_tennokoe_bank_PCE(int bank_index) {
uint32_t processed_size = 0;
uint32_t verify_loop;
uint8_t verify_flag = 1;
@ -599,8 +592,8 @@ void read_tennokoe_bank_PCE(int bank_index)
}
if (block_index == 0 && sdBuffer[2] == 0x42 && sdBuffer[3] == 0x4D) {
if (sdBuffer[0] != 0x48 || sdBuffer[1] != 0x55) {
sdBuffer[0] = 0x48; // H
sdBuffer[1] = 0x55; // U
sdBuffer[0] = 0x48; // H
sdBuffer[1] = 0x55; // U
println_Msg(F("Corrected header"));
} else {
println_Msg(F("Header is correct"));
@ -613,11 +606,9 @@ void read_tennokoe_bank_PCE(int bank_index)
//Close the file:
myFile.close();
}
void write_tennokoe_bank_PCE(int bank_index)
{
void write_tennokoe_bank_PCE(int bank_index) {
//Display file Browser and wait user to select a file. Size must be 2KB.
filePath[0] = '\0';
sd.chdir("/");
@ -708,14 +699,12 @@ void write_tennokoe_bank_PCE(int bank_index)
println_Msg(F("Finished"));
display_Update();
wait();
}
else {
} else {
print_Error(F("File doesn't exist"), false);
}
}
void read_rom_PCE(void)
{
void read_rom_PCE(void) {
uint32_t rom_size;
uint32_t processed_size = 0;
@ -762,36 +751,31 @@ void read_rom_PCE(void)
//Initialize progress bar by setting processed size as 0
draw_progressbar(0, rom_size * 1024UL);
uint32_t crc = 0xFFFFFFFFUL; //Initialize CRC
if (rom_size == 384)
{
uint32_t crc = 0xFFFFFFFFUL; //Initialize CRC
if (rom_size == 384) {
//Read two sections. 0x000000--0x040000 and 0x080000--0x0A0000 for 384KB
read_bank_PCE_ROM(0, 0x40000, &processed_size, rom_size * 1024UL, &crc);
read_bank_PCE_ROM(0x80000, 0xA0000, &processed_size, rom_size * 1024UL, &crc);
}
else if (rom_size == 2560)
{
} else if (rom_size == 2560) {
//Dump Street fighter II' Champion Edition
read_bank_PCE_ROM(0, 0x80000, &processed_size, rom_size * 1024UL, &crc); //Read first bank
data_output_PCE();
write_byte_PCE(0x1FF0, 0xFF); //Display second bank
write_byte_PCE(0x1FF0, 0xFF); //Display second bank
data_input_PCE();
read_bank_PCE_ROM(0x80000, 0x100000, &processed_size, rom_size * 1024UL, &crc); //Read second bank
read_bank_PCE_ROM(0x80000, 0x100000, &processed_size, rom_size * 1024UL, &crc); //Read second bank
data_output_PCE();
write_byte_PCE(0x1FF1, 0xFF); //Display third bank
write_byte_PCE(0x1FF1, 0xFF); //Display third bank
data_input_PCE();
read_bank_PCE_ROM(0x80000, 0x100000, &processed_size, rom_size * 1024UL, &crc); //Read third bank
read_bank_PCE_ROM(0x80000, 0x100000, &processed_size, rom_size * 1024UL, &crc); //Read third bank
data_output_PCE();
write_byte_PCE(0x1FF2, 0xFF); //Display forth bank
write_byte_PCE(0x1FF2, 0xFF); //Display forth bank
data_input_PCE();
read_bank_PCE_ROM(0x80000, 0x100000, &processed_size, rom_size * 1024UL, &crc); //Read forth bank
read_bank_PCE_ROM(0x80000, 0x100000, &processed_size, rom_size * 1024UL, &crc); //Read forth bank
data_output_PCE();
write_byte_PCE(0x1FF3, 0xFF); //Display fifth bank
write_byte_PCE(0x1FF3, 0xFF); //Display fifth bank
data_input_PCE();
read_bank_PCE_ROM(0x80000, 0x100000, &processed_size, rom_size * 1024UL, &crc); //Read fifth bank
}
else
{
read_bank_PCE_ROM(0x80000, 0x100000, &processed_size, rom_size * 1024UL, &crc); //Read fifth bank
} else {
//Read start form 0x000000 and keep reading until end of ROM
read_bank_PCE_ROM(0, rom_size * 1024UL, &processed_size, rom_size * 1024UL, &crc);
}
@ -810,8 +794,7 @@ void pceMenu() {
// create menu with title and 7 options to choose from
unsigned char mainMenu;
if (pce_internal_mode == HUCARD || pce_internal_mode == HUCARD_NOSWAP)
{
if (pce_internal_mode == HUCARD || pce_internal_mode == HUCARD_NOSWAP) {
sprintf(pceCartMenuItem2, "Read RAM Bank %d", tennokoe_bank_index + 1);
sprintf(pceCartMenuItem3, "Write RAM Bank %d", tennokoe_bank_index + 1);
strcpy(menuOptionspceCart[0], pceCartMenuItem1);
@ -829,8 +812,7 @@ void pceMenu() {
mainMenu = question_box(F("PCE HuCARD menu"), menuOptionspceCart, 7, 0);
// wait for user choice to come back from the question box menu
switch (mainMenu)
{
switch (mainMenu) {
case 0:
display_Clear();
// Change working dir to root
@ -862,16 +844,13 @@ void pceMenu() {
pce_force_rom_size = 1024;
break;
}
}
else
{
} else {
// Copy menuOptions out of progmem
convertPgm(menuOptionspceTC, 2);
mainMenu = question_box(F("TG TurboChip menu"), menuOptions, 2, 0);
// wait for user choice to come back from the question box menu
switch (mainMenu)
{
switch (mainMenu) {
case 0:
display_Clear();
// Change working dir to root

View File

@ -75,19 +75,23 @@
#define NAND_1A_HIGH PORTH |= (1 << 3)
#define NAND_1A_LOW PORTH &= ~(1 << 3)
#define NAND_1B_HIGH PORTH |= (1 << 4)
#define NAND_1B_LOW PORTH &= ~(1 << 4) // Built-in RAM + I/O
#define NAND_1B_LOW PORTH &= ~(1 << 4) // Built-in RAM + I/O
#define WE_HIGH PORTH |= (1 << 5)
#define WE_LOW PORTH &= ~(1 << 5)
#define OE_HIGH PORTH |= (1 << 6)
#define OE_LOW PORTH &= ~(1 << 6)
#define MODE_READ DDRC = 0 // [INPUT]
#define MODE_WRITE DDRC = 0xFF //[OUTPUT]
#define MODE_READ DDRC = 0 // [INPUT]
#define MODE_WRITE DDRC = 0xFF //[OUTPUT]
#define DATA_READ { DDRC = 0; PORTC = 0xFF; } // [INPUT PULLUP]
#define ADDR_WRITE DDRC = 0xFF // [OUTPUT]
#define DATA_READ \
{ \
DDRC = 0; \
PORTC = 0xFF; \
} // [INPUT PULLUP]
#define ADDR_WRITE DDRC = 0xFF // [OUTPUT]
boolean multipack = 0; // Multi-Pack Cart
boolean multipack = 0; // Multi-Pack Cart
byte bank0;
byte bank1;
@ -107,17 +111,17 @@ void setup_PCW() {
DDRH |= (1 << 0) | (1 << 1) | (1 << 3) | (1 << 4) | (1 << 5) | (1 << 6);
// Set TIME(PJ0) to Output (UNUSED)
DDRJ |= (1 << 0);
DDRJ |= (1 << 0);
// Set Address/Data Pins AD0-AD7 (PC0-PC7) to Input
MODE_READ; // DDRC = 0
MODE_READ; // DDRC = 0
// Setting Control Pins to HIGH
// LE(PH0) ---(PH1) 1A(PH3) 1B(PH4) WE(PH5) OE(PH6)
PORTH |= (1 << 0) | (1 << 1) | (1 << 3) | (1 << 4) | (1 << 5) | (1 << 6);
// Set Unused Pins HIGH
PORTJ |= (1 << 0); // TIME(PJ0)
PORTJ |= (1 << 0); // TIME(PJ0)
// Multi-Pack Cart Check
check_multi_PCW();
@ -134,15 +138,13 @@ static const char pcwmenuItem1[] PROGMEM = "Read ROM";
static const char pcwmenuItem2[] PROGMEM = "Read SRAM";
static const char pcwmenuItem3[] PROGMEM = "Write SRAM";
static const char pcwmenuItem4[] PROGMEM = "Reset";
static const char* const menuOptionsPCW[] PROGMEM = {pcwmenuItem1, pcwmenuItem2, pcwmenuItem3, pcwmenuItem4};
static const char* const menuOptionsPCW[] PROGMEM = { pcwmenuItem1, pcwmenuItem2, pcwmenuItem3, pcwmenuItem4 };
void pcwMenu()
{
void pcwMenu() {
convertPgm(menuOptionsPCW, 4);
uint8_t mainMenu = question_box(F(" POCKET CHALLENGE W"), menuOptions, 4, 0);
switch (mainMenu)
{
switch (mainMenu) {
case 0:
// Read ROM
sd.chdir("/");
@ -178,8 +180,7 @@ void pcwMenu()
if (writeErrors == 0) {
println_Msg(F("SRAM verified OK"));
display_Update();
}
else {
} else {
print_Msg(F("Error: "));
print_Msg(writeErrors);
println_Msg(F(" bytes "));
@ -215,14 +216,15 @@ unsigned char read_rom_byte_PCW(unsigned long address) {
PORTK = (address >> 8) & 0xFF;
// Latch Address on AD0-AD7
ADDR_WRITE;
LE_HIGH; // Latch Enable
PORTC = address & 0xFF; // A0-A7
LE_LOW; // Address Latched
__asm__("nop\n\t""nop\n\t");
LE_HIGH; // Latch Enable
PORTC = address & 0xFF; // A0-A7
LE_LOW; // Address Latched
__asm__("nop\n\t"
"nop\n\t");
// Read Data on AD0-AD7
OE_LOW;
DATA_READ;
delayMicroseconds(5); // 3+ Microseconds for Problem Carts
delayMicroseconds(5); // 3+ Microseconds for Problem Carts
unsigned char data = PINC;
OE_HIGH;
@ -237,18 +239,33 @@ unsigned char read_ram_byte_1A_PCW(unsigned long address) {
PORTK = (address >> 8) & 0xFF;
// Latch Address on AD0-AD7
ADDR_WRITE;
LE_HIGH; // Latch Enable
PORTC = address & 0xFF; // A0-A7
LE_LOW; // Address Latched
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");
LE_HIGH; // Latch Enable
PORTC = address & 0xFF; // A0-A7
LE_LOW; // Address Latched
__asm__("nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t");
// Read Data on AD0-AD7
OE_LOW;
DATA_READ;
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");
__asm__("nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t");
unsigned char data = PINC;
OE_HIGH;
NAND_1A_HIGH;
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");
__asm__("nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t");
return data;
}
@ -267,18 +284,33 @@ unsigned char read_ram_byte_1B_PCW(unsigned long address) {
PORTK = (address >> 8) & 0xFF;
// Latch Address on AD0-AD7
ADDR_WRITE;
LE_HIGH; // Latch Enable
PORTC = address & 0xFF; // A0-A7
LE_LOW; // Address Latched
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");
LE_HIGH; // Latch Enable
PORTC = address & 0xFF; // A0-A7
LE_LOW; // Address Latched
__asm__("nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t");
// Read Data on AD0-AD7
OE_LOW;
DATA_READ;
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");
__asm__("nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t");
unsigned char data = PINC;
OE_HIGH;
NAND_1B_HIGH;
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");
__asm__("nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t");
return data;
}
@ -290,13 +322,16 @@ void write_ram_byte_1A_PCW(unsigned long address, unsigned char data) {
PORTK = (address >> 8) & 0xFF;
// Latch Address on AD0-AD7
ADDR_WRITE;
LE_HIGH; // Latch Enable
PORTC = address & 0xFF; // A0-A7
LE_LOW; // Address Latched
LE_HIGH; // Latch Enable
PORTC = address & 0xFF; // A0-A7
LE_LOW; // Address Latched
// Write Data on AD0-AD7 - WE LOW ~240-248ns
WE_LOW;
PORTC = data;
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t");
__asm__("nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t");
WE_HIGH;
NAND_1A_HIGH;
}
@ -311,14 +346,22 @@ void write_ram_byte_1B_PCW(unsigned long address, unsigned char data) {
PORTK = (address >> 8) & 0xFF;
// Latch Address on AD0-AD7
ADDR_WRITE;
LE_HIGH; // Latch Enable
PORTC = address & 0xFF; // A0-A7
LE_LOW; // Address Latched
LE_HIGH; // Latch Enable
PORTC = address & 0xFF; // A0-A7
LE_LOW; // Address Latched
// Write Data on AD0-AD7 - WE LOW ~740ns
WE_LOW;
PORTC = data;
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");
__asm__("nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t");
__asm__("nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t");
WE_HIGH;
NAND_1B_HIGH;
}
@ -353,18 +396,18 @@ void write_ram_byte_1B_PCW(unsigned long address, unsigned char data) {
// MULTI-PACK CART CHECK
void check_multi_PCW() {
read_setup_PCW();
byte tempbyte = read_rom_byte_PCW(0x3FFC); // Bank 0 Switch
byte tempbyte = read_rom_byte_PCW(0x3FFC); // Bank 0 Switch
if (tempbyte) {
bank0 = tempbyte; // Store Bank 0 Switch
tempbyte = read_rom_byte_PCW(0x3FFD); // Bank 1 Switch
bank0 = tempbyte; // Store Bank 0 Switch
tempbyte = read_rom_byte_PCW(0x3FFD); // Bank 1 Switch
if (tempbyte) {
bank1 = tempbyte; // Store Bank 1 Switch
bank1 = tempbyte; // Store Bank 1 Switch
// Check for 00s
tempbyte = read_rom_byte_PCW(0x3FFB); // Should be 00
tempbyte = read_rom_byte_PCW(0x3FFB); // Should be 00
if (!tempbyte) {
tempbyte = read_rom_byte_PCW(0x3FFF); // Should be 00
tempbyte = read_rom_byte_PCW(0x3FFF); // Should be 00
if (!tempbyte)
multipack = 1; // Flag Multi-Cart
multipack = 1; // Flag Multi-Cart
else {
bank0 = 0;
bank1 = 0;
@ -380,26 +423,33 @@ void write_bank_byte_PCW(unsigned char data) {
NAND_1B_LOW;
// Write to Address 0xFFFF
PORTL = 0x00;
PORTK = 0xFF; // A8-A15
PORTK = 0xFF; // A8-A15
// Latch Address on AD0-AD7
ADDR_WRITE;
LE_HIGH; // Latch Enable
PORTC = 0xFF; // A0-A7
LE_LOW; // Address Latched
LE_HIGH; // Latch Enable
PORTC = 0xFF; // A0-A7
LE_LOW; // Address Latched
// Write Data on AD0-AD7 - WE LOW ~728-736ns
WE_LOW;
PORTC = data;
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");
__asm__("nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t");
__asm__("nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t");
WE_HIGH;
NAND_1B_HIGH;
}
void switchBank_PCW(int bank) {
if (bank == 1) { // Upper Half
if (bank == 1) { // Upper Half
write_bank_byte_PCW(bank1);
}
else { // Lower Half (default)
} else { // Lower Half (default)
write_bank_byte_PCW(bank0);
}
}
@ -430,7 +480,7 @@ void readROM_PCW() {
print_Error(F("SD Error"), true);
}
read_setup_PCW();
for (unsigned long address = 0; address < 0x400000; address += 512) { // 4MB
for (unsigned long address = 0; address < 0x400000; address += 512) { // 4MB
for (unsigned int x = 0; x < 512; x++) {
sdBuffer[x] = read_rom_byte_PCW(address + x);
}
@ -478,7 +528,7 @@ void readMultiROM_PCW() {
read_setup_PCW();
// Lower Half
switchBank_PCW(0);
for (unsigned long address = 0; address < 0x200000; address += 512) { // 2MB
for (unsigned long address = 0; address < 0x200000; address += 512) { // 2MB
for (unsigned int x = 0; x < 512; x++) {
sdBuffer[x] = read_rom_byte_PCW(address + x);
}
@ -487,7 +537,7 @@ void readMultiROM_PCW() {
read_setup_PCW();
// Upper Half
switchBank_PCW(1);
for (unsigned long address = 0x200000; address < 0x400000; address += 512) { // 2MB
for (unsigned long address = 0x200000; address < 0x400000; address += 512) { // 2MB
for (unsigned int x = 0; x < 512; x++) {
sdBuffer[x] = read_rom_byte_PCW(address + x);
}
@ -513,7 +563,7 @@ void readMultiROM_PCW() {
// SRAM
//******************************************
void readSRAM_PCW() { // readSRAM_1A()
void readSRAM_PCW() { // readSRAM_1A()
strcpy(fileName, romName);
strcat(fileName, ".srm");
@ -530,7 +580,7 @@ void readSRAM_PCW() { // readSRAM_1A()
}
display_Clear();
read_setup_PCW();
for (unsigned long address = 0x0; address < 0x8000; address += 512) { // 32K
for (unsigned long address = 0x0; address < 0x8000; address += 512) { // 32K
for (unsigned int x = 0; x < 512; x++) {
sdBuffer[x] = read_ram_byte_1A_PCW(address + x);
}
@ -563,7 +613,7 @@ void writeSRAM_PCW() {
//open file on sd card
if (myFile.open(filePath, O_READ)) {
read_setup_PCW();
for (unsigned int address = 0x0; address < 0x8000; address += 512) { // 32K
for (unsigned int address = 0x0; address < 0x8000; address += 512) { // 32K
myFile.read(sdBuffer, 512);
for (unsigned int x = 0; x < 512; x++) {
write_ram_byte_1A_PCW(address + x, sdBuffer[x]);
@ -572,12 +622,10 @@ void writeSRAM_PCW() {
myFile.close();
println_Msg(F("Done"));
display_Update();
}
else {
} else {
print_Error(F("SD Error"), true);
}
}
else {
} else {
print_Error(F("SD Error"), true);
}
display_Clear();
@ -588,7 +636,7 @@ unsigned long verifySRAM_PCW() {
if (myFile.open(filePath, O_READ)) {
read_setup_PCW();
for (unsigned int address = 0x0; address < 0x8000; address += 512) { // 32K
for (unsigned int address = 0x0; address < 0x8000; address += 512) { // 32K
for (unsigned int x = 0; x < 512; x++) {
byte myByte = read_ram_byte_1A_PCW(address + x);
sdBuffer[x] = myByte;
@ -600,8 +648,7 @@ unsigned long verifySRAM_PCW() {
}
}
myFile.close();
}
else {
} else {
print_Error(F("SD Error"), true);
}

View File

@ -35,7 +35,7 @@ boolean hirom[8];
static const char sfmMenuItem1[] PROGMEM = "Game Menu";
static const char sfmMenuItem2[] PROGMEM = "Flash Menu";
static const char sfmMenuItem3[] PROGMEM = "Reset";
static const char* const menuOptionsSFM[] PROGMEM = {sfmMenuItem1, sfmMenuItem2, sfmMenuItem3};
static const char* const menuOptionsSFM[] PROGMEM = { sfmMenuItem1, sfmMenuItem2, sfmMenuItem3 };
// SFM flash menu items
static const char sfmFlashMenuItem1[] PROGMEM = "Read Flash";
@ -44,7 +44,7 @@ static const char sfmFlashMenuItem3[] PROGMEM = "Print Mapping";
static const char sfmFlashMenuItem4[] PROGMEM = "Read Mapping";
static const char sfmFlashMenuItem5[] PROGMEM = "Write Mapping";
static const char sfmFlashMenuItem6[] PROGMEM = "Back";
static const char* const menuOptionsSFMFlash[] PROGMEM = {sfmFlashMenuItem1, sfmFlashMenuItem2, sfmFlashMenuItem3, sfmFlashMenuItem4, sfmFlashMenuItem5, sfmFlashMenuItem6};
static const char* const menuOptionsSFMFlash[] PROGMEM = { sfmFlashMenuItem1, sfmFlashMenuItem2, sfmFlashMenuItem3, sfmFlashMenuItem4, sfmFlashMenuItem5, sfmFlashMenuItem6 };
// SFM game menu items
static const char sfmGameMenuItem1[] PROGMEM = "Read Sram";
@ -52,7 +52,7 @@ static const char sfmGameMenuItem2[] PROGMEM = "Read Game";
static const char sfmGameMenuItem3[] PROGMEM = "Write Sram";
static const char sfmGameMenuItem4[] PROGMEM = "Switch Game";
static const char sfmGameMenuItem5[] PROGMEM = "Reset";
static const char* const menuOptionsSFMGame[] PROGMEM = {sfmGameMenuItem1, sfmGameMenuItem2, sfmGameMenuItem3, sfmGameMenuItem4, sfmGameMenuItem5};
static const char* const menuOptionsSFMGame[] PROGMEM = { sfmGameMenuItem1, sfmGameMenuItem2, sfmGameMenuItem3, sfmGameMenuItem4, sfmGameMenuItem5 };
void sfmMenu() {
// create menu with title and 3 options to choose from
@ -62,8 +62,7 @@ void sfmMenu() {
mainMenu = question_box(F("SF Memory"), menuOptions, 3, 0);
// wait for user choice to come back from the question box menu
switch (mainMenu)
{
switch (mainMenu) {
// Game menu
case 0:
sfmGameMenu();
@ -127,8 +126,7 @@ void sfmGameMenu() {
// Print info
getCartInfo_SFM();
mode = mode_SFM_Game;
}
else {
} else {
// No menu so switch to only game
// Switch to game
send_SFM(0x80);
@ -141,8 +139,7 @@ void sfmGameMenu() {
getCartInfo_SFM();
mode = mode_SFM_Game;
}
}
else {
} else {
print_Error(F("Switch to HiRom failed"), false);
}
}
@ -155,8 +152,7 @@ void sfmGameOptions() {
gameSubMenu = question_box(F("SFM Game Menu"), menuOptions, 5, 0);
// wait for user choice to come back from the question box menu
switch (gameSubMenu)
{
switch (gameSubMenu) {
// Read sram
case 0:
display_Clear();
@ -185,8 +181,7 @@ void sfmGameOptions() {
if (wrErrors == 0) {
println_Msg(F("Verified OK"));
display_Update();
}
else {
} else {
print_Msg(F("Error: "));
print_Msg(wrErrors);
println_Msg(F(" bytes "));
@ -221,8 +216,7 @@ void sfmFlashMenu() {
flashSubMenu = question_box(F("SFM Flash Menu"), menuOptions, 6, 0);
// wait for user choice to come back from the question box menu
switch (flashSubMenu)
{
switch (flashSubMenu) {
// Read Flash
case 0:
// Clear screen
@ -258,8 +252,7 @@ void sfmFlashMenu() {
// Read flash
readFlash_SFM();
}
else {
} else {
print_Error(F("Switch to HiRom failed"), false);
}
break;
@ -328,16 +321,13 @@ void sfmFlashMenu() {
printMapping();
resetFlash_SFM(0xC0);
resetFlash_SFM(0xE0);
}
else {
} else {
print_Error(F("Error: Wrong Flash ID"), true);
}
}
else {
} else {
print_Error(F("Error: Wrong Flash ID"), true);
}
}
else {
} else {
print_Error(F("failed"), false);
}
break;
@ -368,16 +358,13 @@ void sfmFlashMenu() {
readMapping();
resetFlash_SFM(0xC0);
resetFlash_SFM(0xE0);
}
else {
} else {
print_Error(F("Error: Wrong Flash ID"), true);
}
}
else {
} else {
print_Error(F("Error: Wrong Flash ID"), true);
}
}
else {
} else {
print_Error(F("failed"), false);
}
break;
@ -410,8 +397,7 @@ void sfmFlashMenu() {
if (blankcheckMapping_SFM()) {
println_Msg(F("OK"));
display_Update();
}
else {
} else {
println_Msg(F("Nope"));
break;
}
@ -458,7 +444,7 @@ void getGames() {
controlIn_SFM();
// Check if menu is present
byte menuString[] = {0x4D, 0x45, 0x4E, 0x55, 0x20, 0x50, 0x52, 0x4F, 0x47, 0x52, 0x41, 0x4D};
byte menuString[] = { 0x4D, 0x45, 0x4E, 0x55, 0x20, 0x50, 0x52, 0x4F, 0x47, 0x52, 0x41, 0x4D };
for (int i = 0; i < 12; i++) {
if (menuString[i] != readBank_SFM(0xC0, 0x7FC0 + i)) {
hasMenu = false;
@ -468,7 +454,7 @@ void getGames() {
if (hasMenu) {
// Count number of games
for (word i = 0x0000; i < 0xE000; i += 0x2000) {
if (readBank_SFM(0xC6, i) == numGames )
if (readBank_SFM(0xC6, i) == numGames)
numGames++;
}
@ -482,11 +468,9 @@ void getGames() {
//check if hirom
if (readBank_SFM(gameAddress[i], 0xFFD5) == 0x31) {
hirom[i] = true;
}
else if (readBank_SFM(gameAddress[i], 0xFFD5) == 0x21) {
} else if (readBank_SFM(gameAddress[i], 0xFFD5) == 0x21) {
hirom[i] = true;
}
else {
} else {
hirom[i] = false;
}
@ -510,13 +494,11 @@ void getGames() {
// End char array in case game code is less than 9 chars
gameCode[i][myLength] = '\0';
}
}
else {
} else {
//check if hirom
if (readBank_SFM(0xC0, 0xFFD5) == 0x31) {
hirom[0] = true;
}
else {
} else {
hirom[0] = false;
}
@ -537,8 +519,7 @@ void getGames() {
gameSize[0] = 1;
while (romSizeExp--)
gameSize[0] *= 2;
}
else {
} else {
gameVersion[0] = readBank_SFM(0xC0, 0x7FDB);
gameCode[0][0] = 'G';
gameCode[0][1] = 'A';
@ -674,19 +655,56 @@ void writeBank_SFM(byte myBank, word myAddress, byte myData) {
// Arduino running at 16Mhz -> one nop = 62.5ns
// Wait till output is stable
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");
__asm__("nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t");
// Switch WR(PH5) to LOW
PORTH &= ~(1 << 5);
// Leave WR low for at least 60ns
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");
__asm__("nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t");
// Switch WR(PH5) to HIGH
PORTH |= (1 << 5);
// Leave WR high for at least 50ns
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");
__asm__("nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t");
}
// Read one byte of data from a location specified by bank and address, 00:0000
@ -696,7 +714,22 @@ byte readBank_SFM(byte myBank, word myAddress) {
PORTK = (myAddress >> 8) & 0xFF;
// Arduino running at 16Mhz -> one nop = 62.5ns -> 1000ns total
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");
__asm__("nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t");
// Read
byte tempByte = PINC;
@ -781,10 +814,9 @@ boolean checkcart_SFM() {
romType = readBank_SFM(0, 0xFFD5);
if ((romType >> 5) != 1) { // Detect invalid romType byte due to too long ROM name (22 chars)
romType = 0; // LoROM // Krusty's Super Fun House (U) 1.0 & Contra 3 (U)
}
else {
romType &= 1; // Must be LoROM or HiROM
romType = 0; // LoROM // Krusty's Super Fun House (U) 1.0 & Contra 3 (U)
} else {
romType &= 1; // Must be LoROM or HiROM
}
// Check RomSize
@ -846,8 +878,7 @@ boolean checkcart_SFM() {
sramSize = 1;
while (sramSizeExp--)
sramSize *= 2;
}
else {
} else {
sramSize = 0;
}
@ -855,11 +886,10 @@ boolean checkcart_SFM() {
romVersion = readBank_SFM(0, 65499);
// Test if checksum is equal to reverse checksum
if (((word(readBank_SFM(0, 65500)) + (word(readBank_SFM(0, 65501)) * 256)) + (word(readBank_SFM(0, 65502)) + (word(readBank_SFM(0, 65503)) * 256))) == 65535 ) {
if (((word(readBank_SFM(0, 65500)) + (word(readBank_SFM(0, 65501)) * 256)) + (word(readBank_SFM(0, 65502)) + (word(readBank_SFM(0, 65503)) * 256))) == 65535) {
if (strcmp("0000", checksumStr) == 0) {
return 0;
}
else {
} else {
return 1;
}
}
@ -953,8 +983,7 @@ void resetFlash_SFM(int startBank) {
writeBank_SFM(startBank, 0x5555L * 2, 0xaa);
writeBank_SFM(startBank, 0x2AAAL * 2, 0x55);
writeBank_SFM(startBank, 0x5555L * 2, 0xf0);
}
else {
} else {
writeBank_SFM(1, 0x8000 + 0x1555L * 2, 0xaa);
writeBank_SFM(0, 0x8000 + 0x2AAAL * 2, 0x55);
writeBank_SFM(1, 0x8000 + 0x1555L * 2, 0xf0);
@ -981,8 +1010,7 @@ void idFlash_SFM(int startBank) {
// Read the two id bytes into a string
sprintf(flashid, "%x%x", readBank_SFM(startBank, 0x00), readBank_SFM(startBank, 0x02));
}
else {
} else {
writeBank_SFM(1, 0x8000 + 0x1555L * 2, 0xaa);
writeBank_SFM(0, 0x8000 + 0x2AAAL * 2, 0x55);
writeBank_SFM(1, 0x8000 + 0x1555L * 2, 0x90);
@ -1042,8 +1070,7 @@ void writeFlash_SFM(int startBank, uint32_t pos) {
busyCheck_SFM(startBank);
}
}
}
else {
} else {
// Write lorom
for (int currBank = 0; currBank < numBanks; currBank++) {
for (unsigned long currByte = 0x8000; currByte < 0x10000; currByte += 128) {
@ -1070,8 +1097,7 @@ void writeFlash_SFM(int startBank, uint32_t pos) {
// Close the file:
myFile.close();
println_Msg("");
}
else {
} else {
print_Error(F("Can't open file on SD"), true);
}
}
@ -1126,8 +1152,7 @@ void eraseFlash_SFM(int startBank) {
writeBank_SFM(startBank, 0x5555L * 2, 0xaa);
writeBank_SFM(startBank, 0x2AAAL * 2, 0x55);
writeBank_SFM(startBank, 0x5555L * 2, 0x10);
}
else {
} else {
writeBank_SFM(1, 0x8000 + 0x1555L * 2, 0xaa);
writeBank_SFM(0, 0x8000 + 0x2AAAL * 2, 0x55);
writeBank_SFM(1, 0x8000 + 0x1555L * 2, 0x80);
@ -1153,13 +1178,12 @@ byte blankcheck_SFM(int startBank) {
for (int currBank = startBank; currBank < startBank + numBanks; currBank++) {
for (unsigned long currByte = 0; currByte < 0x10000; currByte++) {
if (readBank_SFM(currBank, currByte) != 0xFF) {
currBank = startBank + numBanks;
currBank = startBank + numBanks;
blank = 0;
}
}
}
}
else {
} else {
for (int currBank = 0; currBank < numBanks; currBank++) {
for (unsigned long currByte = 0x8000; currByte < 0x10000; currByte++) {
if (readBank_SFM(currBank, currByte) != 0xFF) {
@ -1174,7 +1198,7 @@ byte blankcheck_SFM(int startBank) {
// Check if a write succeeded, returns 0 if all is ok and number of errors if not
unsigned long verifyFlash_SFM(int startBank, uint32_t pos) {
unsigned long verified = 0;
unsigned long verified = 0;
// Open file on sd card
if (myFile.open(filePath, O_READ)) {
@ -1199,8 +1223,7 @@ unsigned long verifyFlash_SFM(int startBank, uint32_t pos) {
}
}
}
}
else {
} else {
for (int currBank = 0; currBank < numBanks; currBank++) {
for (unsigned long currByte = 0x8000; currByte < 0x10000; currByte += 512) {
// Fill SDBuffer
@ -1215,8 +1238,7 @@ unsigned long verifyFlash_SFM(int startBank, uint32_t pos) {
}
// Close the file:
myFile.close();
}
else {
} else {
// SD Error
verified = 999999;
print_Error(F("Can't open file on SD"), false);
@ -1250,8 +1272,7 @@ void readFlash_SFM() {
myFile.write(sdBuffer, 512);
}
}
}
else {
} else {
for (int currBank = 0; currBank < numBanks; currBank++) {
for (unsigned long currByte = 0x8000; currByte < 0x10000; currByte += 512) {
for (int c = 0; c < 512; c++) {
@ -1320,7 +1341,7 @@ void printMapping() {
for (int currByte = 0xFF00; currByte < 0xFF50; currByte += 10) {
for (int c = 0; c < 10; c++) {
itoa (readBank_SFM(0xC0, currByte + c), buffer, 16);
itoa(readBank_SFM(0xC0, currByte + c), buffer, 16);
for (int i = 0; i < 2 - strlen(buffer); i++) {
print_Msg(F("0"));
}
@ -1469,12 +1490,10 @@ void eraseMapping(byte startBank) {
// Switch to read
dataIn();
controlIn_SFM();
}
else {
} else {
print_Error(F("Error: Wrong Flash ID"), true);
}
}
else {
} else {
print_Error(F("Unlock failed"), true);
}
}
@ -1599,20 +1618,17 @@ void writeMapping_SFM(byte startBank, uint32_t pos) {
// Close the file:
myFile.close();
println_Msg("");
}
else {
} else {
print_Error(F("Can't open file on SD"), false);
}
// Switch to read
dataIn();
controlIn_SFM();
}
else {
} else {
print_Error(F("Error: Wrong Flash ID"), true);
}
}
else {
} else {
print_Error(F("Unlock failed"), true);
}
}
@ -1636,14 +1652,12 @@ boolean unlockHirom() {
println_Msg(F("OK"));
display_Update();
return 1;
}
else {
} else {
println_Msg(F("failed"));
display_Update();
return 0;
}
}
else {
} else {
println_Msg(F("failed"));
display_Update();
return 0;
@ -1709,8 +1723,7 @@ void write_SFM(int startBank, uint32_t pos) {
if (blankcheck_SFM(startBank)) {
println_Msg(F("OK"));
display_Update();
}
else {
} else {
println_Msg(F("Nope"));
display_Clear();
print_Msg(F("Erasing..."));
@ -1723,8 +1736,7 @@ void write_SFM(int startBank, uint32_t pos) {
if (blankcheck_SFM(startBank)) {
println_Msg(F("OK"));
display_Update();
}
else {
} else {
print_Error(F("Could not erase flash"), true);
}
}
@ -1741,19 +1753,16 @@ void write_SFM(int startBank, uint32_t pos) {
if (writeErrors == 0) {
println_Msg(F("OK"));
display_Update();
}
else {
} else {
print_Msg(F("Error: "));
print_Msg(writeErrors);
println_Msg(F(" bytes "));
print_Error(F("did not verify."), true);
}
}
else {
} else {
print_Error(F("Error: Wrong Flash ID"), true);
}
}
else {
} else {
print_Error(F("Unlock failed"), true);
}
}

View File

@ -12,7 +12,7 @@ static const char SMSAdapterItem2[] PROGMEM = "SG-1000 raphnet";
static const char SMSAdapterItem3[] PROGMEM = "SMS Retrode";
static const char SMSAdapterItem4[] PROGMEM = "GG Retrode";
static const char SMSAdapterItem5[] PROGMEM = "GG Retron 3in1";
static const char* const menuAdapterSMS[] PROGMEM = {SMSAdapterItem1, SMSAdapterItem2, SMSAdapterItem3, SMSAdapterItem4, SMSAdapterItem5};
static const char* const menuAdapterSMS[] PROGMEM = { SMSAdapterItem1, SMSAdapterItem2, SMSAdapterItem3, SMSAdapterItem4, SMSAdapterItem5 };
// MD menu items
static const char SMSMenuItem1[] PROGMEM = "Read Rom";
@ -20,7 +20,7 @@ static const char SMSMenuItem2[] PROGMEM = "Read from SRAM";
static const char SMSMenuItem3[] PROGMEM = "Write to SRAM";
static const char SMSMenuItem4[] PROGMEM = "Reset";
static const char SMSMenuItem5[] PROGMEM = "Change Retrode Mode";
static const char* const menuOptionsSMS[] PROGMEM = {SMSMenuItem1, SMSMenuItem2, SMSMenuItem3, SMSMenuItem4, SMSMenuItem5};
static const char* const menuOptionsSMS[] PROGMEM = { SMSMenuItem1, SMSMenuItem2, SMSMenuItem3, SMSMenuItem4, SMSMenuItem5 };
// Rom Size menu
static const char SMSRomItem1[] PROGMEM = "8KB";
@ -30,12 +30,12 @@ static const char SMSRomItem4[] PROGMEM = "32KB";
static const char SMSRomItem5[] PROGMEM = "40KB";
static const char SMSRomItem6[] PROGMEM = "48KB";
static const char SMSRomItem7[] PROGMEM = "512KB";
static const char* const romOptionsSMS[] PROGMEM = {SMSRomItem1, SMSRomItem2, SMSRomItem3, SMSRomItem4, SMSRomItem5, SMSRomItem6, SMSRomItem7};
static const char* const romOptionsSMS[] PROGMEM = { SMSRomItem1, SMSRomItem2, SMSRomItem3, SMSRomItem4, SMSRomItem5, SMSRomItem6, SMSRomItem7 };
// Set retrode_mode to true when using a retrode SMS/GG adapter
static bool retrode_mode = false;
static bool retrode_mode_sms = false; // true: SMS/Mark3 false: GG
static bool raphnet_mode_sg1000 = false; // true: SG-1000 false: SMS/Mark3
static bool retrode_mode_sms = false; // true: SMS/Mark3 false: GG
static bool raphnet_mode_sg1000 = false; // true: SG-1000 false: SMS/Mark3
static bool retron_mode = false;
@ -48,21 +48,18 @@ void _smsMenu() {
int noptions = sizeof(menuOptionsSMS) / sizeof(menuOptionsSMS[0]);
convertPgm(menuOptionsSMS, noptions);
mainMenu = question_box(retrode_mode ? (retrode_mode_sms ? F("Retrode:SMS") : F("Retrode:GG")) : F("SMS/GG Retrode:NO"), menuOptions, noptions, 0);
}
else if (retron_mode) {
} else if (retron_mode) {
// Copy menuOptions out of progmem
convertPgm(menuOptionsSMS, 4);
mainMenu = question_box(F("Game Gear"), menuOptions, 4, 0);
}
else {
} else {
// Copy menuOptions out of progmem
convertPgm(menuOptionsSMS, (raphnet_mode_sg1000 ? 1 : 4));
mainMenu = question_box((raphnet_mode_sg1000 ? F("SG-1000") : F("SMS/Mark III") ), menuOptions, (raphnet_mode_sg1000 ? 1 : 4), 0);
convertPgm(menuOptionsSMS, (raphnet_mode_sg1000 ? 1 : 4));
mainMenu = question_box((raphnet_mode_sg1000 ? F("SG-1000") : F("SMS/Mark III")), menuOptions, (raphnet_mode_sg1000 ? 1 : 4), 0);
}
// wait for user choice to come back from the question box menu
switch (mainMenu)
{
switch (mainMenu) {
case 0:
display_Clear();
mode = mode_SMS;
@ -72,8 +69,7 @@ void _smsMenu() {
readROM_SMS();
if ((retrode_mode && !retrode_mode_sms) || retron_mode) {
compareCRC("gg.txt", 0, 1, 0);
}
else {
} else {
compareCRC("sms.txt", 0, 1, 0);
}
#ifdef global_log
@ -117,8 +113,7 @@ void _smsMenu() {
if (retrode_mode) {
println_Msg(retrode_mode ? (retrode_mode_sms ? F("Retrode Mode SMS") : F("Retrode Mode GG")) : F("Retrode Mode Off"));
println_Msg(F("Press Button..."));
}
else {
} else {
println_Msg(F(""));
println_Msg(F("Press Button..."));
}
@ -134,8 +129,7 @@ void smsMenu() {
SMSAdapterMenu = question_box(F("Select System/Adapter"), menuOptions, 5, 0);
// wait for user choice to come back from the question box menu
switch (SMSAdapterMenu)
{
switch (SMSAdapterMenu) {
case 0:
// raphnet SMS/Mark3
retrode_mode = false;
@ -267,7 +261,10 @@ void writeByte_SMS(word myAddress, byte myData) {
// Arduino running at 16Mhz -> one nop = 62.5ns
// Wait till output is stable
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t");
__asm__("nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t");
if (retrode_mode) {
// Switch WR(PL5) and OE/CE(PH6) to LOW
@ -280,7 +277,10 @@ void writeByte_SMS(word myAddress, byte myData) {
}
// Leave WR low for at least 60ns
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t");
__asm__("nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t");
if (retrode_mode) {
// Switch WR(PL5) and OE/CE(PH6) to HIGH
@ -293,7 +293,10 @@ void writeByte_SMS(word myAddress, byte myData) {
}
// Leave WR high for at least 50ns
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t");
__asm__("nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t");
if (retrode_mode && !retrode_mode_sms) {
// Set Data Pins (D8-D15) to Input
@ -321,7 +324,10 @@ byte readByte_SMS(word myAddress) {
PORTH = (PORTH & 0b11110111) | ((myAddress >> 12) & 0b00001000);
}
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t");
__asm__("nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t");
if (retrode_mode) {
// Switch RD(PL6) and OE(PH6) to LOW
@ -333,7 +339,10 @@ byte readByte_SMS(word myAddress) {
PORTH &= ~(1 << 6);
}
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t");
__asm__("nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t");
// Read
byte tempByte = (retrode_mode && !retrode_mode_sms) ? PINA : PINC;
@ -348,7 +357,10 @@ byte readByte_SMS(word myAddress) {
PORTL |= (1 << 1);
}
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t");
__asm__("nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t");
return tempByte;
}
@ -372,38 +384,38 @@ void getCartInfo_SMS() {
switch (readNibble(readByte_SMS(0x7fff), 0)) {
case 0xa:
// Adding UL gets rid of integer overflow compiler warning
cartSize = 8 * 1024UL;
cartSize = 8 * 1024UL;
break;
case 0xb:
cartSize = 16 * 1024UL;
cartSize = 16 * 1024UL;
break;
case 0xc:
cartSize = 32 * 1024UL;
cartSize = 32 * 1024UL;
break;
case 0xd:
cartSize = 48 * 1024UL;
cartSize = 48 * 1024UL;
break;
case 0xe:
cartSize = 64 * 1024UL;
cartSize = 64 * 1024UL;
break;
case 0xf:
cartSize = 128 * 1024UL;
cartSize = 128 * 1024UL;
break;
case 0x0:
cartSize = 256 * 1024UL;
cartSize = 256 * 1024UL;
break;
case 0x1:
cartSize = 512 * 1024UL;
cartSize = 512 * 1024UL;
break;
case 0x2:
cartSize = 512 * 1024UL;
cartSize = 512 * 1024UL;
break;
case 0x3:
// 0x3 is (only?) used in The Pro Yakyuu '91 (Game Gear)
cartSize = 128 * 1024UL;
cartSize = 128 * 1024UL;
break;
default:
cartSize = 48 * 1024UL;
cartSize = 48 * 1024UL;
// LED Error
setColor_RGB(0, 0, 255);
@ -455,7 +467,7 @@ void getCartInfo_SMS() {
if (strcmp(headerFZ, "COPYRIGHT SEGAPRG. BY T.ASAI") == 0) {
strcpy(romName, "TMR SEGA");
cartSize = 128 * 1024UL;
cartSize = 128 * 1024UL;
}
}
@ -464,45 +476,44 @@ void getCartInfo_SMS() {
// Set cartsize manually
unsigned char SMSRomMenu;
// Copy menuOptions out of progmem
convertPgm(romOptionsSMS, (raphnet_mode_sg1000 ? 4 : 7));
SMSRomMenu = question_box(F("Select ROM size"), menuOptions, (raphnet_mode_sg1000 ? 4 : 7), 0);
convertPgm(romOptionsSMS, (raphnet_mode_sg1000 ? 4 : 7));
SMSRomMenu = question_box(F("Select ROM size"), menuOptions, (raphnet_mode_sg1000 ? 4 : 7), 0);
// wait for user choice to come back from the question box menu
switch (SMSRomMenu)
{
switch (SMSRomMenu) {
case 0:
// 8KB
cartSize = 8 * 1024UL;
cartSize = 8 * 1024UL;
break;
case 1:
// 16KB
cartSize = 16 * 1024UL;
cartSize = 16 * 1024UL;
break;
case 2:
// 24KB
cartSize = 24 * 1024UL;
cartSize = 24 * 1024UL;
break;
case 3:
// 32KB
cartSize = 32 * 1024UL;
cartSize = 32 * 1024UL;
break;
case 4:
// 40KB
cartSize = 40 * 1024UL;
cartSize = 40 * 1024UL;
break;
case 5:
// 48KB
cartSize = 48 * 1024UL;
cartSize = 48 * 1024UL;
break;
case 6:
// 512KB
cartSize = 512 * 1024UL;
cartSize = 512 * 1024UL;
break;
}
@ -523,8 +534,7 @@ void getCartInfo_SMS() {
display_Clear();
if ((retrode_mode && !retrode_mode_sms) || retron_mode) {
println_Msg(F("GG Header Info"));
}
else {
} else {
println_Msg(F("SMS Header Info"));
}
println_Msg(F(" "));
@ -552,8 +562,7 @@ void readROM_SMS() {
strcpy(fileName, romName);
if ((retrode_mode && !retrode_mode_sms) || retron_mode) {
strcat(fileName, ".gg");
}
else {
} else {
strcat(fileName, ".sms");
}
@ -561,8 +570,7 @@ void readROM_SMS() {
EEPROM_readAnything(0, foldern);
if ((retrode_mode && !retrode_mode_sms) || retron_mode) {
sprintf(folder, "GG/ROM/%s/%d", romName, foldern);
}
else {
} else {
sprintf(folder, "SMS/ROM/%s/%d", romName, foldern);
}
sd.mkdir(folder, true);
@ -609,7 +617,7 @@ void readROM_SMS() {
for (word currBuffer = 0; currBuffer < bankSize; currBuffer += 512) {
// Fill SD buffer
for (int currByte = 0; currByte < 512; currByte++) {
sdBuffer[currByte] = readByte_SMS((raphnet_mode_sg1000 || (cartSize == 32 * 1024UL) ? 0 : 0x8000) + currBuffer + currByte);
sdBuffer[currByte] = readByte_SMS((raphnet_mode_sg1000 || (cartSize == 32 * 1024UL) ? 0 : 0x8000) + currBuffer + currByte);
}
// hexdump for debugging:
// if (currBank == 0 && currBuffer == 0) {
@ -647,8 +655,7 @@ void readSRAM_SMS() {
EEPROM_readAnything(0, foldern);
if ((retrode_mode && !retrode_mode_sms) || retron_mode) {
sprintf(folder, "GG/SAVE/%s/%d", romName, foldern);
}
else {
} else {
sprintf(folder, "SMS/SAVE/%s/%d", romName, foldern);
}
sd.mkdir(folder, true);
@ -694,8 +701,7 @@ void writeSRAM_SMS() {
if (false) {
print_Error(F("DISABLED"), false);
}
else {
} else {
fileBrowser(F("Select file"));
sd.chdir();
@ -736,16 +742,15 @@ void writeSRAM_SMS() {
println_Msg(F(""));
println_Msg(F("DONE"));
display_Update();
}
else {
} else {
print_Error(F("SD ERROR"), true);
}
}
display_Clear();
sd.chdir(); // root
filePath[0] = '\0'; // Reset filePath
sd.chdir(); // root
filePath[0] = '\0'; // Reset filePath
}
#endif

File diff suppressed because it is too large Load Diff

View File

@ -17,7 +17,7 @@ extern void draw_progressbar(uint32_t processedsize, uint32_t totalsize);
//void svMenu();
void readROM_SV();
//void setup_SV();
void writeROM_SV (void);
void writeROM_SV(void);
void eraseCheck_SV(void);
void supplyCheck_SV(void);
void writeCheck_SV(void);
@ -38,7 +38,7 @@ static const char svFlashMenuItem2[] PROGMEM = "Write Memory Pack";
static const char svFlashMenuItem3[] PROGMEM = "Read BS-X Sram";
static const char svFlashMenuItem4[] PROGMEM = "Write BS-X Sram";
static const char svFlashMenuItem5[] PROGMEM = "Back";
static const char* const menuOptionsSVFlash[] PROGMEM = {svFlashMenuItem1, svFlashMenuItem2, svFlashMenuItem3, svFlashMenuItem4, svFlashMenuItem5};
static const char* const menuOptionsSVFlash[] PROGMEM = { svFlashMenuItem1, svFlashMenuItem2, svFlashMenuItem3, svFlashMenuItem4, svFlashMenuItem5 };
void svMenu() {
@ -49,8 +49,7 @@ void svMenu() {
mainMenu = question_box(F("Satellaview 8M Memory"), menuOptions, 5, 0);
// wait for user choice to come back from the question box menu
switch (mainMenu)
{
switch (mainMenu) {
// Read memory pack
case 0:
// Change working dir to root
@ -82,8 +81,7 @@ void svMenu() {
if (wrErrors == 0) {
println_Msg(F("Verified OK"));
display_Update();
}
else {
} else {
print_Msg(F("Error: "));
print_Msg(wrErrors);
println_Msg(F(" bytes "));
@ -181,7 +179,7 @@ void setup_SV() {
//PORTJ &= ~(1 << 0);
// Start CIC by outputting a low signal to cicrstPin(PG1)
PORTG &= ~(1 << 1);
PORTG &= ~(1 << 1);
// Wait for CIC reset
delay(1000);
@ -199,19 +197,56 @@ void writeBank_SV(byte myBank, word myAddress, byte myData) {
// Arduino running at 16Mhz -> one nop = 62.5ns
// Wait till output is stable
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");
__asm__("nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t");
// Switch WR(PH5) to LOW
PORTH &= ~(1 << 5);
// Leave WR low for at least 60ns
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");
__asm__("nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t");
// Switch WR(PH5) to HIGH
PORTH |= (1 << 5);
// Leave WR high for at least 50ns
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");
__asm__("nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t");
}
// Read one byte of data from a location specified by bank and address, 00:0000
@ -221,7 +256,22 @@ byte readBank_SV(byte myBank, word myAddress) {
PORTK = (myAddress >> 8) & 0xFF;
// Arduino running at 16Mhz -> one nop = 62.5ns -> 1000ns total
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");
__asm__("nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t");
// Read
byte tempByte = PINC;
@ -231,7 +281,7 @@ byte readBank_SV(byte myBank, word myAddress) {
/******************************************
SatellaView BS-X Sram functions
*****************************************/
void readSRAM_SV () {
void readSRAM_SV() {
// set control
controlIn_SNES();
@ -254,7 +304,7 @@ void readSRAM_SV () {
}
int sramBanks = 0;
readBank_SV(0x10, 0); // Preconfigure to fix corrupt 1st byte
readBank_SV(0x10, 0); // Preconfigure to fix corrupt 1st byte
// Sram size
long lastByte = (long(sramSize) * 0x80);
@ -325,8 +375,7 @@ void writeSRAM_SV() {
println_Msg("");
println_Msg(F("SRAM writing finished"));
display_Update();
}
else {
} else {
print_Error(F("File doesnt exist"), false);
}
}
@ -361,8 +410,7 @@ unsigned long verifySRAM_SV() {
// Close the file:
myFile.close();
return writeErrors;
}
else {
} else {
print_Error(F("Can't open file"), false);
}
}
@ -412,7 +460,7 @@ void readROM_SV() {
myFile.write(sdBuffer, 512);
}
}
draw_progressbar(0x100000, 0x100000); //Finish drawing progress bar
draw_progressbar(0x100000, 0x100000); //Finish drawing progress bar
// Close the file:
myFile.close();
@ -421,15 +469,14 @@ void readROM_SV() {
wait();
}
void writeROM_SV (void) {
void writeROM_SV(void) {
// Get Checksum as string to make sure that BS-X cart is inserted
dataIn();
controlIn_SNES();
sprintf(checksumStr, "%02X%02X", readBank_SV(0, 65503), readBank_SV(0, 65502));
//if CRC is not 8B86, BS-X cart is not inserted. Display error and reset
if (strcmp("8B86", checksumStr) != 0)
{
if (strcmp("8B86", checksumStr) != 0) {
display_Clear();
print_Error(F("Error: Must use BS-X cart"), true);
}
@ -457,8 +504,8 @@ void writeROM_SV (void) {
//Disable 8M memory pack write protection
dataOut();
controlOut_SNES();
writeBank_SV(0x0C, 0x5000, 0x80); //Modify write enable register
writeBank_SV(0x0E, 0x5000, 0x80); //Commit register modification
writeBank_SV(0x0C, 0x5000, 0x80); //Modify write enable register
writeBank_SV(0x0E, 0x5000, 0x80); //Commit register modification
//Erase memory pack
println_Msg(F("Erasing pack..."));
@ -474,8 +521,7 @@ void writeROM_SV (void) {
for (int currBank = 0xC0; currBank < 0xD0; currBank++) {
draw_progressbar(((currBank - 0xC0) * 0x10000), 0x100000);
for (long currByte = 0; currByte < 65536; currByte++) {
if (0xFF != readBank_SV(currBank, currByte))
{
if (0xFF != readBank_SV(currBank, currByte)) {
println_Msg(F(""));
println_Msg(F("Erase failed"));
display_Update();
@ -496,30 +542,29 @@ void writeROM_SV (void) {
draw_progressbar(((currBank - 0xC0) * 0x10000), 0x100000);
for (long currByte = 0; currByte < 65536; currByte++) {
writeBank_SV(0xC0, 0x0000, 0x10); //Program Byte
writeBank_SV(0xC0, 0x0000, 0x10); //Program Byte
writeBank_SV(currBank, currByte, myFile.read());
writeBank_SV(0xC0, 0x0000, 0x70); //Status Mode
writeBank_SV(0xC0, 0x0000, 0x70); //Status Mode
writeCheck_SV();
}
}
writeBank_SV(0xC0, 0x0000, 0x70); //Status Mode
writeBank_SV(0xC0, 0x0000, 0x70); //Status Mode
writeCheck_SV();
writeBank_SV(0xC0, 0x0000, 0xFF); //Terminate write
writeBank_SV(0xC0, 0x0000, 0xFF); //Terminate write
draw_progressbar(0x100000, 0x100000);
//Verify
dataIn(); //Set pins to input
dataIn(); //Set pins to input
controlIn_SNES();
myFile.seekSet(0); // Go back to file beginning
myFile.seekSet(0); // Go back to file beginning
println_Msg(F("Verifying..."));
display_Update();
for (int currBank = 0xC0; currBank < 0xD0; currBank++) {
draw_progressbar(((currBank - 0xC0) * 0x10000), 0x100000);
for (long currByte = 0; currByte < 65536; currByte++) {
if (myFile.read() != readBank_SV(currBank, currByte))
{
if (myFile.read() != readBank_SV(currBank, currByte)) {
println_Msg(F(""));
println_Msg(F("Verify failed"));
display_Update();
@ -537,8 +582,7 @@ void writeROM_SV (void) {
display_Update();
wait();
}
else {
} else {
print_Error(F("File doesn't exist"), false);
}
}
@ -553,15 +597,25 @@ void eraseCheck_SV(void) {
// CE or OE must be toggled with each subsequent status read or the
// completion of a program or erase operation will not be evident.
while ((ret & 0x80) == 0x00) { //Wait until X.bit7 = 1
while ((ret & 0x80) == 0x00) { //Wait until X.bit7 = 1
controlOut_SNES();
// Switch CS(PH3) High
PORTH |= (1 << 3);
// Leave CE high for at least 60ns
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");
__asm__("nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t");
controlIn_SNES();
// Leave CE low for at least 50ns
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");
__asm__("nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t");
// Read register
ret = readBank_SV(0xC0, 0x0004);
}
@ -580,15 +634,25 @@ void supplyCheck_SV(void) {
// CE or OE must be toggled with each subsequent status read or the
// completion of a program or erase operation will not be evident.
while ((ret & 0x08) == 0x08) { //Wait until X.bit3 = 0
while ((ret & 0x08) == 0x08) { //Wait until X.bit3 = 0
controlOut_SNES();
// Switch CS(PH3) High
PORTH |= (1 << 3);
// Leave CE high for at least 60ns
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");
__asm__("nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t");
controlIn_SNES();
// Leave CE low for at least 50ns
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");
__asm__("nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t");
// Read register
ret = readBank_SV(0xC0, 0x0004);
}
@ -612,10 +676,20 @@ void writeCheck_SV(void) {
// Switch CS(PH3) High
PORTH |= (1 << 3);
// Leave CE high for at least 60ns
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");
__asm__("nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t");
controlIn_SNES();
// Leave CE low for at least 50ns
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");
__asm__("nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t");
// Read register
ret = readBank_SV(0xC0, 0x0000);
}
@ -638,8 +712,7 @@ void detectCheck_SV(void) {
// completion of a program or erase operation will not be evident.
while ((ret & 0x80) == 0x00) {
i++;
if ( i > 10000)
{
if (i > 10000) {
//timeout
break;
}
@ -647,10 +720,20 @@ void detectCheck_SV(void) {
// Switch CS(PH3) High
PORTH |= (1 << 3);
// Leave CE high for at least 60ns
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");
__asm__("nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t");
controlIn_SNES();
// Leave CE low for at least 50ns
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");
__asm__("nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t");
// Read register
ret = readBank_SV(0xC0, 0x0002);
}
@ -660,18 +743,17 @@ void detectCheck_SV(void) {
}
void eraseAll_SV(void)
{
void eraseAll_SV(void) {
dataOut();
controlOut_SNES();
writeBank_SV(0xC0, 0x0000, 0x50); //Clear Status Registers
writeBank_SV(0xC0, 0x0000, 0x71); //Status Mode
writeBank_SV(0xC0, 0x0000, 0x50); //Clear Status Registers
writeBank_SV(0xC0, 0x0000, 0x71); //Status Mode
supplyCheck_SV();
writeBank_SV(0xC0, 0x0000, 0xA7); //Chip Erase
writeBank_SV(0xC0, 0x0000, 0xD0); //Confirm
writeBank_SV(0xC0, 0x0000, 0x71); //Status Mode
writeBank_SV(0xC0, 0x0000, 0xA7); //Chip Erase
writeBank_SV(0xC0, 0x0000, 0xD0); //Confirm
writeBank_SV(0xC0, 0x0000, 0x71); //Status Mode
eraseCheck_SV();
writeBank_SV(0xC0, 0x0000, 0xFF); //Teriminate
writeBank_SV(0xC0, 0x0000, 0xFF); //Teriminate
}
#endif

View File

@ -55,8 +55,7 @@
// SETUP
//******************************************
void setup_VBOY()
{
void setup_VBOY() {
// Set Address Pins to Output
//A0-A7
DDRF = 0xFF;
@ -70,7 +69,7 @@ void setup_VBOY()
DDRH |= (1 << 0) | (1 << 1) | (1 << 3) | (1 << 4) | (1 << 5) | (1 << 6);
// Set TIME(PJ0) to Output (UNUSED)
DDRJ |= (1 << 0);
DDRJ |= (1 << 0);
// Set Pins (D0-D15) to Input
DDRC = 0x00;
@ -83,7 +82,7 @@ void setup_VBOY()
PORTH &= ~(1 << 0);
// Set Unused Pins HIGH
PORTJ |= (1 << 0); // TIME(PJ0)
PORTJ |= (1 << 0); // TIME(PJ0)
getCartInfo_VB();
@ -99,15 +98,13 @@ static const char vboyMenuItem1[] PROGMEM = "Read ROM";
static const char vboyMenuItem2[] PROGMEM = "Read SRAM";
static const char vboyMenuItem3[] PROGMEM = "Write SRAM";
static const char vboyMenuItem4[] PROGMEM = "Reset";
static const char* const menuOptionsVBOY[] PROGMEM = {vboyMenuItem1, vboyMenuItem2, vboyMenuItem3, vboyMenuItem4};
static const char* const menuOptionsVBOY[] PROGMEM = { vboyMenuItem1, vboyMenuItem2, vboyMenuItem3, vboyMenuItem4 };
void vboyMenu()
{
void vboyMenu() {
convertPgm(menuOptionsVBOY, 4);
uint8_t mainMenu = question_box(F("VIRTUALBOY MENU"), menuOptions, 4, 0);
switch (mainMenu)
{
switch (mainMenu) {
case 0:
// Read ROM
sd.chdir("/");
@ -124,8 +121,7 @@ void vboyMenu()
display_Update();
readSRAM_VB();
sd.chdir("/");
}
else {
} else {
print_Error(F("Cart has no SRAM"), false);
}
#if (defined(enable_OLED) || defined(enable_LCD))
@ -148,15 +144,13 @@ void vboyMenu()
if (writeErrors == 0) {
println_Msg(F("SRAM verified OK"));
display_Update();
}
else {
} else {
print_Msg(F("Error: "));
print_Msg(writeErrors);
println_Msg(F(" bytes "));
print_Error(F("did not verify."), false);
}
}
else {
} else {
print_Error(F("Cart has no SRAM"), false);
}
#if (defined(enable_OLED) || defined(enable_LCD))
@ -192,12 +186,22 @@ void writeByte_VB(unsigned long myAddress, byte myData) {
// Set /CS1(PH4), /WE0(PH5) to LOW
PORTH &= ~(1 << 4) & ~(1 << 5);
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");
__asm__("nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t");
// Set CS2(PH0), /CS1(PH4), /WE0(PH5) to HIGH
PORTH |= (1 << 0) | (1 << 4) | (1 << 5);
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");
__asm__("nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t");
}
word readWord_VB(unsigned long myAddress) {
@ -212,21 +216,31 @@ word readWord_VB(unsigned long myAddress) {
// Set /CE(PH3), /OE(PH6) to LOW
PORTH &= ~(1 << 3) & ~(1 << 6);
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");
__asm__("nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t");
word tempWord = ( ( PINA & 0xFF ) << 8 ) | ( PINC & 0xFF );
word tempWord = ((PINA & 0xFF) << 8) | (PINC & 0xFF);
// Set /CE(PH3), /OE(PH6) to HIGH
PORTH |= (1 << 3) | (1 << 6);
// Setting CS2(PH0) LOW
PORTH &= ~(1 << 0);
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");
__asm__("nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t");
return tempWord;
}
byte readByte_VB(unsigned long myAddress) { // SRAM BYTE
byte readByte_VB(unsigned long myAddress) { // SRAM BYTE
PORTF = myAddress & 0xFF;
PORTK = (myAddress >> 8) & 0xFF;
PORTL = (myAddress >> 16) & 0xFF;
@ -238,18 +252,33 @@ byte readByte_VB(unsigned long myAddress) { // SRAM BYTE
// Set /CS1(PH4), /OE(PH6) to LOW
PORTH &= ~(1 << 4) & ~(1 << 6);
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");
__asm__("nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t");
byte tempByte = PINA;
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");
__asm__("nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t");
// Set /CS1(PH4), /OE(PH6) to HIGH
PORTH |= (1 << 3) | (1 << 6);
// Setting CS2(PH0) LOW
PORTH &= ~(1 << 0);
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");
__asm__("nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t");
return tempByte;
}
@ -277,52 +306,51 @@ void getCartInfo_VB() {
cartSize = 0;
for (unsigned long address = 0x80000; address <= 0x400000; address *= 2) {
// Get Serial
word vbSerial = readWord_VB((address - 0x204) / 2); // Cart Serial
word vbSerial = readWord_VB((address - 0x204) / 2); // Cart Serial
switch (vbSerial)
{
case 0x4D54: // MT = Mario's Tennis
case 0x4832: // H2 = Panic Bomber/Tobidase! Panibomb
case 0x5350: // SP = Space Invaders
case 0x5353: // SS = Space Squash
case 0x5452: // TR = V-Tetris
cartSize = 0x80000; // 512KB
switch (vbSerial) {
case 0x4D54: // MT = Mario's Tennis
case 0x4832: // H2 = Panic Bomber/Tobidase! Panibomb
case 0x5350: // SP = Space Invaders
case 0x5353: // SS = Space Squash
case 0x5452: // TR = V-Tetris
cartSize = 0x80000; // 512KB
break;
case 0x494D: // IM = Insmouse no Yakata
case 0x4A42: // JB = Jack Bros.
case 0x4D43: // MC = Mario Clash
case 0x5245: // RE = Red Alarm
case 0x4833: // H3 = Vertical Force
case 0x5642: // VB = Virtual Bowling
case 0x5646: // VF = Virtual Fishing
case 0x4A56: // JV = Virtual Lab
case 0x5650: // VP = Virtual League Baseball/Virtual Pro Yakyuu '95
cartSize = 0x100000; // 1MB
case 0x494D: // IM = Insmouse no Yakata
case 0x4A42: // JB = Jack Bros.
case 0x4D43: // MC = Mario Clash
case 0x5245: // RE = Red Alarm
case 0x4833: // H3 = Vertical Force
case 0x5642: // VB = Virtual Bowling
case 0x5646: // VF = Virtual Fishing
case 0x4A56: // JV = Virtual Lab
case 0x5650: // VP = Virtual League Baseball/Virtual Pro Yakyuu '95
cartSize = 0x100000; // 1MB
break;
case 0x5042: // PB = 3-D Tetris
case 0x4750: // GP = Galactic Pinball
case 0x5344: // SD = SD Gundam Dimension War
case 0x5442: // TB = Teleroboxer
cartSize = 0x100000; // 1MB
sramSize = 0x2000; // 8KB
case 0x5042: // PB = 3-D Tetris
case 0x4750: // GP = Galactic Pinball
case 0x5344: // SD = SD Gundam Dimension War
case 0x5442: // TB = Teleroboxer
cartSize = 0x100000; // 1MB
sramSize = 0x2000; // 8KB
break;
case 0x5647: // VG = Golf/T&E Virtual Golf
case 0x4E46: // NF = Nester's Funky Bowling
case 0x5745: // WE = Waterworld
cartSize = 0x200000; // 2MB
case 0x5647: // VG = Golf/T&E Virtual Golf
case 0x4E46: // NF = Nester's Funky Bowling
case 0x5745: // WE = Waterworld
cartSize = 0x200000; // 2MB
break;
case 0x5743: // WC = Virtual Boy Wario Land
cartSize = 0x200000; // 2MB
sramSize = 0x2000; // 8KB
case 0x5743: // WC = Virtual Boy Wario Land
cartSize = 0x200000; // 2MB
sramSize = 0x2000; // 8KB
break;
case 0x4644: // FD = Hyper Fighting
cartSize = 0x400000; // 4MB
sramSize = 0x2000; // 8KB
case 0x4644: // FD = Hyper Fighting
cartSize = 0x400000; // 4MB
sramSize = 0x2000; // 8KB
break;
}
@ -355,14 +383,13 @@ void getCartInfo_VB() {
print_Msg(F("Name: "));
println_Msg(romName);
print_Msg(F("Size: "));
print_Msg(cartSize * 8 / 1024 / 1024 );
print_Msg(cartSize * 8 / 1024 / 1024);
println_Msg(F(" MBit"));
print_Msg(F("Sram: "));
if (sramSize > 0) {
print_Msg(sramSize * 8 / 1024);
println_Msg(F(" KBit"));
}
else
} else
println_Msg(F("None"));
println_Msg(F(" "));
@ -413,20 +440,19 @@ void readROM_VB() {
for (int currWord = 0; currWord < 256; currWord++) {
word myWord = readWord_VB(currBuffer + currWord);
// Split word into two bytes
sdBuffer[d] = (( myWord >> 8 ) & 0xFF);
sdBuffer[d] = ((myWord >> 8) & 0xFF);
sdBuffer[d + 1] = (myWord & 0xFF);
d += 2;
}
myFile.write(sdBuffer, 512);
d = 0;
}
}
else {
} else {
for (unsigned long currBuffer = 0; currBuffer < cartSize / 2; currBuffer += 256) {
for (int currWord = 0; currWord < 256; currWord++) {
word myWord = readWord_VB(currBuffer + currWord);
// Split word into two bytes
sdBuffer[d] = (( myWord >> 8 ) & 0xFF);
sdBuffer[d] = ((myWord >> 8) & 0xFF);
sdBuffer[d + 1] = (myWord & 0xFF);
d += 2;
}
@ -469,8 +495,7 @@ void writeSRAM_VB() {
myFile.close();
println_Msg(F("Done"));
display_Update();
}
else {
} else {
print_Error(F("SD Error"), true);
}
dataIn_VB();
@ -524,8 +549,7 @@ unsigned long verifySRAM_VB() {
}
}
myFile.close();
}
else {
} else {
print_Error(F("SD Error"), true);
}

View File

@ -37,7 +37,7 @@ static const char wsMenuItem2[] PROGMEM = "Read Save";
static const char wsMenuItem3[] PROGMEM = "Write Save";
static const char wsMenuItem4[] PROGMEM = "Reset";
static const char wsMenuItem5[] PROGMEM = "Write WitchOS";
static const char* const menuOptionsWS[] PROGMEM = {wsMenuItem1, wsMenuItem2, wsMenuItem3, wsMenuItem4, wsMenuItem5};
static const char *const menuOptionsWS[] PROGMEM = { wsMenuItem1, wsMenuItem2, wsMenuItem3, wsMenuItem4, wsMenuItem5 };
static const uint8_t wwLaunchCode[] PROGMEM = { 0xea, 0x00, 0x00, 0x00, 0xe0, 0x00, 0xff, 0xff };
@ -47,8 +47,7 @@ static uint16_t wsGameChecksum = 0;
static uint8_t wsEepromShiftReg[2];
static boolean wsWitch = false;
void setup_WS()
{
void setup_WS() {
// A-1 - A6
DDRF = 0xff;
// A7 - A14
@ -88,8 +87,7 @@ void setup_WS()
do {
unlockMMC2003_WS();
}
while (!headerCheck());
} while (!headerCheck());
getCartInfo_WS();
@ -100,18 +98,18 @@ boolean headerCheck() {
dataIn_WS();
for (uint32_t i = 0; i < 16; i += 2)
* ((uint16_t*)(sdBuffer + i)) = readWord_WS(0xffff0 + i);
*((uint16_t *)(sdBuffer + i)) = readWord_WS(0xffff0 + i);
uint8_t startByte = sdBuffer[0];
if (startByte == 0xEA) { // Start should be 0xEA
if (startByte == 0xEA) { // Start should be 0xEA
uint8_t zeroByte = sdBuffer[5];
if (zeroByte == 0) { // Zero Byte
if (zeroByte == 0) { // Zero Byte
uint8_t systemByte = sdBuffer[7];
if (systemByte < 2) { // System < 2
if (systemByte < 2) { // System < 2
uint8_t revisionByte = sdBuffer[9];
if ((revisionByte < 7) || (revisionByte == 0x80)) { // Known Revisions: 0 to 6 and 0x80
if ((revisionByte < 7) || (revisionByte == 0x80)) { // Known Revisions: 0 to 6 and 0x80
uint8_t sizeByte = sdBuffer[10];
if (sizeByte < 10) // Rom Size < 10
if (sizeByte < 10) // Rom Size < 10
return true;
}
}
@ -120,15 +118,13 @@ boolean headerCheck() {
return false;
}
void wsMenu()
{
void wsMenu() {
uint8_t mainMenu = (wsWitch ? 5 : 4);
convertPgm(menuOptionsWS, mainMenu);
mainMenu = question_box(F("WS Menu"), menuOptions, mainMenu, 0);
switch (mainMenu)
{
switch (mainMenu) {
case 0:
{
// Read Rom
@ -142,8 +138,7 @@ void wsMenu()
{
// Read Save
sd.chdir("/");
switch (saveType)
{
switch (saveType) {
case 0: println_Msg(F("No save for this game")); break;
case 1: readSRAM_WS(); break;
case 2: readEEPROM_WS(); break;
@ -156,8 +151,7 @@ void wsMenu()
{
// Write Save
sd.chdir("/");
switch (saveType)
{
switch (saveType) {
case 0: println_Msg(F("No save for this game")); break;
case 1:
{
@ -184,7 +178,7 @@ void wsMenu()
default:
{
// reset
asm volatile (" jmp 0");
asm volatile(" jmp 0");
break;
}
}
@ -196,20 +190,18 @@ void wsMenu()
wait();
}
uint8_t getCartInfo_WS()
{
uint8_t getCartInfo_WS() {
dataIn_WS();
// for (uint32_t i = 0; i < 16; i += 2)
// *((uint16_t*)(sdBuffer + i)) = readWord_WS(0xffff0 + i);
wsGameChecksum = *(uint16_t*)(sdBuffer + 14);
wsGameChecksum = *(uint16_t *)(sdBuffer + 14);
wsWitch = false;
// some game has wrong info in header
// patch here
switch (wsGameChecksum)
{
switch (wsGameChecksum) {
// games with wrong save type/size
// 256kbits sram
case 0xe600: // BAN007
@ -247,11 +239,9 @@ uint8_t getCartInfo_WS()
{
// developerId/cartId/checksum are all filled with 0x00 in witch based games
dataIn_WS();
if (readWord_WS(0xf0000) == 0x4c45 && readWord_WS(0xf0002) == 0x5349 && readWord_WS(0xf0004) == 0x0041)
{
if (readWord_WS(0xf0000) == 0x4c45 && readWord_WS(0xf0002) == 0x5349 && readWord_WS(0xf0004) == 0x0041) {
// check witch BIOS
if (readWord_WS(0xfff5e) == 0x006c && readWord_WS(0xfff60) == 0x5b1b)
{
if (readWord_WS(0xfff5e) == 0x006c && readWord_WS(0xfff60) == 0x5b1b) {
// check flashchip
// should be a MBM29DL400TC
dataOut_WS();
@ -272,39 +262,30 @@ uint8_t getCartInfo_WS()
sdBuffer[8] = 0x03;
}
// check service menu
else if (readWord_WS(0xfff22) == 0x006c && readWord_WS(0xfff24) == 0x5b1b)
{
if (readWord_WS(0x93246) == 0x4a2f && readWord_WS(0x93248) == 0x5353 && readWord_WS(0x9324a) == 0x2e32)
{
else if (readWord_WS(0xfff22) == 0x006c && readWord_WS(0xfff24) == 0x5b1b) {
if (readWord_WS(0x93246) == 0x4a2f && readWord_WS(0x93248) == 0x5353 && readWord_WS(0x9324a) == 0x2e32) {
// jss2
sdBuffer[6] = 0xff; // WWGP
sdBuffer[8] = 0x1a; // 2001A
sdBuffer[7] = 0x01; // color only
sdBuffer[6] = 0xff; // WWGP
sdBuffer[8] = 0x1a; // 2001A
sdBuffer[7] = 0x01; // color only
if (readWord_WS(0x93e9c) == 0x4648 && readWord_WS(0x93e9e) == 0x0050)
{
if (readWord_WS(0x93e9c) == 0x4648 && readWord_WS(0x93e9e) == 0x0050) {
// WWGP2001A3 -> HFP Version
sdBuffer[9] = 0x03;
wsGameChecksum = 0x4870;
}
else
{
} else {
// TODO check other jss2 version
}
}
else if (readWord_WS(0xe4260) == 0x6b64 && readWord_WS(0xe4262) == 0x696e)
{
} else if (readWord_WS(0xe4260) == 0x6b64 && readWord_WS(0xe4262) == 0x696e) {
// dknight
sdBuffer[6] = 0xff; // WWGP
sdBuffer[8] = 0x2b; // 2002B
sdBuffer[7] = 0x01; // color only
sdBuffer[6] = 0xff; // WWGP
sdBuffer[8] = 0x2b; // 2002B
sdBuffer[7] = 0x01; // color only
sdBuffer[9] = 0x00;
wsGameChecksum = 0x8b1c;
}
}
}
else if (sdBuffer[6] == 0x2a && sdBuffer[8] == 0x01 && sdBuffer[9] == 0x01)
{
} else if (sdBuffer[6] == 0x2a && sdBuffer[8] == 0x01 && sdBuffer[9] == 0x01) {
// Mobile WonderGate v1.1, checksum is filled with 0x0000
wsGameChecksum = 0x1da0;
}
@ -313,7 +294,7 @@ uint8_t getCartInfo_WS()
}
}
romType = (sdBuffer[7] & 0x01); // wsc only = 1
romType = (sdBuffer[7] & 0x01); // wsc only = 1
romVersion = sdBuffer[9];
romSize = sdBuffer[10];
sramSize = sdBuffer[11];
@ -325,8 +306,7 @@ uint8_t getCartInfo_WS()
snprintf(checksumStr, 5, "%04X", wsGameChecksum);
snprintf(romName, 17, "%s%s", vendorID, cartID);
switch (romSize)
{
switch (romSize) {
case 0x01: cartSize = 131072 * 2; break;
case 0x02: cartSize = 131072 * 4; break;
case 0x03: cartSize = 131072 * 8; break;
@ -339,17 +319,43 @@ uint8_t getCartInfo_WS()
default: cartSize = 0; break;
}
switch (sramSize)
{
case 0x00: saveType = 0; sramSize = 0; break;
case 0x01: saveType = 1; sramSize = 64; break;
case 0x02: saveType = 1; sramSize = 256; break;
case 0x03: saveType = 1; sramSize = 1024; break;
case 0x04: saveType = 1; sramSize = 2048; break;
case 0x05: saveType = 1; sramSize = 4096; break;
case 0x10: saveType = 2; sramSize = 1; break;
case 0x20: saveType = 2; sramSize = 16; break;
case 0x50: saveType = 2; sramSize = 8; break;
switch (sramSize) {
case 0x00:
saveType = 0;
sramSize = 0;
break;
case 0x01:
saveType = 1;
sramSize = 64;
break;
case 0x02:
saveType = 1;
sramSize = 256;
break;
case 0x03:
saveType = 1;
sramSize = 1024;
break;
case 0x04:
saveType = 1;
sramSize = 2048;
break;
case 0x05:
saveType = 1;
sramSize = 4096;
break;
case 0x10:
saveType = 2;
sramSize = 1;
break;
case 0x20:
saveType = 2;
sramSize = 16;
break;
case 0x50:
saveType = 2;
sramSize = 8;
break;
default: saveType = 0xff; break;
}
@ -360,8 +366,7 @@ uint8_t getCartInfo_WS()
return sdBuffer[0];
}
void showCartInfo_WS()
{
void showCartInfo_WS() {
display_Clear();
println_Msg(F("WS Cart Info"));
@ -372,18 +377,24 @@ void showCartInfo_WS()
print_Msg(F("Rom Size: "));
if (cartSize == 0x00)
println_Msg(romSize, HEX);
else
{
else {
print_Msg((cartSize >> 17));
println_Msg(F(" Mb"));
}
print_Msg(F("Save: "));
switch (saveType)
{
switch (saveType) {
case 0: println_Msg(F("None")); break;
case 1: print_Msg(F("Sram ")); print_Msg(sramSize); println_Msg(F(" Kb")); break;
case 2: print_Msg(F("Eeprom ")); print_Msg(sramSize); println_Msg(F(" Kb")); break;
case 1:
print_Msg(F("Sram "));
print_Msg(sramSize);
println_Msg(F(" Kb"));
break;
case 2:
print_Msg(F("Eeprom "));
print_Msg(sramSize);
println_Msg(F(" Kb"));
break;
default: println_Msg(sramSize, HEX); break;
}
@ -398,15 +409,13 @@ void showCartInfo_WS()
wait();
}
void getDeveloperName(uint8_t id, char *buf, size_t length)
{
void getDeveloperName(uint8_t id, char *buf, size_t length) {
if (buf == NULL)
return;
char *devName = NULL;
switch (id)
{
switch (id) {
case 0x01: devName = PSTR("BAN"); break;
case 0x02: devName = PSTR("TAT"); break;
case 0x03: devName = PSTR("TMY"); break;
@ -433,7 +442,7 @@ void getDeveloperName(uint8_t id, char *buf, size_t length)
case 0x1e: devName = PSTR("NAP"); break;
case 0x1f: devName = PSTR("BVL"); break;
case 0x20: devName = PSTR("ATN"); break;
case 0x21: devName = PSTR("KDX"); break; // KDK for Memories of Festa?
case 0x21: devName = PSTR("KDX"); break; // KDK for Memories of Festa?
case 0x22: devName = PSTR("HAL"); break;
case 0x23: devName = PSTR("YKE"); break;
case 0x24: devName = PSTR("OMM"); break;
@ -452,17 +461,18 @@ void getDeveloperName(uint8_t id, char *buf, size_t length)
// custom developerId
case 0x7a: devName = PSTR("7AC"); break; // witch
case 0xff: devName = PSTR("WWGP"); break; // WWGP series (jss2, dknight)
case 0xff:
devName = PSTR("WWGP");
break; // WWGP series (jss2, dknight)
// if not found, use id
default: snprintf(buf, length, "%02X", id); return;
default: snprintf(buf, length, "%02X", id); return;
}
strlcpy_P(buf, devName, length);
}
void readROM_WS(char *outPathBuf, size_t bufferSize)
{
void readROM_WS(char *outPathBuf, size_t bufferSize) {
// generate fullname of rom file
snprintf(fileName, FILENAME_LENGTH, "%s.ws%c", romName, ((romType & 1) ? 'c' : '\0'));
@ -497,8 +507,7 @@ void readROM_WS(char *outPathBuf, size_t bufferSize)
draw_progressbar(0, cartSize);
// start reading rom
for (; bank <= 0xff; bank++)
{
for (; bank <= 0xff; bank++) {
// switch bank on segment 0x2
dataOut_WS();
writeByte_WSPort(0xc2, bank);
@ -508,14 +517,13 @@ void readROM_WS(char *outPathBuf, size_t bufferSize)
writeByte_WSPort(0xcd, (bank & 0x03));
dataIn_WS();
for (uint32_t addr = 0; addr < 0x10000; addr += 512)
{
for (uint32_t addr = 0; addr < 0x10000; addr += 512) {
// blink LED
if ((addr & ((1 << 14) - 1)) == 0)
blinkLED();
for (uint32_t w = 0; w < 512; w += 2)
* ((uint16_t*)(sdBuffer + w)) = readWord_WS(0x20000 + addr + w);
*((uint16_t *)(sdBuffer + w)) = readWord_WS(0x20000 + addr + w);
myFile.write(sdBuffer, 512);
progress += 512;
@ -525,8 +533,7 @@ void readROM_WS(char *outPathBuf, size_t bufferSize)
}
// turn off LEDs (only for BANC33)
if (wsGameChecksum == 0xeafd)
{
if (wsGameChecksum == 0xeafd) {
dataOut_WS();
writeByte_WSPort(0xcd, 0x00);
}
@ -534,8 +541,7 @@ void readROM_WS(char *outPathBuf, size_t bufferSize)
myFile.close();
}
void readSRAM_WS()
{
void readSRAM_WS() {
// generate fullname of rom file
snprintf(fileName, FILENAME_LENGTH, "%s.sav", romName);
@ -565,14 +571,12 @@ void readSRAM_WS()
uint16_t bank = 0;
do
{
do {
dataOut_WS();
writeByte_WSPort(0xc1, bank);
dataIn_WS();
for (uint32_t addr = 0; addr < bank_size; addr += 512)
{
for (uint32_t addr = 0; addr < bank_size; addr += 512) {
// blink LED
if ((addr & ((1 << 14) - 1)) == 0)
blinkLED();
@ -591,13 +595,11 @@ void readSRAM_WS()
display_Update();
}
void verifySRAM_WS()
{
void verifySRAM_WS() {
print_Msg(F("Verifying... "));
display_Update();
if (myFile.open(filePath, O_READ))
{
if (myFile.open(filePath, O_READ)) {
uint32_t bank_size = (sramSize << 7);
uint16_t end_bank = (bank_size >> 16); // 64KB per bank
uint16_t bank = 0;
@ -606,19 +608,16 @@ void verifySRAM_WS()
if (bank_size > 0x10000)
bank_size = 0x10000;
do
{
do {
dataOut_WS();
writeByte_WSPort(0xc1, bank);
dataIn_WS();
for (uint32_t addr = 0; addr < bank_size && myFile.available(); addr += 512)
{
for (uint32_t addr = 0; addr < bank_size && myFile.available(); addr += 512) {
myFile.read(sdBuffer, 512);
// SRAM data on D0-D7, with A-1 to select high/low byte
for (uint32_t w = 0; w < 512; w++)
{
for (uint32_t w = 0; w < 512; w++) {
if (readByte_WS(0x10000 + addr + w) != sdBuffer[w])
write_errors++;
}
@ -627,27 +626,21 @@ void verifySRAM_WS()
myFile.close();
if (write_errors == 0)
{
if (write_errors == 0) {
println_Msg(F("passed"));
}
else
{
} else {
println_Msg(F("failed"));
print_Msg(F("Error: "));
print_Msg(write_errors);
println_Msg(F(" bytes "));
print_Error(F("did not verify."), false);
}
}
else
{
} else {
print_Error(F("File doesn't exist"), false);
}
}
void writeSRAM_WS()
{
void writeSRAM_WS() {
filePath[0] = 0;
sd.chdir("/");
fileBrowser(F("Select sav file"));
@ -659,8 +652,7 @@ void writeSRAM_WS()
println_Msg(F("..."));
display_Update();
if (myFile.open(filePath, O_READ))
{
if (myFile.open(filePath, O_READ)) {
uint32_t bank_size = (sramSize << 7);
uint16_t end_bank = (bank_size >> 16); // 64KB per bank
@ -669,12 +661,10 @@ void writeSRAM_WS()
uint16_t bank = 0;
dataOut_WS();
do
{
do {
writeByte_WSPort(0xc1, bank);
for (uint32_t addr = 0; addr < bank_size && myFile.available(); addr += 512)
{
for (uint32_t addr = 0; addr < bank_size && myFile.available(); addr += 512) {
// blink LED
if ((addr & ((1 << 14) - 1)) == 0)
blinkLED();
@ -691,15 +681,12 @@ void writeSRAM_WS()
println_Msg(F("Writing finished"));
display_Update();
}
else
{
} else {
print_Error(F("File doesn't exist"), false);
}
}
void readEEPROM_WS()
{
void readEEPROM_WS() {
// generate fullname of eep file
snprintf(fileName, FILENAME_LENGTH, "%s.eep", romName);
@ -724,10 +711,8 @@ void readEEPROM_WS()
uint32_t eepromSize = (sramSize << 7);
uint32_t bufSize = (eepromSize < 512 ? eepromSize : 512);
for (uint32_t i = 0; i < eepromSize; i += bufSize)
{
for (uint32_t j = 0; j < bufSize; j += 2)
{
for (uint32_t i = 0; i < eepromSize; i += bufSize) {
for (uint32_t j = 0; j < bufSize; j += 2) {
// blink LED
if ((j & 0x1f) == 0x00)
blinkLED();
@ -756,23 +741,19 @@ void readEEPROM_WS()
println_Msg(F("Done"));
}
void verifyEEPROM_WS()
{
void verifyEEPROM_WS() {
print_Msg(F("Verifying... "));
display_Update();
if (myFile.open(filePath, O_READ))
{
if (myFile.open(filePath, O_READ)) {
uint32_t write_errors = 0;
uint32_t eepromSize = (sramSize << 7);
uint32_t bufSize = (eepromSize < 512 ? eepromSize : 512);
for (uint32_t i = 0; i < eepromSize; i += bufSize)
{
for (uint32_t i = 0; i < eepromSize; i += bufSize) {
myFile.read(sdBuffer, bufSize);
for (uint32_t j = 0; j < bufSize; j += 2)
{
for (uint32_t j = 0; j < bufSize; j += 2) {
// blink LED
if ((j & 0x1f) == 0x00)
blinkLED();
@ -799,27 +780,21 @@ void verifyEEPROM_WS()
myFile.close();
if (write_errors == 0)
{
if (write_errors == 0) {
println_Msg(F("passed"));
}
else
{
} else {
println_Msg(F("failed"));
print_Msg(F("Error: "));
print_Msg(write_errors);
println_Msg(F(" bytes "));
print_Error(F("did not verify."), false);
}
}
else
{
} else {
print_Error(F("File doesn't exist"), false);
}
}
void writeEEPROM_WS()
{
void writeEEPROM_WS() {
filePath[0] = 0;
sd.chdir("/");
fileBrowser(F("Select eep file"));
@ -831,17 +806,14 @@ void writeEEPROM_WS()
println_Msg(F("..."));
display_Update();
if (myFile.open(filePath, O_READ))
{
if (myFile.open(filePath, O_READ)) {
uint32_t eepromSize = (sramSize << 7);
uint32_t bufSize = (eepromSize < 512 ? eepromSize : 512);
for (uint32_t i = 0; i < eepromSize; i += bufSize)
{
for (uint32_t i = 0; i < eepromSize; i += bufSize) {
myFile.read(sdBuffer, bufSize);
for (uint32_t j = 0; j < bufSize; j += 2)
{
for (uint32_t j = 0; j < bufSize; j += 2) {
// blink LED
if ((j & 0x1f) == 0x00)
blinkLED();
@ -861,23 +833,19 @@ void writeEEPROM_WS()
dataIn_WS();
do {
pulseCLK_WS(128);
}
while ((readByte_WSPort(0xc8) & 0x02) == 0x00);
} while ((readByte_WSPort(0xc8) & 0x02) == 0x00);
}
}
myFile.close();
println_Msg(F("Done"));
}
else
{
} else {
print_Error(F("File doesn't exist"), false);
}
}
void writeWitchOS_WS()
{
void writeWitchOS_WS() {
// make sure that OS sectors not protected
dataOut_WS();
writeWord_WS(0x80aaa, 0xaaaa);
@ -885,13 +853,10 @@ void writeWitchOS_WS()
writeWord_WS(0xe0aaa, 0x9090);
dataIn_WS();
if (readWord_WS(0xe0004) || readWord_WS(0xe4004) || readWord_WS(0xec004) || readWord_WS(0xee004))
{
if (readWord_WS(0xe0004) || readWord_WS(0xe4004) || readWord_WS(0xec004) || readWord_WS(0xee004)) {
display_Clear();
print_Error(F("OS sectors are protected!"), false);
}
else
{
} else {
filePath[0] = 0;
sd.chdir("/");
fileBrowser(F("Select fbin file"));
@ -899,8 +864,7 @@ void writeWitchOS_WS()
display_Clear();
if (myFile.open(filePath, O_READ))
{
if (myFile.open(filePath, O_READ)) {
println_Msg(F("Erasing OS..."));
display_Update();
eraseWitchFlashSector_WS(0xe0000);
@ -930,8 +894,7 @@ void writeWitchOS_WS()
writeWord_WS(0x80aaa, 0x2020);
// 128bytes per block
for (i = 0; i < fbin_length; i += 128)
{
for (i = 0; i < fbin_length; i += 128) {
// blink LED
if ((i & 0x3ff) == 0)
blinkLED();
@ -940,8 +903,7 @@ void writeWitchOS_WS()
key = 0xff;
bytes_read = myFile.read(sdBuffer, 128);
for (uint32_t j = 0; j < bytes_read; j += 2)
{
for (uint32_t j = 0; j < bytes_read; j += 2) {
// for each decoded[n] = encoded[n] ^ key
// where key = encoded[n - 1]
// key = 0xff when n = 0, 0 <= n < 128
@ -954,10 +916,10 @@ void writeWitchOS_WS()
// write jmpf instruction and block counts at 0xe0000
memcpy_P(sdBuffer, wwLaunchCode, 8);
*((uint16_t*)(sdBuffer + 6)) = ((i >> 7) & 0xffff);
*((uint16_t *)(sdBuffer + 6)) = ((i >> 7) & 0xffff);
for (uint32_t i = 0; i < 8; i += 2)
fastProgramWitchFlash_WS(0xefff0 + i, *((uint16_t*)(sdBuffer + i)));
fastProgramWitchFlash_WS(0xefff0 + i, *((uint16_t *)(sdBuffer + i)));
// leave fast program mode
dataOut_WS();
@ -967,9 +929,7 @@ void writeWitchOS_WS()
myFile.close();
println_Msg(F("Done"));
}
else
{
} else {
print_Error(F("File doesn't exist"), false);
}
}
@ -978,19 +938,18 @@ void writeWitchOS_WS()
writeWord_WS(0x80000, 0xf0f0);
}
void fastProgramWitchFlash_WS(uint32_t addr, uint16_t data)
{
void fastProgramWitchFlash_WS(uint32_t addr, uint16_t data) {
dataOut_WS();
writeWord_WS(addr, 0xa0a0);
writeWord_WS(addr, data);
dataIn_WS();
while (readWord_WS(addr) != data);
while (readWord_WS(addr) != data)
;
}
void eraseWitchFlashSector_WS(uint32_t sector_addr)
{
void eraseWitchFlashSector_WS(uint32_t sector_addr) {
// blink LED
blinkLED();
@ -1003,19 +962,18 @@ void eraseWitchFlashSector_WS(uint32_t sector_addr)
writeWord_WS(sector_addr, 0x3030);
dataIn_WS();
while ((readWord_WS(sector_addr) & 0x0080) == 0x0000);
while ((readWord_WS(sector_addr) & 0x0080) == 0x0000)
;
}
boolean compareChecksum_WS(const char *wsFilePath)
{
boolean compareChecksum_WS(const char *wsFilePath) {
if (wsFilePath == NULL)
return 0;
println_Msg(F("Calculating Checksum"));
display_Update();
if (!myFile.open(wsFilePath, O_READ))
{
if (!myFile.open(wsFilePath, O_READ)) {
print_Error(F("Failed to open file"), false);
return 0;
}
@ -1023,15 +981,13 @@ boolean compareChecksum_WS(const char *wsFilePath)
uint32_t calLength = myFile.fileSize() - 512;
uint32_t checksum = 0;
if (wsWitch)
{
if (wsWitch) {
// only calcuate last 128Kbytes for wonderwitch (OS and BIOS region)
myFile.seekCur(myFile.fileSize() - 131072);
calLength = 131072 - 512;
}
for (uint32_t i = 0; i < calLength; i += 512)
{
for (uint32_t i = 0; i < calLength; i += 512) {
myFile.read(sdBuffer, 512);
for (uint32_t j = 0; j < 512; j++)
checksum += sdBuffer[j];
@ -1056,21 +1012,17 @@ boolean compareChecksum_WS(const char *wsFilePath)
print_Msg(F("Result: "));
println_Msg(result);
if (checksum == calLength)
{
if (checksum == calLength) {
println_Msg(F("Checksum matches"));
display_Update();
return 1;
}
else
{
} else {
print_Error(F("Checksum Error"), false);
return 0;
}
}
void writeByte_WSPort(uint8_t port, uint8_t data)
{
void writeByte_WSPort(uint8_t port, uint8_t data) {
PORTF = (port & 0x0f);
PORTL = (port >> 4);
@ -1086,14 +1038,14 @@ void writeByte_WSPort(uint8_t port, uint8_t data)
// switch WE(PH5) to HIGH
PORTH |= (1 << 5);
NOP; NOP;
NOP;
NOP;
// switch CART(PH3), MMC(PH4) to HIGH
PORTH |= ((1 << 3) | (1 << 4));
}
uint8_t readByte_WSPort(uint8_t port)
{
uint8_t readByte_WSPort(uint8_t port) {
PORTF = (port & 0x0f);
PORTL = (port >> 4);
@ -1102,7 +1054,9 @@ uint8_t readByte_WSPort(uint8_t port)
// switch OE(PH6) to LOW
PORTH &= ~(1 << 6);
NOP; NOP; NOP;
NOP;
NOP;
NOP;
uint8_t ret = PINC;
@ -1115,8 +1069,7 @@ uint8_t readByte_WSPort(uint8_t port)
return ret;
}
void writeWord_WS(uint32_t addr, uint16_t data)
{
void writeWord_WS(uint32_t addr, uint16_t data) {
PORTF = addr & 0xff;
PORTK = (addr >> 8) & 0xff;
PORTL = (addr >> 16) & 0x0f;
@ -1130,18 +1083,20 @@ void writeWord_WS(uint32_t addr, uint16_t data)
// switch CART(PH3) and WE(PH5) to HIGH
PORTH |= (1 << 3) | (1 << 5);
NOP; NOP;
NOP;
NOP;
}
uint16_t readWord_WS(uint32_t addr)
{
uint16_t readWord_WS(uint32_t addr) {
PORTF = addr & 0xff;
PORTK = (addr >> 8) & 0xff;
PORTL = (addr >> 16) & 0x0f;
// switch CART(PH3) and OE(PH6) to LOW
PORTH &= ~((1 << 3) | (1 << 6));
NOP; NOP; NOP;
NOP;
NOP;
NOP;
uint16_t ret = ((PINA << 8) | PINC);
@ -1151,8 +1106,7 @@ uint16_t readWord_WS(uint32_t addr)
return ret;
}
void writeByte_WS(uint32_t addr, uint8_t data)
{
void writeByte_WS(uint32_t addr, uint8_t data) {
PORTF = addr & 0xff;
PORTK = (addr >> 8) & 0xff;
PORTL = (addr >> 16) & 0x0f;
@ -1165,18 +1119,20 @@ void writeByte_WS(uint32_t addr, uint8_t data)
// switch CART(PH3) and WE(PH5) to HIGH
PORTH |= (1 << 3) | (1 << 5);
NOP; NOP;
NOP;
NOP;
}
uint8_t readByte_WS(uint32_t addr)
{
uint8_t readByte_WS(uint32_t addr) {
PORTF = addr & 0xff;
PORTK = (addr >> 8) & 0xff;
PORTL = (addr >> 16) & 0x0f;
// switch CART(PH3) and OE(PH6) to LOW
PORTH &= ~((1 << 3) | (1 << 6));
NOP; NOP; NOP;
NOP;
NOP;
NOP;
uint8_t ret = PINC;
@ -1186,8 +1142,7 @@ uint8_t readByte_WS(uint32_t addr)
return ret;
}
void unprotectEEPROM()
{
void unprotectEEPROM() {
generateEepromInstruction_WS(wsEepromShiftReg, 0x0, 0x3);
dataOut_WS();
@ -1201,23 +1156,19 @@ void unprotectEEPROM()
// generate data for port 0xc6 to 0xc7
// number of CLK pulses needed for each instruction is 1 + (16 or 32) + 3
void generateEepromInstruction_WS(uint8_t *instruction, uint8_t opcode, uint16_t addr)
{
void generateEepromInstruction_WS(uint8_t *instruction, uint8_t opcode, uint16_t addr) {
uint8_t addr_bits = (sramSize > 1 ? 10 : 6);
uint16_t *ptr = (uint16_t*)instruction;
*ptr = 0x0001; // initial with a start bit
uint16_t *ptr = (uint16_t *)instruction;
*ptr = 0x0001; // initial with a start bit
if (opcode == 0)
{
if (opcode == 0) {
// 2bits opcode = 0x00
*ptr <<= 2;
// 2bits ext cmd (from addr)
*ptr <<= 2;
*ptr |= (addr & 0x0003);
*ptr <<= (addr_bits - 2);
}
else
{
} else {
// 2bits opcode
*ptr <<= 2;
*ptr |= (opcode & 0x03);
@ -1230,8 +1181,7 @@ void generateEepromInstruction_WS(uint8_t *instruction, uint8_t opcode, uint16_t
// 2003 MMC need to be unlock,
// or it will reject all reading and bank switching
// All signals' timing are analyzed by using LogicAnalyzer
boolean unlockMMC2003_WS()
{
boolean unlockMMC2003_WS() {
// initialize all control pin state
// RST(PH0) and CLK(PE3or5) to LOW
// CART(PH3) MMC(PH4) WE(PH5) OE(PH6) to HIGH
@ -1261,8 +1211,7 @@ boolean unlockMMC2003_WS()
writeByte_WSPort(0xc3, 0x55);
dataIn_WS();
if (readByte_WSPort(0xc2) == 0xaa && readByte_WSPort(0xc3) == 0x55)
{
if (readByte_WSPort(0xc2) == 0xaa && readByte_WSPort(0xc3) == 0x55) {
// now set initial bank number to MMC
dataOut_WS();
writeByte_WSPort(0xc0, 0x2f);
@ -1276,35 +1225,31 @@ boolean unlockMMC2003_WS()
}
// doing a L->H on CLK pin
void pulseCLK_WS(uint8_t count)
{
void pulseCLK_WS(uint8_t count) {
register uint8_t tic;
// about 384KHz, 50% duty cycle
asm volatile
("L0_%=:\n\t"
"cpi %[count], 0\n\t"
"breq L3_%=\n\t"
"dec %[count]\n\t"
"cbi %[porte], %[ws_clk_bit]\n\t"
"ldi %[tic], 6\n\t"
"L1_%=:\n\t"
"dec %[tic]\n\t"
"brne L1_%=\n\t"
"sbi %[porte], %[ws_clk_bit]\n\t"
"ldi %[tic], 5\n\t"
"L2_%=:\n\t"
"dec %[tic]\n\t"
"brne L2_%=\n\t"
"rjmp L0_%=\n\t"
"L3_%=:\n\t"
: [tic] "=a" (tic)
: [count] "a" (count), [porte] "I" (_SFR_IO_ADDR(PORTE)), [ws_clk_bit] "I" (WS_CLK_BIT)
);
asm volatile("L0_%=:\n\t"
"cpi %[count], 0\n\t"
"breq L3_%=\n\t"
"dec %[count]\n\t"
"cbi %[porte], %[ws_clk_bit]\n\t"
"ldi %[tic], 6\n\t"
"L1_%=:\n\t"
"dec %[tic]\n\t"
"brne L1_%=\n\t"
"sbi %[porte], %[ws_clk_bit]\n\t"
"ldi %[tic], 5\n\t"
"L2_%=:\n\t"
"dec %[tic]\n\t"
"brne L2_%=\n\t"
"rjmp L0_%=\n\t"
"L3_%=:\n\t"
: [tic] "=a"(tic)
: [count] "a"(count), [porte] "I"(_SFR_IO_ADDR(PORTE)), [ws_clk_bit] "I"(WS_CLK_BIT));
}
void dataIn_WS()
{
void dataIn_WS() {
DDRC = 0x00;
DDRA = 0x00;
@ -1314,8 +1259,7 @@ void dataIn_WS()
PORTA = 0x00;
}
void dataOut_WS()
{
void dataOut_WS() {
DDRC = 0xff;
DDRA = 0xff;
}

View File

@ -38,9 +38,9 @@
// /WR - (PH5)
// /RD - (PH6)
word WSV[] = {32, 64, 512};
byte wsvlo = 0; // Lowest Entry
byte wsvhi = 2; // Highest Entry
word WSV[] = { 32, 64, 512 };
byte wsvlo = 0; // Lowest Entry
byte wsvhi = 2; // Highest Entry
byte wsvsize;
byte newwsvsize;
@ -52,8 +52,7 @@ byte newwsvsize;
// SETUP
//******************************************
void setup_WSV()
{
void setup_WSV() {
// Set Address Pins to Output
//A0-A7
DDRF = 0xFF;
@ -87,7 +86,7 @@ void setup_WSV()
// Set Unused Pins HIGH
PORTL = 0xE0;
PORTA = 0xFF;
PORTJ |= (1 << 0); // TIME(PJ0)
PORTJ |= (1 << 0); // TIME(PJ0)
checkStatus_WSV();
strcpy(romName, "SUPERVISION");
@ -104,15 +103,13 @@ static const char wsvMenuItem1[] PROGMEM = "Select Cart";
static const char wsvMenuItem2[] PROGMEM = "Read ROM";
static const char wsvMenuItem3[] PROGMEM = "Set Size";
static const char wsvMenuItem4[] PROGMEM = "Reset";
static const char* const menuOptionsSV[] PROGMEM = {wsvMenuItem1, wsvMenuItem2, wsvMenuItem3, wsvMenuItem4};
static const char* const menuOptionsSV[] PROGMEM = { wsvMenuItem1, wsvMenuItem2, wsvMenuItem3, wsvMenuItem4 };
void wsvMenu()
{
void wsvMenu() {
convertPgm(menuOptionsSV, 4);
uint8_t mainMenu = question_box(F("SUPERVISION MENU"), menuOptions, 4, 0);
switch (mainMenu)
{
switch (mainMenu) {
case 0:
// Select Cart
setCart_WSV();
@ -157,25 +154,27 @@ void controlIn_WSV() {
PORTH &= ~(1 << 6);
}
void dataIn_WSV()
{
void dataIn_WSV() {
DDRC = 0x00;
}
void dataOut_WSV()
{
void dataOut_WSV() {
DDRC = 0xFF;
}
uint8_t readByte_WSV(uint32_t addr)
{
uint8_t readByte_WSV(uint32_t addr) {
PORTF = addr & 0xFF;
PORTK = (addr >> 8) & 0xFF;
PORTL = (addr >> 16) & 0xFF;
// Wait for data bus
// 6 x 62.5ns = 375ns
NOP; NOP; NOP; NOP; NOP; NOP;
NOP;
NOP;
NOP;
NOP;
NOP;
NOP;
uint8_t ret = PINC;
NOP;
@ -187,8 +186,7 @@ uint8_t readByte_WSV(uint32_t addr)
// READ CODE
//******************************************
void readROM_WSV()
{
void readROM_WSV() {
strcpy(fileName, romName);
strcat(fileName, ".sv");
@ -223,8 +221,7 @@ void readROM_WSV()
if (romSize < 64)
romStart = 0x8000;
uint32_t romEnd = (uint32_t)romSize * 0x400;
for (uint32_t addr = 0; addr < romEnd; addr += 512)
{
for (uint32_t addr = 0; addr < romEnd; addr += 512) {
for (uint16_t w = 0; w < 512; w++)
sdBuffer[w] = readByte_WSV(romStart + addr + w);
myFile.write(sdBuffer, 512);
@ -245,8 +242,7 @@ void readROM_WSV()
// ROM SIZE
//******************************************
void setROMSize_WSV()
{
void setROMSize_WSV() {
#if (defined(enable_OLED) || defined(enable_LCD))
display_Clear();
if (wsvlo == wsvhi)
@ -270,7 +266,7 @@ void setROMSize_WSV()
while (1) {
b = checkButton();
if (b == 2) { // Previous (doubleclick)
if (b == 2) { // Previous (doubleclick)
if (i == wsvlo)
i = wsvhi;
else
@ -290,7 +286,7 @@ void setROMSize_WSV()
#endif
display_Update();
}
if (b == 1) { // Next (press)
if (b == 1) { // Next (press)
if (i == wsvhi)
i = wsvlo;
else
@ -310,12 +306,12 @@ void setROMSize_WSV()
#endif
display_Update();
}
if (b == 3) { // Long Press - Execute (hold)
if (b == 3) { // Long Press - Execute (hold)
newwsvsize = i;
break;
}
}
display.setCursor(0, 56); // Display selection at bottom
display.setCursor(0, 56); // Display selection at bottom
}
print_Msg(F("ROM SIZE "));
print_Msg(WSV[newwsvsize]);
@ -354,11 +350,10 @@ setrom:
wsvsize = newwsvsize;
}
void checkStatus_WSV()
{
void checkStatus_WSV() {
EEPROM_readAnything(8, wsvsize);
if (wsvsize > 2) {
wsvsize = 1; // default 64K
wsvsize = 1; // default 64K
EEPROM_writeAnything(8, wsvsize);
}
@ -416,12 +411,10 @@ void setCart_WSV() {
while (1) {
if (myFile.curPosition() == 0) {
break;
}
else if (myFile.peek() == '\n') {
} else if (myFile.peek() == '\n') {
myFile.seekSet(myFile.curPosition() - 1);
break;
}
else {
} else {
myFile.seekSet(myFile.curPosition() - 1);
}
}
@ -463,9 +456,8 @@ void setCart_WSV() {
// Remove leading 0 for single digit cart sizes
if (cartSize != 0) {
cartSize = cartSize * 10 + myFile.read() - 48;
}
else {
cartSize = cartSize * 10 + myFile.read() - 48;
} else {
cartSize = myFile.read() - 48;
}
@ -513,12 +505,10 @@ void setCart_WSV() {
while (1) {
if (myFile.curPosition() == 0) {
break;
}
else if (myFile.peek() == '\n') {
} else if (myFile.peek() == '\n') {
myFile.seekSet(myFile.curPosition() - 1);
break;
}
else {
} else {
myFile.seekSet(myFile.curPosition() - 1);
}
}
@ -550,8 +540,7 @@ void setCart_WSV() {
}
}
}
}
else {
} else {
print_Error(F("Database file not found"), true);
}
}