V27A: Add Mega Drive SRAM read/write

Only tested with the game STRIKER. There are probably multiple types of SRAM games so not all will work yet.
This commit is contained in:
sanni 2017-06-27 23:27:10 +02:00 committed by GitHub
parent 80e0e12c82
commit 9335e1d2aa
3 changed files with 221 additions and 46 deletions

View File

@ -2,8 +2,8 @@
Cartridge Reader for Arduino Mega2560 Cartridge Reader for Arduino Mega2560
Author: sanni Author: sanni
Date: 2017-06-26 Date: 2017-06-27
Version: V27 Version: V27A
SD lib: https://github.com/greiman/SdFat SD lib: https://github.com/greiman/SdFat
LCD lib: https://github.com/adafruit/Adafruit_SSD1306 LCD lib: https://github.com/adafruit/Adafruit_SSD1306
@ -34,7 +34,7 @@
YamaArashi - GBA flashrom bank switch command YamaArashi - GBA flashrom bank switch command
**********************************************************************************/ **********************************************************************************/
char ver[5] = "V27"; char ver[5] = "V27A";
/****************************************** /******************************************
Define Output Define Output
@ -192,6 +192,7 @@ char cartID[5];
unsigned long cartSize; unsigned long cartSize;
char flashid[5]; char flashid[5];
unsigned long fileSize; unsigned long fileSize;
unsigned long sramBase;
// Variable to count errors // Variable to count errors
unsigned long writeErrors; unsigned long writeErrors;

View File

@ -2,6 +2,11 @@
// SEGA MEGA DRIVE // SEGA MEGA DRIVE
//****************************************** //******************************************
/******************************************
Variables
*****************************************/
unsigned long sramEnd;
/****************************************** /******************************************
Menu Menu
*****************************************/ *****************************************/
@ -18,7 +23,7 @@ void mdMenu() {
unsigned char mainMenu; unsigned char mainMenu;
// Copy menuOptions out of progmem // Copy menuOptions out of progmem
convertPgm(menuOptionsMD, 5); convertPgm(menuOptionsMD, 5);
mainMenu = question_box("MEGA DRIVE Reader", menuOptions, 1, 0); mainMenu = question_box("MEGA DRIVE Reader", menuOptions, 3, 0);
// wait for user choice to come back from the question box menu // wait for user choice to come back from the question box menu
switch (mainMenu) switch (mainMenu)
@ -31,13 +36,15 @@ void mdMenu() {
//compare_checksum_MD(); //compare_checksum_MD();
break; break;
/*case 1: case 1:
display_Clear(); display_Clear();
// Does cartridge have SRAM // Does cartridge have SRAM
if () { if ((saveType == 1) || (saveType == 2)) {
// Change working dir to root // Change working dir to root
sd.chdir("/"); sd.chdir("/");
readSRAM_MD(); println_Msg(F("Reading Sram..."));
display_Update();
readSram_MD();
} }
else { else {
print_Error(F("Cart has no Sram"), false); print_Error(F("Cart has no Sram"), false);
@ -47,19 +54,22 @@ void mdMenu() {
case 2: case 2:
display_Clear(); display_Clear();
// Does cartridge have SRAM // Does cartridge have SRAM
if () { if ((saveType == 1) || (saveType == 2)) {
// Change working dir to root // Change working dir to root
sd.chdir("/"); sd.chdir("/");
writeSRAM_MD(); // Launch file browser
unsigned long wrErrors; fileBrowser("Select srm file");
wrErrors = verifySRAM_MD(); display_Clear();
if (wrErrors == 0) {
println_Msg(F("Verified OK")); writeSram_MD();
writeErrors = verifySram_MD();
if (writeErrors == 0) {
println_Msg(F("Sram verified OK"));
display_Update(); display_Update();
} }
else { else {
print_Msg(F("Error: ")); print_Msg(F("Error: "));
print_Msg(wrErrors); print_Msg(writeErrors);
println_Msg(F(" bytes ")); println_Msg(F(" bytes "));
print_Error(F("did not verify."), false); print_Error(F("did not verify."), false);
} }
@ -69,7 +79,7 @@ void mdMenu() {
} }
break; break;
case 3: /*case 3:
// Change working dir to root // Change working dir to root
sd.chdir("/"); sd.chdir("/");
writeFlash_MD(); writeFlash_MD();
@ -134,7 +144,7 @@ void writeWord_MD(unsigned long myAddress, word myData) {
// Arduino running at 16Mhz -> one nop = 62.5ns // Arduino running at 16Mhz -> one nop = 62.5ns
// Wait till output is stable // Wait till output is stable
__asm__("nop\n\t"); __asm__("nop\n\t""nop\n\t");
// Switch WR(PH5) to LOW // Switch WR(PH5) to LOW
PORTH &= ~(1 << 5); PORTH &= ~(1 << 5);
@ -155,7 +165,7 @@ word readWord_MD(unsigned long myAddress) {
PORTL = (myAddress >> 16) & 0xFF; PORTL = (myAddress >> 16) & 0xFF;
// Arduino running at 16Mhz -> one nop = 62.5ns // 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");
// Setting OE(PH6) LOW // Setting OE(PH6) LOW
PORTH &= ~(1 << 6); PORTH &= ~(1 << 6);
@ -188,8 +198,40 @@ void dataIn_MD() {
MEGA DRIVE functions MEGA DRIVE functions
*****************************************/ *****************************************/
void getCartInfo_MD() { void getCartInfo_MD() {
// Set control
dataIn_MD();
cartSize = ((long(readWord_MD(0xD2)) << 16) | readWord_MD(0xD3)) + 1; cartSize = ((long(readWord_MD(0xD2)) << 16) | readWord_MD(0xD3)) + 1;
sramSize = ((long(readWord_MD(0xDC)) << 16) | readWord_MD(0xDD)) - ((long(readWord_MD(0xDA)) << 16) | readWord_MD(0xDB)) + 2;
// Check if cart has sram
if ((readWord_MD(0xD8) == 0x5241) && (readWord_MD(0xD9) == 0xF820)) {
// Get sram start and end
sramBase = ((long(readWord_MD(0xDA)) << 16) | readWord_MD(0xDB));
sramEnd = ((long(readWord_MD(0xDC)) << 16) | readWord_MD(0xDD));
// Check alignment of sram
if (sramBase == 0x200001) {
// low byte
saveType = 1;
sramSize = (sramEnd - sramBase + 2) / 2;
// Right shift sram base address so [A21] is set to high 0x200000 = 0b001[0]00000000000000000000
sramBase = sramBase >> 1;
}
else if (sramBase == 0x200000) {
// high byte
saveType = 2;
sramSize = (sramEnd - sramBase + 1) / 2;
// Right shift sram base address so [A21] is set to high 0x200000 = 0b001[0]00000000000000000000
sramBase = sramBase / 2;
}
else
print_Error(F("Unknown Sram Base"), true);
}
else {
// Either no save or eeprom save
saveType = 0;
sramSize = 0;
}
// Get name // Get name
for (byte c = 0; c < 48; c += 2) { for (byte c = 0; c < 48; c += 2) {
@ -219,12 +261,16 @@ void getCartInfo_MD() {
print_Msg(cartSize / 1024 / 1024); print_Msg(cartSize / 1024 / 1024);
println_Msg(F("MB")); println_Msg(F("MB"));
print_Msg(F("Sram: ")); print_Msg(F("Sram: "));
if (sramSize > 0) {
print_Msg(sramSize / 1024); print_Msg(sramSize / 1024);
println_Msg(F("KB")); println_Msg(F("KB"));
}
else
println_Msg(F("None"));
println_Msg(F(" "));
// Wait for user input // Wait for user input
if (enable_OLED) { if (enable_OLED) {
println_Msg(F(" "));
println_Msg(F("Press Button...")); println_Msg(F("Press Button..."));
display_Update(); display_Update();
wait(); wait();
@ -233,6 +279,9 @@ void getCartInfo_MD() {
// Read rom and save to the SD card // Read rom and save to the SD card
void readROM_MD() { void readROM_MD() {
// Set control
dataIn_MD();
// 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, ".MD"); strcat(fileName, ".MD");
@ -280,3 +329,126 @@ void readROM_MD() {
myFile.close(); myFile.close();
} }
/******************************************
SRAM functions
*****************************************/
// Write sram to cartridge
void writeSram_MD() {
dataOut_MD();
// Create filepath
sprintf(filePath, "%s/%s", filePath, fileName);
println_Msg(F("Writing..."));
println_Msg(filePath);
display_Update();
// Open file on sd card
if (myFile.open(filePath, O_READ)) {
// Write to the lower byte
if (saveType == 1) {
for (unsigned long currByte = sramBase; currByte < sramBase + sramSize; currByte++) {
writeWord_MD(currByte, (myFile.read() & 0xFF));
}
}
// Write to the upper byte
else if (saveType == 2) {
for (unsigned long currByte = sramBase; currByte < sramBase + sramSize; currByte++) {
writeWord_MD(currByte, ((myFile.read() << 8 ) & 0xFF));
}
}
else
print_Error(F("Unknown save type"), false);
// Close the file:
myFile.close();
println_Msg(F("Done"));
display_Update();
}
else {
print_Error(F("SD Error"), true);
}
dataIn_MD();
}
// Read sram and save to the SD card
void readSram_MD() {
dataIn_MD();
// Get name, add extension and convert to char array for sd lib
strcpy(fileName, romName);
strcat(fileName, ".srm");
// create a new folder for the save file
EEPROM_readAnything(10, foldern);
sprintf(folder, "MD/SAVE/%s/%d", romName, foldern);
sd.mkdir(folder, true);
sd.chdir(folder);
// write new folder number back to eeprom
foldern = foldern + 1;
EEPROM_writeAnything(10, foldern);
// Open file on sd card
if (!myFile.open(fileName, O_RDWR | O_CREAT)) {
print_Error(F("SD Error"), true);
}
for (unsigned long currBuffer = sramBase; currBuffer < sramBase + sramSize; currBuffer += 512) {
for (int currWord = 0; currWord < 512; currWord++) {
word myWord = readWord_MD(currBuffer + currWord);
if (saveType == 2) {
// Only use the upper byte
sdBuffer[currWord] = (( myWord >> 8 ) & 0xFF);
}
else if (saveType == 1) {
// Only use the lower byte
sdBuffer[currWord] = (myWord & 0xFF);
}
}
myFile.write(sdBuffer, 512);
}
// Close the file:
myFile.close();
print_Msg(F("Saved to "));
print_Msg(folder);
println_Msg(F("/"));
display_Update();
}
unsigned long verifySram_MD() {
dataIn_MD();
writeErrors = 0;
// Open file on sd card
if (myFile.open(filePath, O_READ)) {
for (unsigned long currBuffer = sramBase; currBuffer < sramBase + sramSize; currBuffer += 512) {
for (int currWord = 0; currWord < 512; currWord++) {
word myWord = readWord_MD(currBuffer + currWord);
if (saveType == 2) {
// Only use the upper byte
sdBuffer[currWord] = (( myWord >> 8 ) & 0xFF);
}
else if (saveType == 1) {
// Only use the lower byte
sdBuffer[currWord] = (myWord & 0xFF);
}
}
// Check sdBuffer content against file on sd card
for (int i = 0; i < 512; i++) {
if (myFile.read() != sdBuffer[i]) {
writeErrors++;
}
}
}
// Close the file:
myFile.close();
}
else {
print_Error(F("SD Error"), true);
}
// Return 0 if verified ok, or number of errors
return writeErrors;
}

View File

@ -37,7 +37,6 @@ String lastbutton = "N/A";
// Rom base address // Rom base address
unsigned long romBase = 0x10000000; unsigned long romBase = 0x10000000;
unsigned long sramBase = 0x08000000;
// Flashram type // Flashram type
byte flashramType = 1; byte flashramType = 1;
@ -277,6 +276,9 @@ void setup_N64_Cart() {
// Activate Internal Pullup Resistors // Activate Internal Pullup Resistors
//PORTH |= (1 << 4); //PORTH |= (1 << 4);
// Set sram base address
sramBase = 0x08000000;
// Wait until all is stable // Wait until all is stable
delay(300); delay(300);