mirror of
https://github.com/sanni/cartreader.git
synced 2024-11-27 15:04:15 +01:00
commit
dece32c130
@ -257,6 +257,7 @@ void print_STR(byte string_number, boolean newline) {
|
|||||||
#define mode_5200 37
|
#define mode_5200 37
|
||||||
#define mode_7800 38
|
#define mode_7800 38
|
||||||
#define mode_VECTREX 39
|
#define mode_VECTREX 39
|
||||||
|
#define mode_ST 40
|
||||||
|
|
||||||
// optimization-safe nop delay
|
// optimization-safe nop delay
|
||||||
#define NOP __asm__ __volatile__("nop\n\t")
|
#define NOP __asm__ __volatile__("nop\n\t")
|
||||||
@ -3592,6 +3593,11 @@ void loop() {
|
|||||||
svMenu();
|
svMenu();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef enable_ST
|
||||||
|
else if (mode == mode_ST) {
|
||||||
|
stMenu();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
#ifdef enable_NES
|
#ifdef enable_NES
|
||||||
else if (mode == mode_NES) {
|
else if (mode == mode_NES) {
|
||||||
nesMenu();
|
nesMenu();
|
||||||
|
@ -223,6 +223,13 @@
|
|||||||
|
|
||||||
/****/
|
/****/
|
||||||
|
|
||||||
|
/* [ Super Famicom Sufami Turbo ----------------------------------- ]
|
||||||
|
*/
|
||||||
|
|
||||||
|
// #define enable_ST
|
||||||
|
|
||||||
|
/****/
|
||||||
|
|
||||||
/* [ Super Nintendo ----------------------------------------------- ]
|
/* [ Super Nintendo ----------------------------------------------- ]
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -32,14 +32,15 @@ boolean altconf = 0;
|
|||||||
static const char snsMenuItem1[] PROGMEM = "SNES/SFC cartridge";
|
static const char snsMenuItem1[] PROGMEM = "SNES/SFC cartridge";
|
||||||
static const char snsMenuItem2[] PROGMEM = "SF Memory Cassette";
|
static const char snsMenuItem2[] PROGMEM = "SF Memory Cassette";
|
||||||
static const char snsMenuItem3[] PROGMEM = "Satellaview BS-X";
|
static const char snsMenuItem3[] PROGMEM = "Satellaview BS-X";
|
||||||
static const char snsMenuItem4[] PROGMEM = "Flash repro";
|
static const char snsMenuItem4[] PROGMEM = "Sufami Turbo";
|
||||||
|
static const char snsMenuItem5[] PROGMEM = "Flash repro";
|
||||||
#ifdef clockgen_calibration
|
#ifdef clockgen_calibration
|
||||||
static const char snsMenuItem5[] PROGMEM = "Calibrate Clock";
|
static const char snsMenuItem6[] PROGMEM = "Calibrate Clock";
|
||||||
|
//static const char snsMenuItem7[] PROGMEM = "Reset"; (stored in common strings array)
|
||||||
|
static const char* const menuOptionsSNS[] PROGMEM = { snsMenuItem1, snsMenuItem2, snsMenuItem3, snsMenuItem4, snsMenuItem5, snsMenuItem6, string_reset2 };
|
||||||
|
#else
|
||||||
//static const char snsMenuItem6[] PROGMEM = "Reset"; (stored in common strings array)
|
//static const char snsMenuItem6[] PROGMEM = "Reset"; (stored in common strings array)
|
||||||
static const char* const menuOptionsSNS[] PROGMEM = { snsMenuItem1, snsMenuItem2, snsMenuItem3, snsMenuItem4, snsMenuItem5, string_reset2 };
|
static const char* const menuOptionsSNS[] PROGMEM = { snsMenuItem1, snsMenuItem2, snsMenuItem3, snsMenuItem4, snsMenuItem5, string_reset2 };
|
||||||
#else
|
|
||||||
//static const char snsMenuItem5[] PROGMEM = "Reset"; (stored in common strings array)
|
|
||||||
static const char* const menuOptionsSNS[] PROGMEM = { snsMenuItem1, snsMenuItem2, snsMenuItem3, snsMenuItem4, string_reset2 };
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// SNES menu items
|
// SNES menu items
|
||||||
@ -132,15 +133,15 @@ void reproMenu() {
|
|||||||
|
|
||||||
// SNES start menu
|
// SNES start menu
|
||||||
void snsMenu() {
|
void snsMenu() {
|
||||||
// create menu with title and 6 options to choose from
|
// create menu with title and 7 options to choose from
|
||||||
unsigned char snsCart;
|
unsigned char snsCart;
|
||||||
// Copy menuOptions out of progmem
|
// Copy menuOptions out of progmem
|
||||||
#ifdef clockgen_calibration
|
#ifdef clockgen_calibration
|
||||||
|
convertPgm(menuOptionsSNS, 7);
|
||||||
|
snsCart = question_box(F("Select Cart Type"), menuOptions, 7, 0);
|
||||||
|
#else
|
||||||
convertPgm(menuOptionsSNS, 6);
|
convertPgm(menuOptionsSNS, 6);
|
||||||
snsCart = question_box(F("Select Cart Type"), menuOptions, 6, 0);
|
snsCart = question_box(F("Select Cart Type"), menuOptions, 6, 0);
|
||||||
#else
|
|
||||||
convertPgm(menuOptionsSNS, 5);
|
|
||||||
snsCart = question_box(F("Select Cart Type"), menuOptions, 5, 0);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// wait for user choice to come back from the question box menu
|
// wait for user choice to come back from the question box menu
|
||||||
@ -170,19 +171,28 @@ void snsMenu() {
|
|||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef enable_FLASH
|
#ifdef enable_ST
|
||||||
case 3:
|
case 3:
|
||||||
|
display_Clear();
|
||||||
|
display_Update();
|
||||||
|
setup_ST();
|
||||||
|
mode = mode_ST;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef enable_FLASH
|
||||||
|
case 4:
|
||||||
setup_FlashVoltage();
|
setup_FlashVoltage();
|
||||||
reproMenu();
|
reproMenu();
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
case 4:
|
case 5:
|
||||||
#ifdef clockgen_calibration
|
#ifdef clockgen_calibration
|
||||||
clkcal();
|
clkcal();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 5:
|
case 6:
|
||||||
#endif
|
#endif
|
||||||
resetArduino();
|
resetArduino();
|
||||||
break;
|
break;
|
||||||
|
205
Cart_Reader/ST.ino
Normal file
205
Cart_Reader/ST.ino
Normal file
@ -0,0 +1,205 @@
|
|||||||
|
/******************************************
|
||||||
|
SUPER FAMICOM SUFAMI TURBO MODULE
|
||||||
|
******************************************/
|
||||||
|
#ifdef enable_ST
|
||||||
|
|
||||||
|
/******************************************
|
||||||
|
Menu
|
||||||
|
*****************************************/
|
||||||
|
// Sufami Turbo menu items
|
||||||
|
static const char stMenuItem1[] PROGMEM = "Read cart in Slot A";
|
||||||
|
static const char stMenuItem2[] PROGMEM = "Read cart in Slot B";
|
||||||
|
static const char* const menuOptionsST[] PROGMEM = { stMenuItem1, stMenuItem2, string_reset2 };
|
||||||
|
|
||||||
|
void stMenu() {
|
||||||
|
// Create ST menu with title and 3 options to choose from
|
||||||
|
unsigned char mainMenu;
|
||||||
|
convertPgm(menuOptionsST, 3);
|
||||||
|
mainMenu = question_box(F("Sufami Turbo"), menuOptions, 3, 0);
|
||||||
|
|
||||||
|
// Wait for user choice to come back from the question box menu
|
||||||
|
switch (mainMenu) {
|
||||||
|
// Read cart in ST slot A
|
||||||
|
case 0:
|
||||||
|
readSlot(0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Read cart in ST slot B
|
||||||
|
case 1:
|
||||||
|
readSlot(1);
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Reset
|
||||||
|
case 2:
|
||||||
|
resetArduino();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************
|
||||||
|
Setup
|
||||||
|
*****************************************/
|
||||||
|
void setup_ST() {
|
||||||
|
// Request 5V
|
||||||
|
setVoltage(VOLTS_SET_5V);
|
||||||
|
|
||||||
|
// Set cicrstPin(PG1) to Output
|
||||||
|
DDRG |= (1 << 1);
|
||||||
|
// Output a high signal until we're ready to start
|
||||||
|
PORTG |= (1 << 1);
|
||||||
|
// Set cichstPin(PG0) to Input
|
||||||
|
DDRG &= ~(1 << 0);
|
||||||
|
|
||||||
|
// Set Address Pins to Output
|
||||||
|
//A0-A7
|
||||||
|
DDRF = 0xFF;
|
||||||
|
//A8-A15
|
||||||
|
DDRK = 0xFF;
|
||||||
|
//BA0-BA7
|
||||||
|
DDRL = 0xFF;
|
||||||
|
//PA0-PA7
|
||||||
|
DDRA = 0xFF;
|
||||||
|
|
||||||
|
// Set Control Pins to Output RST(PH0) CS(PH3) WR(PH5) RD(PH6)
|
||||||
|
DDRH |= (1 << 0) | (1 << 3) | (1 << 5) | (1 << 6);
|
||||||
|
// Switch RST(PH0) and WR(PH5) to HIGH
|
||||||
|
PORTH |= (1 << 0) | (1 << 5);
|
||||||
|
// Switch CS(PH3) and RD(PH6) to LOW
|
||||||
|
PORTH &= ~((1 << 3) | (1 << 6));
|
||||||
|
// Set Refresh(PE5) to Output
|
||||||
|
DDRE |= (1 << 5);
|
||||||
|
// Switch Refresh(PE5) to LOW (needed for SA-1)
|
||||||
|
PORTE &= ~(1 << 5);
|
||||||
|
// Set CPU Clock(PH1) to Output
|
||||||
|
DDRH |= (1 << 1);
|
||||||
|
// Set IRQ(PH4) to Input
|
||||||
|
DDRH &= ~(1 << 4);
|
||||||
|
// Set expand(PG5) to Input
|
||||||
|
DDRG &= ~(1 << 5);
|
||||||
|
// Set Data Pins (D0-D7) to Input
|
||||||
|
DDRC = 0x00;
|
||||||
|
// Unused pins
|
||||||
|
// Set wram(PE4) to Output
|
||||||
|
DDRE |= (1 << 4);
|
||||||
|
// Set pawr(PJ1) to Output
|
||||||
|
DDRJ |= (1 << 1);
|
||||||
|
// Set pard(PJ0) to Output
|
||||||
|
DDRJ |= (1 << 0);
|
||||||
|
|
||||||
|
//Check if Sufami Turbo adapter is inserted
|
||||||
|
if (!getHeader(0)) {
|
||||||
|
display_Clear();
|
||||||
|
println_Msg(F("Sufami Turbo adapter"));
|
||||||
|
println_Msg(F("was not found."));
|
||||||
|
display_Update();
|
||||||
|
wait();
|
||||||
|
resetArduino();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************
|
||||||
|
ROM Functions
|
||||||
|
******************************************/
|
||||||
|
// Verify if 'BANDAI' header is present in specified bank
|
||||||
|
bool getHeader(unsigned int bank) {
|
||||||
|
byte snesHeader[16];
|
||||||
|
PORTL = bank;
|
||||||
|
|
||||||
|
// Read first bytes
|
||||||
|
for (uint16_t c = 0, currByte = 0; c < 16; c++, currByte++) {
|
||||||
|
PORTF = (currByte & 0xFF);
|
||||||
|
PORTK = ((currByte >> 8) & 0xFF);
|
||||||
|
NOP;
|
||||||
|
NOP;
|
||||||
|
NOP;
|
||||||
|
NOP;
|
||||||
|
NOP;
|
||||||
|
NOP;
|
||||||
|
snesHeader[c] = PINC;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Format internal name
|
||||||
|
buildRomName(romName, &snesHeader[0], 14);
|
||||||
|
|
||||||
|
// Check if 'BANDAI' header is present
|
||||||
|
if (strncmp(romName, "BANDAI SFC-ADX", 14) == 0)
|
||||||
|
return(1);
|
||||||
|
else
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Select the slot to use and detect cart size
|
||||||
|
void readSlot(bool cartSlot) {
|
||||||
|
// Set control
|
||||||
|
dataIn();
|
||||||
|
controlIn_SNES();
|
||||||
|
sd.chdir("/");
|
||||||
|
display_Clear();
|
||||||
|
|
||||||
|
if(!cartSlot) { // Slot A was selected
|
||||||
|
if (getHeader(32)) { // Look for a cart in slot A
|
||||||
|
if (getHeader(48)) // Look for mirrored data in slot A
|
||||||
|
readRom_ST(32,48); // Dump 512KB cart
|
||||||
|
else
|
||||||
|
readRom_ST(32,64); // Dump 1MB cart
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
println_Msg(F("No cart detected in Slot A"));
|
||||||
|
display_Update();
|
||||||
|
wait();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else { // Slot B was selected
|
||||||
|
if (getHeader(64)) { // Look for a cart in slot B
|
||||||
|
if (getHeader(80)) // Look for mirrored data in slot B
|
||||||
|
readRom_ST(64,80); // Dump 512KB cart
|
||||||
|
else
|
||||||
|
readRom_ST(64,96); // Dump 1MB cart
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
println_Msg(F("No cart detected in Slot B"));
|
||||||
|
display_Update();
|
||||||
|
wait();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read ST rom to SD card
|
||||||
|
void readRom_ST(unsigned int bankStart, unsigned int bankEnd) {
|
||||||
|
// create a new folder to save rom file
|
||||||
|
EEPROM_readAnything(0, foldern);
|
||||||
|
strcpy(fileName, "SUFAMI_TURBO.st");
|
||||||
|
sprintf(folder, "ST/%s/%d", romName, foldern);
|
||||||
|
sd.mkdir(folder, true);
|
||||||
|
sd.chdir(folder);
|
||||||
|
|
||||||
|
display_Clear();
|
||||||
|
print_STR(saving_to_STR, 0);
|
||||||
|
print_Msg(folder);
|
||||||
|
println_Msg(F("/..."));
|
||||||
|
display_Update();
|
||||||
|
|
||||||
|
// write new folder number back to eeprom
|
||||||
|
foldern++;
|
||||||
|
EEPROM_writeAnything(0, foldern);
|
||||||
|
|
||||||
|
//open file on sd card
|
||||||
|
if (!myFile.open(fileName, O_RDWR | O_CREAT)) {
|
||||||
|
print_FatalError(create_file_STR);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read specified banks
|
||||||
|
readLoRomBanks(bankStart + 0x80, bankEnd + 0x80, &myFile);
|
||||||
|
|
||||||
|
// Close file:
|
||||||
|
myFile.close();
|
||||||
|
|
||||||
|
print_STR(press_button_STR, 1);
|
||||||
|
display_Update();
|
||||||
|
wait();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//******************************************
|
||||||
|
// End of File
|
||||||
|
//******************************************
|
@ -22,7 +22,7 @@ Happy making. 🔧🔨😊
|
|||||||
|
|
||||||
#### Supported Systems:
|
#### Supported Systems:
|
||||||
- NES/Famicom/Family Basic
|
- NES/Famicom/Family Basic
|
||||||
- Super Nintendo/Super Famicom (including SF Memory and Satellaview)
|
- Super Nintendo/Super Famicom (including SF Memory, Satellaview, and Sufami Turbo)
|
||||||
- Nintendo 64 (including Controller Pak, Gameshark, and Xplorer 64)
|
- Nintendo 64 (including Controller Pak, Gameshark, and Xplorer 64)
|
||||||
- Game Boy Color (including GB Memory, Codebreaker, and Gameshark)
|
- Game Boy Color (including GB Memory, Codebreaker, and Gameshark)
|
||||||
- Game Boy Advance
|
- Game Boy Advance
|
||||||
|
Loading…
Reference in New Issue
Block a user