cartreader/Cart_Reader/MD.ino
sanni 80e0e12c82 V27: Add basic Mega Drive Support
Just dumping of roms right now, no save games. Not sure if all games will dump or if there are some special ones.
2017-06-26 23:48:07 +02:00

283 lines
6.9 KiB
C++

//******************************************
// SEGA MEGA DRIVE
//******************************************
/******************************************
Menu
*****************************************/
// MD menu items
static const char MDMenuItem1[] PROGMEM = "Read Rom";
static const char MDMenuItem2[] PROGMEM = "Read Save";
static const char MDMenuItem3[] PROGMEM = "Write Save";
static const char MDMenuItem4[] PROGMEM = "Write Flashcart";
static const char MDMenuItem5[] PROGMEM = "Reset";
static const char* const menuOptionsMD[] PROGMEM = {MDMenuItem1, MDMenuItem2, MDMenuItem3, MDMenuItem4, MDMenuItem5};
void mdMenu() {
// create menu with title and 5 options to choose from
unsigned char mainMenu;
// Copy menuOptions out of progmem
convertPgm(menuOptionsMD, 5);
mainMenu = question_box("MEGA DRIVE Reader", menuOptions, 1, 0);
// wait for user choice to come back from the question box menu
switch (mainMenu)
{
case 0:
display_Clear();
// Change working dir to root
sd.chdir("/");
readROM_MD();
//compare_checksum_MD();
break;
/*case 1:
display_Clear();
// Does cartridge have SRAM
if () {
// Change working dir to root
sd.chdir("/");
readSRAM_MD();
}
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:
// Change working dir to root
sd.chdir("/");
writeFlash_MD();
// Reset
wait();
asm volatile (" jmp 0");
break;
case 4:
asm volatile (" jmp 0");
break;*/
}
println_Msg(F(""));
println_Msg(F("Press Button..."));
display_Update();
wait();
}
/******************************************
Setup
*****************************************/
void setup_MD() {
// Set Address Pins to Output
//A0-A7
DDRF = 0xFF;
//A8-A15
DDRK = 0xFF;
//A16-A23
DDRL = 0xFF;
// Set Control Pins to Output CS(PH3) WR(PH5) OE(PH6)
DDRH |= (1 << 3) | (1 << 5) | (1 << 6);
// Set Data Pins (D0-D15) to Input
DDRC = 0x00;
DDRA = 0x00;
// Setting WR(PH5) OE(PH6) HIGH
PORTH |= (1 << 5) | (1 << 6);
// Setting CS(PH3) LOW
PORTH &= ~(1 << 3);
delay(200);
// Print all the info
getCartInfo_MD();
}
/******************************************
I/O Functions
*****************************************/
/******************************************
Low level functions
*****************************************/
void writeWord_MD(unsigned long myAddress, word myData) {
PORTF = myAddress & 0xFF;
PORTK = (myAddress >> 8) & 0xFF;
PORTL = (myAddress >> 16) & 0xFF;
PORTC = myData;
PORTA = (myData >> 8) & 0xFF;
// Arduino running at 16Mhz -> one nop = 62.5ns
// Wait till output is stable
__asm__("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");
// 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");
}
word readWord_MD(unsigned long myAddress) {
PORTF = myAddress & 0xFF;
PORTK = (myAddress >> 8) & 0xFF;
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");
// Setting OE(PH6) LOW
PORTH &= ~(1 << 6);
__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 );
// Setting OE(PH6) HIGH
PORTH |= (1 << 6);
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");
return tempWord;
}
// Switch data pins to write
void dataOut_MD() {
DDRC = 0xFF;
DDRA = 0xFF;
}
// Switch data pins to read
void dataIn_MD() {
DDRC = 0x00;
DDRA = 0x00;
}
/******************************************
MEGA DRIVE functions
*****************************************/
void getCartInfo_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;
// Get name
for (byte c = 0; c < 48; c += 2) {
// split word
word myWord = readWord_MD((0x150 + c) / 2);
byte loByte = myWord & 0xFF;
byte hiByte = myWord >> 8;
// write to buffer
sdBuffer[c] = hiByte;
sdBuffer[c + 1] = loByte;
}
byte myLength = 0;
for (unsigned int i = 0; i < 48; i++) {
if (((char(sdBuffer[i]) >= 48 && char(sdBuffer[i]) <= 57) || (char(sdBuffer[i]) >= 65 && char(sdBuffer[i]) <= 122)) && myLength < 15) {
romName[myLength] = char(sdBuffer[i]);
myLength++;
}
}
display_Clear();
println_Msg(F("Cart Info"));
println_Msg(F(" "));
print_Msg(F("Name: "));
println_Msg(romName);
print_Msg(F("Size: "));
print_Msg(cartSize / 1024 / 1024);
println_Msg(F("MB"));
print_Msg(F("Sram: "));
print_Msg(sramSize / 1024);
println_Msg(F("KB"));
// Wait for user input
if (enable_OLED) {
println_Msg(F(" "));
println_Msg(F("Press Button..."));
display_Update();
wait();
}
}
// Read rom and save to the SD card
void readROM_MD() {
// Get name, add extension and convert to char array for sd lib
strcpy(fileName, romName);
strcat(fileName, ".MD");
// create a new folder
EEPROM_readAnything(10, foldern);
sprintf(folder, "MD/ROM/%s/%d", romName, foldern);
sd.mkdir(folder, true);
sd.chdir(folder);
display_Clear();
print_Msg(F("Saving to "));
print_Msg(folder);
println_Msg(F("/..."));
display_Update();
// 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);
}
word d = 0;
for (unsigned long currBuffer = 0; currBuffer < cartSize / 2; currBuffer += 256) {
// Blink led
if (currBuffer % 16384 == 0)
PORTB ^= (1 << 4);
for (int currWord = 0; currWord < 256; currWord++) {
word myWord = readWord_MD(currBuffer + currWord);
// Split word into two bytes
// Left
sdBuffer[d] = (( myWord >> 8 ) & 0xFF);
// Right
sdBuffer[d + 1] = (myWord & 0xFF);
d += 2;
}
myFile.write(sdBuffer, 512);
d = 0;
}
// Close the file:
myFile.close();
}