mirror of
https://github.com/sanni/cartreader.git
synced 2024-12-24 03:51:54 +01:00
Add Virtual Boy and Watara Supervision (thx to skaman)
This commit is contained in:
parent
dc867db7ed
commit
3b7d6bd4fc
@ -4,8 +4,8 @@
|
||||
This project represents a community-driven effort to provide
|
||||
an easy to build and easy to modify cartridge dumper.
|
||||
|
||||
Date: 19.08.2022
|
||||
Version: 9.5
|
||||
Date: 21.08.2022
|
||||
Version: 9.6
|
||||
|
||||
SD lib: https://github.com/greiman/SdFat
|
||||
OLED lib: https://github.com/adafruit/Adafruit_SSD1306
|
||||
@ -25,7 +25,7 @@
|
||||
MichlK - ROM Reader for Super Nintendo
|
||||
Jeff Saltzman - 4-Way Button
|
||||
Wayne and Layne - Video Game Shield menu
|
||||
skaman - Cart ROM READER SNES ENHANCED, Famicom Cart Dumper, Coleco- and Intellivision modules
|
||||
skaman - Cart ROM READER SNES ENHANCED, Famicom Cart Dumper, Coleco-, Intellivision, Virtual Boy, WSV modules
|
||||
Tamanegi_taro - PCE and Satellaview modules
|
||||
splash5 - GBSmart, Wonderswan and NGP modules
|
||||
hkz & themanbehindthecurtain - N64 flashram commands
|
||||
@ -60,7 +60,7 @@
|
||||
|
||||
**********************************************************************************/
|
||||
|
||||
char ver[5] = "9.5";
|
||||
char ver[5] = "9.6";
|
||||
|
||||
//******************************************
|
||||
// !!! CHOOSE HARDWARE VERSION !!!
|
||||
@ -97,6 +97,7 @@ char ver[5] = "9.5";
|
||||
// #define enable_INTV
|
||||
// #define enable_COLV
|
||||
// #define enable_VBOY
|
||||
// #define enable_WSV
|
||||
|
||||
//******************************************
|
||||
// HW CONFIGS
|
||||
@ -305,6 +306,7 @@ bool i2c_found;
|
||||
#define mode_INTV 23
|
||||
#define mode_COL 24
|
||||
#define mode_VBOY 25
|
||||
#define mode_WSV 26
|
||||
|
||||
// optimization-safe nop delay
|
||||
#define NOP __asm__ __volatile__ ("nop\n\t")
|
||||
@ -683,7 +685,8 @@ boolean compareCRC(char* database, char* crcString, boolean renamerom, int offse
|
||||
}
|
||||
}
|
||||
else {
|
||||
println_Msg(F(" -> database file not found"));
|
||||
println_Msg(F(" -> Error"));
|
||||
println_Msg(F("Database missing"));
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
@ -807,19 +810,20 @@ static const char modeItem9[] PROGMEM = "NeoGeo Pocket";
|
||||
static const char modeItem10[] PROGMEM = "Intellvision";
|
||||
static const char modeItem11[] PROGMEM = "Colecovision";
|
||||
static const char modeItem12[] PROGMEM = "Virtual Boy";
|
||||
static const char modeItem13[] PROGMEM = "Flashrom Programmer";
|
||||
static const char modeItem14[] PROGMEM = "About";
|
||||
static const char* const modeOptions[] PROGMEM = {modeItem1, modeItem2, modeItem3, modeItem4, modeItem5, modeItem6, modeItem7, modeItem8, modeItem9, modeItem10, modeItem11, modeItem12, modeItem13, modeItem14};
|
||||
static const char modeItem13[] PROGMEM = "Watara Supervision";
|
||||
static const char modeItem14[] PROGMEM = "Flashrom Programmer";
|
||||
static const char modeItem15[] PROGMEM = "About";
|
||||
static const char* const modeOptions[] PROGMEM = {modeItem1, modeItem2, modeItem3, modeItem4, modeItem5, modeItem6, modeItem7, modeItem8, modeItem9, modeItem10, modeItem11, modeItem12, modeItem13, modeItem14, modeItem15};
|
||||
|
||||
// All included slots
|
||||
void mainMenu() {
|
||||
// create menu with title and 13 options to choose from
|
||||
// create menu with title and 15 options to choose from
|
||||
unsigned char modeMenu;
|
||||
|
||||
// Main menu spans across two pages
|
||||
currPage = 1;
|
||||
lastPage = 1;
|
||||
numPages = 2;
|
||||
numPages = 3;
|
||||
|
||||
while (1) {
|
||||
if (currPage == 1) {
|
||||
@ -832,6 +836,11 @@ void mainMenu() {
|
||||
convertPgm(modeOptions, 7, 7);
|
||||
modeMenu = question_box(F("OPEN SOURCE CART READER"), menuOptions, 7, 0);
|
||||
}
|
||||
if (currPage == 3) {
|
||||
// Copy menuOptions out of progmem
|
||||
convertPgm(modeOptions, 14, 1);
|
||||
modeMenu = question_box(F("OPEN SOURCE CART READER"), menuOptions, 1, 0);
|
||||
}
|
||||
if (numPages == 0) {
|
||||
// Execute choice
|
||||
modeMenu = (currPage - 1) * 7 + modeMenu;
|
||||
@ -941,8 +950,15 @@ void mainMenu() {
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef enable_FLASH
|
||||
#ifdef enable_WSV
|
||||
case 12:
|
||||
setup_WSV();
|
||||
wsvMenu();
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef enable_FLASH
|
||||
case 13:
|
||||
#ifdef enable_FLASH16
|
||||
flashMenu();
|
||||
#else
|
||||
@ -951,7 +967,7 @@ void mainMenu() {
|
||||
break;
|
||||
#endif
|
||||
|
||||
case 13:
|
||||
case 14:
|
||||
aboutScreen();
|
||||
break;
|
||||
|
||||
@ -997,8 +1013,9 @@ static const char* const consolesOptions[] PROGMEM = {consolesItem1, consolesIte
|
||||
static const char handheldsItem1[] PROGMEM = "Virtual Boy";
|
||||
static const char handheldsItem2[] PROGMEM = "WonderSwan";
|
||||
static const char handheldsItem3[] PROGMEM = "NeoGeo Pocket";
|
||||
static const char handheldsItem4[] PROGMEM = "Reset";
|
||||
static const char* const handheldsOptions[] PROGMEM = {handheldsItem1, handheldsItem2, handheldsItem3, handheldsItem4};
|
||||
static const char handheldsItem4[] PROGMEM = "Watara Supervision";
|
||||
static const char handheldsItem5[] PROGMEM = "Reset";
|
||||
static const char* const handheldsOptions[] PROGMEM = {handheldsItem1, handheldsItem2, handheldsItem3, handheldsItem4, handheldsItem5};
|
||||
|
||||
// All included slots
|
||||
void mainMenu() {
|
||||
@ -1160,21 +1177,19 @@ void consoleMenu() {
|
||||
|
||||
// Everything that needs an adapter
|
||||
void handheldMenu() {
|
||||
// create menu with title and 4 options to choose from
|
||||
// create menu with title and 5 options to choose from
|
||||
unsigned char handheldsMenu;
|
||||
// Copy menuOptions out of progmem
|
||||
convertPgm(handheldsOptions, 4);
|
||||
handheldsMenu = question_box(F("Choose Adapter"), menuOptions, 4, 0);
|
||||
convertPgm(handheldsOptions, 5);
|
||||
handheldsMenu = question_box(F("Choose Adapter"), menuOptions, 5, 0);
|
||||
|
||||
// wait for user choice to come back from the question box menu
|
||||
switch (handheldsMenu)
|
||||
{
|
||||
#ifdef enable_VBOY
|
||||
case 0:
|
||||
mode = mode_VBOY;
|
||||
display_Clear();
|
||||
display_Update();
|
||||
setup_VBOY();
|
||||
vboyMenu();
|
||||
break;
|
||||
#endif
|
||||
|
||||
@ -1196,7 +1211,14 @@ void handheldMenu() {
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef enable_WSV
|
||||
case 3:
|
||||
setup_WSV();
|
||||
wsvMenu();
|
||||
break;
|
||||
#endif
|
||||
|
||||
case 4:
|
||||
resetArduino();
|
||||
break;
|
||||
|
||||
@ -3372,6 +3394,11 @@ void loop() {
|
||||
else if (mode == mode_VBOY) {
|
||||
vboyMenu();
|
||||
}
|
||||
#endif
|
||||
#ifdef enable_WSV
|
||||
else if (mode == mode_WSV) {
|
||||
wsvMenu();
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
display_Clear();
|
||||
|
534
Cart_Reader/VBOY.ino
Normal file
534
Cart_Reader/VBOY.ino
Normal file
@ -0,0 +1,534 @@
|
||||
//******************************************
|
||||
// VIRTUALBOY MODULE
|
||||
//******************************************
|
||||
#ifdef enable_VBOY
|
||||
// Nintendo VirtualBoy
|
||||
// Cartridge Pinout
|
||||
// 60P 2.00mm pitch connector
|
||||
//
|
||||
// TOP SIDE BOTTOM SIDE
|
||||
// +-------+
|
||||
// GND -| 1 2 |- GND
|
||||
// /WE0 (SRAM WRITE ENABLE) -| 3 4 |- nc
|
||||
// nc -| 5 6 |- /CS1 (SRAM ENABLE)
|
||||
// CS2 (SRAM) -| 7 8 |- VCC(+5V)
|
||||
// nc -| 9 10 |- A23
|
||||
// A19 -| 11 12 |- A22
|
||||
// A18 -| 13 14 |- A21
|
||||
// A8 -| 15 16 |- A20
|
||||
// A7 -| 17 18 |- A9
|
||||
// A6 -| 19 20 |- A10
|
||||
// A5 -| 21 22 |- A11
|
||||
// A4 -| 23 24 |- A12
|
||||
// A3 -| 25 26 |- A13
|
||||
// A2 -| 27 28 |- A14
|
||||
// A1 -| 29 30 |- A15
|
||||
// /CE (ROM) -| 31 32 |- A16
|
||||
// GND -| 33 34 |- A17
|
||||
// /OE -| 35 36 |- VCC(+5V)
|
||||
// D8 -| 37 38 |- D7
|
||||
// D0 -| 39 40 |- D15
|
||||
// D9 -| 41 42 |- D6
|
||||
// D1 -| 43 44 |- D14
|
||||
// D10 -| 45 46 |- D5
|
||||
// D2 -| 47 48 |- D13
|
||||
// D11 -| 49 50 |- D4
|
||||
// D3 -| 51 52 |- D12
|
||||
// VCC(+5V) -| 53 54 |- VCC(+5V)
|
||||
// nc -| 55 56 |- nc
|
||||
// nc -| 57 58 |- nc
|
||||
// GND -| 59 60 |- GND
|
||||
// +-------+
|
||||
//
|
||||
|
||||
// CONTROL PINS:
|
||||
// CS2(SRAM) - (PH0) - VBOY PIN 7 - SNES RST
|
||||
// /CE(ROM) - (PH3) - VBOY PIN 31 - SNES /CS
|
||||
// /CS1(SRAM ENABLE) - (PH4) - VBOY PIN 6 - SNES /IRQ
|
||||
// /WE0(SRAM WRITE ENABLE) - (PH5) - VBOY PIN 3 - SNES /WR
|
||||
// /OE - (PH6) - VBOY PIN 35 - SNES /RD
|
||||
|
||||
// NOT CONNECTED:
|
||||
// CLK(PH1) - N/C
|
||||
|
||||
//******************************************
|
||||
// SETUP
|
||||
//******************************************
|
||||
|
||||
void setup_VBOY()
|
||||
{
|
||||
// Set Address Pins to Output
|
||||
//A0-A7
|
||||
DDRF = 0xFF;
|
||||
//A8-A15
|
||||
DDRK = 0xFF;
|
||||
//A16-A23
|
||||
DDRL = 0xFF;
|
||||
|
||||
// Set Control Pins to Output
|
||||
// CS2(PH0) ---(PH1) /CE(PH3) /CS1(PH4) /WE0(PH5) /OE(PH6)
|
||||
DDRH |= (1 << 0) | (1 << 1) | (1 << 3) | (1 << 4) | (1 << 5) | (1 << 6);
|
||||
|
||||
// Set TIME(PJ0) to Output (UNUSED)
|
||||
DDRJ |= (1 << 0);
|
||||
|
||||
// Set Pins (D0-D15) to Input
|
||||
DDRC = 0x00;
|
||||
DDRA = 0x00;
|
||||
|
||||
// Setting Control Pins to HIGH
|
||||
// ---(PH1) /CE(PH3) /CS1(PH4) /WE0(PH5) /OE(PH6)
|
||||
PORTH |= (1 << 1) | (1 << 3) | (1 << 4) | (1 << 5) | (1 << 6);
|
||||
// Set CS2(PH0) to LOW
|
||||
PORTH &= ~(1 << 0);
|
||||
|
||||
// Set Unused Pins HIGH
|
||||
PORTJ |= (1 << 0); // TIME(PJ0)
|
||||
|
||||
getCartInfo_VB();
|
||||
|
||||
mode = mode_VBOY;
|
||||
}
|
||||
|
||||
//******************************************
|
||||
// MENU
|
||||
//******************************************
|
||||
|
||||
// Base Menu
|
||||
static const char vboyMenuItem1[] PROGMEM = "Read ROM";
|
||||
static const char vboyMenuItem2[] PROGMEM = "Read SRAM";
|
||||
static const char vboyMenuItem3[] PROGMEM = "Write SRAM";
|
||||
static const char vboyMenuItem4[] PROGMEM = "Reset";
|
||||
static const char* const menuOptionsVBOY[] PROGMEM = {vboyMenuItem1, vboyMenuItem2, vboyMenuItem3, vboyMenuItem4};
|
||||
|
||||
void vboyMenu()
|
||||
{
|
||||
convertPgm(menuOptionsVBOY, 4);
|
||||
uint8_t mainMenu = question_box(F("VIRTUALBOY MENU"), menuOptions, 4, 0);
|
||||
|
||||
switch (mainMenu)
|
||||
{
|
||||
case 0:
|
||||
// Read ROM
|
||||
sd.chdir("/");
|
||||
readROM_VB();
|
||||
sd.chdir("/");
|
||||
break;
|
||||
|
||||
case 1:
|
||||
// Read SRAM
|
||||
if (sramSize) {
|
||||
sd.chdir("/");
|
||||
display_Clear();
|
||||
println_Msg(F("Reading SRAM..."));
|
||||
display_Update();
|
||||
readSRAM_VB();
|
||||
sd.chdir("/");
|
||||
}
|
||||
else {
|
||||
print_Error(F("Cart has no SRAM"), false);
|
||||
}
|
||||
#if (defined(enable_OLED) || defined(enable_LCD))
|
||||
// Wait for user input
|
||||
println_Msg(F("Press Button..."));
|
||||
display_Update();
|
||||
wait();
|
||||
#endif
|
||||
break;
|
||||
|
||||
case 2:
|
||||
// Write SRAM
|
||||
if (sramSize) {
|
||||
// Change working dir to root
|
||||
sd.chdir("/");
|
||||
fileBrowser(F("Select SRM file"));
|
||||
display_Clear();
|
||||
writeSRAM_VB();
|
||||
writeErrors = verifySRAM_VB();
|
||||
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);
|
||||
}
|
||||
#if (defined(enable_OLED) || defined(enable_LCD))
|
||||
// Wait for user input
|
||||
println_Msg(F("Press Button..."));
|
||||
display_Update();
|
||||
wait();
|
||||
#endif
|
||||
break;
|
||||
|
||||
case 3:
|
||||
// reset
|
||||
resetArduino();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//******************************************
|
||||
// LOW LEVEL FUNCTIONS
|
||||
//******************************************
|
||||
|
||||
void writeByte_VB(unsigned long myAddress, byte myData) {
|
||||
PORTF = myAddress & 0xFF;
|
||||
PORTK = (myAddress >> 8) & 0xFF;
|
||||
PORTL = (myAddress >> 16) & 0xFF;
|
||||
|
||||
__asm__("nop\n\t");
|
||||
|
||||
PORTA = myData;
|
||||
|
||||
// Set CS2(PH0), /CE(PH3), /OE(PH6) to HIGH
|
||||
PORTH |= (1 << 0) | (1 << 3) | (1 << 6);
|
||||
// Set /CS1(PH4), /WE0(PH5) to LOW
|
||||
PORTH &= ~(1 << 4) & ~(1 << 5);
|
||||
|
||||
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");
|
||||
|
||||
// Set CS2(PH0), /CS1(PH4), /WE0(PH5) to HIGH
|
||||
PORTH |= (1 << 0) | (1 << 4) | (1 << 5);
|
||||
|
||||
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");
|
||||
}
|
||||
|
||||
word readWord_VB(unsigned long myAddress) {
|
||||
PORTF = myAddress & 0xFF;
|
||||
PORTK = (myAddress >> 8) & 0xFF;
|
||||
PORTL = (myAddress >> 16) & 0xFF;
|
||||
|
||||
__asm__("nop\n\t");
|
||||
|
||||
// Set CS2(PH0), /CS1(PH4), /WE0(PH5) to HIGH
|
||||
PORTH |= (1 << 0) | (1 << 4) | (1 << 5);
|
||||
// Set /CE(PH3), /OE(PH6) to LOW
|
||||
PORTH &= ~(1 << 3) & ~(1 << 6);
|
||||
|
||||
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");
|
||||
|
||||
word tempWord = ( ( PINA & 0xFF ) << 8 ) | ( PINC & 0xFF );
|
||||
|
||||
// Set /CE(PH3), /OE(PH6) to HIGH
|
||||
PORTH |= (1 << 3) | (1 << 6);
|
||||
// Setting CS2(PH0) LOW
|
||||
PORTH &= ~(1 << 0);
|
||||
|
||||
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");
|
||||
|
||||
return tempWord;
|
||||
}
|
||||
|
||||
byte readByte_VB(unsigned long myAddress) { // SRAM BYTE
|
||||
PORTF = myAddress & 0xFF;
|
||||
PORTK = (myAddress >> 8) & 0xFF;
|
||||
PORTL = (myAddress >> 16) & 0xFF;
|
||||
|
||||
__asm__("nop\n\t");
|
||||
|
||||
// Set CS2(PH0), /CE(PH3), /WE0(PH5) to HIGH
|
||||
PORTH |= (1 << 0) | (1 << 3) | (1 << 5);
|
||||
// Set /CS1(PH4), /OE(PH6) to LOW
|
||||
PORTH &= ~(1 << 4) & ~(1 << 6);
|
||||
|
||||
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");
|
||||
|
||||
byte tempByte = PINA;
|
||||
|
||||
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");
|
||||
|
||||
// Set /CS1(PH4), /OE(PH6) to HIGH
|
||||
PORTH |= (1 << 3) | (1 << 6);
|
||||
// Setting CS2(PH0) LOW
|
||||
PORTH &= ~(1 << 0);
|
||||
|
||||
__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_VB() {
|
||||
DDRC = 0xFF;
|
||||
DDRA = 0xFF;
|
||||
}
|
||||
|
||||
// Switch data pins to read
|
||||
void dataIn_VB() {
|
||||
DDRC = 0x00;
|
||||
DDRA = 0x00;
|
||||
}
|
||||
|
||||
//******************************************
|
||||
// CART INFO
|
||||
//******************************************
|
||||
|
||||
void getCartInfo_VB() {
|
||||
// Set control
|
||||
dataIn_VB();
|
||||
|
||||
cartSize = 0;
|
||||
for (unsigned long address = 0x80000; address <= 0x400000; address *= 2) {
|
||||
// Get Serial
|
||||
word vbSerial = readWord_VB((address - 0x204) / 2); // Cart Serial
|
||||
|
||||
switch (vbSerial)
|
||||
{
|
||||
case 0x4D54: // MT = Mario's Tennis
|
||||
case 0x4832: // H2 = Panic Bomber/Tobidase! Panibomb
|
||||
case 0x5350: // SP = Space Invaders
|
||||
case 0x5353: // SS = Space Squash
|
||||
case 0x5452: // TR = V-Tetris
|
||||
cartSize = 0x80000; // 512KB
|
||||
break;
|
||||
|
||||
case 0x494D: // IM = Insmouse no Yakata
|
||||
case 0x4A42: // JB = Jack Bros.
|
||||
case 0x4D43: // MC = Mario Clash
|
||||
case 0x5245: // RE = Red Alarm
|
||||
case 0x4833: // H3 = Vertical Force
|
||||
case 0x5642: // VB = Virtual Bowling
|
||||
case 0x5646: // VF = Virtual Fishing
|
||||
case 0x4A56: // JV = Virtual Lab
|
||||
case 0x5650: // VP = Virtual League Baseball/Virtual Pro Yakyuu '95
|
||||
cartSize = 0x100000; // 1MB
|
||||
break;
|
||||
|
||||
case 0x5042: // PB = 3-D Tetris
|
||||
case 0x4750: // GP = Galactic Pinball
|
||||
case 0x5344: // SD = SD Gundam Dimension War
|
||||
case 0x5442: // TB = Teleroboxer
|
||||
cartSize = 0x100000; // 1MB
|
||||
sramSize = 0x2000; // 8KB
|
||||
break;
|
||||
|
||||
case 0x5647: // VG = Golf/T&E Virtual Golf
|
||||
case 0x4E46: // NF = Nester's Funky Bowling
|
||||
case 0x5745: // WE = Waterworld
|
||||
cartSize = 0x200000; // 2MB
|
||||
break;
|
||||
|
||||
case 0x5743: // WC = Virtual Boy Wario Land
|
||||
cartSize = 0x200000; // 2MB
|
||||
sramSize = 0x2000; // 8KB
|
||||
break;
|
||||
|
||||
case 0x4644: // FD = Hyper Fighting
|
||||
cartSize = 0x400000; // 4MB
|
||||
sramSize = 0x2000; // 8KB
|
||||
break;
|
||||
}
|
||||
|
||||
if (cartSize)
|
||||
break;
|
||||
}
|
||||
|
||||
// Get name
|
||||
for (byte c = 0; c < 20; c += 2) {
|
||||
// split word
|
||||
word myWord = readWord_VB((cartSize - 0x220 + 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 < 20; 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(" "));
|
||||
|
||||
#if (defined(enable_OLED) || defined(enable_LCD))
|
||||
// Wait for user input
|
||||
println_Msg(F("Press Button..."));
|
||||
display_Update();
|
||||
wait();
|
||||
#endif
|
||||
}
|
||||
|
||||
//******************************************
|
||||
// READ CODE
|
||||
//******************************************
|
||||
|
||||
void readROM_VB() {
|
||||
dataIn_VB();
|
||||
|
||||
strcpy(fileName, romName);
|
||||
strcat(fileName, ".vb");
|
||||
|
||||
EEPROM_readAnything(10, foldern);
|
||||
sprintf(folder, "VBOY/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();
|
||||
|
||||
foldern = foldern + 1;
|
||||
EEPROM_writeAnything(10, foldern);
|
||||
|
||||
if (!myFile.open(fileName, O_RDWR | O_CREAT)) {
|
||||
print_Error(F("SD Error"), true);
|
||||
}
|
||||
|
||||
word d = 0;
|
||||
// HYPER FIGHTING FIX
|
||||
// VIRTUAL BOY ADDRESSING IS TOP DOWN
|
||||
// ONLY FOR HYPER FIGHTING PLUGIN WITH ALL ADDRESS LINES CONNECTED
|
||||
// NORMAL PLUGIN DOES NOT HAVE THE UPPER ADDRESS LINES CONNECTED
|
||||
if (cartSize == 0x400000) {
|
||||
unsigned long romData = 0x1000000 - (cartSize / 2);
|
||||
for (unsigned long currBuffer = romData; currBuffer < 0x1000000; currBuffer += 256) {
|
||||
for (int currWord = 0; currWord < 256; currWord++) {
|
||||
word myWord = readWord_VB(currBuffer + currWord);
|
||||
// Split word into two bytes
|
||||
sdBuffer[d] = (( myWord >> 8 ) & 0xFF);
|
||||
sdBuffer[d + 1] = (myWord & 0xFF);
|
||||
d += 2;
|
||||
}
|
||||
myFile.write(sdBuffer, 512);
|
||||
d = 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (unsigned long currBuffer = 0; currBuffer < cartSize / 2; currBuffer += 256) {
|
||||
for (int currWord = 0; currWord < 256; currWord++) {
|
||||
word myWord = readWord_VB(currBuffer + currWord);
|
||||
// Split word into two bytes
|
||||
sdBuffer[d] = (( myWord >> 8 ) & 0xFF);
|
||||
sdBuffer[d + 1] = (myWord & 0xFF);
|
||||
d += 2;
|
||||
}
|
||||
myFile.write(sdBuffer, 512);
|
||||
d = 0;
|
||||
}
|
||||
}
|
||||
myFile.close();
|
||||
|
||||
// Compare CRC32 to database and rename ROM if found
|
||||
// Arguments: database name, precalculated crc string or 0 to calculate, rename rom or not, starting offset
|
||||
compareCRC("vb.txt", 0, 1, 0);
|
||||
|
||||
#if (defined(enable_OLED) || defined(enable_LCD))
|
||||
// Wait for user input
|
||||
println_Msg(F(""));
|
||||
println_Msg(F("Press Button..."));
|
||||
display_Update();
|
||||
wait();
|
||||
#endif
|
||||
}
|
||||
|
||||
//******************************************
|
||||
// SRAM
|
||||
//******************************************
|
||||
|
||||
void writeSRAM_VB() {
|
||||
dataOut_VB();
|
||||
|
||||
sprintf(filePath, "%s/%s", filePath, fileName);
|
||||
println_Msg(F("Writing..."));
|
||||
println_Msg(filePath);
|
||||
display_Update();
|
||||
|
||||
if (myFile.open(filePath, O_READ)) {
|
||||
for (unsigned long currByte = 0; currByte < sramSize; currByte++) {
|
||||
// writeWord_VB(currByte, ((myFile.read() << 8 ) & 0xFF));
|
||||
writeByte_VB(currByte, (myFile.read()));
|
||||
}
|
||||
myFile.close();
|
||||
println_Msg(F("Done"));
|
||||
display_Update();
|
||||
}
|
||||
else {
|
||||
print_Error(F("SD Error"), true);
|
||||
}
|
||||
dataIn_VB();
|
||||
}
|
||||
|
||||
void readSRAM_VB() {
|
||||
dataIn_VB();
|
||||
|
||||
strcpy(fileName, romName);
|
||||
strcat(fileName, ".srm");
|
||||
|
||||
EEPROM_readAnything(10, foldern);
|
||||
sprintf(folder, "VBOY/SAVE/%s/%d", romName, foldern);
|
||||
sd.mkdir(folder, true);
|
||||
sd.chdir(folder);
|
||||
|
||||
foldern = foldern + 1;
|
||||
EEPROM_writeAnything(10, foldern);
|
||||
|
||||
if (!myFile.open(fileName, O_RDWR | O_CREAT)) {
|
||||
print_Error(F("SD Error"), true);
|
||||
}
|
||||
for (unsigned long currBuffer = 0; currBuffer < sramSize; currBuffer += 512) {
|
||||
for (int currByte = 0; currByte < 512; currByte++) {
|
||||
byte myByte = readByte_VB(currBuffer + currByte);
|
||||
sdBuffer[currByte] = myByte;
|
||||
}
|
||||
myFile.write(sdBuffer, 512);
|
||||
}
|
||||
myFile.close();
|
||||
print_Msg(F("Saved to "));
|
||||
print_Msg(folder);
|
||||
println_Msg(F("/"));
|
||||
display_Update();
|
||||
}
|
||||
|
||||
unsigned long verifySRAM_VB() {
|
||||
dataIn_VB();
|
||||
writeErrors = 0;
|
||||
|
||||
if (myFile.open(filePath, O_READ)) {
|
||||
for (unsigned long currBuffer = 0; currBuffer < sramSize; currBuffer += 512) {
|
||||
for (int currByte = 0; currByte < 512; currByte++) {
|
||||
byte myByte = readByte_VB(currBuffer + currByte);
|
||||
sdBuffer[currByte] = myByte;
|
||||
}
|
||||
for (int i = 0; i < 512; i++) {
|
||||
if (myFile.read() != sdBuffer[i]) {
|
||||
writeErrors++;
|
||||
}
|
||||
}
|
||||
}
|
||||
myFile.close();
|
||||
}
|
||||
else {
|
||||
print_Error(F("SD Error"), true);
|
||||
}
|
||||
|
||||
return writeErrors;
|
||||
}
|
||||
#endif
|
@ -1,6 +1,7 @@
|
||||
//******************************************
|
||||
// WS MODULE
|
||||
//******************************************
|
||||
#ifdef enable_WS
|
||||
// Cartridge pinout
|
||||
// 48P 1.25mm pitch connector
|
||||
// C1, C48 : GND
|
||||
@ -22,8 +23,6 @@
|
||||
// C46 : INT (for RTC alarm interrupt)
|
||||
// C47 : CLK (384KHz on WS)
|
||||
|
||||
#ifdef enable_WS
|
||||
|
||||
#ifdef ws_adapter_v2
|
||||
#define WS_CLK_BIT 5 // USE PE5 as CLK
|
||||
#else
|
||||
|
562
Cart_Reader/WSV.ino
Normal file
562
Cart_Reader/WSV.ino
Normal file
@ -0,0 +1,562 @@
|
||||
//******************************************
|
||||
// WSV MODULE
|
||||
//******************************************
|
||||
#ifdef enable_WSV
|
||||
// Watara Supervision
|
||||
// Cartridge Pinout
|
||||
// 40P 2.5mm pitch connector
|
||||
//
|
||||
// BACK LABEL
|
||||
// SIDE SIDE
|
||||
// +-------+
|
||||
// /RD -| 1 40 |- +5V
|
||||
// A0 -| 2 39 |- nc
|
||||
// A1 -| 3 38 |- nc
|
||||
// A2 -| 4 37 |- nc
|
||||
// A3 -| 5 36 |- nc
|
||||
// A4 -| 6 35 |- /WR
|
||||
// A5 -| 7 34 |- D0
|
||||
// A6 -| 8 33 |- D1
|
||||
// A7 -| 9 32 |- D2
|
||||
// A8 -| 10 31 |- D3
|
||||
// A9 -| 11 30 |- D4
|
||||
// A10 -| 12 29 |- D5
|
||||
// A11 -| 13 28 |- D6
|
||||
// A12 -| 14 27 |- D7
|
||||
// A13 -| 15 26 |- nc
|
||||
// A14 -| 16 25 |- nc
|
||||
// A15 -| 17 24 |- L1
|
||||
// A16 -| 18 23 |- L2
|
||||
// L3 -| 19 22 |- GND
|
||||
// L0 -| 20 21 |- PWR GND
|
||||
// +-------+
|
||||
//
|
||||
// L3 - L0 are the Link Port's I/O - only the 'MAGNUM' variant
|
||||
// routed these to the cartridge slot as additional banking bits.
|
||||
//
|
||||
// CONTROL PINS:
|
||||
// /WR - (PH5)
|
||||
// /RD - (PH6)
|
||||
|
||||
word WSV[] = {32, 64, 512};
|
||||
byte wsvlo = 0; // Lowest Entry
|
||||
byte wsvhi = 2; // Highest Entry
|
||||
|
||||
byte wsvsize;
|
||||
byte newwsvsize;
|
||||
|
||||
// EEPROM MAPPING
|
||||
// 08 ROM SIZE
|
||||
|
||||
//******************************************
|
||||
// SETUP
|
||||
//******************************************
|
||||
|
||||
void setup_WSV()
|
||||
{
|
||||
// Set Address Pins to Output
|
||||
//A0-A7
|
||||
DDRF = 0xFF;
|
||||
//A8-A15
|
||||
DDRK = 0xFF;
|
||||
//BA0-BA7 (BA5-BA7 UNUSED)
|
||||
DDRL = 0xFF;
|
||||
//PA0-PA7 (UNUSED)
|
||||
DDRA = 0xFF;
|
||||
|
||||
// Set Data Pins (D0-D7) to Input
|
||||
// D0 - D7
|
||||
DDRC = 0x00;
|
||||
|
||||
// Set Control Pins to Output
|
||||
// WR(PH5) RD(PH6)
|
||||
// DDRH |= (1 << 5) | (1 << 6);
|
||||
// ---(PH0) ---(PH1) ---(PH3) ---(PH4) /WR(PH5) /RD(PH6)
|
||||
DDRH |= (1 << 0) | (1 << 1) | (1 << 3) | (1 << 4) | (1 << 5) | (1 << 6);
|
||||
|
||||
// Switch WR(PH5) to HIGH
|
||||
// PORTH |= (1 << 5);
|
||||
// Switch RD(PH6) to LOW
|
||||
// PORTH &= ~(1 << 6);
|
||||
// Setting Control Pins to HIGH
|
||||
// ---(PH0) ---(PH1) ---(PH3) ---(PH4) /WR(PH5)
|
||||
PORTH |= (1 << 0) | (1 << 1) | (1 << 3) | (1 << 4) | (1 << 5);
|
||||
// Switch RD(PH6) to LOW
|
||||
PORTH &= ~(1 << 6);
|
||||
|
||||
// Set Unused Pins HIGH
|
||||
PORTL = 0xE0;
|
||||
PORTA = 0xFF;
|
||||
PORTJ |= (1 << 0); // TIME(PJ0)
|
||||
|
||||
checkStatus_WSV();
|
||||
strcpy(romName, "SUPERVISION");
|
||||
|
||||
mode = mode_WSV;
|
||||
}
|
||||
|
||||
//******************************************
|
||||
// MENU
|
||||
//******************************************
|
||||
|
||||
// Base Menu
|
||||
static const char wsvMenuItem1[] PROGMEM = "Select Cart";
|
||||
static const char wsvMenuItem2[] PROGMEM = "Read ROM";
|
||||
static const char wsvMenuItem3[] PROGMEM = "Set Size";
|
||||
static const char wsvMenuItem4[] PROGMEM = "Reset";
|
||||
static const char* const menuOptionsSV[] PROGMEM = {wsvMenuItem1, wsvMenuItem2, wsvMenuItem3, wsvMenuItem4};
|
||||
|
||||
void wsvMenu()
|
||||
{
|
||||
convertPgm(menuOptionsSV, 4);
|
||||
uint8_t mainMenu = question_box(F("SUPERVISION MENU"), menuOptions, 4, 0);
|
||||
|
||||
switch (mainMenu)
|
||||
{
|
||||
case 0:
|
||||
// Select Cart
|
||||
setCart_WSV();
|
||||
setup_WSV();
|
||||
break;
|
||||
|
||||
case 1:
|
||||
// Read Rom
|
||||
sd.chdir("/");
|
||||
readROM_WSV();
|
||||
sd.chdir("/");
|
||||
break;
|
||||
|
||||
case 2:
|
||||
setROMSize_WSV();
|
||||
break;
|
||||
|
||||
case 3:
|
||||
// reset
|
||||
resetArduino();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//******************************************
|
||||
// LOW LEVEL FUNCTIONS
|
||||
//******************************************
|
||||
|
||||
// WRITE
|
||||
void controlOut_WSV() {
|
||||
// Switch RD(PH6) to HIGH
|
||||
PORTH |= (1 << 6);
|
||||
// Switch WR(PH5) to LOW
|
||||
PORTH &= ~(1 << 5);
|
||||
}
|
||||
|
||||
// READ
|
||||
void controlIn_WSV() {
|
||||
// Switch WR(PH5) to HIGH
|
||||
PORTH |= (1 << 5);
|
||||
// Switch RD(PH6) to LOW
|
||||
PORTH &= ~(1 << 6);
|
||||
}
|
||||
|
||||
void dataIn_WSV()
|
||||
{
|
||||
DDRC = 0x00;
|
||||
}
|
||||
|
||||
void dataOut_WSV()
|
||||
{
|
||||
DDRC = 0xFF;
|
||||
}
|
||||
|
||||
uint8_t readByte_WSV(uint32_t addr)
|
||||
{
|
||||
PORTF = addr & 0xFF;
|
||||
PORTK = (addr >> 8) & 0xFF;
|
||||
PORTL = (addr >> 16) & 0xFF;
|
||||
|
||||
// Wait for data bus
|
||||
// 6 x 62.5ns = 375ns
|
||||
NOP; NOP; NOP; NOP; NOP; NOP;
|
||||
|
||||
uint8_t ret = PINC;
|
||||
NOP;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
//******************************************
|
||||
// READ CODE
|
||||
//******************************************
|
||||
|
||||
void readROM_WSV()
|
||||
{
|
||||
strcpy(fileName, romName);
|
||||
strcat(fileName, ".sv");
|
||||
|
||||
// create a new folder for storing rom file
|
||||
EEPROM_readAnything(0, foldern);
|
||||
//sprintf(folder, "WSV/ROM/%s/%d", romName, foldern);
|
||||
sprintf(folder, "WSV/ROM/%d", foldern);
|
||||
sd.mkdir(folder, true);
|
||||
sd.chdir(folder);
|
||||
|
||||
display_Clear();
|
||||
print_Msg(F("Saving to "));
|
||||
print_Msg(folder);
|
||||
println_Msg(F("/..."));
|
||||
display_Update();
|
||||
|
||||
// open file on sdcard
|
||||
if (!myFile.open(fileName, O_RDWR | O_CREAT))
|
||||
print_Error(F("Can't create file on SD"), true);
|
||||
|
||||
// write new folder number back to EEPROM
|
||||
foldern++;
|
||||
EEPROM_writeAnything(0, foldern);
|
||||
|
||||
// start reading rom
|
||||
dataIn_WSV();
|
||||
controlIn_WSV();
|
||||
|
||||
romSize = WSV[wsvsize];
|
||||
|
||||
uint32_t romStart = 0;
|
||||
if (romSize < 64)
|
||||
romStart = 0x8000;
|
||||
uint32_t romEnd = (uint32_t)romSize * 0x400;
|
||||
for (uint32_t addr = 0; addr < romEnd; addr += 512)
|
||||
{
|
||||
for (uint16_t w = 0; w < 512; w++)
|
||||
sdBuffer[w] = readByte_WSV(romStart + addr + w);
|
||||
myFile.write(sdBuffer, 512);
|
||||
}
|
||||
myFile.close();
|
||||
|
||||
// Compare CRC32 to database and rename ROM if found
|
||||
// Arguments: database name, precalculated crc string or 0 to calculate, rename rom or not, starting offset
|
||||
compareCRC("wsv.txt", 0, 1, 0);
|
||||
|
||||
println_Msg(F(""));
|
||||
println_Msg(F("Press Button..."));
|
||||
display_Update();
|
||||
wait();
|
||||
}
|
||||
|
||||
//******************************************
|
||||
// ROM SIZE
|
||||
//******************************************
|
||||
|
||||
void setROMSize_WSV()
|
||||
{
|
||||
#if (defined(enable_OLED) || defined(enable_LCD))
|
||||
display_Clear();
|
||||
if (wsvlo == wsvhi)
|
||||
newwsvsize = wsvlo;
|
||||
else {
|
||||
int b = 0;
|
||||
int i = wsvlo;
|
||||
|
||||
display_Clear();
|
||||
print_Msg(F("ROM Size: "));
|
||||
println_Msg(WSV[i]);
|
||||
println_Msg(F(""));
|
||||
#if defined(enable_OLED)
|
||||
println_Msg(F("Press left to Change"));
|
||||
println_Msg(F("and right to Select"));
|
||||
#elif defined(enable_LCD)
|
||||
println_Msg(F("Rotate to Change"));
|
||||
println_Msg(F("Press to Select"));
|
||||
#endif
|
||||
display_Update();
|
||||
|
||||
while (1) {
|
||||
b = checkButton();
|
||||
if (b == 2) { // Previous (doubleclick)
|
||||
if (i == wsvlo)
|
||||
i = wsvhi;
|
||||
else
|
||||
i--;
|
||||
|
||||
// Only update display after input because of slow LCD library
|
||||
display_Clear();
|
||||
print_Msg(F("ROM Size: "));
|
||||
println_Msg(WSV[i]);
|
||||
println_Msg(F(""));
|
||||
#if defined(enable_OLED)
|
||||
println_Msg(F("Press left to Change"));
|
||||
println_Msg(F("and right to Select"));
|
||||
#elif defined(enable_LCD)
|
||||
println_Msg(F("Rotate to Change"));
|
||||
println_Msg(F("Press to Select"));
|
||||
#endif
|
||||
display_Update();
|
||||
}
|
||||
if (b == 1) { // Next (press)
|
||||
if (i == wsvhi)
|
||||
i = wsvlo;
|
||||
else
|
||||
i++;
|
||||
|
||||
// Only update display after input because of slow LCD library
|
||||
display_Clear();
|
||||
print_Msg(F("ROM Size: "));
|
||||
println_Msg(WSV[i]);
|
||||
println_Msg(F(""));
|
||||
#if defined(enable_OLED)
|
||||
println_Msg(F("Press left to Change"));
|
||||
println_Msg(F("and right to Select"));
|
||||
#elif defined(enable_LCD)
|
||||
println_Msg(F("Rotate to Change"));
|
||||
println_Msg(F("Press to Select"));
|
||||
#endif
|
||||
display_Update();
|
||||
}
|
||||
if (b == 3) { // Long Press - Execute (hold)
|
||||
newwsvsize = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
display.setCursor(0, 56); // Display selection at bottom
|
||||
}
|
||||
print_Msg(F("ROM SIZE "));
|
||||
print_Msg(WSV[newwsvsize]);
|
||||
println_Msg(F("K"));
|
||||
display_Update();
|
||||
delay(1000);
|
||||
#else
|
||||
if (wsvlo == wsvhi)
|
||||
newwsvsize = wsvlo;
|
||||
else {
|
||||
setrom:
|
||||
String sizeROM;
|
||||
for (int i = 0; i < (wsvhi - wsvlo + 1); i++) {
|
||||
Serial.print(F("Select ROM Size: "));
|
||||
Serial.print(i);
|
||||
Serial.print(F(" = "));
|
||||
Serial.print(WSV[i + wsvlo]);
|
||||
Serial.println(F("K"));
|
||||
}
|
||||
Serial.print(F("Enter ROM Size: "));
|
||||
while (Serial.available() == 0) {}
|
||||
sizeROM = Serial.readStringUntil('\n');
|
||||
Serial.println(sizeROM);
|
||||
newwsvsize = sizeROM.toInt() + wsvlo;
|
||||
if (newwsvsize > wsvhi) {
|
||||
Serial.println(F("SIZE NOT SUPPORTED"));
|
||||
Serial.println(F(""));
|
||||
goto setrom;
|
||||
}
|
||||
}
|
||||
Serial.print(F("ROM Size = "));
|
||||
Serial.print(WSV[newwsvsize]);
|
||||
Serial.println(F("K"));
|
||||
#endif
|
||||
EEPROM_writeAnything(8, newwsvsize);
|
||||
wsvsize = newwsvsize;
|
||||
}
|
||||
|
||||
void checkStatus_WSV()
|
||||
{
|
||||
EEPROM_readAnything(8, wsvsize);
|
||||
if (wsvsize > 2) {
|
||||
wsvsize = 1; // default 64K
|
||||
EEPROM_writeAnything(8, wsvsize);
|
||||
}
|
||||
|
||||
#if (defined(enable_OLED) || defined(enable_LCD))
|
||||
display_Clear();
|
||||
println_Msg(F("WATARA SUPERVISION"));
|
||||
println_Msg(F("CURRENT SETTINGS"));
|
||||
println_Msg(F(""));
|
||||
print_Msg(F("ROM SIZE: "));
|
||||
print_Msg(WSV[wsvsize]);
|
||||
println_Msg(F("K"));
|
||||
display_Update();
|
||||
wait();
|
||||
#else
|
||||
Serial.print(F("CURRENT ROM SIZE: "));
|
||||
Serial.print(WSV[wsvsize]);
|
||||
Serial.println(F("K"));
|
||||
Serial.println(F(""));
|
||||
#endif
|
||||
}
|
||||
|
||||
//******************************************
|
||||
// CART SELECT CODE
|
||||
//******************************************
|
||||
void setCart_WSV() {
|
||||
char gamename[100];
|
||||
char tempStr2[2];
|
||||
char crc_search[9];
|
||||
|
||||
//go to root
|
||||
sd.chdir();
|
||||
|
||||
// Select starting letter
|
||||
byte myLetter = starting_letter();
|
||||
|
||||
// Open database
|
||||
if (myFile.open("wsv.txt", O_READ)) {
|
||||
// Skip ahead to selected starting letter
|
||||
if ((myLetter > 0) && (myLetter <= 26)) {
|
||||
while (myFile.available()) {
|
||||
// Read current name
|
||||
get_line(gamename, &myFile, 96);
|
||||
|
||||
// Compare selected letter with first letter of current name until match
|
||||
while (gamename[0] != 64 + myLetter) {
|
||||
skip_line(&myFile);
|
||||
skip_line(&myFile);
|
||||
get_line(gamename, &myFile, 96);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// Rewind one line
|
||||
for (byte count_newline = 0; count_newline < 2; count_newline++) {
|
||||
while (1) {
|
||||
if (myFile.curPosition() == 0) {
|
||||
break;
|
||||
}
|
||||
else if (myFile.peek() == '\n') {
|
||||
myFile.seekSet(myFile.curPosition() - 1);
|
||||
break;
|
||||
}
|
||||
else {
|
||||
myFile.seekSet(myFile.curPosition() - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (myFile.curPosition() != 0)
|
||||
myFile.seekSet(myFile.curPosition() + 2);
|
||||
}
|
||||
|
||||
// Display database
|
||||
while (myFile.available()) {
|
||||
display_Clear();
|
||||
|
||||
// Read game name
|
||||
#if defined(enable_OLED)
|
||||
get_line(gamename, &myFile, 42);
|
||||
#else
|
||||
get_line(gamename, &myFile, 96);
|
||||
#endif
|
||||
|
||||
// Read CRC32 checksum
|
||||
sprintf(checksumStr, "%c", myFile.read());
|
||||
for (byte i = 0; i < 7; i++) {
|
||||
sprintf(tempStr2, "%c", myFile.read());
|
||||
strcat(checksumStr, tempStr2);
|
||||
}
|
||||
|
||||
// Skip over semicolon
|
||||
myFile.seekSet(myFile.curPosition() + 1);
|
||||
|
||||
// Read CRC32 of first 512 bytes
|
||||
sprintf(crc_search, "%c", myFile.read());
|
||||
for (byte i = 0; i < 7; i++) {
|
||||
sprintf(tempStr2, "%c", myFile.read());
|
||||
strcat(crc_search, tempStr2);
|
||||
}
|
||||
|
||||
// Skip over semicolon
|
||||
myFile.seekSet(myFile.curPosition() + 1);
|
||||
|
||||
// Read rom size
|
||||
// Read the next ascii character and subtract 48 to convert to decimal
|
||||
cartSize = myFile.read() - 48;
|
||||
|
||||
// Remove leading 0 for single digit cart sizes
|
||||
if (cartSize != 0) {
|
||||
cartSize = cartSize * 10 + myFile.read() - 48;
|
||||
}
|
||||
else {
|
||||
cartSize = myFile.read() - 48;
|
||||
}
|
||||
|
||||
// Skip rest of line
|
||||
myFile.seekSet(myFile.curPosition() + 2);
|
||||
|
||||
// Skip every 3rd line
|
||||
skip_line(&myFile);
|
||||
|
||||
println_Msg(F("Select your cartridge"));
|
||||
println_Msg(F(""));
|
||||
println_Msg(gamename);
|
||||
print_Msg(F("Size: "));
|
||||
if (cartSize == 51)
|
||||
print_Msg(F("512"));
|
||||
else
|
||||
print_Msg(cartSize);
|
||||
println_Msg(F("KB"));
|
||||
println_Msg(F(""));
|
||||
#if defined(enable_OLED)
|
||||
println_Msg(F("Press left to Change"));
|
||||
println_Msg(F("and right to Select"));
|
||||
#elif defined(enable_LCD)
|
||||
println_Msg(F("Rotate to Change"));
|
||||
println_Msg(F("Press to Select"));
|
||||
#elif defined(SERIAL_MONITOR)
|
||||
println_Msg(F("U/D to Change"));
|
||||
println_Msg(F("Space to Select"));
|
||||
#endif
|
||||
display_Update();
|
||||
|
||||
int b = 0;
|
||||
while (1) {
|
||||
// Check button input
|
||||
b = checkButton();
|
||||
|
||||
// Next
|
||||
if (b == 1) {
|
||||
break;
|
||||
}
|
||||
|
||||
// Previous
|
||||
else if (b == 2) {
|
||||
for (byte count_newline = 0; count_newline < 7; count_newline++) {
|
||||
while (1) {
|
||||
if (myFile.curPosition() == 0) {
|
||||
break;
|
||||
}
|
||||
else if (myFile.peek() == '\n') {
|
||||
myFile.seekSet(myFile.curPosition() - 1);
|
||||
break;
|
||||
}
|
||||
else {
|
||||
myFile.seekSet(myFile.curPosition() - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (myFile.curPosition() != 0)
|
||||
myFile.seekSet(myFile.curPosition() + 2);
|
||||
break;
|
||||
}
|
||||
|
||||
// Selection
|
||||
else if (b == 3) {
|
||||
//word WSV[] = {32,64,512};
|
||||
switch (cartSize) {
|
||||
case 32:
|
||||
wsvsize = 0;
|
||||
break;
|
||||
|
||||
case 64:
|
||||
wsvsize = 1;
|
||||
break;
|
||||
|
||||
case 51:
|
||||
wsvsize = 2;
|
||||
break;
|
||||
}
|
||||
EEPROM_writeAnything(8, wsvsize);
|
||||
myFile.close();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
print_Error(F("Database file not found"), true);
|
||||
}
|
||||
}
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user