mirror of
https://github.com/sanni/cartreader.git
synced 2024-11-27 15:04:15 +01:00
Merge branch 'master' into master
This commit is contained in:
commit
f2e2196ab9
@ -2,15 +2,15 @@
|
||||
Cartridge Reader for Arduino Mega2560
|
||||
|
||||
Author: sanni
|
||||
Date: 2017-02-11
|
||||
Version: V22
|
||||
Date: 2017-09-18
|
||||
Version: V28E
|
||||
|
||||
SD lib: https://github.com/greiman/SdFat
|
||||
LCD lib: https://github.com/adafruit/Adafruit_SSD1306
|
||||
Clockgen: https://github.com/etherkit/Si5351Arduino
|
||||
RGB Tools lib: https://github.com/joushx/Arduino-RGB-Tools
|
||||
|
||||
Compiled with Arduino 1.8.0
|
||||
Compiled with Arduino 1.8.3
|
||||
|
||||
Thanks to:
|
||||
MichlK - ROM-Reader for Super Nintendo
|
||||
@ -34,12 +34,11 @@
|
||||
YamaArashi - GBA flashrom bank switch command
|
||||
|
||||
**********************************************************************************/
|
||||
char ver[5] = "V22";
|
||||
char ver[5] = "V28E";
|
||||
|
||||
/******************************************
|
||||
Define Output
|
||||
******************************************/
|
||||
// If you don't have an OLED screen change
|
||||
// enable_OLED to 0 and enable_Serial to 1
|
||||
#define enable_OLED 1
|
||||
#define enable_Serial 0
|
||||
@ -106,7 +105,6 @@ typedef enum COLOR_T {
|
||||
|
||||
// SD Card (Pin 50 = MISO, Pin 51 = MOSI, Pin 52 = SCK, Pin 53 = SS)
|
||||
#include <SdFat.h>
|
||||
#include <SdFatUtil.h>
|
||||
#define chipSelectPin 53
|
||||
SdFat sd;
|
||||
SdFile myFile;
|
||||
@ -118,13 +116,15 @@ SdFile myFile;
|
||||
#define mode_N64_Cart 0
|
||||
#define mode_N64_Controller 1
|
||||
#define mode_SNES 2
|
||||
#define mode_NP 3
|
||||
#define mode_NPFlash 4
|
||||
#define mode_NPGame 5
|
||||
#define mode_SFM 3
|
||||
#define mode_SFM_Flash 4
|
||||
#define mode_SFM_Game 5
|
||||
#define mode_GB 6
|
||||
#define mode_FLASH8 7
|
||||
#define mode_FLASH16 8
|
||||
#define mode_GBA 9
|
||||
#define mode_GBM 10
|
||||
#define mode_MD 11
|
||||
|
||||
/******************************************
|
||||
Variables
|
||||
@ -166,10 +166,11 @@ int incomingByte;
|
||||
int choice = 0;
|
||||
// Temporary array that holds the menu option read out of progmem
|
||||
char menuOptions[7][20];
|
||||
boolean ignoreError = 0;
|
||||
|
||||
// File browser
|
||||
char fileName[26];
|
||||
char filePath[36];
|
||||
char filePath[50];
|
||||
byte currPage;
|
||||
byte lastPage;
|
||||
byte numPages;
|
||||
@ -178,11 +179,11 @@ boolean filebrowse = 0;
|
||||
char fileOptions[30][20];
|
||||
|
||||
// Common
|
||||
char romName[10];
|
||||
int sramSize = 0;
|
||||
char romName[17];
|
||||
unsigned long sramSize = 0;
|
||||
int romType = 0;
|
||||
byte saveType;
|
||||
int romSize = 0;
|
||||
word romSize = 0;
|
||||
byte numBanks = 128;
|
||||
char checksumStr[5];
|
||||
bool errorLvl = 0;
|
||||
@ -190,6 +191,8 @@ byte romVersion = 0;
|
||||
char cartID[5];
|
||||
unsigned long cartSize;
|
||||
char flashid[5];
|
||||
unsigned long fileSize;
|
||||
unsigned long sramBase;
|
||||
|
||||
// Variable to count errors
|
||||
unsigned long writeErrors;
|
||||
@ -199,7 +202,7 @@ byte mode;
|
||||
|
||||
//remember folder number to create a new folder for every save
|
||||
int foldern;
|
||||
char folder[24];
|
||||
char folder[36];
|
||||
|
||||
// Array that holds the data
|
||||
byte sdBuffer[512];
|
||||
@ -319,45 +322,52 @@ static const unsigned char PROGMEM sig [] = {
|
||||
*****************************************/
|
||||
// All menus and menu entries are stored in progmem to save on sram
|
||||
// Main menu
|
||||
const char modeItem1[] PROGMEM = "Nintendo 64";
|
||||
const char modeItem2[] PROGMEM = "Super Nintendo";
|
||||
const char modeItem3[] PROGMEM = "Nintendo Power";
|
||||
const char modeItem4[] PROGMEM = "Game Boy";
|
||||
const char modeItem5[] PROGMEM = "Flashrom Programmer";
|
||||
const char modeItem6[] PROGMEM = "About";
|
||||
const char* const modeOptions[] PROGMEM = {modeItem1, modeItem2, modeItem3, modeItem4, modeItem5, modeItem6};
|
||||
static const char modeItem1[] PROGMEM = "Nintendo 64";
|
||||
static const char modeItem2[] PROGMEM = "Super Nintendo";
|
||||
static const char modeItem3[] PROGMEM = "Nintendo Power";
|
||||
static const char modeItem4[] PROGMEM = "Game Boy";
|
||||
static const char modeItem5[] PROGMEM = "Mega Drive";
|
||||
static const char modeItem6[] PROGMEM = "Flashrom Programmer";
|
||||
static const char modeItem7[] PROGMEM = "About";
|
||||
static const char* const modeOptions[] PROGMEM = {modeItem1, modeItem2, modeItem3, modeItem4, modeItem5, modeItem6, modeItem7};
|
||||
|
||||
// N64 Submenu
|
||||
const char n64MenuItem1[] PROGMEM = "Cart Slot";
|
||||
const char n64MenuItem2[] PROGMEM = "Controller";
|
||||
const char* const menuOptionsN64[] PROGMEM = {n64MenuItem1, n64MenuItem2};
|
||||
static const char n64MenuItem1[] PROGMEM = "Cart Slot";
|
||||
static const char n64MenuItem2[] PROGMEM = "Controller";
|
||||
static const char n64MenuItem3[] PROGMEM = "Flash Repro";
|
||||
static const char* const menuOptionsN64[] PROGMEM = {n64MenuItem1, n64MenuItem2, n64MenuItem3};
|
||||
|
||||
// Nintendo Power Submenu
|
||||
static const char npMenuItem1[] PROGMEM = "SF Memory";
|
||||
static const char npMenuItem2[] PROGMEM = "GB Memory";
|
||||
static const char* const menuOptionsNP[] PROGMEM = {npMenuItem1, npMenuItem2};
|
||||
|
||||
// Flash Submenu
|
||||
const char flashMenuItem1[] PROGMEM = "8bit slot";
|
||||
const char flashMenuItem2[] PROGMEM = "16bit slot";
|
||||
const char* const menuOptionsFlash[] PROGMEM = {flashMenuItem1, flashMenuItem2};
|
||||
static const char flashMenuItem1[] PROGMEM = "8bit slot";
|
||||
static const char flashMenuItem2[] PROGMEM = "16bit slot";
|
||||
static const char* const menuOptionsFlash[] PROGMEM = {flashMenuItem1, flashMenuItem2};
|
||||
|
||||
// GBx Submenu
|
||||
const char gbxMenuItem1[] PROGMEM = "Game Boy (Color)";
|
||||
const char gbxMenuItem2[] PROGMEM = "Game Boy Advance";
|
||||
const char* const menuOptionsGBx[] PROGMEM = {gbxMenuItem1, gbxMenuItem2};
|
||||
static const char gbxMenuItem1[] PROGMEM = "Game Boy (Color)";
|
||||
static const char gbxMenuItem2[] PROGMEM = "Game Boy Advance";
|
||||
static const char* const menuOptionsGBx[] PROGMEM = {gbxMenuItem1, gbxMenuItem2};
|
||||
|
||||
void mainMenu() {
|
||||
// create menu with title and 6 options to choose from
|
||||
unsigned char modeMenu;
|
||||
// Copy menuOptions out of progmem
|
||||
convertPgm(modeOptions, 6);
|
||||
modeMenu = question_box("Cartridge Reader", menuOptions, 6, 0);
|
||||
convertPgm(modeOptions, 7);
|
||||
modeMenu = question_box("Cartridge Reader", menuOptions, 7, 0);
|
||||
|
||||
// wait for user choice to come back from the question box menu
|
||||
switch (modeMenu)
|
||||
{
|
||||
case 0:
|
||||
// create menu with title and 2 options to choose from
|
||||
// create menu with title and 3 options to choose from
|
||||
unsigned char n64Dev;
|
||||
// Copy menuOptions out of progmem
|
||||
convertPgm(menuOptionsN64, 2);
|
||||
n64Dev = question_box("Select N64 device", menuOptions, 2, 0);
|
||||
convertPgm(menuOptionsN64, 3);
|
||||
n64Dev = question_box("Select N64 device", menuOptions, 3, 0);
|
||||
|
||||
// wait for user choice to come back from the question box menu
|
||||
switch (n64Dev)
|
||||
@ -366,6 +376,7 @@ void mainMenu() {
|
||||
display_Clear();
|
||||
display_Update();
|
||||
setup_N64_Cart();
|
||||
printCartInfo_N64();
|
||||
mode = mode_N64_Cart;
|
||||
break;
|
||||
|
||||
@ -375,6 +386,16 @@ void mainMenu() {
|
||||
setup_N64_Controller();
|
||||
mode = mode_N64_Controller;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
display_Clear();
|
||||
display_Update();
|
||||
setup_N64_Cart();
|
||||
flashRepro_N64();
|
||||
printCartInfo_N64();
|
||||
mode = mode_N64_Cart;
|
||||
break;
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
@ -386,10 +407,29 @@ void mainMenu() {
|
||||
break;
|
||||
|
||||
case 2:
|
||||
display_Clear();
|
||||
display_Update();
|
||||
setup_NP();
|
||||
mode = mode_NP;
|
||||
// create menu with title and 2 options to choose from
|
||||
unsigned char npCart;
|
||||
// Copy menuOptions out of progmem
|
||||
convertPgm(menuOptionsNP, 2);
|
||||
npCart = question_box("Select NP Cart", menuOptions, 2, 0);
|
||||
|
||||
// wait for user choice to come back from the question box menu
|
||||
switch (npCart)
|
||||
{
|
||||
case 0:
|
||||
display_Clear();
|
||||
display_Update();
|
||||
setup_SFM();
|
||||
mode = mode_SFM;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
display_Clear();
|
||||
display_Update();
|
||||
setup_GBM();
|
||||
mode = mode_GBM;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case 3:
|
||||
@ -419,6 +459,13 @@ void mainMenu() {
|
||||
break;
|
||||
|
||||
case 4:
|
||||
display_Clear();
|
||||
display_Update();
|
||||
setup_MD();
|
||||
mode = mode_MD;
|
||||
break;
|
||||
|
||||
case 5:
|
||||
// create menu with title and 2 options to choose from
|
||||
unsigned char flashSlot;
|
||||
// Copy menuOptions out of progmem
|
||||
@ -444,7 +491,7 @@ void mainMenu() {
|
||||
}
|
||||
break;
|
||||
|
||||
case 5:
|
||||
case 6:
|
||||
display_Clear();
|
||||
// Draw the Logo
|
||||
display.drawBitmap(0, 0, sig, 128, 64, 1);
|
||||
@ -481,7 +528,7 @@ void mainMenu() {
|
||||
display_Update();
|
||||
delay(2000);
|
||||
foldern = 0;
|
||||
EEPROM_writeAnything(0, foldern);
|
||||
EEPROM_writeAnything(10, foldern);
|
||||
asm volatile (" jmp 0");
|
||||
}
|
||||
}
|
||||
@ -506,8 +553,11 @@ void setup() {
|
||||
//PORTD |= (1 << 7);
|
||||
//PORTG |= (1 << 2);
|
||||
|
||||
// Initialize LED
|
||||
rgb.setColor(0, 0, 0);
|
||||
|
||||
// Read current folder number out of eeprom
|
||||
EEPROM_readAnything(0, foldern);
|
||||
EEPROM_readAnything(10, foldern);
|
||||
|
||||
if (enable_OLED) {
|
||||
// GLCD
|
||||
@ -532,11 +582,6 @@ void setup() {
|
||||
Serial.println(F("Cartridge Reader"));
|
||||
Serial.println(F("2017 sanni"));
|
||||
Serial.println("");
|
||||
|
||||
// Print available RAM
|
||||
Serial.print(F("Free Ram: "));
|
||||
Serial.print(FreeRam());
|
||||
Serial.println(F("Bytes"));
|
||||
}
|
||||
|
||||
// Init SD card
|
||||
@ -592,7 +637,19 @@ void print_Error(const __FlashStringHelper *errorMessage, boolean forceReset) {
|
||||
println_Msg(F("Press Button..."));
|
||||
display_Update();
|
||||
wait();
|
||||
asm volatile (" jmp 0");
|
||||
if (ignoreError == 0) {
|
||||
asm volatile (" jmp 0");
|
||||
}
|
||||
else {
|
||||
ignoreError = 0;
|
||||
display_Clear();
|
||||
println_Msg(F(""));
|
||||
println_Msg(F(""));
|
||||
println_Msg(F(""));
|
||||
println_Msg(F(" Error Overwrite"));
|
||||
display_Update();
|
||||
delay(2000);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -894,12 +951,9 @@ int checkButton2() {
|
||||
|
||||
// Wait for user to push button
|
||||
void wait_btn() {
|
||||
|
||||
// Change led to green
|
||||
if (errorLvl == 0)
|
||||
rgbLed(green_color);
|
||||
else
|
||||
errorLvl = 0;
|
||||
|
||||
while (1)
|
||||
{
|
||||
@ -907,16 +961,22 @@ void wait_btn() {
|
||||
int b = checkButton();
|
||||
|
||||
// Send some clock pulses to the Eeprom in case it locked up
|
||||
if (mode == mode_N64_Cart) {
|
||||
if ((mode == mode_N64_Cart) && ((saveType == 5) || (saveType == 6))) {
|
||||
pulseClock_N64(1);
|
||||
}
|
||||
// if the cart readers input button is pressed shortly
|
||||
if (b == 1) {
|
||||
errorLvl = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
// if the cart readers input button is pressed long
|
||||
if (b == 3) {
|
||||
if (errorLvl) {
|
||||
// Debug
|
||||
//ignoreError = 1;
|
||||
errorLvl = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -1240,8 +1300,8 @@ void loop() {
|
||||
else if (mode == mode_FLASH16) {
|
||||
flashromMenu16();
|
||||
}
|
||||
else if (mode == mode_NP) {
|
||||
npMenu();
|
||||
else if (mode == mode_SFM) {
|
||||
sfmMenu();
|
||||
}
|
||||
else if (mode == mode_GB) {
|
||||
gbMenu();
|
||||
@ -1249,11 +1309,17 @@ void loop() {
|
||||
else if (mode == mode_GBA) {
|
||||
gbaMenu();
|
||||
}
|
||||
else if (mode == mode_NPFlash) {
|
||||
NPFlashMenu();
|
||||
else if (mode == mode_SFM_Flash) {
|
||||
sfmFlashMenu();
|
||||
}
|
||||
else if (mode == mode_NPGame) {
|
||||
NPGameOptions();
|
||||
else if (mode == mode_SFM_Game) {
|
||||
sfmGameOptions();
|
||||
}
|
||||
else if (mode == mode_GBM) {
|
||||
gbmMenu();
|
||||
}
|
||||
else if (mode == mode_MD) {
|
||||
mdMenu();
|
||||
}
|
||||
else {
|
||||
display_Clear();
|
||||
|
@ -16,24 +16,24 @@ unsigned long blank;
|
||||
Menu
|
||||
*****************************************/
|
||||
// 8bit Flash menu items
|
||||
const char flash8MenuItem1[] PROGMEM = "Blankcheck";
|
||||
const char flash8MenuItem2[] PROGMEM = "Erase";
|
||||
const char flash8MenuItem3[] PROGMEM = "Read";
|
||||
const char flash8MenuItem4[] PROGMEM = "Write";
|
||||
const char flash8MenuItem5[] PROGMEM = "ID";
|
||||
const char flash8MenuItem6[] PROGMEM = "Print";
|
||||
const char flash8MenuItem7[] PROGMEM = "Reset";
|
||||
const char* const menuOptionsFLASH8[] PROGMEM = {flash8MenuItem1, flash8MenuItem2, flash8MenuItem3, flash8MenuItem4, flash8MenuItem5, flash8MenuItem6, flash8MenuItem7};
|
||||
static const char flash8MenuItem1[] PROGMEM = "Blankcheck";
|
||||
static const char flash8MenuItem2[] PROGMEM = "Erase";
|
||||
static const char flash8MenuItem3[] PROGMEM = "Read";
|
||||
static const char flash8MenuItem4[] PROGMEM = "Write";
|
||||
static const char flash8MenuItem5[] PROGMEM = "ID";
|
||||
static const char flash8MenuItem6[] PROGMEM = "Print";
|
||||
static const char flash8MenuItem7[] PROGMEM = "Reset";
|
||||
static const char* const menuOptionsFLASH8[] PROGMEM = {flash8MenuItem1, flash8MenuItem2, flash8MenuItem3, flash8MenuItem4, flash8MenuItem5, flash8MenuItem6, flash8MenuItem7};
|
||||
|
||||
// 16bit Flash menu items
|
||||
const char flash16MenuItem1[] PROGMEM = "Blankcheck";
|
||||
const char flash16MenuItem2[] PROGMEM = "Erase";
|
||||
const char flash16MenuItem3[] PROGMEM = "Read";
|
||||
const char flash16MenuItem4[] PROGMEM = "Write";
|
||||
const char flash16MenuItem5[] PROGMEM = "ID";
|
||||
const char flash16MenuItem6[] PROGMEM = "Print";
|
||||
const char flash16MenuItem7[] PROGMEM = "Reset";
|
||||
const char* const menuOptionsFLASH16[] PROGMEM = {flash16MenuItem1, flash16MenuItem2, flash16MenuItem3, flash16MenuItem4, flash16MenuItem5, flash16MenuItem6, flash16MenuItem7};
|
||||
static const char flash16MenuItem1[] PROGMEM = "Blankcheck";
|
||||
static const char flash16MenuItem2[] PROGMEM = "Erase";
|
||||
static const char flash16MenuItem3[] PROGMEM = "Read";
|
||||
static const char flash16MenuItem4[] PROGMEM = "Write";
|
||||
static const char flash16MenuItem5[] PROGMEM = "ID";
|
||||
static const char flash16MenuItem6[] PROGMEM = "Print";
|
||||
static const char flash16MenuItem7[] PROGMEM = "Reset";
|
||||
static const char* const menuOptionsFLASH16[] PROGMEM = {flash16MenuItem1, flash16MenuItem2, flash16MenuItem3, flash16MenuItem4, flash16MenuItem5, flash16MenuItem6, flash16MenuItem7};
|
||||
|
||||
void flashromMenu8() {
|
||||
// create menu with title and 7 options to choose from
|
||||
@ -68,8 +68,6 @@ void flashromMenu8() {
|
||||
}
|
||||
else {
|
||||
eraseFlash29F1610();
|
||||
delay(1000);
|
||||
busyCheck29F1610();
|
||||
}
|
||||
println_Msg(F("Flashrom erased"));
|
||||
display_Update();
|
||||
@ -96,21 +94,26 @@ void flashromMenu8() {
|
||||
time = millis();
|
||||
if (flashromType == 1)
|
||||
writeFlash29F032();
|
||||
else if (flashromType == 2)
|
||||
writeFlash29F1610();
|
||||
|
||||
else if (flashromType == 2) {
|
||||
if (strcmp(flashid, "C2F3") == 0)
|
||||
writeFlash29F1601();
|
||||
else if (strcmp(flashid, "C2A8") == 0)
|
||||
writeFlash29LV320();
|
||||
else if (strcmp(flashid, "C2C9") == 0)
|
||||
writeFlash29LV640();
|
||||
else
|
||||
writeFlash29F1610();
|
||||
}
|
||||
delay(100);
|
||||
// Reset twice just to be sure
|
||||
delay(1000);
|
||||
if (flashromType == 1)
|
||||
resetFlash29F032();
|
||||
else
|
||||
resetFlash29F1610();
|
||||
delay(1000);
|
||||
if (flashromType == 1)
|
||||
resetFlash29F032();
|
||||
else
|
||||
resetFlash29F1610();
|
||||
delay(1000);
|
||||
verifyFlash();
|
||||
break;
|
||||
|
||||
@ -150,7 +153,6 @@ void flashromMenu8() {
|
||||
resetFlash29F032();
|
||||
else
|
||||
resetFlash29F1610();
|
||||
delay(500);
|
||||
asm volatile (" jmp 0");
|
||||
break;
|
||||
}
|
||||
@ -189,12 +191,10 @@ void flashromMenu16() {
|
||||
println_Msg(F("Erase Flashrom"));
|
||||
display_Update();
|
||||
time = millis();
|
||||
resetFlash16();
|
||||
eraseFlash16();
|
||||
delay(1000);
|
||||
busyCheck16();
|
||||
println_Msg(F("Flashrom erased."));
|
||||
display_Update();
|
||||
resetFlash16();
|
||||
break;
|
||||
|
||||
case 2:
|
||||
@ -210,7 +210,12 @@ void flashromMenu16() {
|
||||
fileBrowser("Select file");
|
||||
display_Clear();
|
||||
time = millis();
|
||||
writeFlash16();
|
||||
if (strcmp(flashid, "C2F3") == 0) {
|
||||
writeFlash16_29F1601();
|
||||
}
|
||||
else {
|
||||
writeFlash16();
|
||||
}
|
||||
delay(100);
|
||||
resetFlash16();
|
||||
delay(100);
|
||||
@ -241,7 +246,6 @@ void flashromMenu16() {
|
||||
display_Clear();
|
||||
display_Update();
|
||||
resetFlash16();
|
||||
delay(500);
|
||||
asm volatile (" jmp 0");
|
||||
break;
|
||||
}
|
||||
@ -296,12 +300,27 @@ idtheflash:
|
||||
flashSize = 2097152;
|
||||
flashromType = 2;
|
||||
}
|
||||
else if (strcmp(flashid, "C2F3") == 0) {
|
||||
println_Msg(F("MX29F1601 detected"));
|
||||
flashSize = 2097152;
|
||||
flashromType = 2;
|
||||
}
|
||||
else if (strcmp(flashid, "C2F9") == 0) {
|
||||
println_Msg(F("MX29L3211 detected"));
|
||||
println_Msg(F("ATTENTION 3.3V"));
|
||||
flashSize = 4194304;
|
||||
flashromType = 2;
|
||||
}
|
||||
else if (strcmp(flashid, "C2A8") == 0) {
|
||||
println_Msg(F("MX29LV320"));
|
||||
flashSize = 4194304;
|
||||
flashromType = 2;
|
||||
}
|
||||
else if (strcmp(flashid, "C2C9") == 0) {
|
||||
println_Msg(F("MX29LV640"));
|
||||
flashSize = 8388608;
|
||||
flashromType = 2;
|
||||
}
|
||||
else if (strcmp(flashid, "0141") == 0) {
|
||||
println_Msg(F("AM29F032B"));
|
||||
flashSize = 4194304;
|
||||
@ -359,7 +378,7 @@ void setup_Flash16() {
|
||||
// Setting CE(PH6) LOW
|
||||
PORTH &= ~(1 << 6);
|
||||
|
||||
delay(10);
|
||||
delay(100);
|
||||
|
||||
// ID flash
|
||||
idFlash16();
|
||||
@ -375,6 +394,11 @@ void setup_Flash16() {
|
||||
flashSize = 2097152;
|
||||
flashromType = 2;
|
||||
}
|
||||
else if (strcmp(flashid, "C2F3") == 0) {
|
||||
println_Msg(F("MX29F1601 detected"));
|
||||
flashSize = 2097152;
|
||||
flashromType = 2;
|
||||
}
|
||||
else if (strcmp(flashid, "C2F9") == 0) {
|
||||
println_Msg(F("MX29L3211 detected"));
|
||||
println_Msg(F("ATTENTION 3.3V"));
|
||||
@ -522,6 +546,8 @@ void resetFlash29F032() {
|
||||
|
||||
// Set data pins to input again
|
||||
dataIn8();
|
||||
|
||||
delay(500);
|
||||
}
|
||||
|
||||
void idFlash29F032() {
|
||||
@ -578,12 +604,16 @@ void writeFlash29F032() {
|
||||
|
||||
// Open file on sd card
|
||||
if (myFile.open(filePath, O_READ)) {
|
||||
// Get rom size from file
|
||||
fileSize = myFile.fileSize();
|
||||
if (fileSize > flashSize)
|
||||
print_Error(F("File size exceeds flash size."), true);
|
||||
|
||||
// Set data pins to output
|
||||
dataOut();
|
||||
|
||||
// Fill sdBuffer
|
||||
for (unsigned long currByte = 0; currByte < flashSize; currByte += 512) {
|
||||
for (unsigned long currByte = 0; currByte < fileSize; currByte += 512) {
|
||||
myFile.read(sdBuffer, 512);
|
||||
// Blink led
|
||||
if (currByte % 2048 == 0)
|
||||
@ -644,6 +674,8 @@ void resetFlash29F1610() {
|
||||
|
||||
// Set data pins to input again
|
||||
dataIn8();
|
||||
|
||||
delay(500);
|
||||
}
|
||||
|
||||
void writeFlash29F1610() {
|
||||
@ -655,10 +687,15 @@ void writeFlash29F1610() {
|
||||
|
||||
// Open file on sd card
|
||||
if (myFile.open(filePath, O_READ)) {
|
||||
// Get rom size from file
|
||||
fileSize = myFile.fileSize();
|
||||
if (fileSize > flashSize)
|
||||
print_Error(F("File size exceeds flash size."), true);
|
||||
|
||||
// Set data pins to output
|
||||
dataOut();
|
||||
|
||||
for (unsigned long currByte = 0; currByte < flashSize; currByte += 128) {
|
||||
for (unsigned long currByte = 0; currByte < fileSize; currByte += 128) {
|
||||
// Fill sdBuffer with 1 page at a time then write it repeat until all bytes are written
|
||||
myFile.read(sdBuffer, 128);
|
||||
|
||||
@ -681,6 +718,69 @@ void writeFlash29F1610() {
|
||||
}
|
||||
}
|
||||
|
||||
// Check if write is complete
|
||||
busyCheck29F1610();
|
||||
|
||||
// Set data pins to input again
|
||||
dataIn8();
|
||||
|
||||
// Close the file:
|
||||
myFile.close();
|
||||
}
|
||||
else {
|
||||
println_Msg(F("Can't open file on SD"));
|
||||
display_Update();
|
||||
}
|
||||
}
|
||||
|
||||
void writeFlash29F1601() {
|
||||
// Create filepath
|
||||
sprintf(filePath, "%s/%s", filePath, fileName);
|
||||
println_Msg(F("Flashing file "));
|
||||
println_Msg(filePath);
|
||||
display_Update();
|
||||
|
||||
// Open file on sd card
|
||||
if (myFile.open(filePath, O_READ)) {
|
||||
// Get rom size from file
|
||||
fileSize = myFile.fileSize();
|
||||
if (fileSize > flashSize)
|
||||
print_Error(F("File size exceeds flash size."), true);
|
||||
|
||||
// Set data pins to output
|
||||
dataOut();
|
||||
|
||||
for (unsigned long currByte = 0; currByte < fileSize; currByte += 128) {
|
||||
// Fill sdBuffer with 1 page at a time then write it repeat until all bytes are written
|
||||
myFile.read(sdBuffer, 128);
|
||||
|
||||
// Blink led
|
||||
if (currByte % 3072 == 0)
|
||||
PORTB ^= (1 << 4);
|
||||
|
||||
// Check if write is complete
|
||||
delayMicroseconds(100);
|
||||
busyCheck29F1610();
|
||||
|
||||
// Write command sequence
|
||||
writeByte_Flash(0x5555 << 1, 0xaa);
|
||||
writeByte_Flash(0x2aaa << 1, 0x55);
|
||||
writeByte_Flash(0x5555 << 1, 0xa0);
|
||||
|
||||
// Write one full page at a time
|
||||
for (byte c = 0; c < 128; c++) {
|
||||
writeByte_Flash(currByte + c, sdBuffer[c]);
|
||||
|
||||
if (c == 127) {
|
||||
// Write the last byte twice or else it won't write at all
|
||||
writeByte_Flash(currByte + c, sdBuffer[c]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check if write is complete
|
||||
busyCheck29F1610();
|
||||
|
||||
// Set data pins to input again
|
||||
dataIn8();
|
||||
|
||||
@ -740,6 +840,8 @@ void eraseFlash29F1610() {
|
||||
|
||||
// Set data pins to input again
|
||||
dataIn8();
|
||||
|
||||
busyCheck29F1610();
|
||||
}
|
||||
|
||||
// Delay between write operations based on status register
|
||||
@ -758,6 +860,112 @@ void busyCheck29F1610() {
|
||||
dataOut();
|
||||
}
|
||||
|
||||
/******************************************
|
||||
MX29LV flashrom functions
|
||||
*****************************************/
|
||||
void busyCheck29LV640(unsigned long myAddress, byte myData) {
|
||||
// Set data pins to input
|
||||
dataIn8();
|
||||
// Read the status register
|
||||
byte statusReg = readByte_Flash(myAddress);
|
||||
while ((statusReg & 0x80) != (myData & 0x80)) {
|
||||
statusReg = readByte_Flash(myAddress);
|
||||
}
|
||||
// Set data pins to output
|
||||
dataOut();
|
||||
}
|
||||
|
||||
void writeFlash29LV320() {
|
||||
// Create filepath
|
||||
sprintf(filePath, "%s/%s", filePath, fileName);
|
||||
println_Msg(F("Flashing file "));
|
||||
println_Msg(filePath);
|
||||
display_Update();
|
||||
|
||||
// Open file on sd card
|
||||
if (myFile.open(filePath, O_READ)) {
|
||||
// Get rom size from file
|
||||
fileSize = myFile.fileSize();
|
||||
if (fileSize > flashSize)
|
||||
print_Error(F("File size exceeds flash size."), true);
|
||||
|
||||
// Set data pins to output
|
||||
dataOut();
|
||||
|
||||
for (unsigned long currByte = 0; currByte < fileSize; currByte += 512) {
|
||||
// Fill sdBuffer
|
||||
myFile.read(sdBuffer, 512);
|
||||
|
||||
// Blink led
|
||||
if (currByte % 2048 == 0)
|
||||
PORTB ^= (1 << 4);
|
||||
|
||||
for (int c = 0; c < 512; c++) {
|
||||
// Write command sequence
|
||||
writeByte_Flash(0x555 << 1, 0xaa);
|
||||
writeByte_Flash(0x2aa << 1, 0x55);
|
||||
writeByte_Flash(0x555 << 1, 0xa0);
|
||||
// Write current byte
|
||||
writeByte_Flash(currByte + c, sdBuffer[c]);
|
||||
// Check if write is complete
|
||||
busyCheck29F032(sdBuffer[c]);
|
||||
}
|
||||
}
|
||||
|
||||
// Set data pins to input again
|
||||
dataIn8();
|
||||
|
||||
// Close the file:
|
||||
myFile.close();
|
||||
}
|
||||
else {
|
||||
println_Msg(F("Can't open file on SD"));
|
||||
display_Update();
|
||||
}
|
||||
}
|
||||
void writeFlash29LV640() {
|
||||
// Create filepath
|
||||
sprintf(filePath, "%s/%s", filePath, fileName);
|
||||
println_Msg(F("Flashing file "));
|
||||
println_Msg(filePath);
|
||||
display_Update();
|
||||
// Open file on sd card
|
||||
if (myFile.open(filePath, O_READ)) {
|
||||
// Get rom size from file
|
||||
fileSize = myFile.fileSize();
|
||||
if (fileSize > flashSize)
|
||||
print_Error(F("File size exceeds flash size."), true);
|
||||
|
||||
// Set data pins to output
|
||||
dataOut();
|
||||
for (unsigned long currByte = 0; currByte < fileSize; currByte += 512) {
|
||||
// Fill sdBuffer
|
||||
myFile.read(sdBuffer, 512);
|
||||
// Blink led
|
||||
if (currByte % 2048 == 0)
|
||||
PORTB ^= (1 << 4);
|
||||
for (int c = 0; c < 512; c++) {
|
||||
// Write command sequence
|
||||
writeByte_Flash(0x555 << 1, 0xaa);
|
||||
writeByte_Flash(0x2aa << 1, 0x55);
|
||||
writeByte_Flash(0x555 << 1, 0xa0);
|
||||
// Write current byte
|
||||
writeByte_Flash(currByte + c, sdBuffer[c]);
|
||||
// Check if write is complete
|
||||
busyCheck29LV640(currByte + c, sdBuffer[c]);
|
||||
}
|
||||
}
|
||||
// Set data pins to input again
|
||||
dataIn8();
|
||||
// Close the file:
|
||||
myFile.close();
|
||||
}
|
||||
else {
|
||||
println_Msg(F("Can't open file on SD"));
|
||||
display_Update();
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************
|
||||
Common flashrom functions
|
||||
*****************************************/
|
||||
@ -783,15 +991,18 @@ void blankcheck_Flash() {
|
||||
}
|
||||
|
||||
void verifyFlash() {
|
||||
println_Msg(F("Verifying against"));
|
||||
println_Msg(filePath);
|
||||
println_Msg(F("Verifying..."));
|
||||
display_Update();
|
||||
|
||||
// Open file on sd card
|
||||
if (myFile.open(filePath, O_READ)) {
|
||||
// Get rom size from file
|
||||
fileSize = myFile.fileSize();
|
||||
if (fileSize > flashSize)
|
||||
print_Error(F("File size exceeds flash size."), true);
|
||||
|
||||
blank = 0;
|
||||
for (unsigned long currByte = 0; currByte < flashSize; currByte += 512) {
|
||||
for (unsigned long currByte = 0; currByte < fileSize; currByte += 512) {
|
||||
//fill sdBuffer
|
||||
myFile.read(sdBuffer, 512);
|
||||
for (int c = 0; c < 512; c++) {
|
||||
@ -824,14 +1035,14 @@ void readFlash() {
|
||||
sd.chdir("/");
|
||||
|
||||
// Get name, add extension and convert to char array for sd lib
|
||||
EEPROM_readAnything(0, foldern);
|
||||
EEPROM_readAnything(10, foldern);
|
||||
sd.mkdir("FLASH", true);
|
||||
sd.chdir("FLASH");
|
||||
sprintf(fileName, "FL%d", foldern);
|
||||
strcat(fileName, ".bin");
|
||||
// write new folder number back to eeprom
|
||||
foldern = foldern + 1;
|
||||
EEPROM_writeAnything(0, foldern);
|
||||
EEPROM_writeAnything(10, foldern);
|
||||
|
||||
display_Clear();
|
||||
print_Msg(F("Saving as "));
|
||||
@ -887,6 +1098,8 @@ void resetFlash16() {
|
||||
|
||||
// Set data pins to input again
|
||||
dataIn16();
|
||||
|
||||
delay(500);
|
||||
}
|
||||
|
||||
void writeFlash16() {
|
||||
@ -898,12 +1111,17 @@ void writeFlash16() {
|
||||
|
||||
// Open file on sd card
|
||||
if (myFile.open(filePath, O_READ)) {
|
||||
// Get rom size from file
|
||||
fileSize = myFile.fileSize();
|
||||
if (fileSize > flashSize)
|
||||
print_Error(F("File size exceeds flash size."), true);
|
||||
|
||||
// Set data pins to output
|
||||
dataOut16();
|
||||
|
||||
// Fill sdBuffer with 1 page at a time then write it repeat until all bytes are written
|
||||
int d = 0;
|
||||
for (unsigned long currByte = 0; currByte < flashSize / 2; currByte += 64) {
|
||||
for (unsigned long currByte = 0; currByte < fileSize / 2; currByte += 64) {
|
||||
myFile.read(sdBuffer, 128);
|
||||
|
||||
// Blink led
|
||||
@ -921,13 +1139,80 @@ void writeFlash16() {
|
||||
|
||||
// Write one full page at a time
|
||||
for (byte c = 0; c < 64; c++) {
|
||||
word currWord = ((sdBuffer[d + 1] << 8) | sdBuffer[d]);
|
||||
word currWord = ( ( sdBuffer[d + 1] & 0xFF ) << 8 ) | ( sdBuffer[d] & 0xFF );
|
||||
writeWord_Flash(currByte + c, currWord);
|
||||
d += 2;
|
||||
}
|
||||
d = 0;
|
||||
}
|
||||
|
||||
// Check if write is complete
|
||||
busyCheck16();
|
||||
|
||||
// Set data pins to input again
|
||||
dataIn16();
|
||||
|
||||
// Close the file:
|
||||
myFile.close();
|
||||
}
|
||||
else {
|
||||
println_Msg(F("Can't open file on SD."));
|
||||
display_Update();
|
||||
}
|
||||
}
|
||||
|
||||
void writeFlash16_29F1601() {
|
||||
// Create filepath
|
||||
sprintf(filePath, "%s/%s", filePath, fileName);
|
||||
println_Msg(F("Flashing file "));
|
||||
println_Msg(filePath);
|
||||
display_Update();
|
||||
|
||||
// Open file on sd card
|
||||
if (myFile.open(filePath, O_READ)) {
|
||||
// Get rom size from file
|
||||
fileSize = myFile.fileSize();
|
||||
if (fileSize > flashSize)
|
||||
print_Error(F("File size exceeds flash size."), true);
|
||||
|
||||
// Set data pins to output
|
||||
dataOut16();
|
||||
|
||||
// Fill sdBuffer with 1 page at a time then write it repeat until all bytes are written
|
||||
int d = 0;
|
||||
for (unsigned long currByte = 0; currByte < fileSize / 2; currByte += 64) {
|
||||
myFile.read(sdBuffer, 128);
|
||||
|
||||
// Blink led
|
||||
if (currByte % 2048 == 0)
|
||||
PORTB ^= (1 << 4);
|
||||
|
||||
// Check if write is complete
|
||||
delayMicroseconds(100);
|
||||
busyCheck16();
|
||||
|
||||
// Write command sequence
|
||||
writeWord_Flash(0x5555, 0xaa);
|
||||
writeWord_Flash(0x2aaa, 0x55);
|
||||
writeWord_Flash(0x5555, 0xa0);
|
||||
|
||||
// Write one full page at a time
|
||||
for (byte c = 0; c < 64; c++) {
|
||||
word currWord = ( ( sdBuffer[d + 1] & 0xFF ) << 8 ) | ( sdBuffer[d] & 0xFF );
|
||||
writeWord_Flash(currByte + c, currWord);
|
||||
|
||||
if (c == 63) {
|
||||
// Write the last byte twice or else it won't write at all
|
||||
writeWord_Flash(currByte + c, sdBuffer[d + 1]);
|
||||
}
|
||||
d += 2;
|
||||
}
|
||||
d = 0;
|
||||
}
|
||||
|
||||
// Check if write is complete
|
||||
busyCheck16();
|
||||
|
||||
// Set data pins to input again
|
||||
dataIn16();
|
||||
|
||||
@ -987,6 +1272,8 @@ void eraseFlash16() {
|
||||
|
||||
// Set data pins to input again
|
||||
dataIn16();
|
||||
|
||||
busyCheck16();
|
||||
}
|
||||
|
||||
void blankcheck16() {
|
||||
@ -1006,29 +1293,30 @@ void blankcheck16() {
|
||||
display_Update();
|
||||
}
|
||||
else {
|
||||
println_Msg(F("Error: Not blank!"));
|
||||
display_Update();
|
||||
print_Error(F("Error: Not blank"), false);
|
||||
}
|
||||
}
|
||||
|
||||
void verifyFlash16() {
|
||||
|
||||
println_Msg(F("Verifying against"));
|
||||
println_Msg(filePath);
|
||||
println_Msg(F("Verifying..."));
|
||||
display_Update();
|
||||
|
||||
// Open file on sd card
|
||||
if (myFile.open(filePath, O_READ)) {
|
||||
// Get rom size from file
|
||||
fileSize = myFile.fileSize();
|
||||
if (fileSize > flashSize) {
|
||||
print_Error(F("File size exceeds flash size."), true);
|
||||
}
|
||||
|
||||
blank = 0;
|
||||
word d = 0;
|
||||
for (unsigned long currByte = 0; currByte < flashSize / 2; currByte += 256) {
|
||||
for (unsigned long currByte = 0; currByte < fileSize / 2; currByte += 256) {
|
||||
//fill sdBuffer
|
||||
myFile.read(sdBuffer, 512);
|
||||
for (int c = 0; c < 256; c++) {
|
||||
word currWord = ((sdBuffer[d] << 8) | sdBuffer[d + 1]);
|
||||
// Swap bytes in word
|
||||
currWord = ((currWord >> 8) & 0x00FF00FF) | ((currWord & 0x00FF00FF) << 8);
|
||||
word currWord = ((sdBuffer[d + 1] << 8) | sdBuffer[d]);
|
||||
|
||||
if (readWord_Flash(currByte + c) != currWord) {
|
||||
blank++;
|
||||
}
|
||||
@ -1060,14 +1348,14 @@ void readFlash16() {
|
||||
sd.chdir("/");
|
||||
|
||||
// Get name, add extension and convert to char array for sd lib
|
||||
EEPROM_readAnything(0, foldern);
|
||||
EEPROM_readAnything(10, foldern);
|
||||
sd.mkdir("FLASH", true);
|
||||
sd.chdir("FLASH");
|
||||
sprintf(fileName, "FL%d", foldern);
|
||||
strcat(fileName, ".bin");
|
||||
// write new folder number back to eeprom
|
||||
foldern = foldern + 1;
|
||||
EEPROM_writeAnything(0, foldern);
|
||||
EEPROM_writeAnything(10, foldern);
|
||||
|
||||
display_Clear();
|
||||
print_Msg(F("Saving as "));
|
||||
@ -1085,13 +1373,11 @@ void readFlash16() {
|
||||
for (unsigned long currByte = 0; currByte < flashSize / 2; currByte += 256) {
|
||||
for (word c = 0; c < 256; c++) {
|
||||
word currWord = readWord_Flash(currByte + c);
|
||||
// Swap bytes in word
|
||||
currWord = ((currWord >> 8) & 0x00FF00FF) | ((currWord & 0x00FF00FF) << 8);
|
||||
// Split word into two bytes
|
||||
// Left
|
||||
sdBuffer[d] = (( currWord >> 8 ) & 0xFF);
|
||||
// Right
|
||||
sdBuffer[d + 1] = (currWord & 0xFF);
|
||||
sdBuffer[d + 1] = (( currWord >> 8 ) & 0xFF);
|
||||
// Left
|
||||
sdBuffer[d] = (currWord & 0xFF);
|
||||
d += 2;
|
||||
}
|
||||
myFile.write(sdBuffer, 512);
|
||||
@ -1111,33 +1397,31 @@ void printFlash16(int numBytes) {
|
||||
short_val = ( ( left_byte & 0xFF ) << 8 ) | ( right_byte & 0xFF );
|
||||
*/
|
||||
|
||||
char buffer[3];
|
||||
char buf[3];
|
||||
|
||||
for (int currByte = 0; currByte < numBytes / 2; currByte += 5) {
|
||||
// 5 words per line
|
||||
for (int c = 0; c < 5; c++) {
|
||||
|
||||
word currWord = readWord_Flash(currByte + c);
|
||||
|
||||
// Swap bytes in word
|
||||
currWord = ((currWord >> 8) & 0x00FF00FF) | ((currWord & 0x00FF00FF) << 8);
|
||||
|
||||
// Split word into two bytes
|
||||
byte right_byte = currWord & 0xFF;
|
||||
byte left_byte = ( currWord >> 8 ) & 0xFF;
|
||||
byte left_byte = currWord & 0xFF;
|
||||
byte right_byte = ( currWord >> 8 ) & 0xFF;
|
||||
|
||||
itoa (left_byte, buffer, 16);
|
||||
for (int i = 0; i < 2 - strlen(buffer); i++) {
|
||||
print_Msg('0');
|
||||
|
||||
sprintf (buf, "%x", left_byte);
|
||||
for (int i = 0; i < 2 - strlen(buf); i++) {
|
||||
print_Msg("0");
|
||||
}
|
||||
// Now print the significant bits
|
||||
print_Msg(buffer);
|
||||
print_Msg(buf);
|
||||
|
||||
itoa (right_byte, buffer, 16);
|
||||
for (int i = 0; i < 2 - strlen(buffer); i++) {
|
||||
print_Msg('0');
|
||||
sprintf (buf, "%x", right_byte);
|
||||
for (int i = 0; i < 2 - strlen(buf); i++) {
|
||||
print_Msg("0");
|
||||
}
|
||||
// Now print the significant bits
|
||||
print_Msg(buffer);
|
||||
print_Msg(buf);
|
||||
}
|
||||
println_Msg("");
|
||||
}
|
||||
|
@ -14,12 +14,12 @@ uint16_t sramEndAddress = 0;
|
||||
Menu
|
||||
*****************************************/
|
||||
// GB menu items
|
||||
const char GBMenuItem1[] PROGMEM = "Read Rom";
|
||||
const char GBMenuItem2[] PROGMEM = "Read Save";
|
||||
const char GBMenuItem3[] PROGMEM = "Write Save";
|
||||
const char GBMenuItem4[] PROGMEM = "Write Flashcart";
|
||||
const char GBMenuItem5[] PROGMEM = "Reset";
|
||||
const char* const menuOptionsGB[] PROGMEM = {GBMenuItem1, GBMenuItem2, GBMenuItem3, GBMenuItem4, GBMenuItem5};
|
||||
static const char GBMenuItem1[] PROGMEM = "Read Rom";
|
||||
static const char GBMenuItem2[] PROGMEM = "Read Save";
|
||||
static const char GBMenuItem3[] PROGMEM = "Write Save";
|
||||
static const char GBMenuItem4[] PROGMEM = "Write Flashcart";
|
||||
static const char GBMenuItem5[] PROGMEM = "Reset";
|
||||
static const char* const menuOptionsGB[] PROGMEM = {GBMenuItem1, GBMenuItem2, GBMenuItem3, GBMenuItem4, GBMenuItem5};
|
||||
|
||||
void gbMenu() {
|
||||
// create menu with title and 5 options to choose from
|
||||
@ -128,7 +128,7 @@ void setup_GB() {
|
||||
display_Clear();
|
||||
if (strcmp(checksumStr, "00") != 0) {
|
||||
println_Msg(F("GB Cart Info"));
|
||||
print_Msg(F("Rom Name: "));
|
||||
print_Msg(F("Name: "));
|
||||
println_Msg(romName);
|
||||
print_Msg(F("Rom Type: "));
|
||||
switch (romType) {
|
||||
@ -329,13 +329,13 @@ void getCartInfo_GB() {
|
||||
// Get Checksum as string
|
||||
sprintf(checksumStr, "%02X%02X", readByte_GB(0x014E), readByte_GB(0x014F));
|
||||
|
||||
// Dump name into 8.3 compatible format
|
||||
// Get name
|
||||
byte myByte = 0;
|
||||
byte myLength = 0;
|
||||
|
||||
for (int addr = 0x0134; addr <= 0x13C; addr++) {
|
||||
myByte = readByte_GB(addr);
|
||||
if (((char(myByte) >= 48 && char(myByte) <= 57) || (char(myByte) >= 65 && char(myByte) <= 122)) && myLength < 8) {
|
||||
if (((char(myByte) >= 48 && char(myByte) <= 57) || (char(myByte) >= 65 && char(myByte) <= 122)) && myLength < 15) {
|
||||
romName[myLength] = char(myByte);
|
||||
myLength++;
|
||||
}
|
||||
@ -345,25 +345,24 @@ void getCartInfo_GB() {
|
||||
// Dump ROM
|
||||
void readROM_GB() {
|
||||
// Get name, add extension and convert to char array for sd lib
|
||||
char fileName[26];
|
||||
strcpy(fileName, romName);
|
||||
strcat(fileName, ".GB");
|
||||
|
||||
// create a new folder for the rom file
|
||||
EEPROM_readAnything(0, foldern);
|
||||
sprintf(folder, "ROM/%s/%d", romName, foldern);
|
||||
EEPROM_readAnything(10, foldern);
|
||||
sprintf(folder, "GB/ROM/%s/%d", romName, foldern);
|
||||
sd.mkdir(folder, true);
|
||||
sd.chdir(folder);
|
||||
|
||||
//clear the screen
|
||||
display_Clear();
|
||||
println_Msg(F("Creating folder: "));
|
||||
println_Msg(folder);
|
||||
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(0, foldern);
|
||||
EEPROM_writeAnything(10, foldern);
|
||||
|
||||
//open file on sd card
|
||||
if (!myFile.open(fileName, O_RDWR | O_CREAT)) {
|
||||
@ -406,10 +405,6 @@ void readROM_GB() {
|
||||
|
||||
// Close the file:
|
||||
myFile.close();
|
||||
|
||||
// Signal end of process
|
||||
print_Msg(F("Saved as "));
|
||||
println_Msg(fileName);
|
||||
}
|
||||
|
||||
unsigned int calc_checksum_GB (char* fileName, char* folder) {
|
||||
@ -451,13 +446,12 @@ boolean compare_checksum_GB() {
|
||||
println_Msg(F("Calculating Checksum"));
|
||||
display_Update();
|
||||
|
||||
char fileName[26];
|
||||
strcpy(fileName, romName);
|
||||
strcat(fileName, ".GB");
|
||||
|
||||
// last used rom folder
|
||||
EEPROM_readAnything(0, foldern);
|
||||
sprintf(folder, "ROM/%s/%d", romName, foldern - 1);
|
||||
EEPROM_readAnything(10, foldern);
|
||||
sprintf(folder, "GB/ROM/%s/%d", romName, foldern - 1);
|
||||
|
||||
char calcsumStr[5];
|
||||
sprintf(calcsumStr, "%04X", calc_checksum_GB(fileName, folder));
|
||||
@ -483,19 +477,18 @@ void readSRAM_GB() {
|
||||
if (sramEndAddress > 0) {
|
||||
|
||||
// Get name, add extension and convert to char array for sd lib
|
||||
char fileName[26];
|
||||
strcpy(fileName, romName);
|
||||
strcat(fileName, ".sav");
|
||||
|
||||
// create a new folder for the save file
|
||||
EEPROM_readAnything(0, foldern);
|
||||
sprintf(folder, "SAVE/%s/%d", romName, foldern);
|
||||
EEPROM_readAnything(10, foldern);
|
||||
sprintf(folder, "GB/SAVE/%s/%d", romName, foldern);
|
||||
sd.mkdir(folder, true);
|
||||
sd.chdir(folder);
|
||||
|
||||
// write new folder number back to eeprom
|
||||
foldern = foldern + 1;
|
||||
EEPROM_writeAnything(0, foldern);
|
||||
EEPROM_writeAnything(10, foldern);
|
||||
|
||||
//open file on sd card
|
||||
if (!myFile.open(fileName, O_RDWR | O_CREAT)) {
|
||||
@ -540,12 +533,9 @@ void readSRAM_GB() {
|
||||
myFile.close();
|
||||
|
||||
// Signal end of process
|
||||
print_Msg(F("Saved to SAVE/"));
|
||||
print_Msg(romName);
|
||||
print_Msg(F("/"));
|
||||
print_Msg(foldern - 1);
|
||||
print_Msg(F("/"));
|
||||
println_Msg(fileName);
|
||||
print_Msg(F("Saved to "));
|
||||
print_Msg(folder);
|
||||
println_Msg(F("/"));
|
||||
display_Update();
|
||||
}
|
||||
else {
|
||||
|
1337
Cart_Reader/GBA.ino
1337
Cart_Reader/GBA.ino
File diff suppressed because it is too large
Load Diff
487
Cart_Reader/MD.ino
Normal file
487
Cart_Reader/MD.ino
Normal file
@ -0,0 +1,487 @@
|
||||
//******************************************
|
||||
// SEGA MEGA DRIVE
|
||||
//******************************************
|
||||
|
||||
/******************************************
|
||||
Variables
|
||||
*****************************************/
|
||||
unsigned long sramEnd;
|
||||
|
||||
/******************************************
|
||||
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, 3, 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 ((saveType == 1) || (saveType == 2)) {
|
||||
// Change working dir to root
|
||||
sd.chdir("/");
|
||||
println_Msg(F("Reading Sram..."));
|
||||
display_Update();
|
||||
enableSram_MD(1);
|
||||
readSram_MD();
|
||||
enableSram_MD(0);
|
||||
}
|
||||
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();
|
||||
enableSram_MD(1);
|
||||
writeSram_MD();
|
||||
writeErrors = verifySram_MD();
|
||||
enableSram_MD(0);
|
||||
if (writeErrors == 0) {
|
||||
println_Msg(F("Sram verified OK"));
|
||||
display_Update();
|
||||
}
|
||||
else {
|
||||
print_Msg(F("Error: "));
|
||||
print_Msg(writeErrors);
|
||||
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 RST(PH0) CS(PH3) WRH(PH4) WRL(PH5) OE(PH6)
|
||||
DDRH |= (1 << 3) | (1 << 4) | (1 << 5) | (1 << 6);
|
||||
|
||||
// Set TIME(PJ0) to Output
|
||||
DDRJ |= (1 << 0);
|
||||
|
||||
// Set Data Pins (D0-D15) to Input
|
||||
DDRC = 0x00;
|
||||
DDRA = 0x00;
|
||||
|
||||
// Setting RST(PH0) CS(PH3) WRH(PH4) WRL(PH5) OE(PH6) HIGH
|
||||
PORTH |= (1 << 0) | (1 << 3) | (1 << 4) | (1 << 5) | (1 << 6);
|
||||
|
||||
// Setting TIME(PJ0) HIGH
|
||||
PORTJ |= (1 << 0);
|
||||
|
||||
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""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");
|
||||
}
|
||||
|
||||
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");
|
||||
|
||||
// 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
|
||||
word tempWord = ( ( PINA & 0xFF ) << 8 ) | ( 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 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() {
|
||||
// Set control
|
||||
dataIn_MD();
|
||||
|
||||
cartSize = ((long(readWord_MD(0xD2)) << 16) | readWord_MD(0xD3)) + 1;
|
||||
|
||||
// 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) {
|
||||
// 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 * 8 / 1024 / 1024 );
|
||||
println_Msg(F(" MBit"));
|
||||
print_Msg(F("Sram: "));
|
||||
if (sramSize > 0) {
|
||||
print_Msg(sramSize * 8 / 1024);
|
||||
println_Msg(F(" KBit"));
|
||||
}
|
||||
else
|
||||
println_Msg(F("None"));
|
||||
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_MD() {
|
||||
// Set control
|
||||
dataIn_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();
|
||||
}
|
||||
|
||||
/******************************************
|
||||
SRAM functions
|
||||
*****************************************/
|
||||
// Sonic 3 sram enable
|
||||
void enableSram_MD(boolean enableSram) {
|
||||
dataOut_MD();
|
||||
|
||||
// Set D0 to either 1(enable SRAM) or 0(enable ROM)
|
||||
PORTC = enableSram;
|
||||
|
||||
// Strobe TIME(PJ0) LOW to latch the data
|
||||
PORTJ &= ~(1 << 0);
|
||||
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");
|
||||
// Set TIME(PJ0) HIGH
|
||||
PORTJ |= (1 << 0);
|
||||
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");
|
||||
|
||||
dataIn_MD();
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,2 +1,68 @@
|
||||
Double click on Cart_Reader.ino to open the program in the Arduino IDE.
|
||||
And don't forget to copy the files from the sd folder to the root of your sd card.
|
||||
This Arduino code is written by a beginner for beginners, therefore I tried to comment every line of code. To an experienced coder this probably will seem very wrong but it really helps if you're just starting out.
|
||||
|
||||
Source code files:
|
||||
- Cart_Reader.ino is the main file that contains functions and variables being used by multiple submodules and also the main menu
|
||||
- EEPROMAnything.h helps with reading and writing to the Atmega's internal eeprom
|
||||
- FLASH.ino is for reading and writing 29F016, 29F032, 29F033, 29F1610 and 29L3211 flashroms
|
||||
- GB.ino includes everything Game Boy and Game Boy Color
|
||||
- GBA.ino includes everything Game Boy Advance
|
||||
- MD.ino includes everything for the SEGA Mega Drive
|
||||
- N64.ino includes everything Nintendo 64
|
||||
- NP.ino includes everything for Nintendo Power SF Memory and GB Memory cartridges
|
||||
- SNES.ino includes everything Super Nintendo
|
||||
|
||||
Every submodule has it's own setup_XX() function that configures the needed pins and a submenu that lets you choose what you want to do.
|
||||
The code directly addresses the pins via the DDR, PIN and PORT registers.
|
||||
Please also refer to the [pinout Excel sheet](https://github.com/sanni/cartreader/blob/master/pinout.xls).
|
||||
```
|
||||
void setup_N64_Controller() {
|
||||
// Output a low signal
|
||||
PORTH &= ~(1 << 4);
|
||||
// Set Controller Data Pin(PH4) to Input
|
||||
DDRH &= ~(1 << 4);
|
||||
}
|
||||
```
|
||||
|
||||
Would be the same as this in a more traditional Arduino sketch:
|
||||
```
|
||||
int dataPin = 7;
|
||||
|
||||
void setup(){
|
||||
// Output a low signal
|
||||
digitalWrite(dataPin, LOW);
|
||||
// Set controller data pin to input
|
||||
pinMode(dataPin, INPUT);
|
||||
}
|
||||
```
|
||||
To preserve memory every string is saved into the flash of the Arduino, also called progmem. This is done by using the F() macro.
|
||||
```
|
||||
println_Msg(F("Press Button."));
|
||||
```
|
||||
Also all the menus are stored in progmem and are only recalled to sram when needed.
|
||||
```
|
||||
// N64 controller menu items
|
||||
const char N64ContMenuItem1[] PROGMEM = "Test Controller";
|
||||
const char N64ContMenuItem2[] PROGMEM = "Read ControllerPak";
|
||||
const char N64ContMenuItem3[] PROGMEM = "Write ControllerPak";
|
||||
const char N64ContMenuItem4[] PROGMEM = "Reset";
|
||||
const char* const menuOptionsN64Controller[] PROGMEM = {N64ContMenuItem1, N64ContMenuItem2, N64ContMenuItem3, N64ContMenuItem4};
|
||||
```
|
||||
In an effort to keep the codebase as portable as possible instead of using the functions supplied by the OLED library directly to print out text helper functions like `println_Msg` are being used. So if you want to change to another display library you don't need to change all the code but only the helper functions.
|
||||
```
|
||||
void print_Msg(long unsigned int message) {
|
||||
if (enable_OLED)
|
||||
display.print(message);
|
||||
if (enable_Serial)
|
||||
Serial.print(message);
|
||||
}
|
||||
```
|
||||
|
||||
For development purposes you can route all the text output to the Arduino's Serial Monitor instead of to the OLED screen. In this case you control the cart reader by typing numbers into the serial monitor corresponding to the action you want to perform. If you are asked to press the button just send a random number.
|
||||
```
|
||||
// If you don't have an OLED screen change
|
||||
// enable_OLED to 0 and enable_Serial to 1
|
||||
#define enable_OLED 0
|
||||
#define enable_Serial 1
|
||||
```
|
||||
|
||||
To compile and upload the code please have a look at [this wiki article](https://github.com/sanni/cartreader/wiki/How-to-flash-the-Arduino-Code-to-your-Cart-Reader).
|
||||
|
File diff suppressed because it is too large
Load Diff
34
README.md
34
README.md
@ -1,25 +1,28 @@
|
||||
# Cartridge Reader for Arduino Mega2560
|
||||
# Cartridge Reader Shield for Arduino Mega 2560
|
||||
|
||||
![image](https://dl.dropboxusercontent.com/u/20912715/snes/Snes_Cart_Reader_Mega_Shield/v9/cartreaders.JPG)
|
||||
![image](https://dl.dropboxusercontent.com/s/o26c0yey8onuha2/v11_front_diagonal.jpg?dl=1)
|
||||
|
||||
####Features:
|
||||
#### Features:
|
||||
- Reads SNES roms and reads/writes save games from and to the SNES cartridge
|
||||
Supported cartridge types so far: LoRom, HiRom, ExHiRom, SuperFX, SuperFX2, SDD1, SA1(needs Adafruit Clock Generator)
|
||||
- Reads and writes SFC Nintendo Power Cartridges (also known as SF Memory, needs Adafruit Clock Generator for best result)
|
||||
- Reads and writes SFC Nintendo Power Flash Cartridges (also known as SF Memory, needs Adafruit Clock Generator for best result)
|
||||
- Reads N64 roms and reads/writes save games(4K/16K Eeprom + Sram + all 3 types of Flashram)
|
||||
- Reads and writes N64 controller paks and also can test a N64 controller's buttons and thumbstick
|
||||
- Reads Game Boy (Color) roms and reads/writes save games(only tested with MBC5)
|
||||
- Programs custom made Game Boy Color flashcarts
|
||||
- Reads Game Boy Advance roms and reads/writes save games(4K Eeprom, 64K Eeprom, Sram/Fram, SST39VF512 512K flash + MX29L010 1M flash)
|
||||
- Programs Flashroms like 29F016, 29F032, 29F033, 29F1610 and 29L3211(needs 3.3V)
|
||||
- Reflashes N64 Repros with Spansion S29GL256N or Intel 4400L0ZDQ0 flashroms
|
||||
- Reads Game Boy (Color) roms and reads/writes save games
|
||||
- Programs custom made Game Boy Color flashcarts with MX29F033 flashrom
|
||||
- Reads Game Boy Advance roms and reads/writes most of the save games(4K Eeprom, 64K Eeprom, Sram/Fram, SST39VF512 512K flash + MX29L010 1M flash)
|
||||
- Reflashes GBA Repros with Intel 4000L0YBQ0, Macronix MX29GL128E or Fujitsu MSP55LV128 flashroms
|
||||
- Reads Sega Mega Drive roms and reads/writes save games(Sram/Fram)
|
||||
- Programs Flashroms like 29F016, 29F032, 29F033, 29F1610 and 29L3211
|
||||
|
||||
![image](https://dl.dropboxusercontent.com/u/20912715/snes/Snes_Cart_Reader_Mega_Shield/v9/cartreader_bottom.JPG)
|
||||
![image](https://dl.dropboxusercontent.com/s/goc70t6cg9v7sfa/v11_switches.jpg?dl=1)
|
||||
|
||||
####Be sure to check the guides in the wiki too.
|
||||
#### Be sure to check the guides in the [Wiki](https://github.com/sanni/cartreader/wiki) too.
|
||||
|
||||
[![](https://dl.dropboxusercontent.com/u/20912715/snes/Snes_Cart_Reader_Mega_Shield/wiki/youtubevideo.jpg)](https://www.youtube.com/watch?v=1BviR53_6NQ)
|
||||
[![](https://dl.dropboxusercontent.com/s/950svg0i21syq3j/youtube_preview.jpg?dl=1)](https://www.youtube.com/watch?v=AD_o7J85bCg)
|
||||
|
||||
####Thanks to:
|
||||
#### Thanks to:
|
||||
MichlK - ROM-Reader for Super Nintendo
|
||||
Jeff Saltzman - 4-Way Button
|
||||
Wayne and Layne - Video-Game-Shield menu
|
||||
@ -39,7 +42,8 @@
|
||||
insidegadgets - GBCartRead
|
||||
RobinTheHood - GameboyAdvanceRomDumper
|
||||
YamaArashi - GBA flashrom bank switch command
|
||||
|
||||
![image](https://dl.dropboxusercontent.com/s/0be9rp9ss37vq2c/v11_rear.jpg?dl=1)
|
||||
|
||||
![image](https://dl.dropboxusercontent.com/u/20912715/snes/Snes_Cart_Reader_Mega_Shield/wiki/v82_components.jpg)
|
||||
|
||||
####Please join the discussion at: http://forum.arduino.cc/index.php?topic=158974.0
|
||||
#### Please join the discussion at: http://forum.arduino.cc/index.php?topic=158974.0
|
||||
And also feel free to send me a private message over the Arduino Forum in case you need help with ordering the parts or soldering or really anything else.
|
||||
|
Binary file not shown.
BIN
extras/byteswapper/Tool64_v1.11.zip
Normal file
BIN
extras/byteswapper/Tool64_v1.11.zip
Normal file
Binary file not shown.
@ -1,2 +1 @@
|
||||
A simple tool used to byteswap or wordswap N64 roms.
|
||||
Made by Skelux.
|
||||
Here are two tools that can byteswap a N64 rom for you.
|
||||
|
BIN
extras/byteswapper/ucon64-2.0.3-win32-vc-bin.zip
Normal file
BIN
extras/byteswapper/ucon64-2.0.3-win32-vc-bin.zip
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
pcb/3d_model.skp
BIN
pcb/3d_model.skp
Binary file not shown.
@ -1,41 +1,40 @@
|
||||
###Here you will find all the printed circuit boards needed to build the Arduino Cartridge Reader
|
||||
### Here you will find all the printed circuit boards needed to build the Arduino Cartridge Reader
|
||||
|
||||
####cartreader.zip is the main PCB, PCB thickness is 1.6mm and size is 10x10cm
|
||||
#### cartreader.zip is the main PCB, PCB thickness is 1.6mm and size is 10x10cm
|
||||
|
||||
![image](https://dl.dropboxusercontent.com/u/20912715/snes/Snes_Cart_Reader_Mega_Shield/wiki/cartreader.png)
|
||||
![image](https://dl.dropboxusercontent.com/s/b21houxm5bvdds1/cartreader.png?dl=01)
|
||||
|
||||
####adapter.zip are various adapter PCBs, PCB thickness is 1.2mm and size is 10x10cm
|
||||
#### gbaadapter.zip is an adapter for Game Boy and Game Boy Advance cartridges, PCB thickness is 1.2mm
|
||||
|
||||
![image](https://dl.dropboxusercontent.com/u/20912715/snes/Snes_Cart_Reader_Mega_Shield/wiki/adapter.png)
|
||||
![image](https://dl.dropboxusercontent.com/s/rnnnstkn3ynv10g/gbaadapter_pcb.png?dl=1)
|
||||
|
||||
Contains:
|
||||
- Game Boy (Color)/ Game Boy Advance cartridge adapter
|
||||
- small pcb for soldering a 29F032 flashrom into a Mission Impossible Game Boy Color cartridge
|
||||
- flash adapter for flashing 29F016, 29F032, 29F033, 29F1610 and 29L3211 flashroms
|
||||
- adapter for soldering a 29F032 into a SNES cartridge
|
||||
#### flash_adapter.zip is an adapter for 8bit and 16bit flashroms like the 29F032 or the 29L3211, PCB thickness is 1.2mm
|
||||
|
||||
####backplate.dxf are the acrylic pieces for laser cutting, the thickness is 4mm and size is 10x10cm, you need to tell the manufacturer that you need all the cut-outs too
|
||||
![image](https://dl.dropboxusercontent.com/s/3oovzhcgdt3a3x9/flashadapter.png?dl=1)
|
||||
|
||||
![image](https://dl.dropboxusercontent.com/u/20912715/snes/Snes_Cart_Reader_Mega_Shield/wiki/backplate.png)
|
||||
#### snes_spacer.stl is a small 3d printed spacer to relieve pressure from the pins of SNES clone console slot
|
||||
|
||||
Contains:
|
||||
- backplate
|
||||
- 2x SD card spacer
|
||||
- display protector
|
||||
![image](https://dl.dropboxusercontent.com/s/07slhy8pi9ujiri/snes_spacer.png?dl=1)
|
||||
|
||||
####snes_spacer.stl is a small 3d printed spacer to relieve pressure from the pins of SNES clone console slot
|
||||
#### n64sleeve.stl helps with aligning N64 cartridges if the clone slot is not long/wide enough
|
||||
|
||||
![image](https://dl.dropboxusercontent.com/u/20912715/snes/Snes_Cart_Reader_Mega_Shield/wiki/snes_spacer.png)
|
||||
![image](https://dl.dropboxusercontent.com/s/s6jxobazww3sm81/n64sleeve.png?dl=1)
|
||||
|
||||
####gbslot.stl is a 3d printed case for the Game Boy (Advance) adapter pcb
|
||||
#### gbaadapter.stl is a 3d printed case for the Game Boy (Advance) adapter pcb
|
||||
|
||||
![image](https://dl.dropboxusercontent.com/u/20912715/snes/Snes_Cart_Reader_Mega_Shield/wiki/gbslot.png)
|
||||
![image](https://dl.dropboxusercontent.com/s/ainwnoclzzq24ez/gbaadapter.png?dl=1)
|
||||
|
||||
####backplate_3dprint.stl is an alternative backplate for 3d printing
|
||||
#### backplate.stl is the backplate that holds the Arduino
|
||||
|
||||
![image](https://dl.dropboxusercontent.com/u/20912715/snes/Snes_Cart_Reader_Mega_Shield/wiki/backplate_3dprint.png)
|
||||
![image](https://dl.dropboxusercontent.com/s/0qixf0n33emi1ed/backplate.png?dl=1)
|
||||
|
||||
####For the needed parts list see here: https://github.com/sanni/cartreader/wiki/PCB-Needed-Parts
|
||||
####How to order a PCB: https://github.com/sanni/cartreader/wiki/PCB-How-to-order-printed-circuit-boards
|
||||
#### sd_spacer.stl holds the RGB led and fits between the SD card and the Cart Reader pcb
|
||||
|
||||
###Attention: While I have tested all the parts I can not guarantee flawless operation, so use at own risk and always check the boards for short circuits
|
||||
![image](https://dl.dropboxusercontent.com/s/fn6g1pm88puq8h6/sd_spacer.png?dl=1)
|
||||
|
||||
#### sidewall.stl secures the Arduino Mega to the backplate with three M2x10 screws
|
||||
|
||||
![image](https://dl.dropboxusercontent.com/s/3wqdbc4p9au7dqw/sidewall.png?dl=1)
|
||||
|
||||
#### For the needed parts list see here: https://github.com/sanni/cartreader/wiki/Needed-Parts
|
||||
#### How to order a PCB: https://github.com/sanni/cartreader/wiki/How-to-order-printed-circuit-boards
|
||||
|
BIN
pcb/adapter.zip
BIN
pcb/adapter.zip
Binary file not shown.
4586
pcb/backplate.dxf
4586
pcb/backplate.dxf
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Binary file not shown.
BIN
pcb/flash_adapter.zip
Normal file
BIN
pcb/flash_adapter.zip
Normal file
Binary file not shown.
11958
pcb/gbaadapter.stl
Normal file
11958
pcb/gbaadapter.stl
Normal file
File diff suppressed because it is too large
Load Diff
BIN
pcb/gbaadapter.zip
Normal file
BIN
pcb/gbaadapter.zip
Normal file
Binary file not shown.
15262
pcb/gbslot.stl
15262
pcb/gbslot.stl
File diff suppressed because it is too large
Load Diff
226
pcb/n64sleeve.stl
Normal file
226
pcb/n64sleeve.stl
Normal file
@ -0,0 +1,226 @@
|
||||
solid n64slotsleeve
|
||||
facet normal 0.0 -1.0 0.0
|
||||
outer loop
|
||||
vertex 70.5 -0.30000000000000004 15.0
|
||||
vertex -0.5 -0.30000000000000004 0.0
|
||||
vertex 70.5 -0.30000000000000004 0.0
|
||||
endloop
|
||||
endfacet
|
||||
facet normal 0.0 -1.0 0.0
|
||||
outer loop
|
||||
vertex -0.5 -0.30000000000000004 0.0
|
||||
vertex 70.5 -0.30000000000000004 15.0
|
||||
vertex -0.5 -0.30000000000000004 15.0
|
||||
endloop
|
||||
endfacet
|
||||
facet normal 0.0 0.0 -1.0
|
||||
outer loop
|
||||
vertex -0.5 10.299999999999999 0.0
|
||||
vertex 0.0 9.8 0.0
|
||||
vertex -0.5 -0.30000000000000004 0.0
|
||||
endloop
|
||||
endfacet
|
||||
facet normal 0.0 0.0 -1.0
|
||||
outer loop
|
||||
vertex 0.0 9.8 0.0
|
||||
vertex -0.5 10.299999999999999 0.0
|
||||
vertex 70.5 10.299999999999999 0.0
|
||||
endloop
|
||||
endfacet
|
||||
facet normal 0.0 0.0 -1.0
|
||||
outer loop
|
||||
vertex 0.0 9.8 0.0
|
||||
vertex 70.5 10.299999999999999 0.0
|
||||
vertex 70.0 9.8 0.0
|
||||
endloop
|
||||
endfacet
|
||||
facet normal 0.0 0.0 -1.0
|
||||
outer loop
|
||||
vertex 70.0 9.8 0.0
|
||||
vertex 70.5 10.299999999999999 0.0
|
||||
vertex 70.0 0.20000000000000004 0.0
|
||||
endloop
|
||||
endfacet
|
||||
facet normal 0.0 0.0 -1.0
|
||||
outer loop
|
||||
vertex -0.5 -0.30000000000000004 0.0
|
||||
vertex 0.0 0.20000000000000004 0.0
|
||||
vertex 70.5 -0.30000000000000004 0.0
|
||||
endloop
|
||||
endfacet
|
||||
facet normal 0.0 0.0 -1.0
|
||||
outer loop
|
||||
vertex 0.0 0.20000000000000004 0.0
|
||||
vertex -0.5 -0.30000000000000004 0.0
|
||||
vertex 0.0 9.8 0.0
|
||||
endloop
|
||||
endfacet
|
||||
facet normal 0.0 0.0 -1.0
|
||||
outer loop
|
||||
vertex 70.5 -0.30000000000000004 0.0
|
||||
vertex 0.0 0.20000000000000004 0.0
|
||||
vertex 70.0 0.20000000000000004 0.0
|
||||
endloop
|
||||
endfacet
|
||||
facet normal 0.0 0.0 -1.0
|
||||
outer loop
|
||||
vertex 70.5 -0.30000000000000004 0.0
|
||||
vertex 70.0 0.20000000000000004 0.0
|
||||
vertex 70.5 10.299999999999999 0.0
|
||||
endloop
|
||||
endfacet
|
||||
facet normal 0.0 1.0 0.0
|
||||
outer loop
|
||||
vertex -0.5 10.299999999999999 15.0
|
||||
vertex 70.5 10.299999999999999 0.0
|
||||
vertex -0.5 10.299999999999999 0.0
|
||||
endloop
|
||||
endfacet
|
||||
facet normal 0.0 1.0 0.0
|
||||
outer loop
|
||||
vertex 70.5 10.299999999999999 0.0
|
||||
vertex -0.5 10.299999999999999 15.0
|
||||
vertex 70.5 10.299999999999999 15.0
|
||||
endloop
|
||||
endfacet
|
||||
facet normal -0.0 -0.0 1.0
|
||||
outer loop
|
||||
vertex -0.5 -0.30000000000000004 15.0
|
||||
vertex 0.0 0.20000000000000004 15.0
|
||||
vertex -0.5 10.299999999999999 15.0
|
||||
endloop
|
||||
endfacet
|
||||
facet normal -0.0 -0.0 1.0
|
||||
outer loop
|
||||
vertex 0.0 0.20000000000000004 15.0
|
||||
vertex -0.5 -0.30000000000000004 15.0
|
||||
vertex 70.5 -0.30000000000000004 15.0
|
||||
endloop
|
||||
endfacet
|
||||
facet normal -0.0 -0.0 1.0
|
||||
outer loop
|
||||
vertex 0.0 0.20000000000000004 15.0
|
||||
vertex 70.5 -0.30000000000000004 15.0
|
||||
vertex 70.0 0.20000000000000004 15.0
|
||||
endloop
|
||||
endfacet
|
||||
facet normal -0.0 -0.0 1.0
|
||||
outer loop
|
||||
vertex 70.0 0.20000000000000004 15.0
|
||||
vertex 70.5 -0.30000000000000004 15.0
|
||||
vertex 70.0 9.8 15.0
|
||||
endloop
|
||||
endfacet
|
||||
facet normal -0.0 -0.0 1.0
|
||||
outer loop
|
||||
vertex -0.5 10.299999999999999 15.0
|
||||
vertex 0.0 9.8 15.0
|
||||
vertex 70.5 10.299999999999999 15.0
|
||||
endloop
|
||||
endfacet
|
||||
facet normal -0.0 -0.0 1.0
|
||||
outer loop
|
||||
vertex 0.0 9.8 15.0
|
||||
vertex -0.5 10.299999999999999 15.0
|
||||
vertex 0.0 0.20000000000000004 15.0
|
||||
endloop
|
||||
endfacet
|
||||
facet normal -0.0 -0.0 1.0
|
||||
outer loop
|
||||
vertex 70.5 10.299999999999999 15.0
|
||||
vertex 0.0 9.8 15.0
|
||||
vertex 70.0 9.8 15.0
|
||||
endloop
|
||||
endfacet
|
||||
facet normal -0.0 -0.0 1.0
|
||||
outer loop
|
||||
vertex 70.5 10.299999999999999 15.0
|
||||
vertex 70.0 9.8 15.0
|
||||
vertex 70.5 -0.30000000000000004 15.0
|
||||
endloop
|
||||
endfacet
|
||||
facet normal 1.0 0.0 0.0
|
||||
outer loop
|
||||
vertex 70.5 10.299999999999999 0.0
|
||||
vertex 70.5 -0.30000000000000004 15.0
|
||||
vertex 70.5 -0.30000000000000004 0.0
|
||||
endloop
|
||||
endfacet
|
||||
facet normal 1.0 0.0 0.0
|
||||
outer loop
|
||||
vertex 70.5 -0.30000000000000004 15.0
|
||||
vertex 70.5 10.299999999999999 0.0
|
||||
vertex 70.5 10.299999999999999 15.0
|
||||
endloop
|
||||
endfacet
|
||||
facet normal -1.0 0.0 0.0
|
||||
outer loop
|
||||
vertex -0.5 10.299999999999999 15.0
|
||||
vertex -0.5 -0.30000000000000004 0.0
|
||||
vertex -0.5 -0.30000000000000004 15.0
|
||||
endloop
|
||||
endfacet
|
||||
facet normal -1.0 0.0 0.0
|
||||
outer loop
|
||||
vertex -0.5 -0.30000000000000004 0.0
|
||||
vertex -0.5 10.299999999999999 15.0
|
||||
vertex -0.5 10.299999999999999 0.0
|
||||
endloop
|
||||
endfacet
|
||||
facet normal 0.0 -1.0 0.0
|
||||
outer loop
|
||||
vertex 70.0 9.8 15.0
|
||||
vertex 0.0 9.8 0.0
|
||||
vertex 70.0 9.8 0.0
|
||||
endloop
|
||||
endfacet
|
||||
facet normal 0.0 -1.0 0.0
|
||||
outer loop
|
||||
vertex 0.0 9.8 0.0
|
||||
vertex 70.0 9.8 15.0
|
||||
vertex 0.0 9.8 15.0
|
||||
endloop
|
||||
endfacet
|
||||
facet normal 1.0 -0.0 -0.0
|
||||
outer loop
|
||||
vertex 0.0 9.8 0.0
|
||||
vertex 0.0 0.20000000000000004 15.0
|
||||
vertex 0.0 0.20000000000000004 0.0
|
||||
endloop
|
||||
endfacet
|
||||
facet normal 1.0 -0.0 -0.0
|
||||
outer loop
|
||||
vertex 0.0 0.20000000000000004 15.0
|
||||
vertex 0.0 9.8 0.0
|
||||
vertex 0.0 9.8 15.0
|
||||
endloop
|
||||
endfacet
|
||||
facet normal -1.0 0.0 0.0
|
||||
outer loop
|
||||
vertex 70.0 9.8 15.0
|
||||
vertex 70.0 0.20000000000000004 0.0
|
||||
vertex 70.0 0.20000000000000004 15.0
|
||||
endloop
|
||||
endfacet
|
||||
facet normal -1.0 0.0 0.0
|
||||
outer loop
|
||||
vertex 70.0 0.20000000000000004 0.0
|
||||
vertex 70.0 9.8 15.0
|
||||
vertex 70.0 9.8 0.0
|
||||
endloop
|
||||
endfacet
|
||||
facet normal 0.0 1.0 0.0
|
||||
outer loop
|
||||
vertex 0.0 0.20000000000000004 15.0
|
||||
vertex 70.0 0.20000000000000004 0.0
|
||||
vertex 0.0 0.20000000000000004 0.0
|
||||
endloop
|
||||
endfacet
|
||||
facet normal 0.0 1.0 0.0
|
||||
outer loop
|
||||
vertex 70.0 0.20000000000000004 0.0
|
||||
vertex 0.0 0.20000000000000004 15.0
|
||||
vertex 70.0 0.20000000000000004 15.0
|
||||
endloop
|
||||
endfacet
|
||||
endsolid n64slotsleeve
|
1892
pcb/sd_spacer.stl
Normal file
1892
pcb/sd_spacer.stl
Normal file
File diff suppressed because it is too large
Load Diff
16165
pcb/sidewall.stl
Normal file
16165
pcb/sidewall.stl
Normal file
File diff suppressed because it is too large
Load Diff
BIN
pinout.xls
BIN
pinout.xls
Binary file not shown.
12
sd/README.md
12
sd/README.md
@ -1,6 +1,6 @@
|
||||
####Copy these files to the root of your SD card.
|
||||
#### Copy these files to the root of your SD card.
|
||||
|
||||
####gba.txt
|
||||
#### gba.txt
|
||||
This file stores the GBA database which is needed because the save type and rom size are not stored inside the rom.
|
||||
|
||||
Example:
|
||||
@ -16,7 +16,7 @@ Savetypes:
|
||||
5 = 1024K Flash
|
||||
6 = 512K Sram
|
||||
|
||||
####n64.txt
|
||||
#### n64.txt
|
||||
This file stores the N64 database which is needed because the save type and rom size are not stored inside the rom.
|
||||
The CRC32 checksum is used to verify a good dump.
|
||||
|
||||
@ -31,14 +31,14 @@ Savetypes:
|
||||
5 = 4K Eeprom
|
||||
6 = 16K Eeprom
|
||||
|
||||
####snes.txt
|
||||
#### snes.txt
|
||||
This file is needed for odd sized SNES games like Final Fantasy (JAP), Super Metroid(US/JAP) or Tales of Symphonia. Without this file you will get overdumps and the checksum calculation will fail. There are still a lot games missing from this list.
|
||||
|
||||
Example:
|
||||
A172,24,48
|
||||
checksum, size in Mbit, number of banks (lorom needs twice as many banks as hirom for the same rom size)
|
||||
|
||||
####hirom64.map
|
||||
#### hirom64.map
|
||||
This is a Nintendo Power mapping file that changes the mapping to a single 4MB HiRom game with 64Kbit/8KByte save. The first byte is used to specify the mapping.
|
||||
|
||||
Bit0-1 SRAM Size (0=2K, 1=8K, 2=32K, 3=None) ;ie. 2K SHL (N*2)
|
||||
@ -54,7 +54,7 @@ Example:
|
||||
111 -> 4M
|
||||
01 -> 8K
|
||||
|
||||
####lorom256.map
|
||||
#### lorom256.map
|
||||
This is a Nintendo Power mapping file that changes the mapping to a single 4MB LoRom game with 256Kbit/32 KByte save.
|
||||
|
||||
Example:
|
||||
|
@ -159,12 +159,12 @@ a9417994,NDAJ,32,1
|
||||
b1e87639,NDYP,12,5
|
||||
eb759206,NDYE,12,5
|
||||
5acca298,NDYE,12,5
|
||||
7fdec270,NDQE,20,5
|
||||
7fdec270,NDQE,20,0
|
||||
7737ed9e,NTAP,16,0
|
||||
99c7649d,NTAF,16,0
|
||||
0b0954c5,NTAD,16,0
|
||||
c38ca641,NTAE,16,0
|
||||
c4b0d9ea,NDQP,20,5
|
||||
c4b0d9ea,NDQP,20,0
|
||||
a28c71c6,NDOP,32,6
|
||||
919f7e74,NDOJ,32,6
|
||||
c83dfa15,NDPE,32,6
|
||||
|
Loading…
Reference in New Issue
Block a user