mirror of
https://github.com/sanni/cartreader.git
synced 2024-11-13 08:25:05 +01:00
V3.5 Change Menu and add Sega CD Ram Cart
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).
This commit is contained in:
parent
61f5966a49
commit
0c75bf8aed
@ -2,8 +2,8 @@
|
||||
Cartridge Reader for Arduino Mega2560
|
||||
|
||||
Author: sanni
|
||||
Date: 30-08-2019
|
||||
Version: 3.4
|
||||
Date: 01-09-2019
|
||||
Version: 3.5
|
||||
|
||||
SD lib: https://github.com/greiman/SdFat
|
||||
LCD lib: https://github.com/adafruit/Adafruit_SSD1306
|
||||
@ -16,7 +16,7 @@
|
||||
MichlK - ROM-Reader for Super Nintendo
|
||||
Jeff Saltzman - 4-Way Button
|
||||
Wayne and Layne - Video-Game-Shield menu
|
||||
skaman - SNES enhancements, SA1 sram support,GB flash fix and MD improvements
|
||||
skaman - SNES enhancements, SA1 sram support, GB flash fix, MD improvements, Famicom dumper
|
||||
nocash - Nintendo Power and GBA Eeprom commands and lots of other info
|
||||
crazynation - N64 bus timing
|
||||
hkz/themanbehindthecurtain - N64 flashram commands
|
||||
@ -36,18 +36,18 @@
|
||||
moldov - SF Memory Binary Maker
|
||||
vogelfreiheit - N64 flashram fix
|
||||
rama - code speedup & improvements
|
||||
Megadrive checksum - Gens-gs
|
||||
Gens-gs - Megadrive checksum
|
||||
|
||||
**********************************************************************************/
|
||||
|
||||
#include <SdFat.h>
|
||||
|
||||
char ver[5] = "3.4";
|
||||
char ver[5] = "3.5";
|
||||
|
||||
/******************************************
|
||||
Define Starting Point
|
||||
******************************************/
|
||||
// mainMenu, n64Menu, snsMenu, gbxMenu, segaMenu, flashMenu, pceMenu
|
||||
// mainMenu, n64Menu, snsMenu, gbxMenu, nesMenu, mdMenu, flashMenu, pceMenu
|
||||
#define startMenu mainMenu
|
||||
|
||||
/******************************************
|
||||
@ -74,10 +74,10 @@ char ver[5] = "3.4";
|
||||
/******************************************
|
||||
Options
|
||||
******************************************/
|
||||
// If set to 1 then the crc32 checksum will be calculated after reading a N64 rom
|
||||
boolean n64crc = 1;
|
||||
// Enable 16bit flash adapter menu
|
||||
//#define enable_flash16
|
||||
// Disable splash screen
|
||||
#define fast_start
|
||||
|
||||
/******************************************
|
||||
Libraries
|
||||
@ -90,7 +90,23 @@ boolean n64crc = 1;
|
||||
|
||||
// AVR Eeprom
|
||||
#include <EEPROM.h>
|
||||
#include "EEPROMAnything.h"
|
||||
template <class T> int EEPROM_writeAnything(int ee, const T& value)
|
||||
{
|
||||
const byte* p = (const byte*)(const void*)&value;
|
||||
unsigned int i;
|
||||
for (i = 0; i < sizeof(value); i++)
|
||||
EEPROM.write(ee++, *p++);
|
||||
return i;
|
||||
}
|
||||
|
||||
template <class T> int EEPROM_readAnything(int ee, T& value)
|
||||
{
|
||||
byte* p = (byte*)(void*)&value;
|
||||
unsigned int i;
|
||||
for (i = 0; i < sizeof(value); i++)
|
||||
*p++ = EEPROM.read(ee++);
|
||||
return i;
|
||||
}
|
||||
|
||||
// Graphic I2C LCD
|
||||
#include <Adafruit_GFX.h>
|
||||
@ -141,10 +157,13 @@ SdFile myFile;
|
||||
#define mode_FLASH16 8
|
||||
#define mode_GBA 9
|
||||
#define mode_GBM 10
|
||||
#define mode_MD 11
|
||||
#define mode_MD_Cart 11
|
||||
#define mode_EPROM 12
|
||||
#define mode_PCE 13
|
||||
#define mode_SV 14
|
||||
#define mode_NES 15
|
||||
#define mode_SMS 16
|
||||
#define mode_SEGA_CD 17
|
||||
|
||||
/******************************************
|
||||
optimization-safe nop delay
|
||||
@ -349,23 +368,27 @@ static const unsigned char PROGMEM sig [] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
//For PC Engine
|
||||
extern void pcsMenu(void);
|
||||
extern void pceMenu(void);
|
||||
|
||||
/******************************************
|
||||
Menu
|
||||
*****************************************/
|
||||
// Main menu
|
||||
static const char modeItem1[] PROGMEM = "Nintendo 64";
|
||||
static const char modeItem1[] PROGMEM = "Add-ons";
|
||||
static const char modeItem2[] PROGMEM = "Super Nintendo";
|
||||
static const char modeItem3[] PROGMEM = "Game Boy";
|
||||
static const char modeItem4[] PROGMEM = "Mega Drive";
|
||||
static const char modeItem5[] PROGMEM = "Flashrom Programmer";
|
||||
static const char modeItem6[] PROGMEM = "PC Engine/TG16";
|
||||
static const char modeItem7[] PROGMEM = "About";
|
||||
static const char modeItem3[] PROGMEM = "Mega Drive";
|
||||
static const char modeItem4[] PROGMEM = "Nintendo 64";
|
||||
static const char modeItem5[] PROGMEM = "Game Boy";
|
||||
static const char modeItem6[] PROGMEM = "About";
|
||||
static const char modeItem7[] PROGMEM = "Reset";
|
||||
static const char* const modeOptions[] PROGMEM = {modeItem1, modeItem2, modeItem3, modeItem4, modeItem5, modeItem6, modeItem7};
|
||||
|
||||
// Add-ons submenu
|
||||
static const char addonsItem1[] PROGMEM = "PC Engine/TG16";
|
||||
static const char addonsItem2[] PROGMEM = "Flashrom Programmer";
|
||||
static const char addonsItem3[] PROGMEM = "NES/Famicom";
|
||||
static const char addonsItem4[] PROGMEM = "Sega Master System";
|
||||
static const char addonsItem5[] PROGMEM = "Reset";
|
||||
static const char* const addonsOptions[] PROGMEM = {addonsItem1, addonsItem2, addonsItem3, addonsItem4, addonsItem5};
|
||||
|
||||
void aboutScreen() {
|
||||
display_Clear();
|
||||
// Draw the Logo
|
||||
@ -416,47 +439,6 @@ void aboutScreen() {
|
||||
}
|
||||
}
|
||||
|
||||
void draw_progressbar(uint32_t processed, uint32_t total)
|
||||
{
|
||||
uint8_t current, i;
|
||||
static uint8_t previous;
|
||||
uint8_t steps = 20;
|
||||
|
||||
//Find progressbar length and draw if processed size is not 0
|
||||
if (processed == 0)
|
||||
{
|
||||
previous = 0;
|
||||
print_Msg(F("["));
|
||||
display_Update();
|
||||
return;
|
||||
}
|
||||
|
||||
// Progress bar
|
||||
current = (processed >= total) ? steps : processed / (total / steps);
|
||||
|
||||
//Draw "*" if needed
|
||||
if (current > previous)
|
||||
{
|
||||
for (i = previous; i < current; i++)
|
||||
{
|
||||
// steps are 20, so 20 - 1 = 19.
|
||||
if (i == (19))
|
||||
{
|
||||
//If end of progress bar, finish progress bar by drawing "]"
|
||||
print_Msg(F("]"));
|
||||
}
|
||||
else
|
||||
{
|
||||
print_Msg(F("*"));
|
||||
}
|
||||
}
|
||||
//update previous "*" status
|
||||
previous = current;
|
||||
//Update display
|
||||
display_Update();
|
||||
}
|
||||
}
|
||||
|
||||
void mainMenu() {
|
||||
// create menu with title and 6 options to choose from
|
||||
unsigned char modeMenu;
|
||||
@ -468,7 +450,7 @@ void mainMenu() {
|
||||
switch (modeMenu)
|
||||
{
|
||||
case 0:
|
||||
n64Menu();
|
||||
addonsMenu();
|
||||
break;
|
||||
|
||||
case 1:
|
||||
@ -476,22 +458,94 @@ void mainMenu() {
|
||||
break;
|
||||
|
||||
case 2:
|
||||
gbxMenu();
|
||||
mdMenu();
|
||||
break;
|
||||
|
||||
case 3:
|
||||
segaMenu();
|
||||
n64Menu();
|
||||
break;
|
||||
|
||||
case 4:
|
||||
flashMenu();
|
||||
gbxMenu();
|
||||
break;
|
||||
|
||||
case 5:
|
||||
pcsMenu();
|
||||
break;
|
||||
case 6:
|
||||
aboutScreen();
|
||||
break;
|
||||
|
||||
case 6:
|
||||
resetArduino();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void addonsMenu() {
|
||||
// create menu with title and 5 options to choose from
|
||||
unsigned char addonsMenu;
|
||||
// Copy menuOptions out of progmem
|
||||
convertPgm(addonsOptions, 2);
|
||||
addonsMenu = question_box(F("Choose Adapter"), menuOptions, 2, 0);
|
||||
|
||||
// wait for user choice to come back from the question box menu
|
||||
switch (addonsMenu)
|
||||
{
|
||||
case 0:
|
||||
pcsMenu();
|
||||
break;
|
||||
|
||||
case 1:
|
||||
flashMenu();
|
||||
break;
|
||||
|
||||
case 2:
|
||||
nesMenu();
|
||||
break;
|
||||
|
||||
case 3:
|
||||
smsMenu();
|
||||
break;
|
||||
|
||||
case 4:
|
||||
resetArduino();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************
|
||||
Progressbar
|
||||
*****************************************/
|
||||
void draw_progressbar(uint32_t processed, uint32_t total) {
|
||||
uint8_t current, i;
|
||||
static uint8_t previous;
|
||||
uint8_t steps = 20;
|
||||
|
||||
//Find progressbar length and draw if processed size is not 0
|
||||
if (processed == 0) {
|
||||
previous = 0;
|
||||
print_Msg(F("["));
|
||||
display_Update();
|
||||
return;
|
||||
}
|
||||
|
||||
// Progress bar
|
||||
current = (processed >= total) ? steps : processed / (total / steps);
|
||||
|
||||
//Draw "*" if needed
|
||||
if (current > previous) {
|
||||
for (i = previous; i < current; i++) {
|
||||
// steps are 20, so 20 - 1 = 19.
|
||||
if (i == (19)) {
|
||||
//If end of progress bar, finish progress bar by drawing "]"
|
||||
print_Msg(F("]"));
|
||||
}
|
||||
else {
|
||||
print_Msg(F("*"));
|
||||
}
|
||||
}
|
||||
//update previous "*" status
|
||||
previous = current;
|
||||
//Update display
|
||||
display_Update();
|
||||
}
|
||||
}
|
||||
|
||||
@ -503,8 +557,8 @@ void setup() {
|
||||
DDRD &= ~(1 << 7);
|
||||
DDRG &= ~(1 << 2);
|
||||
// Activate Internal Pullup Resistors
|
||||
//PORTD |= (1 << 7);
|
||||
//PORTG |= (1 << 2);
|
||||
PORTD |= (1 << 7);
|
||||
PORTG |= (1 << 2);
|
||||
|
||||
// Read current folder number out of eeprom
|
||||
EEPROM_readAnything(10, foldern);
|
||||
@ -517,6 +571,8 @@ void setup() {
|
||||
|
||||
// Clear the screen buffer.
|
||||
display_Clear();
|
||||
|
||||
#ifndef fast_start
|
||||
delay(100);
|
||||
|
||||
// Draw line
|
||||
@ -556,6 +612,7 @@ void setup() {
|
||||
display.println(ver);
|
||||
display_Update();
|
||||
delay(200);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (enable_Serial) {
|
||||
@ -1412,8 +1469,8 @@ void loop() {
|
||||
else if (mode == mode_GBM) {
|
||||
gbmMenu();
|
||||
}
|
||||
else if (mode == mode_MD) {
|
||||
mdMenu();
|
||||
else if (mode == mode_MD_Cart) {
|
||||
mdCartMenu();
|
||||
}
|
||||
else if (mode == mode_PCE) {
|
||||
pceMenu();
|
||||
@ -1421,6 +1478,15 @@ void loop() {
|
||||
else if (mode == mode_SV) {
|
||||
svMenu();
|
||||
}
|
||||
else if (mode == mode_NES) {
|
||||
nesMenu();
|
||||
}
|
||||
else if (mode == mode_SMS) {
|
||||
smsMenu();
|
||||
}
|
||||
else if (mode == mode_SEGA_CD) {
|
||||
segaCDMenu();
|
||||
}
|
||||
else {
|
||||
display_Clear();
|
||||
println_Msg(F("Menu Error"));
|
||||
|
@ -1,20 +0,0 @@
|
||||
#include <EEPROM.h>
|
||||
#include <Arduino.h> // for type definitions
|
||||
|
||||
template <class T> int EEPROM_writeAnything(int ee, const T& value)
|
||||
{
|
||||
const byte* p = (const byte*)(const void*)&value;
|
||||
unsigned int i;
|
||||
for (i = 0; i < sizeof(value); i++)
|
||||
EEPROM.write(ee++, *p++);
|
||||
return i;
|
||||
}
|
||||
|
||||
template <class T> int EEPROM_readAnything(int ee, T& value)
|
||||
{
|
||||
byte* p = (byte*)(void*)&value;
|
||||
unsigned int i;
|
||||
for (i = 0; i < sizeof(value); i++)
|
||||
*p++ = EEPROM.read(ee++);
|
||||
return i;
|
||||
}
|
@ -1,15 +1,14 @@
|
||||
//******************************************
|
||||
// SEGA MEGA DRIVE MODULE
|
||||
//******************************************
|
||||
// Writes to Sega CD Backup RAM Cart require an extra wire from MRES (B02) to VRES (B27)
|
||||
|
||||
/******************************************
|
||||
Variables
|
||||
*****************************************/
|
||||
unsigned long sramEnd;
|
||||
|
||||
byte eepbit[8];
|
||||
int eepSize;
|
||||
|
||||
byte eeptemp;
|
||||
word addrhi;
|
||||
word addrlo;
|
||||
@ -81,28 +80,110 @@ byte eepcount = (sizeof(eepid) / sizeof(eepid[0])) / 2;
|
||||
byte index;
|
||||
word eepdata;
|
||||
|
||||
// CD BACKUP RAM
|
||||
unsigned long bramSize = 0;
|
||||
/******************************************
|
||||
Menu
|
||||
*****************************************/
|
||||
// MD menu items
|
||||
static const char MDMenuItem1[] PROGMEM = "Read Rom";
|
||||
static const char MDMenuItem2[] PROGMEM = "Read Sram";
|
||||
static const char MDMenuItem3[] PROGMEM = "Write Sram";
|
||||
static const char MDMenuItem4[] PROGMEM = "Read EEPROM";
|
||||
static const char MDMenuItem5[] PROGMEM = "Write EEPROM";
|
||||
static const char MDMenuItem6[] PROGMEM = "Write Flashcart";
|
||||
static const char MDMenuItem7[] PROGMEM = "Reset";
|
||||
static const char* const menuOptionsMD[] PROGMEM = {MDMenuItem1, MDMenuItem2, MDMenuItem3, MDMenuItem4, MDMenuItem5, MDMenuItem6, MDMenuItem7};
|
||||
static const char MDMenuItem1[] PROGMEM = "Game Cartridge";
|
||||
static const char MDMenuItem2[] PROGMEM = "SegaCD RamCart";
|
||||
static const char MDMenuItem3[] PROGMEM = "Flash Repro";
|
||||
static const char MDMenuItem4[] PROGMEM = "Reset";
|
||||
static const char* const menuOptionsMD[] PROGMEM = {MDMenuItem1, MDMenuItem2, MDMenuItem3, MDMenuItem4};
|
||||
|
||||
// Cart menu items
|
||||
static const char MDCartMenuItem1[] PROGMEM = "Read Rom";
|
||||
static const char MDCartMenuItem2[] PROGMEM = "Read Sram";
|
||||
static const char MDCartMenuItem3[] PROGMEM = "Write Sram";
|
||||
static const char MDCartMenuItem4[] PROGMEM = "Read EEPROM";
|
||||
static const char MDCartMenuItem5[] PROGMEM = "Write EEPROM";
|
||||
static const char MDCartMenuItem6[] PROGMEM = "Reset";
|
||||
static const char* const menuOptionsMDCart[] PROGMEM = {MDCartMenuItem1, MDCartMenuItem2, MDCartMenuItem3, MDCartMenuItem4, MDCartMenuItem5, MDCartMenuItem6};
|
||||
|
||||
// Sega CD Ram Backup Cartridge menu items
|
||||
static const char SCDMenuItem1[] PROGMEM = "Read Backup RAM";
|
||||
static const char SCDMenuItem2[] PROGMEM = "Write Backup RAM";
|
||||
static const char SCDMenuItem3[] PROGMEM = "Reset";
|
||||
static const char* const menuOptionsSCD[] PROGMEM = {SCDMenuItem1, SCDMenuItem2, SCDMenuItem3};
|
||||
|
||||
// Sega start menu
|
||||
void segaMenu() {
|
||||
display_Clear();
|
||||
display_Update();
|
||||
setup_MD();
|
||||
mode = mode_MD;
|
||||
void mdMenu() {
|
||||
// create menu with title and 3 options to choose from
|
||||
unsigned char mdDev;
|
||||
// Copy menuOptions out of progmem
|
||||
convertPgm(menuOptionsMD, 4);
|
||||
mdDev = question_box(F("Select MD device"), menuOptions, 4, 0);
|
||||
|
||||
// wait for user choice to come back from the question box menu
|
||||
switch (mdDev)
|
||||
{
|
||||
case 0:
|
||||
display_Clear();
|
||||
display_Update();
|
||||
setup_MD();
|
||||
mode = mode_MD_Cart;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
display_Clear();
|
||||
display_Update();
|
||||
setup_MD();
|
||||
mode = mode_SEGA_CD;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
display_Clear();
|
||||
display_Update();
|
||||
setup_MD();
|
||||
mode = mode_MD_Cart;
|
||||
// Change working dir to root
|
||||
filePath[0] = '\0';
|
||||
sd.chdir("/");
|
||||
fileBrowser(F("Select file"));
|
||||
display_Clear();
|
||||
// Setting CS(PH3) LOW
|
||||
PORTH &= ~(1 << 3);
|
||||
|
||||
// ID flash
|
||||
resetFlash_MD();
|
||||
idFlash_MD();
|
||||
resetFlash_MD();
|
||||
print_Msg(F("Flash ID: "));
|
||||
println_Msg(flashid);
|
||||
if (strcmp(flashid, "C2F1") == 0) {
|
||||
println_Msg(F("MX29F1610 detected"));
|
||||
flashSize = 2097152;
|
||||
}
|
||||
else {
|
||||
print_Error(F("Error: Unknown flashrom"), true);
|
||||
}
|
||||
display_Update();
|
||||
|
||||
eraseFlash_MD();
|
||||
resetFlash_MD();
|
||||
blankcheck_MD();
|
||||
write29F1610_MD();
|
||||
resetFlash_MD();
|
||||
delay(1000);
|
||||
resetFlash_MD();
|
||||
delay(1000);
|
||||
verifyFlash_MD();
|
||||
// Set CS(PH3) HIGH
|
||||
PORTH |= (1 << 3);
|
||||
println_Msg(F(""));
|
||||
println_Msg(F("Press Button..."));
|
||||
display_Update();
|
||||
wait();
|
||||
break;
|
||||
|
||||
case 3:
|
||||
resetArduino();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void mdMenu() {
|
||||
void mdCartMenu() {
|
||||
// create menu with title and 7 options to choose from
|
||||
unsigned char mainMenu;
|
||||
// Copy menuOptions out of progmem
|
||||
@ -189,43 +270,6 @@ void mdMenu() {
|
||||
break;
|
||||
|
||||
case 5:
|
||||
// Change working dir to root
|
||||
filePath[0] = '\0';
|
||||
sd.chdir("/");
|
||||
fileBrowser(F("Select file"));
|
||||
display_Clear();
|
||||
// Setting CS(PH3) LOW
|
||||
PORTH &= ~(1 << 3);
|
||||
|
||||
// ID flash
|
||||
resetFlash_MD();
|
||||
idFlash_MD();
|
||||
resetFlash_MD();
|
||||
print_Msg(F("Flash ID: "));
|
||||
println_Msg(flashid);
|
||||
if (strcmp(flashid, "C2F1") == 0) {
|
||||
println_Msg(F("MX29F1610 detected"));
|
||||
flashSize = 2097152;
|
||||
}
|
||||
else {
|
||||
print_Error(F("Error: Unknown flashrom"), true);
|
||||
}
|
||||
display_Update();
|
||||
|
||||
eraseFlash_MD();
|
||||
resetFlash_MD();
|
||||
blankcheck_MD();
|
||||
write29F1610_MD();
|
||||
resetFlash_MD();
|
||||
delay(1000);
|
||||
resetFlash_MD();
|
||||
delay(1000);
|
||||
verifyFlash_MD();
|
||||
// Set CS(PH3) HIGH
|
||||
PORTH |= (1 << 3);
|
||||
break;
|
||||
|
||||
case 6:
|
||||
// Reset
|
||||
resetArduino();
|
||||
break;
|
||||
@ -236,6 +280,49 @@ void mdMenu() {
|
||||
wait();
|
||||
}
|
||||
|
||||
void segaCDMenu() {
|
||||
// create menu with title and 3 options to choose from
|
||||
unsigned char scdMenu;
|
||||
// Copy menuOptions out of progmem
|
||||
convertPgm(menuOptionsSCD, 3);
|
||||
scdMenu = question_box(F("SEGA CD RAM"), menuOptions, 3, 0);
|
||||
|
||||
// wait for user choice to come back from the question box menu
|
||||
switch (scdMenu)
|
||||
{
|
||||
case 0:
|
||||
display_Clear();
|
||||
if (bramSize > 0)
|
||||
readBram_MD();
|
||||
else {
|
||||
print_Error(F("Not CD Backup RAM Cart"), false);
|
||||
}
|
||||
break;
|
||||
|
||||
case 1:
|
||||
display_Clear();
|
||||
if (bramSize > 0) {
|
||||
// Launch file browser
|
||||
fileBrowser(F("Select brm file"));
|
||||
display_Clear();
|
||||
writeBram_MD();
|
||||
}
|
||||
else {
|
||||
print_Error(F("Not CD Backup RAM Cart"), false);
|
||||
}
|
||||
break;
|
||||
|
||||
case 2:
|
||||
// Reset
|
||||
asm volatile (" jmp 0");
|
||||
break;
|
||||
}
|
||||
println_Msg(F(""));
|
||||
println_Msg(F("Press Button..."));
|
||||
display_Update();
|
||||
wait();
|
||||
}
|
||||
|
||||
/******************************************
|
||||
Setup
|
||||
*****************************************/
|
||||
@ -455,6 +542,12 @@ void getCartInfo_MD() {
|
||||
}
|
||||
}
|
||||
|
||||
// CD Backup RAM Cart Check
|
||||
// 4 = 128KB (2045 Blocks) Sega CD Backup RAM Cart
|
||||
// 6 = 512KB (8189 Blocks) Ultra CD Backup RAM Cart (Aftermarket)
|
||||
word bramCheck = readWord_MD(0x00);
|
||||
if (((bramCheck == 0x0004) && (chksum == 0x0004)) || ((bramCheck == 0x0006) && (chksum == 0x0006)))
|
||||
bramSize = pow(2, bramCheck) * 0x2000;
|
||||
if (saveType != 4) { // NOT SERIAL EEPROM
|
||||
// Check if cart has sram
|
||||
saveType = 0;
|
||||
@ -1723,6 +1816,86 @@ void writeEEP_MD() {
|
||||
dataIn_MD();
|
||||
}
|
||||
|
||||
//******************************************
|
||||
// CD Backup RAM Functions
|
||||
//******************************************
|
||||
void readBram_MD() {
|
||||
dataIn_MD();
|
||||
|
||||
// Get name, add extension and convert to char array for sd lib
|
||||
strcpy(fileName, "Cart.brm");
|
||||
|
||||
// create a new folder for the save file
|
||||
EEPROM_readAnything(10, foldern);
|
||||
sd.chdir();
|
||||
sprintf(folder, "MD/RAM/%d", foldern);
|
||||
sd.mkdir(folder, true);
|
||||
sd.chdir(folder);
|
||||
|
||||
// write new folder number back to eeprom
|
||||
foldern = foldern + 1;
|
||||
EEPROM_writeAnything(10, foldern);
|
||||
|
||||
println_Msg(F("Reading..."));
|
||||
display_Update();
|
||||
|
||||
// Open file on sd card
|
||||
if (!myFile.open(fileName, O_RDWR | O_CREAT)) {
|
||||
print_Error(F("SD Error"), true);
|
||||
}
|
||||
|
||||
for (unsigned long currByte = 0; currByte < bramSize; currByte += 512) {
|
||||
for (int i = 0; i < 512; i++) {
|
||||
sdBuffer[i] = readWord_MD(0x300000 + currByte + i);
|
||||
}
|
||||
myFile.write(sdBuffer, 512);
|
||||
}
|
||||
|
||||
// Close the file:
|
||||
myFile.close();
|
||||
println_Msg(F(""));
|
||||
display_Clear();
|
||||
print_Msg(F("Saved to "));
|
||||
print_Msg(folder);
|
||||
|
||||
display_Update();
|
||||
}
|
||||
|
||||
void writeBram_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)) {
|
||||
|
||||
// 0x700000-0x7FFFFF: Writes by /LWR latch D0; 1=RAM write enabled, 0=disabled
|
||||
writeWord_MD(0x380000, 1); // Enable BRAM Writes
|
||||
|
||||
for (unsigned long currByte = 0; currByte < bramSize; currByte += 512) {
|
||||
myFile.read(sdBuffer, 512);
|
||||
for (int i = 0; i < 512; i++) {
|
||||
writeWord_MD(0x300000 + currByte + i, sdBuffer[i]);
|
||||
}
|
||||
}
|
||||
writeWord_MD(0x380000, 0); // Disable BRAM Writes
|
||||
// Close the file:
|
||||
myFile.close();
|
||||
println_Msg(F(""));
|
||||
display_Clear();
|
||||
println_Msg(F("Done"));
|
||||
display_Update();
|
||||
}
|
||||
else {
|
||||
print_Error(F("SD Error"), true);
|
||||
}
|
||||
dataIn_MD();
|
||||
}
|
||||
|
||||
//******************************************
|
||||
// End of File
|
||||
//******************************************
|
||||
|
@ -50,7 +50,8 @@ static const char n64MenuItem1[] PROGMEM = "Game Cartridge";
|
||||
static const char n64MenuItem2[] PROGMEM = "Controller Pak";
|
||||
static const char n64MenuItem3[] PROGMEM = "Flash Repro";
|
||||
static const char n64MenuItem4[] PROGMEM = "Flash Gameshark";
|
||||
static const char* const menuOptionsN64[] PROGMEM = {n64MenuItem1, n64MenuItem2, n64MenuItem3, n64MenuItem4};
|
||||
static const char n64MenuItem5[] PROGMEM = "Reset";
|
||||
static const char* const menuOptionsN64[] PROGMEM = {n64MenuItem1, n64MenuItem2, n64MenuItem3, n64MenuItem4, n64MenuItem5};
|
||||
|
||||
// N64 controller menu items
|
||||
static const char N64ContMenuItem1[] PROGMEM = "Test Controller";
|
||||
@ -133,6 +134,10 @@ void n64Menu() {
|
||||
printCartInfo_N64();
|
||||
mode = mode_N64_Cart;
|
||||
break;
|
||||
|
||||
case 4:
|
||||
resetArduino();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -2160,68 +2165,66 @@ readn64rom:
|
||||
|
||||
unsigned long timeElapsed = (millis() - startTime) / 1000; // seconds
|
||||
|
||||
if (n64crc) {
|
||||
print_Msg(F("Check CRC: "));
|
||||
display_Update();
|
||||
// convert checksum to string
|
||||
char crcStr[9];
|
||||
sprintf(crcStr, "%08lx", ~oldcrc32);
|
||||
// Print checksum
|
||||
println_Msg(crcStr);
|
||||
display_Update();
|
||||
print_Msg(F("CRC: "));
|
||||
display_Update();
|
||||
// convert checksum to string
|
||||
char crcStr[9];
|
||||
sprintf(crcStr, "%08lx", ~oldcrc32);
|
||||
// Print checksum
|
||||
println_Msg(crcStr);
|
||||
display_Update();
|
||||
|
||||
// Search n64.txt for crc
|
||||
if (searchCRC(crcStr)) {
|
||||
// Dump was a known good rom
|
||||
println_Msg(F("Checksum matches"));
|
||||
}
|
||||
else {
|
||||
// Dump was bad or unknown
|
||||
rgb.setColor(255, 0, 0);
|
||||
|
||||
// let bad crc show a short while
|
||||
delay(3000);
|
||||
|
||||
// N64 CRC32 error Menu
|
||||
unsigned char CRCMenu;
|
||||
// Copy menuOptions out of progmem
|
||||
convertPgm(menuOptionsN64CRC, 3);
|
||||
|
||||
CRCMenu = question_box(F("CRC ERROR "), menuOptions, 3, 0);
|
||||
|
||||
// wait for user choice to come back from the question box menu
|
||||
switch (CRCMenu)
|
||||
{
|
||||
case 0:
|
||||
// Change to last directory
|
||||
sd.chdir(folder);
|
||||
// Delete old file
|
||||
if (!myFile.open(fileName, O_RDWR | O_CREAT)) {
|
||||
print_Error(F("SD Error"), true);
|
||||
}
|
||||
if (!myFile.remove()) {
|
||||
print_Error(F("Delete Error"), true);
|
||||
}
|
||||
// Dump again
|
||||
display_Clear();
|
||||
println_Msg(F("Reading Rom..."));
|
||||
display_Update();
|
||||
rgb.setColor(0, 0, 0);
|
||||
goto readn64rom;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
// Return to N64 menu
|
||||
break;
|
||||
|
||||
case 2:
|
||||
// Reset
|
||||
resetArduino();
|
||||
break;
|
||||
}
|
||||
}
|
||||
display_Update();
|
||||
// Search n64.txt for crc
|
||||
if (searchCRC(crcStr)) {
|
||||
// Dump was a known good rom
|
||||
println_Msg(F("Checksum matches"));
|
||||
}
|
||||
else {
|
||||
// Dump was bad or unknown
|
||||
rgb.setColor(255, 0, 0);
|
||||
|
||||
// let bad crc show a short while
|
||||
delay(3000);
|
||||
|
||||
// N64 CRC32 error Menu
|
||||
unsigned char CRCMenu;
|
||||
// Copy menuOptions out of progmem
|
||||
convertPgm(menuOptionsN64CRC, 3);
|
||||
|
||||
CRCMenu = question_box(F("CRC ERROR "), menuOptions, 3, 0);
|
||||
|
||||
// wait for user choice to come back from the question box menu
|
||||
switch (CRCMenu)
|
||||
{
|
||||
case 0:
|
||||
// Change to last directory
|
||||
sd.chdir(folder);
|
||||
// Delete old file
|
||||
if (!myFile.open(fileName, O_RDWR | O_CREAT)) {
|
||||
print_Error(F("SD Error"), true);
|
||||
}
|
||||
if (!myFile.remove()) {
|
||||
print_Error(F("Delete Error"), true);
|
||||
}
|
||||
// Dump again
|
||||
display_Clear();
|
||||
println_Msg(F("Reading Rom..."));
|
||||
display_Update();
|
||||
rgb.setColor(0, 0, 0);
|
||||
goto readn64rom;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
// Return to N64 menu
|
||||
break;
|
||||
|
||||
case 2:
|
||||
// Reset
|
||||
resetArduino();
|
||||
break;
|
||||
}
|
||||
}
|
||||
display_Update();
|
||||
|
||||
print_Msg(F("Done ("));
|
||||
print_Msg(timeElapsed); // include elapsed time
|
||||
|
30
Cart_Reader/NES.ino
Normal file
30
Cart_Reader/NES.ino
Normal file
@ -0,0 +1,30 @@
|
||||
//******************************************
|
||||
// NES MODULE
|
||||
//******************************************
|
||||
// unfinished and untested
|
||||
|
||||
/******************************************
|
||||
Variables
|
||||
*****************************************/
|
||||
|
||||
/******************************************
|
||||
Menu
|
||||
*****************************************/
|
||||
void nesMenu() {
|
||||
}
|
||||
|
||||
/******************************************
|
||||
Setup
|
||||
*****************************************/
|
||||
|
||||
/******************************************
|
||||
Low level functions
|
||||
*****************************************/
|
||||
|
||||
/******************************************
|
||||
NES functions
|
||||
*****************************************/
|
||||
|
||||
//******************************************
|
||||
// End of File
|
||||
//******************************************
|
@ -25,9 +25,6 @@
|
||||
/******************************************
|
||||
Prototype Declarations
|
||||
*****************************************/
|
||||
void pcsMenu(void);
|
||||
void pceMenu(void);
|
||||
|
||||
/* Several PCE dedicated functions */
|
||||
void pin_read_write_PCE(void);
|
||||
void pin_init_PCE(void);
|
||||
|
253
Cart_Reader/SMS.ino
Normal file
253
Cart_Reader/SMS.ino
Normal file
@ -0,0 +1,253 @@
|
||||
//******************************************
|
||||
// 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
|
||||
//******************************************
|
Loading…
Reference in New Issue
Block a user