mirror of
https://github.com/sanni/cartreader.git
synced 2024-11-27 23:14:14 +01:00
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:
parent
80e0e12c82
commit
9335e1d2aa
@ -2,8 +2,8 @@
|
||||
Cartridge Reader for Arduino Mega2560
|
||||
|
||||
Author: sanni
|
||||
Date: 2017-06-26
|
||||
Version: V27
|
||||
Date: 2017-06-27
|
||||
Version: V27A
|
||||
|
||||
SD lib: https://github.com/greiman/SdFat
|
||||
LCD lib: https://github.com/adafruit/Adafruit_SSD1306
|
||||
@ -34,7 +34,7 @@
|
||||
YamaArashi - GBA flashrom bank switch command
|
||||
|
||||
**********************************************************************************/
|
||||
char ver[5] = "V27";
|
||||
char ver[5] = "V27A";
|
||||
|
||||
/******************************************
|
||||
Define Output
|
||||
@ -192,6 +192,7 @@ char cartID[5];
|
||||
unsigned long cartSize;
|
||||
char flashid[5];
|
||||
unsigned long fileSize;
|
||||
unsigned long sramBase;
|
||||
|
||||
// Variable to count errors
|
||||
unsigned long writeErrors;
|
||||
|
@ -2,6 +2,11 @@
|
||||
// SEGA MEGA DRIVE
|
||||
//******************************************
|
||||
|
||||
/******************************************
|
||||
Variables
|
||||
*****************************************/
|
||||
unsigned long sramEnd;
|
||||
|
||||
/******************************************
|
||||
Menu
|
||||
*****************************************/
|
||||
@ -18,7 +23,7 @@ void mdMenu() {
|
||||
unsigned char mainMenu;
|
||||
// Copy menuOptions out of progmem
|
||||
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
|
||||
switch (mainMenu)
|
||||
@ -31,45 +36,50 @@ void mdMenu() {
|
||||
//compare_checksum_MD();
|
||||
break;
|
||||
|
||||
/*case 1:
|
||||
case 1:
|
||||
display_Clear();
|
||||
// Does cartridge have SRAM
|
||||
if ((saveType == 1) || (saveType == 2)) {
|
||||
// Change working dir to root
|
||||
sd.chdir("/");
|
||||
println_Msg(F("Reading Sram..."));
|
||||
display_Update();
|
||||
readSram_MD();
|
||||
}
|
||||
else {
|
||||
print_Error(F("Cart has no Sram"), false);
|
||||
}
|
||||
break;
|
||||
|
||||
case 2:
|
||||
display_Clear();
|
||||
// Does cartridge have SRAM
|
||||
if ((saveType == 1) || (saveType == 2)) {
|
||||
// Change working dir to root
|
||||
sd.chdir("/");
|
||||
// Launch file browser
|
||||
fileBrowser("Select srm file");
|
||||
display_Clear();
|
||||
// Does cartridge have SRAM
|
||||
if () {
|
||||
// Change working dir to root
|
||||
sd.chdir("/");
|
||||
readSRAM_MD();
|
||||
|
||||
writeSram_MD();
|
||||
writeErrors = verifySram_MD();
|
||||
if (writeErrors == 0) {
|
||||
println_Msg(F("Sram verified OK"));
|
||||
display_Update();
|
||||
}
|
||||
else {
|
||||
print_Error(F("Cart has no Sram"), false);
|
||||
print_Msg(F("Error: "));
|
||||
print_Msg(writeErrors);
|
||||
println_Msg(F(" bytes "));
|
||||
print_Error(F("did not verify."), false);
|
||||
}
|
||||
break;
|
||||
}
|
||||
else {
|
||||
print_Error(F("Cart has no Sram"), false);
|
||||
}
|
||||
break;
|
||||
|
||||
case 2:
|
||||
display_Clear();
|
||||
// Does cartridge have SRAM
|
||||
if () {
|
||||
// Change working dir to root
|
||||
sd.chdir("/");
|
||||
writeSRAM_MD();
|
||||
unsigned long wrErrors;
|
||||
wrErrors = verifySRAM_MD();
|
||||
if (wrErrors == 0) {
|
||||
println_Msg(F("Verified OK"));
|
||||
display_Update();
|
||||
}
|
||||
else {
|
||||
print_Msg(F("Error: "));
|
||||
print_Msg(wrErrors);
|
||||
println_Msg(F(" bytes "));
|
||||
print_Error(F("did not verify."), false);
|
||||
}
|
||||
}
|
||||
else {
|
||||
print_Error(F("Cart has no Sram"), false);
|
||||
}
|
||||
break;
|
||||
|
||||
case 3:
|
||||
/*case 3:
|
||||
// Change working dir to root
|
||||
sd.chdir("/");
|
||||
writeFlash_MD();
|
||||
@ -134,7 +144,7 @@ void writeWord_MD(unsigned long myAddress, word myData) {
|
||||
|
||||
// Arduino running at 16Mhz -> one nop = 62.5ns
|
||||
// Wait till output is stable
|
||||
__asm__("nop\n\t");
|
||||
__asm__("nop\n\t""nop\n\t");
|
||||
|
||||
// Switch WR(PH5) to LOW
|
||||
PORTH &= ~(1 << 5);
|
||||
@ -155,7 +165,7 @@ word readWord_MD(unsigned long myAddress) {
|
||||
PORTL = (myAddress >> 16) & 0xFF;
|
||||
|
||||
// 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
|
||||
PORTH &= ~(1 << 6);
|
||||
@ -188,8 +198,40 @@ void dataIn_MD() {
|
||||
MEGA DRIVE functions
|
||||
*****************************************/
|
||||
void getCartInfo_MD() {
|
||||
// Set control
|
||||
dataIn_MD();
|
||||
|
||||
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
|
||||
for (byte c = 0; c < 48; c += 2) {
|
||||
@ -219,12 +261,16 @@ void getCartInfo_MD() {
|
||||
print_Msg(cartSize / 1024 / 1024);
|
||||
println_Msg(F("MB"));
|
||||
print_Msg(F("Sram: "));
|
||||
print_Msg(sramSize / 1024);
|
||||
println_Msg(F("KB"));
|
||||
if (sramSize > 0) {
|
||||
print_Msg(sramSize / 1024);
|
||||
println_Msg(F("KB"));
|
||||
}
|
||||
else
|
||||
println_Msg(F("None"));
|
||||
println_Msg(F(" "));
|
||||
|
||||
// Wait for user input
|
||||
if (enable_OLED) {
|
||||
println_Msg(F(" "));
|
||||
println_Msg(F("Press Button..."));
|
||||
display_Update();
|
||||
wait();
|
||||
@ -233,6 +279,9 @@ void getCartInfo_MD() {
|
||||
|
||||
// Read rom and save to the SD card
|
||||
void readROM_MD() {
|
||||
// Set control
|
||||
dataIn_MD();
|
||||
|
||||
// Get name, add extension and convert to char array for sd lib
|
||||
strcpy(fileName, romName);
|
||||
strcat(fileName, ".MD");
|
||||
@ -280,3 +329,126 @@ void readROM_MD() {
|
||||
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;
|
||||
}
|
||||
|
@ -37,7 +37,6 @@ String lastbutton = "N/A";
|
||||
|
||||
// Rom base address
|
||||
unsigned long romBase = 0x10000000;
|
||||
unsigned long sramBase = 0x08000000;
|
||||
|
||||
// Flashram type
|
||||
byte flashramType = 1;
|
||||
@ -277,6 +276,9 @@ void setup_N64_Cart() {
|
||||
// Activate Internal Pullup Resistors
|
||||
//PORTH |= (1 << 4);
|
||||
|
||||
// Set sram base address
|
||||
sramBase = 0x08000000;
|
||||
|
||||
// Wait until all is stable
|
||||
delay(300);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user