mirror of
https://github.com/sanni/cartreader.git
synced 2024-11-27 15:04:15 +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
|
This project represents a community-driven effort to provide
|
||||||
an easy to build and easy to modify cartridge dumper.
|
an easy to build and easy to modify cartridge dumper.
|
||||||
|
|
||||||
Date: 19.08.2022
|
Date: 21.08.2022
|
||||||
Version: 9.5
|
Version: 9.6
|
||||||
|
|
||||||
SD lib: https://github.com/greiman/SdFat
|
SD lib: https://github.com/greiman/SdFat
|
||||||
OLED lib: https://github.com/adafruit/Adafruit_SSD1306
|
OLED lib: https://github.com/adafruit/Adafruit_SSD1306
|
||||||
@ -25,7 +25,7 @@
|
|||||||
MichlK - ROM Reader for Super Nintendo
|
MichlK - ROM Reader for Super Nintendo
|
||||||
Jeff Saltzman - 4-Way Button
|
Jeff Saltzman - 4-Way Button
|
||||||
Wayne and Layne - Video Game Shield menu
|
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
|
Tamanegi_taro - PCE and Satellaview modules
|
||||||
splash5 - GBSmart, Wonderswan and NGP modules
|
splash5 - GBSmart, Wonderswan and NGP modules
|
||||||
hkz & themanbehindthecurtain - N64 flashram commands
|
hkz & themanbehindthecurtain - N64 flashram commands
|
||||||
@ -60,7 +60,7 @@
|
|||||||
|
|
||||||
**********************************************************************************/
|
**********************************************************************************/
|
||||||
|
|
||||||
char ver[5] = "9.5";
|
char ver[5] = "9.6";
|
||||||
|
|
||||||
//******************************************
|
//******************************************
|
||||||
// !!! CHOOSE HARDWARE VERSION !!!
|
// !!! CHOOSE HARDWARE VERSION !!!
|
||||||
@ -97,6 +97,7 @@ char ver[5] = "9.5";
|
|||||||
// #define enable_INTV
|
// #define enable_INTV
|
||||||
// #define enable_COLV
|
// #define enable_COLV
|
||||||
// #define enable_VBOY
|
// #define enable_VBOY
|
||||||
|
// #define enable_WSV
|
||||||
|
|
||||||
//******************************************
|
//******************************************
|
||||||
// HW CONFIGS
|
// HW CONFIGS
|
||||||
@ -305,6 +306,7 @@ bool i2c_found;
|
|||||||
#define mode_INTV 23
|
#define mode_INTV 23
|
||||||
#define mode_COL 24
|
#define mode_COL 24
|
||||||
#define mode_VBOY 25
|
#define mode_VBOY 25
|
||||||
|
#define mode_WSV 26
|
||||||
|
|
||||||
// optimization-safe nop delay
|
// optimization-safe nop delay
|
||||||
#define NOP __asm__ __volatile__ ("nop\n\t")
|
#define NOP __asm__ __volatile__ ("nop\n\t")
|
||||||
@ -683,7 +685,8 @@ boolean compareCRC(char* database, char* crcString, boolean renamerom, int offse
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
println_Msg(F(" -> database file not found"));
|
println_Msg(F(" -> Error"));
|
||||||
|
println_Msg(F("Database missing"));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
@ -807,19 +810,20 @@ static const char modeItem9[] PROGMEM = "NeoGeo Pocket";
|
|||||||
static const char modeItem10[] PROGMEM = "Intellvision";
|
static const char modeItem10[] PROGMEM = "Intellvision";
|
||||||
static const char modeItem11[] PROGMEM = "Colecovision";
|
static const char modeItem11[] PROGMEM = "Colecovision";
|
||||||
static const char modeItem12[] PROGMEM = "Virtual Boy";
|
static const char modeItem12[] PROGMEM = "Virtual Boy";
|
||||||
static const char modeItem13[] PROGMEM = "Flashrom Programmer";
|
static const char modeItem13[] PROGMEM = "Watara Supervision";
|
||||||
static const char modeItem14[] PROGMEM = "About";
|
static const char modeItem14[] PROGMEM = "Flashrom Programmer";
|
||||||
static const char* const modeOptions[] PROGMEM = {modeItem1, modeItem2, modeItem3, modeItem4, modeItem5, modeItem6, modeItem7, modeItem8, modeItem9, modeItem10, modeItem11, modeItem12, modeItem13, modeItem14};
|
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
|
// All included slots
|
||||||
void mainMenu() {
|
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;
|
unsigned char modeMenu;
|
||||||
|
|
||||||
// Main menu spans across two pages
|
// Main menu spans across two pages
|
||||||
currPage = 1;
|
currPage = 1;
|
||||||
lastPage = 1;
|
lastPage = 1;
|
||||||
numPages = 2;
|
numPages = 3;
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
if (currPage == 1) {
|
if (currPage == 1) {
|
||||||
@ -832,6 +836,11 @@ void mainMenu() {
|
|||||||
convertPgm(modeOptions, 7, 7);
|
convertPgm(modeOptions, 7, 7);
|
||||||
modeMenu = question_box(F("OPEN SOURCE CART READER"), menuOptions, 7, 0);
|
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) {
|
if (numPages == 0) {
|
||||||
// Execute choice
|
// Execute choice
|
||||||
modeMenu = (currPage - 1) * 7 + modeMenu;
|
modeMenu = (currPage - 1) * 7 + modeMenu;
|
||||||
@ -941,8 +950,15 @@ void mainMenu() {
|
|||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef enable_FLASH
|
#ifdef enable_WSV
|
||||||
case 12:
|
case 12:
|
||||||
|
setup_WSV();
|
||||||
|
wsvMenu();
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef enable_FLASH
|
||||||
|
case 13:
|
||||||
#ifdef enable_FLASH16
|
#ifdef enable_FLASH16
|
||||||
flashMenu();
|
flashMenu();
|
||||||
#else
|
#else
|
||||||
@ -951,7 +967,7 @@ void mainMenu() {
|
|||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
case 13:
|
case 14:
|
||||||
aboutScreen();
|
aboutScreen();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -997,8 +1013,9 @@ static const char* const consolesOptions[] PROGMEM = {consolesItem1, consolesIte
|
|||||||
static const char handheldsItem1[] PROGMEM = "Virtual Boy";
|
static const char handheldsItem1[] PROGMEM = "Virtual Boy";
|
||||||
static const char handheldsItem2[] PROGMEM = "WonderSwan";
|
static const char handheldsItem2[] PROGMEM = "WonderSwan";
|
||||||
static const char handheldsItem3[] PROGMEM = "NeoGeo Pocket";
|
static const char handheldsItem3[] PROGMEM = "NeoGeo Pocket";
|
||||||
static const char handheldsItem4[] PROGMEM = "Reset";
|
static const char handheldsItem4[] PROGMEM = "Watara Supervision";
|
||||||
static const char* const handheldsOptions[] PROGMEM = {handheldsItem1, handheldsItem2, handheldsItem3, handheldsItem4};
|
static const char handheldsItem5[] PROGMEM = "Reset";
|
||||||
|
static const char* const handheldsOptions[] PROGMEM = {handheldsItem1, handheldsItem2, handheldsItem3, handheldsItem4, handheldsItem5};
|
||||||
|
|
||||||
// All included slots
|
// All included slots
|
||||||
void mainMenu() {
|
void mainMenu() {
|
||||||
@ -1160,21 +1177,19 @@ void consoleMenu() {
|
|||||||
|
|
||||||
// Everything that needs an adapter
|
// Everything that needs an adapter
|
||||||
void handheldMenu() {
|
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;
|
unsigned char handheldsMenu;
|
||||||
// Copy menuOptions out of progmem
|
// Copy menuOptions out of progmem
|
||||||
convertPgm(handheldsOptions, 4);
|
convertPgm(handheldsOptions, 5);
|
||||||
handheldsMenu = question_box(F("Choose Adapter"), menuOptions, 4, 0);
|
handheldsMenu = question_box(F("Choose Adapter"), menuOptions, 5, 0);
|
||||||
|
|
||||||
// wait for user choice to come back from the question box menu
|
// wait for user choice to come back from the question box menu
|
||||||
switch (handheldsMenu)
|
switch (handheldsMenu)
|
||||||
{
|
{
|
||||||
#ifdef enable_VBOY
|
#ifdef enable_VBOY
|
||||||
case 0:
|
case 0:
|
||||||
mode = mode_VBOY;
|
|
||||||
display_Clear();
|
|
||||||
display_Update();
|
|
||||||
setup_VBOY();
|
setup_VBOY();
|
||||||
|
vboyMenu();
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -1196,7 +1211,14 @@ void handheldMenu() {
|
|||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef enable_WSV
|
||||||
case 3:
|
case 3:
|
||||||
|
setup_WSV();
|
||||||
|
wsvMenu();
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
case 4:
|
||||||
resetArduino();
|
resetArduino();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -3372,6 +3394,11 @@ void loop() {
|
|||||||
else if (mode == mode_VBOY) {
|
else if (mode == mode_VBOY) {
|
||||||
vboyMenu();
|
vboyMenu();
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef enable_WSV
|
||||||
|
else if (mode == mode_WSV) {
|
||||||
|
wsvMenu();
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
else {
|
else {
|
||||||
display_Clear();
|
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
|
// WS MODULE
|
||||||
//******************************************
|
//******************************************
|
||||||
|
#ifdef enable_WS
|
||||||
// Cartridge pinout
|
// Cartridge pinout
|
||||||
// 48P 1.25mm pitch connector
|
// 48P 1.25mm pitch connector
|
||||||
// C1, C48 : GND
|
// C1, C48 : GND
|
||||||
@ -22,8 +23,6 @@
|
|||||||
// C46 : INT (for RTC alarm interrupt)
|
// C46 : INT (for RTC alarm interrupt)
|
||||||
// C47 : CLK (384KHz on WS)
|
// C47 : CLK (384KHz on WS)
|
||||||
|
|
||||||
#ifdef enable_WS
|
|
||||||
|
|
||||||
#ifdef ws_adapter_v2
|
#ifdef ws_adapter_v2
|
||||||
#define WS_CLK_BIT 5 // USE PE5 as CLK
|
#define WS_CLK_BIT 5 // USE PE5 as CLK
|
||||||
#else
|
#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