Merge pull request #761 from PsyK0p4T/master

Update SMS.ino
This commit is contained in:
sanni 2023-04-06 23:49:52 +02:00 committed by GitHub
commit 3a38b4b1e3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -1,100 +1,144 @@
//******************************************************** //***********************************************************
// SEGA MASTER SYSTEM/Mark III/SG-1000/GAME GEAR MODULE // SEGA MASTER SYSTEM / MARK III / GAME GEAR / SG-1000 MODULE
//******************************************************** //***********************************************************
#ifdef enable_SMS #ifdef enable_SMS
/****************************************** //******************************************
Menu // Menus
*****************************************/ //******************************************
// Adapter menu // Adapters menu
static const char SMSAdapterItem1[] PROGMEM = "SMS/Mark 3 raphnet"; static const char SMSAdapterItem1[] PROGMEM = "SMS/MarkIII raphnet";
static const char SMSAdapterItem2[] PROGMEM = "SG-1000 raphnet"; static const char SMSAdapterItem2[] PROGMEM = "SMS Retrode";
static const char SMSAdapterItem3[] PROGMEM = "SMS Retrode"; static const char SMSAdapterItem3[] PROGMEM = "SMS Retron3in1";
static const char SMSAdapterItem4[] PROGMEM = "GG Retrode"; static const char SMSAdapterItem4[] PROGMEM = "GameGear Retrode";
static const char SMSAdapterItem5[] PROGMEM = "GG Retron 3in1"; static const char SMSAdapterItem5[] PROGMEM = "GameGear Retron3in1";
static const char* const menuAdapterSMS[] PROGMEM = { SMSAdapterItem1, SMSAdapterItem2, SMSAdapterItem3, SMSAdapterItem4, SMSAdapterItem5 }; static const char SMSAdapterItem6[] PROGMEM = "SG-1000 raphnet";
static const char* const SMSAdapterMenu[] PROGMEM = { SMSAdapterItem1, SMSAdapterItem2, SMSAdapterItem3, SMSAdapterItem4, SMSAdapterItem5, SMSAdapterItem6 };
// MD menu items // Operations menu
static const char SMSMenuItem1[] PROGMEM = "Read Rom"; static const char SMSOperationItem1[] PROGMEM = "Read Rom";
static const char SMSMenuItem2[] PROGMEM = "Read from SRAM"; static const char SMSOperationItem2[] PROGMEM = "Read from SRAM";
static const char SMSMenuItem3[] PROGMEM = "Write to SRAM"; static const char SMSOperationItem3[] PROGMEM = "Write to SRAM";
//static const char SMSMenuItem4[] PROGMEM = "Reset"; (stored in common strings array) static const char* const SMSOperationMenu[] PROGMEM = { SMSOperationItem1, SMSOperationItem2, SMSOperationItem3, string_reset2 };
static const char SMSMenuItem5[] PROGMEM = "Change Retrode Mode";
static const char* const menuOptionsSMS[] PROGMEM = { SMSMenuItem1, SMSMenuItem2, SMSMenuItem3, string_reset2, SMSMenuItem5 };
// Rom Size menu // Rom sizes menu
static const char SMSRomItem1[] PROGMEM = "8KB"; static const char SMSRomSizeItem1[] PROGMEM = "8 KB";
static const char SMSRomItem2[] PROGMEM = "16KB"; static const char SMSRomSizeItem2[] PROGMEM = "16 KB";
static const char SMSRomItem3[] PROGMEM = "24KB"; static const char SMSRomSizeItem3[] PROGMEM = "24 KB";
static const char SMSRomItem4[] PROGMEM = "32KB"; static const char SMSRomSizeItem4[] PROGMEM = "32 KB";
static const char SMSRomItem5[] PROGMEM = "40KB"; static const char SMSRomSizeItem5[] PROGMEM = "40 KB"; //SG-1000 40k mapping not yet supported
static const char SMSRomItem6[] PROGMEM = "48KB"; static const char SMSRomSizeItem6[] PROGMEM = "48 KB"; //SG-1000 40k mapping not yet supported
static const char SMSRomItem7[] PROGMEM = "512KB"; static const char SMSRomSizeItem7[] PROGMEM = "64 KB";
static const char* const romOptionsSMS[] PROGMEM = { SMSRomItem1, SMSRomItem2, SMSRomItem3, SMSRomItem4, SMSRomItem5, SMSRomItem6, SMSRomItem7 }; static const char SMSRomSizeItem8[] PROGMEM = "128 KB";
static const char SMSRomSizeItem9[] PROGMEM = "256 KB";
static const char SMSRomSizeItem10[] PROGMEM = "512 KB";
static const char SMSRomSizeItem11[] PROGMEM = "1024 KB";
static const char* const SG1RomSizeMenu[] PROGMEM = { SMSRomSizeItem1, SMSRomSizeItem2, SMSRomSizeItem3, SMSRomSizeItem4}; // Rom sizes for SG-1000
static const char* const SMSRomSizeMenu[] PROGMEM = { SMSRomSizeItem4, SMSRomSizeItem7, SMSRomSizeItem8, SMSRomSizeItem9, SMSRomSizeItem10, SMSRomSizeItem11}; // Rom sizes for SMS and GG
// Set retrode_mode to true when using a retrode SMS/GG adapter // Init systems
static bool retrode_mode = false; static bool system_sms = false; // SMS or MarkIII
static bool retrode_mode_sms = false; // true: SMS/Mark3 false: GG static bool system_gg = false; // GameGear
static bool raphnet_mode_sg1000 = false; // true: SG-1000 false: SMS/Mark3 static bool system_sg1000 = false; // SG-1000
static bool retron_mode = false;
// Init adapters
static bool adapter_raphnet = false; // raphet adapater (SMS-to-MD or MIII-to-MD)
static bool adapter_retrode = false; // Retrode adapter (SMS-to-MD or GG-to-MD)
static bool adapter_retron = false; // Retron 3in1 adapter (SMS-to-MD or GG-to-MD)
void _smsMenu() { //*********************************************************
// Main menu with systems/adapters setups to choose from
//*********************************************************
void smsMenu() {
setVoltage(VOLTS_SET_5V); setVoltage(VOLTS_SET_5V);
// create menu with title and n options to choose from unsigned char SMSSetup;
unsigned char mainMenu; convertPgm(SMSAdapterMenu, 6);
SMSSetup = question_box(F("Select your setup"), menuOptions, 6, 0);
if (retrode_mode) { switch (SMSSetup) {
// Copy menuOptions out of progmem case 0:
int noptions = sizeof(menuOptionsSMS) / sizeof(menuOptionsSMS[0]); // SMS or MarkIII with raphnet adapter
convertPgm(menuOptionsSMS, noptions); system_sms = true;
mainMenu = question_box(retrode_mode ? (retrode_mode_sms ? F("Retrode:SMS") : F("Retrode:GG")) : F("SMS/GG Retrode:NO"), menuOptions, noptions, 0); adapter_raphnet = true;
} else if (retron_mode) { break;
// Copy menuOptions out of progmem
convertPgm(menuOptionsSMS, 4); case 1:
mainMenu = question_box(F("Game Gear"), menuOptions, 4, 0); // SMS with Retrode adapter
} else { system_sms = true;
// Copy menuOptions out of progmem adapter_retrode = true;
convertPgm(menuOptionsSMS, (raphnet_mode_sg1000 ? 1 : 4)); break;
mainMenu = question_box((raphnet_mode_sg1000 ? F("SG-1000") : F("SMS/Mark III")), menuOptions, (raphnet_mode_sg1000 ? 1 : 4), 0);
case 2:
// SMS with Retron 3in1 adapter
system_sms = true;
adapter_retron = true;
break;
case 3:
// GameGear with Retrode adapter
system_gg = true;
adapter_retrode = true;
break;
case 4:
// GameGear with Retron 3in1 adapter
system_gg = true;
adapter_retron = true;
break;
case 5:
// SG-1000 with raphnet adapter
system_sg1000 = true;
adapter_raphnet = true;
break;
}
for (;;) smsOperations();
}
//****************************************************
// Create custom menu depending on selected setup
//****************************************************
void smsOperations() {
unsigned char SMSOperation = '3';
convertPgm(SMSOperationMenu, 4);
if (system_sms) {
if (adapter_raphnet) {
SMSOperation = question_box(F("SMS/MarkIII raphnet"), menuOptions, 4, 0);
} else if (adapter_retrode) {
SMSOperation = question_box(F("SMS Retrode"), menuOptions, 4, 0);
} else if (adapter_retron) {
SMSOperation = question_box(F("SMS Retron 3in1"), menuOptions, 4, 0);
}
} else if (system_gg) {
if (adapter_retrode) {
SMSOperation = question_box(F("GameGear Retrode"), menuOptions, 4, 0);
} else if (adapter_retron) {
SMSOperation = question_box(F("GameGear Retron 3in1"), menuOptions, 4, 0);
}
} else if (system_sg1000) {
SMSOperation = question_box(F("SG-1000 raphnet"), menuOptions, 1, 0);
} }
// wait for user choice to come back from the question box menu switch (SMSOperation) {
switch (mainMenu) {
case 0: case 0:
display_Clear(); // Read ROM
mode = mode_SMS; mode = mode_SMS;
setup_SMS(); setup_SMS();
// Change working dir to root
sd.chdir("/");
readROM_SMS(); readROM_SMS();
if ((retrode_mode && !retrode_mode_sms) || retron_mode) {
compareCRC("gg.txt", 0, 1, 0);
} else if (raphnet_mode_sg1000) {
compareCRC("sg1000.txt", 0, 1, 0);
} else {
compareCRC("sms.txt", 0, 1, 0);
}
#ifdef global_log
save_log();
#endif
break; break;
case 1: case 1:
display_Clear(); // Read SRAM
mode = mode_SMS; mode = mode_SMS;
setup_SMS(); setup_SMS();
// Change working dir to root
sd.chdir("/");
readSRAM_SMS(); readSRAM_SMS();
break; break;
case 2: case 2:
display_Clear(); // Write SRAM
mode = mode_SMS; mode = mode_SMS;
setup_SMS(); setup_SMS();
// Change working dir to root
sd.chdir("/");
writeSRAM_SMS(); writeSRAM_SMS();
break; break;
@ -102,84 +146,15 @@ void _smsMenu() {
// Reset // Reset
resetArduino(); resetArduino();
break; break;
}
case 4:
if (retrode_mode && !retrode_mode_sms) {
// Change to SMS
retrode_mode_sms = true;
} else if (retrode_mode && retrode_mode_sms) {
// Change to GG
retrode_mode_sms = false;
}
break;
}
if (retrode_mode) {
println_Msg(retrode_mode ? (retrode_mode_sms ? F("Retrode Mode SMS") : F("Retrode Mode GG")) : F("Retrode Mode Off"));
// Prints string out of the common strings array either with or without newline
print_STR(press_button_STR, 1);
} else {
println_Msg(F(""));
// Prints string out of the common strings array either with or without newline
print_STR(press_button_STR, 1);
}
display_Update(); display_Update();
wait(); wait();
} }
void smsMenu() { //********************************
// create main menu with title and 4 options to choose from // Setup I/O
unsigned char SMSAdapterMenu; //********************************
// Copy menuOptions out of progmem
convertPgm(menuAdapterSMS, 5);
SMSAdapterMenu = question_box(F("Select System/Adapter"), menuOptions, 5, 0);
// wait for user choice to come back from the question box menu
switch (SMSAdapterMenu) {
case 0:
// raphnet SMS/Mark3
retrode_mode = false;
retrode_mode_sms = false;
raphnet_mode_sg1000 = false;
retron_mode = false;
break;
case 1:
// raphnet SG-1000
retrode_mode = false;
retrode_mode_sms = false;
raphnet_mode_sg1000 = true;
retron_mode = false;
break;
case 2:
// retrode SMS/Mark3
retrode_mode = true;
retrode_mode_sms = true;
raphnet_mode_sg1000 = false;
retron_mode = false;
break;
case 3:
// retrode GG
retrode_mode = true;
retrode_mode_sms = false;
raphnet_mode_sg1000 = false;
retron_mode = false;
break;
case 4:
// retron 3in1 GG
retrode_mode = false;
retrode_mode_sms = false;
raphnet_mode_sg1000 = false;
retron_mode = true;
}
for (;;) _smsMenu();
}
/******************************************
Setup
*****************************************/
void setup_SMS() { void setup_SMS() {
// Set Address Pins to Output // Set Address Pins to Output
//A0-A7 //A0-A7
@ -189,8 +164,8 @@ void setup_SMS() {
//A15 //A15
DDRH |= (1 << 3); DDRH |= (1 << 3);
if (retrode_mode) { //For Retrode adapter
// Revert changes from the other mode if (adapter_retrode) {
PORTH &= ~((1 << 0) | (1 << 3) | (1 << 5)); PORTH &= ~((1 << 0) | (1 << 3) | (1 << 5));
PORTL &= ~(1 << 1); PORTL &= ~(1 << 1);
DDRH &= ~((1 << 0) | (1 << 5)); DDRH &= ~((1 << 0) | (1 << 5));
@ -199,49 +174,51 @@ void setup_SMS() {
DDRH |= (1 << 6); DDRH |= (1 << 6);
// WR(PL5) and RD(PL6) // WR(PL5) and RD(PL6)
DDRL |= (1 << 5) | (1 << 6); DDRL |= (1 << 5) | (1 << 6);
// Setting OE(PH6) HIGH // Setting OE(PH6) HIGH
PORTH |= (1 << 6); PORTH |= (1 << 6);
// Setting WR(PL5) and RD(PL6) HIGH // Setting WR(PL5) and RD(PL6) HIGH
PORTL |= (1 << 5) | (1 << 6); PORTL |= (1 << 5) | (1 << 6);
} else { }
// Revert changes from the other mode
PORTL &= ~((1 << 5) | (1 << 6)); // For Raphnet and Retron adapters
DDRL &= ~((1 << 5) | (1 << 6)); else {
// Set Control Pins to Output RST(PH0) WR(PH5) OE(PH6) // Set Control Pins to Output RST(PH0) WR(PH5) OE(PH6)
DDRH |= (1 << 0) | (1 << 5) | (1 << 6); DDRH |= (1 << 0) | (1 << 5) | (1 << 6);
// CE(PL1) // CE(PL1)
DDRL |= (1 << 1); DDRL |= (1 << 1);
// Setting RST(PH0) WR(PH5) OE(PH6) HIGH // Setting RST(PH0) WR(PH5) OE(PH6) HIGH
PORTH |= (1 << 0) | (1 << 5) | (1 << 6); PORTH |= (1 << 0) | (1 << 5) | (1 << 6);
// CE(PL1) // CE(PL1)
PORTL |= (1 << 1); PORTL |= (1 << 1);
} }
// ROM has 16KB banks which can be mapped to one of three slots via register writes if (!system_sg1000) {
// Register Slot Address space // SMS/GG ROM has 16KB banks which can be mapped to one of three slots via register writes
// $fffd 0 $0000-$3fff // Register Slot Address space
// $fffe 1 $4000-$7fff // $fffd 0 $0000-$3fff
// $ffff 2 $8000-$bfff // $fffe 1 $4000-$7fff
// Disable sram // $ffff 2 $8000-$bfff
writeByte_SMS(0xFFFC, 0);
// Map first 3 banks so we can read-out the header info // Disable sram
writeByte_SMS(0xFFFD, 0); writeByte_SMS(0xFFFC, 0);
writeByte_SMS(0xFFFE, 1);
writeByte_SMS(0xFFFF, 2); // Map first 3 banks so we can read-out the header info
writeByte_SMS(0xFFFD, 0);
writeByte_SMS(0xFFFE, 1);
writeByte_SMS(0xFFFF, 2);
}
delay(400); delay(400);
// Print all the info // Read and print cart info
getCartInfo_SMS(); getCartInfo_SMS();
} }
/****************************************** //*****************************************
Low level functions // Low level functions
*****************************************/ //*****************************************
void writeByte_SMS(word myAddress, byte myData) { void writeByte_SMS(word myAddress, byte myData) {
if (retrode_mode && !retrode_mode_sms) { if (adapter_retrode && system_gg) {
// Set Data Pins (D8-D15) to Output // Set Data Pins (D8-D15) to Output
DDRA = 0xFF; DDRA = 0xFF;
} else { } else {
@ -252,13 +229,13 @@ void writeByte_SMS(word myAddress, byte myData) {
// Set address // Set address
PORTF = myAddress & 0xFF; PORTF = myAddress & 0xFF;
PORTK = (myAddress >> 8) & 0xFF; PORTK = (myAddress >> 8) & 0xFF;
if (!retrode_mode) { if (!adapter_retrode) {
// CE(PH3) and OE(PH6) are connected // CE(PH3) and OE(PH6) are connected
PORTH = (PORTH & 0b11110111) | ((myAddress >> 12) & 0b00001000); PORTH = (PORTH & 0b11110111) | ((myAddress >> 12) & 0b00001000);
} }
// Output data // Output data
if (retrode_mode && !retrode_mode_sms) { if (adapter_retrode && system_gg) {
PORTA = myData; PORTA = myData;
} else { } else {
PORTC = myData; PORTC = myData;
@ -271,7 +248,7 @@ void writeByte_SMS(word myAddress, byte myData) {
"nop\n\t" "nop\n\t"
"nop\n\t"); "nop\n\t");
if (retrode_mode) { if (adapter_retrode) {
// Switch WR(PL5) and OE/CE(PH6) to LOW // Switch WR(PL5) and OE/CE(PH6) to LOW
PORTL &= ~(1 << 5); PORTL &= ~(1 << 5);
PORTH &= ~(1 << 6); PORTH &= ~(1 << 6);
@ -287,7 +264,7 @@ void writeByte_SMS(word myAddress, byte myData) {
"nop\n\t" "nop\n\t"
"nop\n\t"); "nop\n\t");
if (retrode_mode) { if (adapter_retrode) {
// Switch WR(PL5) and OE/CE(PH6) to HIGH // Switch WR(PL5) and OE/CE(PH6) to HIGH
PORTH |= (1 << 6); PORTH |= (1 << 6);
PORTL |= (1 << 5); PORTL |= (1 << 5);
@ -303,7 +280,7 @@ void writeByte_SMS(word myAddress, byte myData) {
"nop\n\t" "nop\n\t"
"nop\n\t"); "nop\n\t");
if (retrode_mode && !retrode_mode_sms) { if (adapter_retrode && system_gg) {
// Set Data Pins (D8-D15) to Input // Set Data Pins (D8-D15) to Input
DDRA = 0x00; DDRA = 0x00;
} else { } else {
@ -313,7 +290,7 @@ void writeByte_SMS(word myAddress, byte myData) {
} }
byte readByte_SMS(word myAddress) { byte readByte_SMS(word myAddress) {
if (retrode_mode && !retrode_mode_sms) { if (adapter_retrode && system_gg) {
// Set Data Pins (D8-D15) to Input // Set Data Pins (D8-D15) to Input
DDRA = 0x00; DDRA = 0x00;
} else { } else {
@ -324,7 +301,7 @@ byte readByte_SMS(word myAddress) {
// Set Address // Set Address
PORTF = myAddress & 0xFF; PORTF = myAddress & 0xFF;
PORTK = (myAddress >> 8) & 0xFF; PORTK = (myAddress >> 8) & 0xFF;
if (!retrode_mode) { if (!adapter_retrode) {
// CE(PH3) and OE(PH6) are connected // CE(PH3) and OE(PH6) are connected
PORTH = (PORTH & 0b11110111) | ((myAddress >> 12) & 0b00001000); PORTH = (PORTH & 0b11110111) | ((myAddress >> 12) & 0b00001000);
} }
@ -334,7 +311,7 @@ byte readByte_SMS(word myAddress) {
"nop\n\t" "nop\n\t"
"nop\n\t"); "nop\n\t");
if (retrode_mode) { if (adapter_retrode) {
// Switch RD(PL6) and OE(PH6) to LOW // Switch RD(PL6) and OE(PH6) to LOW
PORTL &= ~(1 << 6); PORTL &= ~(1 << 6);
PORTH &= ~(1 << 6); PORTH &= ~(1 << 6);
@ -350,9 +327,9 @@ byte readByte_SMS(word myAddress) {
"nop\n\t"); "nop\n\t");
// Read // Read
byte tempByte = (retrode_mode && !retrode_mode_sms) ? PINA : PINC; byte tempByte = (adapter_retrode && system_gg) ? PINA : PINC;
if (retrode_mode) { if (adapter_retrode) {
// Switch RD(PL6) and OE(PH6) to HIGH // Switch RD(PL6) and OE(PH6) to HIGH
PORTH |= (1 << 6); PORTH |= (1 << 6);
PORTL |= (1 << 6); PORTL |= (1 << 6);
@ -370,25 +347,18 @@ byte readByte_SMS(word myAddress) {
return tempByte; return tempByte;
} }
//unsigned char hex2bcd (unsigned char x) {
// unsigned char y;
// y = (x / 10) << 4;
// y = y | (x % 10);
//return (y);
//}
byte readNibble(byte data, byte number) { byte readNibble(byte data, byte number) {
return ((data >> (number * 4)) & 0xf); return ((data >> (number * 4)) & 0xF);
} }
/****************************************** //*****************************************
Cartridges functions // Cartridges functions
*****************************************/ //*****************************************
void getCartInfo_SMS() { void getCartInfo_SMS() {
// Rom size // Get rom size
switch (readNibble(readByte_SMS(0x7fff), 0)) { switch (readNibble(readByte_SMS(0x7FFF), 0)) {
// Adding UL gets rid of integer overflow compiler warning
case 0xa: case 0xa:
// Adding UL gets rid of integer overflow compiler warning
cartSize = 8 * 1024UL; cartSize = 8 * 1024UL;
break; break;
case 0xb: case 0xb:
@ -421,38 +391,40 @@ void getCartInfo_SMS() {
break; break;
default: default:
cartSize = 48 * 1024UL; cartSize = 48 * 1024UL;
// LED Error // LED Error
setColor_RGB(0, 0, 255); setColor_RGB(0, 0, 255);
break; break;
} }
// Read TMR SEGA string // Get rom name (expecting "TMR SEGA" string)
for (byte i = 0; i < 8; i++) { for (byte i = 0; i < 8; i++) {
romName[i] = char(readByte_SMS(0x7ff0 + i)); romName[i] = char(readByte_SMS(0x7FF0 + i));
} }
romName[8] = '\0'; romName[8] = '\0';
// Attempt to detect cart size by checking if TMR SEGA is mirrored // Attempt to detect cart size by checking if "TMR SEGA" is mirrored
unsigned long mirror_offset = cartSize; unsigned long mirror_offset = cartSize;
char romName2[9]; char romName2[9];
while (mirror_offset < 1024 * 1024UL) { while (mirror_offset < 1024 * 1024UL) {
byte bank = 1 + (mirror_offset / (16 * 1024UL)); byte bank = 1 + (mirror_offset / (16 * 1024UL));
writeByte_SMS(0xFFFE, bank); writeByte_SMS(0xfffe, bank);
for (byte i = 0; i < 8; i++) { for (byte i = 0; i < 8; i++) {
romName2[i] = char(readByte_SMS(0x7ff0 + i)); romName2[i] = char(readByte_SMS(0x7FF0 + i));
} }
romName2[8] = '\0'; romName2[8] = '\0';
// print_Msg(F("Name2: ")); // print_Msg(F("Name2: "));
// println_Msg(romName2); // println_Msg(romName2);
// print_Msg(F("from bank ")); // print_Msg(F("from bank "));
// print_Msg(bank); // print_Msg(bank);
// print_Msg(F(" offset ")); // print_Msg(F(" offset "));
// print_Msg_PaddedHex32(mirror_offset + 0x7ff0); // print_Msg_PaddedHex32(mirror_offset + 0x7FF0);
// println_Msg(F("")); // println_Msg(F(""));
if (strcmp(romName2, romName) == 0) { if (strcmp(romName2, romName) == 0) {
break; break;
} }
if (cartSize == 48 * 1024UL) { if (cartSize == 48 * 1024UL) {
cartSize = 64 * 1024UL; cartSize = 64 * 1024UL;
} else { } else {
@ -460,13 +432,14 @@ void getCartInfo_SMS() {
} }
mirror_offset = cartSize; mirror_offset = cartSize;
} }
writeByte_SMS(0xFFFE, 1); writeByte_SMS(0xFFFE, 1);
// Fix for "Fantasy Zone (J) (V1.0)" that has not the normal header, but "COPYRIGHT SEGAPRG. BY T.ASAI". // Fix for "Fantasy Zone (J) (V1.0)" that has not the normal header, but "COPYRIGHT SEGAPRG. BY T.ASAI".
char headerFZ[29]; char headerFZ[29];
if (strcmp(romName, "G. BY T.A") != 0) { if (strcmp(romName, "G. BY T.A") != 0) {
for (byte i = 0; i < 28; i++) { for (byte i = 0; i < 28; i++) {
headerFZ[i] = char(readByte_SMS(0x7fe0 + i)); headerFZ[i] = char(readByte_SMS(0x7FE0 + i));
} }
headerFZ[28] = '\0'; headerFZ[28] = '\0';
@ -476,54 +449,64 @@ void getCartInfo_SMS() {
} }
} }
// SMS header not found // If "TMR SEGA" header is not found
if (strcmp(romName, "TMR SEGA") != 0) { if (strcmp(romName, "TMR SEGA") != 0) {
// Set cartsize manually // Set rom size manually
unsigned char SMSRomMenu; unsigned char SMSRomSize;
// 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);
// wait for user choice to come back from the question box menu if (system_sg1000) {
switch (SMSRomMenu) { // Rom sizes for SG-1000
case 0: convertPgm(SG1RomSizeMenu, 4);
// 8KB SMSRomSize = question_box(F("Select ROM size"), menuOptions, 4, 0);
cartSize = 8 * 1024UL; switch (SMSRomSize) {
break; case 0:
cartSize = 8 * 1024UL; // 8KB
case 1: break;
// 16KB case 1:
cartSize = 16 * 1024UL; cartSize = 16 * 1024UL; // 16KB
break; break;
case 2:
case 2: cartSize = 24 * 1024UL; // 24KB
// 24KB break;
cartSize = 24 * 1024UL; case 3:
break; cartSize = 32 * 1024UL; // 32KB
break;
case 3: //case 4:
// 32KB // cartSize = 40 * 1024UL; // 40KB
cartSize = 32 * 1024UL; // break;
break; //case 5:
// cartSize = 48 * 1024UL; // 48KB
case 4: // break;
// 40KB }
cartSize = 40 * 1024UL; } else {
break; // Rom sizes for SMS and GG
convertPgm(SMSRomSizeMenu, 6);
case 5: SMSRomSize = question_box(F("Select ROM size"), menuOptions, 6, 0);
// 48KB switch (SMSRomSize) {
cartSize = 48 * 1024UL; case 0:
break; cartSize = 32 * 1024UL; // 32KB
break;
case 6: case 1:
// 512KB cartSize = 64 * 1024UL; // 64KB
cartSize = 512 * 1024UL; break;
break; case 2:
cartSize = 128 * 1024UL; // 128KB
break;
case 3:
cartSize = 256 * 1024UL; // 256KB
break;
case 4:
cartSize = 512 * 1024UL; // 512KB
break;
case 5:
cartSize = 1024 * 1024UL; // 1MB
break;
}
} }
// Display cart info
display_Clear(); display_Clear();
println_Msg(F("SMS/GG Header not found")); println_Msg(F("SMS/GG header not found"));
println_Msg(F(" ")); println_Msg(F(" "));
print_Msg(F("Name: ")); print_Msg(F("Name: "));
println_Msg(romName); println_Msg(romName);
@ -534,13 +517,13 @@ void getCartInfo_SMS() {
sprintf(romName, "UNKNOWN"); sprintf(romName, "UNKNOWN");
} }
// Header found // If "TMR SEGA" header is found
else { else {
display_Clear(); display_Clear();
if ((retrode_mode && !retrode_mode_sms) || retron_mode) { if (system_sms) {
println_Msg(F("GG Header Info")); println_Msg(F("SMS header info"));
} else { } else {
println_Msg(F("SMS Header Info")); println_Msg(F("GG header info"));
} }
println_Msg(F(" ")); println_Msg(F(" "));
print_Msg(F("Name: ")); print_Msg(F("Name: "));
@ -552,33 +535,37 @@ void getCartInfo_SMS() {
} }
// Wait for user input // Wait for user input
#if (defined(enable_LCD) || defined(enable_OLED)) #if (defined(enable_LCD) || defined(enable_OLED))
// Prints string out of the common strings array either with or without newline // Prints string out of the common strings array either with or without newline
print_STR(press_button_STR, 1); print_STR(press_button_STR, 1);
display_Update(); display_Update();
wait(); wait();
#endif #endif
// Turn off LED // Turn off LED
setColor_RGB(0, 0, 0); setColor_RGB(0, 0, 0);
} }
// Read rom and save to the SD card //******************************************
// Read ROM and save it to the SD card
//******************************************
void readROM_SMS() { void readROM_SMS() {
// Get name, add extension depending on the system and convert to char array for sd lib // Get name, add extension depending on the system and convert to char array for sd lib
EEPROM_readAnything(0, foldern); EEPROM_readAnything(0, foldern);
strcpy(fileName, romName); strcpy(fileName, romName);
if ((retrode_mode && !retrode_mode_sms) || retron_mode) { if (system_sms) {
strcat(fileName, ".gg");
sprintf(folder, "GG/ROM/%s/%d", romName, foldern);
} else if (raphnet_mode_sg1000) {
strcat(fileName, ".sg");
sprintf(folder, "SG1000/ROM/%s/%d", romName, foldern);
} else {
strcat(fileName, ".sms"); strcat(fileName, ".sms");
sprintf(folder, "SMS/ROM/%s/%d", romName, foldern); sprintf(folder, "SMS/ROM/%s/%d", romName, foldern);
} else if (system_gg) {
strcat(fileName, ".gg");
sprintf(folder, "GG/ROM/%s/%d", romName, foldern);
} else {
strcat(fileName, ".sg");
sprintf(folder, "SG1000/ROM/%s/%d", romName, foldern);
} }
// Create a new folder // Create a new folder
sd.chdir("/");
sd.mkdir(folder, true); sd.mkdir(folder, true);
sd.chdir(folder); sd.chdir(folder);
@ -588,7 +575,7 @@ void readROM_SMS() {
println_Msg(F("/...")); println_Msg(F("/..."));
display_Update(); display_Update();
// write new folder number back to eeprom // Write new folder number back to eeprom
foldern = foldern + 1; foldern = foldern + 1;
EEPROM_writeAnything(0, foldern); EEPROM_writeAnything(0, foldern);
@ -597,22 +584,22 @@ void readROM_SMS() {
print_FatalError(sd_error_STR); print_FatalError(sd_error_STR);
} }
// set default bank size to 16KB // Set default bank size to 16KB
word bankSize = 16 * 1024UL; word bankSize = 16 * 1024UL;
// for carts not using mappers (SG1000 or SMS/GG 32KB) // For carts not using mappers (SG1000 or SMS/GG 32KB)
if (raphnet_mode_sg1000 || (cartSize == 32 * 1024UL)) { if ((system_sg1000) || (cartSize == 32 * 1024UL)) {
bankSize = cartSize; bankSize = cartSize;
} }
//Initialize progress bar // Initialize progress bar
uint32_t processedProgressBar = 0; uint32_t processedProgressBar = 0;
uint32_t totalProgressBar = (uint32_t)(cartSize); uint32_t totalProgressBar = (uint32_t)(cartSize);
draw_progressbar(0, totalProgressBar); draw_progressbar(0, totalProgressBar);
for (byte currBank = 0x0; currBank < (cartSize / bankSize); currBank++) { for (byte currBank = 0x0; currBank < (cartSize / bankSize); currBank++) {
// Write current 16KB bank to slot 2 register 0xFFFF // Write current 16KB bank to slot 2 register 0xFFFF
if (!raphnet_mode_sg1000) { if (!system_sg1000) {
writeByte_SMS(0xFFFF, currBank); writeByte_SMS(0xFFFF, currBank);
} }
@ -623,7 +610,7 @@ void readROM_SMS() {
for (word currBuffer = 0; currBuffer < bankSize; currBuffer += 512) { for (word currBuffer = 0; currBuffer < bankSize; currBuffer += 512) {
// Fill SD buffer // Fill SD buffer
for (int currByte = 0; currByte < 512; currByte++) { 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(((system_sg1000) || (cartSize == 32 * 1024UL) ? 0 : 0x8000) + currBuffer + currByte);
} }
// hexdump for debugging: // hexdump for debugging:
// if (currBank == 0 && currBuffer == 0) { // if (currBank == 0 && currBuffer == 0) {
@ -643,27 +630,47 @@ void readROM_SMS() {
myFile.write(sdBuffer, 512); myFile.write(sdBuffer, 512);
} }
// update progress bar // Update progress bar
processedProgressBar += bankSize; processedProgressBar += bankSize;
draw_progressbar(processedProgressBar, totalProgressBar); draw_progressbar(processedProgressBar, totalProgressBar);
} }
// Close the file:
// Close file
myFile.close(); myFile.close();
// Compare dump checksum with database values
if (system_sms) {
compareCRC("sms.txt", 0, 1, 0);
} else if (system_gg) {
compareCRC("gg.txt", 0, 1, 0);
} else {
compareCRC("sg1000.txt", 0, 1, 0);
}
#ifdef global_log
save_log();
#endif
print_STR(press_button_STR, 1);
} }
// Read SRAM and save to the SD card //******************************************
// Read SRAM and save to the SD card
///*****************************************
void readSRAM_SMS() { void readSRAM_SMS() {
// Get name, add extension and convert to char array for sd lib // Get name, add extension and convert to char array for sd lib
strcpy(fileName, romName); strcpy(fileName, romName);
strcat(fileName, ".sav"); strcat(fileName, ".sav");
// create a new folder
EEPROM_readAnything(0, foldern); EEPROM_readAnything(0, foldern);
if ((retrode_mode && !retrode_mode_sms) || retron_mode) { if (system_gg) {
sprintf(folder, "GG/SAVE/%s/%d", romName, foldern); sprintf(folder, "GG/SAVE/%s/%d", romName, foldern);
} else { } else {
sprintf(folder, "SMS/SAVE/%s/%d", romName, foldern); sprintf(folder, "SMS/SAVE/%s/%d", romName, foldern);
} }
// Create a new folder
sd.chdir("/");
sd.mkdir(folder, true); sd.mkdir(folder, true);
sd.chdir(folder); sd.chdir(folder);
@ -677,34 +684,39 @@ void readSRAM_SMS() {
foldern = foldern + 1; foldern = foldern + 1;
EEPROM_writeAnything(0, foldern); EEPROM_writeAnything(0, foldern);
// Open file on sd card // Create file on sd card
if (!myFile.open(fileName, O_RDWR | O_CREAT)) { if (myFile.open(fileName, O_RDWR | O_CREAT)) {
print_FatalError(sd_error_STR); // Write the whole 32KB
} // When there is only 8KB of SRAM, the contents should be duplicated
// Write the whole 32KB word bankSize = 16 * 1024UL;
// When there is only 8KB of SRAM, the contents should be duplicated for (byte currBank = 0x0; currBank < 2; currBank++) {
word bankSize = 16 * 1024UL; writeByte_SMS(0xFFFC, 0x08 | (currBank << 2));
for (byte currBank = 0x0; currBank < 2; currBank++) {
writeByte_SMS(0xFFFC, 0x08 | (currBank << 2));
// Blink led // Blink led
blinkLED(); blinkLED();
// Read 16KB from slot 2 which starts at 0x8000
for (word currBuffer = 0; currBuffer < bankSize; currBuffer += 512) { // Read 16KB from slot 2 which starts at 0x8000
// Fill SD buffer for (word currBuffer = 0; currBuffer < bankSize; currBuffer += 512) {
for (int currByte = 0; currByte < 512; currByte++) { // Fill SD buffer
sdBuffer[currByte] = readByte_SMS(0x8000 + currBuffer + currByte); for (int currByte = 0; currByte < 512; currByte++) {
sdBuffer[currByte] = readByte_SMS(0x8000 + currBuffer + currByte);
}
myFile.write(sdBuffer, 512);
} }
myFile.write(sdBuffer, 512);
} }
// Close file
myFile.close();
print_STR(press_button_STR, 1);
display_Update();
} else {
print_FatalError(sd_error_STR);
} }
// Close the file:
myFile.close();
} }
//**********************************************
// Read file from SD card and write it to SRAM
//**********************************************
void writeSRAM_SMS() { void writeSRAM_SMS() {
display_Clear();
if (false) { if (false) {
print_Error(F("DISABLED")); print_Error(F("DISABLED"));
} else { } else {
@ -716,7 +728,6 @@ void writeSRAM_SMS() {
display_Clear(); display_Clear();
println_Msg(F("Restoring from ")); println_Msg(F("Restoring from "));
println_Msg(filePath); println_Msg(filePath);
println_Msg(fileName);
display_Update(); display_Update();
if (myFile.open(filePath, O_READ)) { if (myFile.open(filePath, O_READ)) {
@ -740,21 +751,15 @@ void writeSRAM_SMS() {
writeByte_SMS(0x8000 + page_address + x, sdBuffer[x]); writeByte_SMS(0x8000 + page_address + x, sdBuffer[x]);
} }
} }
// Close file
myFile.close(); myFile.close();
print_STR(press_button_STR, 1);
// Blink led
blinkLED();
println_Msg(F(""));
print_STR(done_STR, 1);
display_Update(); display_Update();
} else { } else {
print_FatalError(sd_error_STR); print_FatalError(sd_error_STR);
} }
} }
display_Clear();
sd.chdir(); // root sd.chdir(); // root
filePath[0] = '\0'; // Reset filePath filePath[0] = '\0'; // Reset filePath
} }
@ -762,4 +767,4 @@ void writeSRAM_SMS() {
//****************************************** //******************************************
// End of File // End of File
//****************************************** //******************************************