mirror of
https://github.com/sanni/cartreader.git
synced 2024-11-13 08:25:05 +01:00
0c75bf8aed
Thanks to skaman for the Sega CD Ram Cart code. Writes to the Sega CD Backup RAM Cart require an extra wire from MRES (B02) to VRES (B27).
254 lines
5.8 KiB
C++
254 lines
5.8 KiB
C++
//******************************************
|
|
// SEGA MASTER SYSTEM MODULE
|
|
//******************************************
|
|
// unfinished and untested
|
|
|
|
/******************************************
|
|
Variables
|
|
*****************************************/
|
|
|
|
/******************************************
|
|
Menu
|
|
*****************************************/
|
|
// MD menu items
|
|
static const char SMSMenuItem1[] PROGMEM = "Read Rom";
|
|
static const char SMSMenuItem2[] PROGMEM = "Reset";
|
|
static const char* const menuOptionsSMS[] PROGMEM = {SMSMenuItem1, SMSMenuItem2};
|
|
|
|
|
|
void smsMenu() {
|
|
// create menu with title and 2 options to choose from
|
|
unsigned char mainMenu;
|
|
// Copy menuOptions out of progmem
|
|
convertPgm(menuOptionsSMS, 2);
|
|
mainMenu = question_box(F("Sega Master System"), menuOptions, 2, 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_SMS();
|
|
break;
|
|
|
|
case 1:
|
|
// Reset
|
|
asm volatile (" jmp 0");
|
|
break;
|
|
}
|
|
println_Msg(F(""));
|
|
println_Msg(F("Press Button..."));
|
|
display_Update();
|
|
wait();
|
|
}
|
|
|
|
/******************************************
|
|
Setup
|
|
*****************************************/
|
|
void setup_SMS() {
|
|
// Set Address Pins to Output
|
|
//A0-A7
|
|
DDRF = 0xFF;
|
|
//A8-A15
|
|
DDRK = 0xFF;
|
|
|
|
// Set Control Pins to Output RST(PH0) CS(PH3) WR(PH5) OE(PH6)
|
|
DDRH |= (1 << 0) | (1 << 3) | (1 << 5) | (1 << 6);
|
|
|
|
// Set Data Pins (D0-D15) to Input
|
|
DDRC = 0x00;
|
|
|
|
// Setting RST(PH0) CS(PH3) WR(PH5) OE(PH6) HIGH
|
|
PORTH |= (1 << 0) | (1 << 3) | (1 << 5) | (1 << 6);
|
|
|
|
delay(200);
|
|
|
|
// Print all the info
|
|
getCartInfo_SMS();
|
|
}
|
|
|
|
/******************************************
|
|
Low level functions
|
|
*****************************************/
|
|
void writeByte_SMS(unsigned long myAddress, word myData) {
|
|
PORTF = myAddress & 0xFF;
|
|
PORTK = (myAddress >> 8) & 0xFF;
|
|
PORTC = myData;
|
|
|
|
// Arduino running at 16Mhz -> one nop = 62.5ns
|
|
// Wait till output is stable
|
|
__asm__("nop\n\t""nop\n\t");
|
|
|
|
// Switch WR(PH5) to LOW
|
|
PORTH &= ~(1 << 5);
|
|
// Setting CS(PH3) LOW
|
|
PORTH &= ~(1 << 3);
|
|
|
|
// Leave WR low for at least 200ns
|
|
__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");
|
|
|
|
// Setting CS(PH3) HIGH
|
|
PORTH |= (1 << 3);
|
|
// 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");
|
|
}
|
|
|
|
byte readByte_SMS(unsigned long myAddress) {
|
|
PORTF = myAddress & 0xFF;
|
|
PORTK = (myAddress >> 8) & 0xFF;
|
|
|
|
// Arduino running at 16Mhz -> one nop = 62.5ns
|
|
__asm__("nop\n\t");
|
|
|
|
// Setting CS(PH3) LOW
|
|
PORTH &= ~(1 << 3);
|
|
// Setting OE(PH6) LOW
|
|
PORTH &= ~(1 << 6);
|
|
|
|
// Long delay here or there will be read errors
|
|
__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");
|
|
|
|
// Read
|
|
byte tempByte = (PINC & 0xFF);
|
|
|
|
// Setting CS(PH3) HIGH
|
|
PORTH |= (1 << 3);
|
|
// 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 tempByte;
|
|
}
|
|
|
|
// Switch data pins to write
|
|
void dataOut_SMS() {
|
|
DDRC = 0xFF;
|
|
}
|
|
|
|
// Switch data pins to read
|
|
void dataIn_SMS() {
|
|
DDRC = 0x00;
|
|
}
|
|
|
|
unsigned char hex2bcd (unsigned char x) {
|
|
unsigned char y;
|
|
y = (x / 10) << 4;
|
|
y = y | (x % 10);
|
|
return (y);
|
|
}
|
|
|
|
/******************************************
|
|
MASTER SYSTEM functions
|
|
*****************************************/
|
|
void getCartInfo_SMS() {
|
|
// Set control
|
|
dataIn_SMS();
|
|
|
|
// Rom size
|
|
switch (readByte_SMS(0x7fff) & 0xFF) {
|
|
case 0xa:
|
|
cartSize = 8 * 1024;
|
|
break;
|
|
case 0xb:
|
|
cartSize = 16 * 1024;
|
|
break;
|
|
case 0xc:
|
|
cartSize = 32 * 1024;
|
|
break;
|
|
case 0xd:
|
|
cartSize = 48 * 1024;
|
|
break;
|
|
case 0xe:
|
|
cartSize = 64 * 1024;
|
|
break;
|
|
case 0xf:
|
|
cartSize = 128 * 1024;
|
|
break;
|
|
case 0x0:
|
|
cartSize = 256 * 1024;
|
|
break;
|
|
case 0x1:
|
|
cartSize = 512 * 1024;
|
|
break;
|
|
case 0x2:
|
|
cartSize = 512 * 1024;
|
|
break;
|
|
}
|
|
|
|
// Get product code
|
|
romName[0] = (readByte_SMS(0x7ffe) >> 4);
|
|
romName[1] = hex2bcd(readByte_SMS(0x7ffd));
|
|
romName[2] = hex2bcd(readByte_SMS(0x7ffc));
|
|
|
|
display_Clear();
|
|
println_Msg(F("Cart Info"));
|
|
println_Msg(F(" "));
|
|
print_Msg(F("Name: "));
|
|
println_Msg(romName);
|
|
print_Msg(F("Size: "));
|
|
print_Msg(cartSize * 8 / 1024 );
|
|
println_Msg(F(" KBit"));
|
|
println_Msg(F(" "));
|
|
|
|
// Wait for user input
|
|
if (enable_OLED) {
|
|
println_Msg(F("Press Button..."));
|
|
display_Update();
|
|
wait();
|
|
}
|
|
}
|
|
|
|
// Read rom and save to the SD card
|
|
void readROM_SMS() {
|
|
// Set control
|
|
dataIn_SMS();
|
|
|
|
// Get name, add extension and convert to char array for sd lib
|
|
strcpy(fileName, romName);
|
|
strcat(fileName, ".SMS");
|
|
|
|
// create a new folder
|
|
EEPROM_readAnything(10, foldern);
|
|
sprintf(folder, "SMS/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);
|
|
}
|
|
|
|
|
|
for (unsigned long currBuffer = 0; currBuffer < cartSize; currBuffer += 512) {
|
|
// Blink led
|
|
if (currBuffer % 16384 == 0)
|
|
PORTB ^= (1 << 4);
|
|
|
|
for (int currByte = 0; currByte < 512; currByte++) {
|
|
sdBuffer[currByte] = readByte_SMS(currBuffer + currByte);
|
|
}
|
|
myFile.write(sdBuffer, 512);
|
|
}
|
|
// Close the file:
|
|
myFile.close();
|
|
}
|
|
|
|
//******************************************
|
|
// End of File
|
|
//******************************************
|