mirror of
https://github.com/sanni/cartreader.git
synced 2024-06-03 02:48:43 +02:00
Compare commits
215 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
2b01f7fc4d | ||
|
740c2698bc | ||
|
ad69abdf57 | ||
|
22e06d8ec1 | ||
|
fb78a1fce5 | ||
|
86059ae070 | ||
|
5b43a162b8 | ||
|
d039c590cc | ||
|
0d9596eb70 | ||
|
cb111077f8 | ||
|
363d18b542 | ||
|
78bf1462d0 | ||
|
41182a7eb0 | ||
|
6abe29fcd9 | ||
|
d1d83bbd10 | ||
|
73700e2886 | ||
|
1aaa90af97 | ||
|
4d000418a8 | ||
|
aaaa6ea3cd | ||
|
a32c6b3bff | ||
|
f82be2d5db | ||
|
d7e795fbed | ||
|
ea0b47de57 | ||
|
9f0aa09197 | ||
|
38b2b2476b | ||
|
dc47202c4d | ||
|
a8cd9c52a6 | ||
|
32f6b4151b | ||
|
c09e772299 | ||
|
7ba32d24fc | ||
|
74352c6e31 | ||
|
ab03ab879c | ||
|
90fa37c491 | ||
|
9e2ef3580c | ||
|
94c6bd460a | ||
|
40238b18a1 | ||
|
8bd6d7dfdc | ||
|
53b71f9108 | ||
|
825a5fe7b6 | ||
|
2c72652671 | ||
|
f4ba8d7af8 | ||
|
2134c9f58b | ||
|
4b70766094 | ||
|
5f3d63a123 | ||
|
990b61ca3a | ||
|
e8e6d15a72 | ||
|
6c05709871 | ||
|
330e615b8c | ||
|
2826ded431 | ||
|
d233387acc | ||
|
254982cbe7 | ||
|
ccc06ef4e4 | ||
|
d7c1afd57c | ||
|
bb12c99fac | ||
|
ecc937bab3 | ||
|
14c3ca2a83 | ||
|
9909fdafb3 | ||
|
06d5f28d0c | ||
|
38f3ebdc8d | ||
|
c3c701cd93 | ||
|
c5c82d4902 | ||
|
fa90691f89 | ||
|
82173ab775 | ||
|
394dcdcf1f | ||
|
254c824292 | ||
|
9f51bb1af7 | ||
|
43e18fce80 | ||
|
a539f9b7de | ||
|
57bf121c06 | ||
|
d2fbb30b95 | ||
|
15c94c110b | ||
|
3ff99bfe48 | ||
|
4502d1e56e | ||
|
d8809b198d | ||
|
3ce23a57ad | ||
|
3441cedfd4 | ||
|
50a147bad7 | ||
|
e7e0da80b0 | ||
|
5d0ae986c9 | ||
|
5a79277a27 | ||
|
ea3adb09bc | ||
|
8b617851a1 | ||
|
dc1e776b19 | ||
|
4c8f8266a1 | ||
|
7fc0f9b154 | ||
|
8458fe6bf7 | ||
|
017da53f42 | ||
|
083182b5fb | ||
|
e1716d48bb | ||
|
cf1d01855d | ||
|
8afd2a580e | ||
|
8fbab1e760 | ||
|
980208e18f | ||
|
229b1ba544 | ||
|
baa7dce0c1 | ||
|
9ad338a821 | ||
|
316f8ef2fd | ||
|
a2924e4f58 | ||
|
385b6b03f4 | ||
|
281639370f | ||
|
d79357d963 | ||
|
44b26960f5 | ||
|
a455b10019 | ||
|
6d89a279f2 | ||
|
4de1c52798 | ||
|
a86f140198 | ||
|
e61ac414d8 | ||
|
3468703a51 | ||
|
35eca2a9f4 | ||
|
f947fb4e3f | ||
|
5f3983b36c | ||
|
ddd8b94bd7 | ||
|
d007c455e7 | ||
|
417e88d7d1 | ||
|
7e2e2a6bf2 | ||
|
f762f29ee4 | ||
|
bbe37d9839 | ||
|
e4e4c7f1f5 | ||
|
24b7c2f2e1 | ||
|
d556e5a4af | ||
|
a8b493026e | ||
|
a9bccaf8f7 | ||
|
2bdba9c8bd | ||
|
c06f1c4e95 | ||
|
5e7861be1c | ||
|
1b70d71518 | ||
|
8ee28d55f4 | ||
|
272c2935e5 | ||
|
319d110339 | ||
|
107dd9f1d7 | ||
|
3a965600cc | ||
|
7078adcd22 | ||
|
dece32c130 | ||
|
3d810823e1 | ||
|
d0fe5c8ca1 | ||
|
70d52636d7 | ||
|
0287ea8ed2 | ||
|
f86a861628 | ||
|
1eac83ef79 | ||
|
ad294f651f | ||
|
5176a15199 | ||
|
a55aa7bbff | ||
|
654686cf15 | ||
|
a06d9ee87b | ||
|
4dc86f40b9 | ||
|
ac1c6db12d | ||
|
68a7958905 | ||
|
1694ae7d5f | ||
|
6b0ded69c7 | ||
|
8fdd93f293 | ||
|
b11330d31b | ||
|
36bd16435c | ||
|
82dbfd79c0 | ||
|
be2089bbdf | ||
|
029c33dfb9 | ||
|
2e72842bb1 | ||
|
0b42d5d1f2 | ||
|
a257fc2ee5 | ||
|
c5a2f3d30b | ||
|
83b854ffeb | ||
|
0e04c1c1a1 | ||
|
c873d3cf9d | ||
|
b270f0c30e | ||
|
4ddd867f87 | ||
|
b2415c0287 | ||
|
603a22116c | ||
|
3c665e35ff | ||
|
559010079c | ||
|
b373b662d2 | ||
|
c88978f5ea | ||
|
4ef394aada | ||
|
cc4ac62f30 | ||
|
c6aa7e49de | ||
|
74fba5e29d | ||
|
4f8ef61355 | ||
|
fafd9caf7f | ||
|
e92e42c581 | ||
|
8ef56ea0f1 | ||
|
e1db41e402 | ||
|
3a30c0f5ed | ||
|
bc62414c59 | ||
|
996d8f77c8 | ||
|
61bfc81ce4 | ||
|
b35e248a41 | ||
|
b748faecde | ||
|
7cf03d3542 | ||
|
749d60de3f | ||
|
03bef214ec | ||
|
d99e2d4040 | ||
|
ec3d048172 | ||
|
19973e479d | ||
|
b2c5999380 | ||
|
2143fe71af | ||
|
8aee244bd0 | ||
|
2e4ea870de | ||
|
e32d30cc8c | ||
|
8d7fc3a486 | ||
|
a969a93281 | ||
|
6a1f14cf91 | ||
|
ce2f2cf4d5 | ||
|
5aac6a40f7 | ||
|
cf460f4a06 | ||
|
74aaaa4d0e | ||
|
8823603630 | ||
|
1bc74f055d | ||
|
5b554bc6e3 | ||
|
dfd765e579 | ||
|
6733c9f57c | ||
|
fee5c867aa | ||
|
1644416a4c | ||
|
527f83c3cb | ||
|
5d3a5e4cc2 | ||
|
42c409baf2 | ||
|
c14e7b2702 | ||
|
63aeb335a4 |
85
.github/ISSUE_TEMPLATE/bug.yml
vendored
Normal file
85
.github/ISSUE_TEMPLATE/bug.yml
vendored
Normal file
|
@ -0,0 +1,85 @@
|
|||
name: "Open New Issue"
|
||||
description: For issues that affect all OSCRs e.g. coding mistakes or hardware oversights.
|
||||
body:
|
||||
- type: input
|
||||
id: version
|
||||
attributes:
|
||||
label: OSCR firmware version
|
||||
description: Which version of the OSCR firmware is currently flashed?
|
||||
validations:
|
||||
required: true
|
||||
- type: dropdown
|
||||
id: hardware
|
||||
attributes:
|
||||
label: OSCR hardware version
|
||||
description: What hardware version are you using?
|
||||
options:
|
||||
- Select hardware version
|
||||
- HW1
|
||||
- HW2
|
||||
- HW3
|
||||
- HW3 Alter
|
||||
- HW4
|
||||
- HW5 Rev1
|
||||
- HW5 Rev2
|
||||
- HW5 Rev3
|
||||
- HW5 Rev4
|
||||
- HW5 Rev5
|
||||
- HW5 Rev6
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: attachment
|
||||
attributes:
|
||||
label: Attach OSCR_LOG.txt file here
|
||||
- type: dropdown
|
||||
id: system
|
||||
attributes:
|
||||
label: System used
|
||||
description: Which system is affected?
|
||||
options:
|
||||
- Select a system
|
||||
- all/none/doesn't matter
|
||||
- NES/Famicom/Family Basic
|
||||
- SNES/Super Famicom
|
||||
- SF Memory
|
||||
- Satellaview
|
||||
- N64 Cartridge
|
||||
- N64 Controller Test
|
||||
- N64 Controller Pak
|
||||
- N64 Gameshark
|
||||
- Game Boy (Color)
|
||||
- GB Memory
|
||||
- Game Boy Advance
|
||||
- Sega Mega Drive/Genesis
|
||||
- Sega Master System
|
||||
- Virtual Boy
|
||||
- Sega Game Gear
|
||||
- Sega Mark III
|
||||
- Sega SG-1000
|
||||
- Sega Cards
|
||||
- PC engine/TG16
|
||||
- WonderSwan (Color)
|
||||
- NeoGeo Pocket (Color)
|
||||
- Intellivision
|
||||
- ColecoVision
|
||||
- Benesse Pocket Challenge W
|
||||
- Benesse Pocket Challenge V2
|
||||
- Watara Supervision
|
||||
- Atari 2600
|
||||
- Emerson Arcadia 2001
|
||||
- Fairchild Channel F
|
||||
- Magnavox Odyssey 2
|
||||
- Super A'Can
|
||||
- MSX
|
||||
- Pokemon Mini
|
||||
- Casio Loopy
|
||||
- Flashrom Programmer
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: bug-desc
|
||||
attributes:
|
||||
label: Describe the issue.
|
||||
validations:
|
||||
required: true
|
5
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
5
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
|
@ -0,0 +1,5 @@
|
|||
blank_issues_enabled: false
|
||||
contact_links:
|
||||
- name: OSCR Discussions forum
|
||||
url: https://github.com/sanni/cartreader/discussions
|
||||
about: For all issues that are specific to your OSCR e.g. soldering mistakes.
|
2
.github/workflows/ci.yml
vendored
2
.github/workflows/ci.yml
vendored
|
@ -47,4 +47,4 @@ jobs:
|
|||
cd Cart_Reader/
|
||||
# Select hardware version by uncommenting it (using regular expression)
|
||||
sed -i 's/^\/\/[\t ]*#define ${{ matrix.hwVersion }}/#define ${{ matrix.hwVersion }}/g' Config.h
|
||||
arduino-cli compile --fqbn arduino:avr:mega --warnings all
|
||||
arduino-cli compile --fqbn arduino:avr:mega --warnings all --build-property compiler.cpp.extra_flags="-DGITHUB_CI"
|
||||
|
|
729
Cart_Reader/2600.ino
Normal file
729
Cart_Reader/2600.ino
Normal file
|
@ -0,0 +1,729 @@
|
|||
//******************************************
|
||||
// ATARI 2600 MODULE
|
||||
//******************************************
|
||||
#if defined(ENABLE_2600)
|
||||
// Atari 2600
|
||||
// Cartridge Pinout
|
||||
// 24P 2.54mm pitch connector
|
||||
//
|
||||
// LABEL SIDE
|
||||
//
|
||||
// GND +5V A8 A9 A11 A10 A12 D7 D6 D5 D4 D3
|
||||
// +--------------------------------------------------+
|
||||
// | 24 23 22 21 20 19 18 17 16 15 14 13 |
|
||||
// LEFT | | RIGHT
|
||||
// | 1 2 3 4 5 6 7 8 9 10 11 12 |
|
||||
// +--------------------------------------------------+
|
||||
// A7 A6 A5 A4 A3 A2 A1 A0 D0 D1 D2 GND
|
||||
//
|
||||
// BOTTOM SIDE
|
||||
|
||||
// Cart Configurations
|
||||
// Format = {mapper,romsize}
|
||||
static const byte PROGMEM a2600mapsize[] = {
|
||||
0x04, 5, // Atari 32K with RAM (F4SC)
|
||||
0x06, 4, // Atari 16K with RAM (F6SC)
|
||||
0x08, 2, // Atari 8K with RAM (F8SC)
|
||||
0x20, 0, // 2K
|
||||
0x3F, 2, // Tigervision 8K
|
||||
0x40, 1, // 4K [DEFAULT]
|
||||
0xC0, 0, // "CV" Commavid 2K
|
||||
0xD0, 2, // "DPC" Pitfall II 10K
|
||||
0xE0, 2, // Parker Bros 8K
|
||||
0xE7, 4, // M-Network 16K
|
||||
0xF0, 6, // Megaboy 64K
|
||||
0xF4, 5, // Atari 32K
|
||||
0xF6, 4, // Atari 16K
|
||||
0xF8, 2, // Atari 8K
|
||||
0xFA, 3, // CBS RAM Plus 12K
|
||||
0xFE, 2, // Activision 8K
|
||||
0xF9, 2, // "TP" Time Pilot 8K
|
||||
0x0A, 2, // "UA" UA Ltd 8K
|
||||
0x3E, 5, // Tigervision 32K with 32K RAM
|
||||
0x07, 6, // X07 64K ROM
|
||||
};
|
||||
|
||||
byte a2600mapcount = (sizeof(a2600mapsize) / sizeof(a2600mapsize[0])) / 2;
|
||||
byte a2600mapselect;
|
||||
int a2600index;
|
||||
|
||||
byte a2600[] = { 2, 4, 8, 12, 16, 32, 64 };
|
||||
byte a2600mapper = 0;
|
||||
byte a2600size;
|
||||
|
||||
// EEPROM MAPPING
|
||||
// 07 MAPPER
|
||||
// 08 ROM SIZE
|
||||
|
||||
//******************************************
|
||||
// Menu
|
||||
//******************************************
|
||||
// Base Menu
|
||||
static const char a2600MenuItem3[] PROGMEM = "Set Mapper";
|
||||
static const char* const menuOptions2600[] PROGMEM = { FSTRING_SELECT_CART, FSTRING_READ_ROM, a2600MenuItem3, FSTRING_RESET };
|
||||
|
||||
void setup_2600() {
|
||||
// Request 5V
|
||||
setVoltage(VOLTS_SET_5V);
|
||||
|
||||
// Set Address Pins to Output
|
||||
// Atari 2600 uses A0-A12 [A13-A23 UNUSED]
|
||||
//A0-A7
|
||||
DDRF = 0xFF;
|
||||
//A8-A15
|
||||
DDRK = 0xFF;
|
||||
//A16-A23
|
||||
DDRL = 0xFF;
|
||||
|
||||
// Set Control Pins to Output [UNUSED]
|
||||
// ---(PH0) ---(PH1) ---(PH3) ---(PH4) ---(PH5) ---(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-D7) to Input
|
||||
DDRC = 0x00;
|
||||
|
||||
// Setting Control Pins to HIGH [UNUSED]
|
||||
// ---(PH0) ---(PH1) ---(PH3) ---(PH4) ---(PH5) ---(PH6)
|
||||
PORTH |= (1 << 0) | (1 << 1) | (1 << 3) | (1 << 4) | (1 << 5) | (1 << 6);
|
||||
|
||||
// Set Unused Data Pins (PA0-PA7) to Output
|
||||
DDRA = 0xFF;
|
||||
|
||||
// Set Unused Pins HIGH
|
||||
PORTA = 0xFF;
|
||||
PORTL = 0xFF; // A16-A23
|
||||
PORTJ |= (1 << 0); // TIME(PJ0)
|
||||
|
||||
checkStatus_2600();
|
||||
strcpy(romName, "ATARI");
|
||||
|
||||
mode = CORE_2600;
|
||||
}
|
||||
|
||||
void a2600Menu() {
|
||||
convertPgm(menuOptions2600, 4);
|
||||
uint8_t mainMenu = question_box(F("ATARI 2600 MENU"), menuOptions, 4, 0);
|
||||
|
||||
switch (mainMenu) {
|
||||
case 0:
|
||||
// Select Cart
|
||||
setCart_2600();
|
||||
setup_2600();
|
||||
break;
|
||||
|
||||
case 1:
|
||||
// Read ROM
|
||||
sd.chdir("/");
|
||||
readROM_2600();
|
||||
sd.chdir("/");
|
||||
break;
|
||||
|
||||
case 2:
|
||||
// Set Mapper
|
||||
setMapper_2600();
|
||||
checkStatus_2600();
|
||||
break;
|
||||
|
||||
case 3:
|
||||
// reset
|
||||
resetArduino();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//******************************************
|
||||
// READ CODE
|
||||
//******************************************
|
||||
|
||||
uint8_t readData_2600(uint16_t addr) // Add Input Pullup
|
||||
{
|
||||
PORTF = addr & 0xFF; // A0-A7
|
||||
PORTK = (addr >> 8) & 0xFF; // A8-A12
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
|
||||
DDRC = 0x00; // Set to Input
|
||||
PORTC = 0xFF; // Input Pullup
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
|
||||
uint8_t ret = PINC;
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void readSegment_2600(uint16_t startaddr, uint16_t endaddr) {
|
||||
for (uint16_t addr = startaddr; addr < endaddr; addr += 512) {
|
||||
readDataArray_2600(addr, 512);
|
||||
}
|
||||
}
|
||||
|
||||
void readDataArray_2600(uint16_t addr, uint16_t size) {
|
||||
for (uint16_t w = 0; w < size; w++) {
|
||||
sdBuffer[w] = readData_2600(addr + w);
|
||||
}
|
||||
myFile.write(sdBuffer, size);
|
||||
}
|
||||
|
||||
void readSegmentF8_2600(uint16_t startaddr, uint16_t endaddr, uint16_t bankaddr) {
|
||||
for (uint16_t addr = startaddr; addr < endaddr; addr += 512) {
|
||||
for (uint16_t w = 0; w < 512; w++) {
|
||||
if (addr > 0x1FF9) // SET BANK ADDRESS FOR 0x1FFA-0x1FFF
|
||||
readData_2600(bankaddr);
|
||||
uint8_t temp = readData_2600(addr + w);
|
||||
sdBuffer[w] = temp;
|
||||
}
|
||||
myFile.write(sdBuffer, 512);
|
||||
}
|
||||
}
|
||||
|
||||
void readSegmentE7_2600(uint8_t start, uint8_t end) {
|
||||
for (uint8_t x = start; x <= end; x++) {
|
||||
readData_2600(0x1FE0 + x);
|
||||
readSegment_2600(0x1000, 0x1800);
|
||||
}
|
||||
}
|
||||
|
||||
void readSegmentFx_2600(bool hasRAM, uint16_t size) {
|
||||
if(hasRAM) {
|
||||
outputFF_2600(0x100); // Skip 0x1000-0x10FF RAM
|
||||
readDataArray_2600(0x1100, 0x100);
|
||||
} else {
|
||||
readSegment_2600(0x1000, 0x1200);
|
||||
}
|
||||
readSegment_2600(0x1200, 0x1E00);
|
||||
// Split Read of Last 0x200 bytes
|
||||
readDataArray_2600(0x1E00, size);
|
||||
}
|
||||
|
||||
void readSegmentTigervision_2600(uint8_t banks) {
|
||||
for (uint8_t x = 0; x < banks; x++) {
|
||||
writeData3F_2600(0x3F, x);
|
||||
readSegment_2600(0x1000, 0x1800);
|
||||
}
|
||||
readSegment_2600(0x1800, 0x2000);
|
||||
}
|
||||
|
||||
void outputFF_2600(uint16_t size) {
|
||||
memset(sdBuffer, 0xFF, size * sizeof(sdBuffer[0]));
|
||||
myFile.write(sdBuffer, size);
|
||||
}
|
||||
|
||||
void writeData_2600(uint16_t addr, uint8_t data) {
|
||||
PORTF = addr & 0xFF; // A0-A7
|
||||
PORTK = (addr >> 8) & 0xFF; // A8-A12
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
|
||||
DDRC = 0xFF; // Set to Output
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
|
||||
PORTC = data;
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
|
||||
DDRC = 0x00; // Reset to Input
|
||||
}
|
||||
|
||||
void writeData3F_2600(uint16_t addr, uint8_t data) {
|
||||
PORTF = addr & 0xFF; // A0-A7
|
||||
PORTK = (addr >> 8) & 0xFF; // A8-A12
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
|
||||
DDRC = 0xFF; // Set to Output
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
|
||||
PORTC = data;
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
|
||||
// Address (0x1000);
|
||||
PORTF = 0x00; // A0-A7
|
||||
PORTK = 0x10; // A8-A12
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
|
||||
DDRC = 0x00; // Reset to Input
|
||||
}
|
||||
|
||||
// E7 Mapper Check - Check Bank for FFs
|
||||
boolean checkE7(uint16_t bank) {
|
||||
writeData_2600(0x1800, 0xFF);
|
||||
readData_2600(0x1FE0 + bank);
|
||||
uint32_t testdata = (readData_2600(0x1000) << 24) | (readData_2600(0x1001) << 16) | (readData_2600(0x1002) << 8) | (readData_2600(0x1003));
|
||||
return (testdata == 0xFFFFFFFF);
|
||||
}
|
||||
|
||||
void readROM_2600() {
|
||||
createFolderAndOpenFile("ATARI", "ROM", romName, "a26");
|
||||
|
||||
// ROM Start 0xF000
|
||||
// Address A12-A0 = 0x1000 = 1 0000 0000 0000 = 4KB
|
||||
// Read Start 0x1000
|
||||
|
||||
switch (a2600mapper) {
|
||||
case 0x20: // 2K Standard 2KB
|
||||
readSegment_2600(0x1000, 0x1800);
|
||||
break;
|
||||
|
||||
case 0x3F: // 3F Mapper 8KB
|
||||
readSegmentTigervision_2600(3);
|
||||
break;
|
||||
|
||||
case 0x3E: // 3E Mapper 32KB ROM 32K RAM
|
||||
readSegmentTigervision_2600(15);
|
||||
break;
|
||||
|
||||
case 0x40: // 4K Default 4KB
|
||||
readSegment_2600(0x1000, 0x2000);
|
||||
break;
|
||||
|
||||
case 0xC0: // CV Mapper 2KB
|
||||
readSegment_2600(0x1800, 0x2000);
|
||||
break;
|
||||
|
||||
case 0xD0: // DPC Mapper 10KB
|
||||
// 8K ROM
|
||||
for (int x = 0; x < 0x2; x++) {
|
||||
readData_2600(0x1FF8 + x);
|
||||
// Split Read of 1st 0x200 bytes
|
||||
// 0x0000-0x0080 are DPC Registers (Random on boot)
|
||||
outputFF_2600(0x80); // Output 0xFFs for Registers
|
||||
readDataArray_2600(0x1080, 0x180);
|
||||
// Read Segment
|
||||
readSegment_2600(0x1200, 0x1800);
|
||||
// 0x1000-0x1080 are DPC Registers (Random on boot)
|
||||
outputFF_2600(0x80); // Output 0xFFs for Registers
|
||||
readDataArray_2600(0x1880, 0x180);
|
||||
// Read Segment
|
||||
readSegment_2600(0x1A00, 0x1E00);
|
||||
// Split Read of Last 0x200 bytes
|
||||
readDataArray_2600(0x1E00, 0x1F8);
|
||||
for (int z = 0; z < 8; z++) {
|
||||
// Set Bank to ensure 0x1FFA-0x1FFF is correct
|
||||
readData_2600(0x1FF8 + x);
|
||||
sdBuffer[z] = readData_2600(0x1FF8 + z);
|
||||
}
|
||||
myFile.write(sdBuffer, 8);
|
||||
}
|
||||
|
||||
// 2K DPC Internal Graphics ROM
|
||||
// Read Registers 0x1008-0x100F (Graphics 0x1008-0x100C)
|
||||
// Write Registers LSB 0x1050-0x1057 AND MSB 0x1058-0x105F
|
||||
|
||||
// Set Data Fetcher 0 Limits
|
||||
writeData_2600(0x1040, 0xFF); // MAX for Data Fetcher 0
|
||||
writeData_2600(0x1048, 0x00); // MIN for Data Fetcher 0
|
||||
// Set Data Fetcher 0 Counter (0x7FF)
|
||||
writeData_2600(0x1050, 0xFF); // LSB for Data Fetcher 0
|
||||
writeData_2600(0x1058, 0x07); // MSB for Data Fetcher 0
|
||||
// Set Data Fetcher 1 Counter (0x7FF)
|
||||
writeData_2600(0x1051, 0xFF); // LSB for Data Fetcher 1
|
||||
writeData_2600(0x1059, 0x07); // MSB for Data Fetcher 1
|
||||
for (int x = 0; x < 0x800; x += 512) {
|
||||
for (int y = 0; y < 512; y++) {
|
||||
sdBuffer[y] = readData_2600(0x1008); // Data Fetcher 0
|
||||
readData_2600(0x1009); // Data Fetcher 1
|
||||
}
|
||||
myFile.write(sdBuffer, 512);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xE0: // E0 Mapper 8KB
|
||||
for (int x = 0; x < 0x7; x++) {
|
||||
readData_2600(0x1FE0 + x);
|
||||
readSegment_2600(0x1000, 0x1400);
|
||||
}
|
||||
readSegment_2600(0x1C00, 0x2000);
|
||||
break;
|
||||
|
||||
case 0xE7: // E7 Mapper 8KB/12KB/16KB
|
||||
writeData_2600(0x1800, 0xFF);
|
||||
// Check Bank 0 - If 0xFFs then Bump 'n' Jump
|
||||
if (checkE7(0)) { // Bump 'n' Jump 8K
|
||||
readSegmentE7_2600(4, 6); // Banks 4-6
|
||||
}
|
||||
// Check Bank 3 - If 0xFFs then BurgerTime
|
||||
else if (checkE7(3)) { // BurgerTime 12K
|
||||
readSegmentE7_2600(0, 1); // Banks 0+1
|
||||
readSegmentE7_2600(4, 6); // Banks 4-6
|
||||
}
|
||||
else { // Masters of the Universe (or Unknown Cart) 16K
|
||||
readSegmentE7_2600(0, 6); // Banks 0-6
|
||||
}
|
||||
readSegment_2600(0x1800, 0x2000); // Bank 7
|
||||
break;
|
||||
|
||||
case 0xF0: // F0 Mapper 64KB
|
||||
for (int x = 0; x < 0x10; x++) {
|
||||
readData_2600(0x1FF0);
|
||||
readSegment_2600(0x1000, 0x2000);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x04: // F4SC Mapper 32KB \w RAM
|
||||
case 0xF4: // F4 Mapper 32KB
|
||||
for (int x = 0; x < 8; x++) {
|
||||
readData_2600(0x1FF4 + x);
|
||||
readSegmentFx_2600(a2600mapper == 0x04, 0x1F4);
|
||||
for (int z = 0; z < 12; z++) {
|
||||
// Set Bank to ensure 0x1FFC-0x1FFF is correct
|
||||
readData_2600(0x1FF4 + x);
|
||||
sdBuffer[z] = readData_2600(0x1FF4 + z);
|
||||
}
|
||||
myFile.write(sdBuffer, 12);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x06: // F6SC Mapper 16KB \w RAM
|
||||
case 0xF6: // F6 Mapper 16KB
|
||||
for (int w = 0; w < 4; w++) {
|
||||
readData_2600(0x1FF6 + w);
|
||||
readSegmentFx_2600(a2600mapper == 0x06, 0x1F6);
|
||||
// Bank Registers 0x1FF6-0x1FF9
|
||||
for (int y = 0; y < 4; y++){
|
||||
readData_2600(0x1FFF); // Reset Bank
|
||||
sdBuffer[y] = readData_2600(0x1FF6 + y);
|
||||
}
|
||||
// End of Bank 0x1FFA-0x1FFF
|
||||
readData_2600(0x1FFF); // Reset Bank
|
||||
readData_2600(0x1FF6 + w); // Set Bank
|
||||
for (int z = 4; z < 10; z++) {
|
||||
sdBuffer[z] = readData_2600(0x1FF6 + z); // 0x1FFA-0x1FFF
|
||||
}
|
||||
myFile.write(sdBuffer, 10);
|
||||
}
|
||||
readData_2600(0x1FFF); // Reset Bank
|
||||
break;
|
||||
|
||||
case 0x08: // F8SC Mapper 8KB \w RAM
|
||||
case 0xF8: // F8 Mapper 8KB
|
||||
for (int w = 0; w < 2; w++) {
|
||||
readData_2600(0x1FF8 + w);
|
||||
readSegmentFx_2600(a2600mapper == 0x08, 0x1F8);
|
||||
// Bank Registers 0x1FF8-0x1FF9
|
||||
for (int y = 0; y < 2; y++){
|
||||
readData_2600(0x1FFF); // Reset Bank
|
||||
sdBuffer[y] = readData_2600(0x1FF8 + y);
|
||||
}
|
||||
// End of Bank 0x1FFA-0x1FFF
|
||||
readData_2600(0x1FFF); // Reset Bank
|
||||
readData_2600(0x1FF8 + w); // Set Bank
|
||||
for (int z = 2; z < 8; z++) {
|
||||
sdBuffer[z] = readData_2600(0x1FF8 + z); // 0x1FFA-0x1FFF
|
||||
}
|
||||
myFile.write(sdBuffer, 8);
|
||||
}
|
||||
readData_2600(0x1FFF); // Reset Bank
|
||||
break;
|
||||
|
||||
case 0xF9: // Time Pilot Mapper 8KB
|
||||
// Bad implementation of the F8 Mapper
|
||||
// kevtris swapped the bank order - swapped banks may not match physical ROM data
|
||||
// Bankswitch code uses 0x1FFC and 0x1FF9
|
||||
for (int w = 3; w >= 0; w -= 3) {
|
||||
readData_2600(0x1FF9 + w);
|
||||
readSegment_2600(0x1000, 0x1E00);
|
||||
// Split Read of Last 0x200 bytes
|
||||
readDataArray_2600(0x1E00, 0x1F9);
|
||||
readData_2600(0x1FFF); // Reset Bank
|
||||
sdBuffer[0] = readData_2600(0x1FF9);
|
||||
// End of Bank 0x1FFA-0x1FFF
|
||||
readData_2600(0x1FFF); // Reset Bank
|
||||
readData_2600(0x1FF9 + w); // Set Bank
|
||||
for (int z = 1; z < 7; z++) {
|
||||
sdBuffer[z] = readData_2600(0x1FF9 + z); // 0x1FFA-0x1FFF
|
||||
}
|
||||
myFile.write(sdBuffer, 7);
|
||||
}
|
||||
// Reset Bank
|
||||
readData_2600(0x1FF9);
|
||||
readData_2600(0x1FFF);
|
||||
readData_2600(0x1FFC);
|
||||
break;
|
||||
|
||||
case 0xFA: // FA Mapper 12KB
|
||||
for (int x = 0; x < 0x3; x++) {
|
||||
writeData_2600(0x1FF8 + x, 0x1); // Set Bank with D0 HIGH
|
||||
readSegment_2600(0x1000, 0x1E00);
|
||||
// Split Read of Last 0x200 bytes
|
||||
readDataArray_2600(0x1E00, 0x1F8);
|
||||
for (int z = 0; z < 8; z++) {
|
||||
// Set Bank to ensure 0x1FFB-0x1FFF is correct
|
||||
writeData_2600(0x1FF8 + x, 0x1); // Set Bank with D0 HIGH
|
||||
sdBuffer[z] = readData_2600(0x1FF8 + z);
|
||||
}
|
||||
myFile.write(sdBuffer, 8);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xFE: // FE Mapper 8KB
|
||||
for (int x = 0; x < 0x2; x++) {
|
||||
writeData_2600(0x01FE, 0xF0 ^ (x << 5));
|
||||
writeData_2600(0x01FF, 0xF0 ^ (x << 5));
|
||||
readSegment_2600(0x1000, 0x2000);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x0A: // UA Mapper 8KB
|
||||
readData_2600(0x220);
|
||||
readSegment_2600(0x1000, 0x2000);
|
||||
readData_2600(0x240);
|
||||
readSegment_2600(0x1000, 0x2000);
|
||||
break;
|
||||
|
||||
case 0x07: // X07 Mapper 64K
|
||||
for (int x = 0; x < 16; x++) {
|
||||
readData_2600(0x080D | (x << 4));
|
||||
readSegment_2600(0x1000, 0x2000);
|
||||
}
|
||||
}
|
||||
myFile.close();
|
||||
|
||||
printCRC(fileName, NULL, 0);
|
||||
|
||||
println_Msg(FS(FSTRING_EMPTY));
|
||||
print_STR(press_button_STR, 1);
|
||||
display_Update();
|
||||
wait();
|
||||
}
|
||||
|
||||
//******************************************
|
||||
// ROM SIZE
|
||||
//******************************************
|
||||
|
||||
void println_Mapper2600(byte mapper) {
|
||||
#if (defined(ENABLE_OLED) || defined(ENABLE_LCD))
|
||||
if (mapper == 0x04)
|
||||
println_Msg(F("F4SC"));
|
||||
else if (mapper == 0x06)
|
||||
println_Msg(F("F6SC"));
|
||||
else if (mapper == 0x08)
|
||||
println_Msg(F("F8SC"));
|
||||
else if (mapper == 0x20)
|
||||
println_Msg(F("2K"));
|
||||
else if (mapper == 0x40)
|
||||
println_Msg(F("4K"));
|
||||
else if (mapper == 0x0A)
|
||||
println_Msg(F("UA"));
|
||||
else if (mapper == 0xC0)
|
||||
println_Msg(F("CV"));
|
||||
else if (mapper == 0xD0)
|
||||
println_Msg(F("DPC"));
|
||||
else if (mapper == 0xF9)
|
||||
println_Msg(F("TP"));
|
||||
else if (mapper == 0x07)
|
||||
println_Msg(F("X07"));
|
||||
else
|
||||
println_Msg(mapper, HEX);
|
||||
#else
|
||||
if (mapper == 0x04)
|
||||
Serial.println(F("F4SC"));
|
||||
else if (mapper == 0x06)
|
||||
Serial.println(F("F6SC"));
|
||||
else if (mapper == 0x08)
|
||||
Serial.println(F("F8SC"));
|
||||
else if (mapper == 0x20)
|
||||
Serial.println(F("2K"));
|
||||
else if (mapper == 0x40)
|
||||
Serial.println(F("4K"));
|
||||
else if (mapper == 0x0A)
|
||||
Serial.println(F("UA"));
|
||||
else if (mapper == 0xC0)
|
||||
Serial.println(F("CV"));
|
||||
else if (mapper == 0xD0)
|
||||
Serial.println(F("DPC"));
|
||||
else if (mapper == 0xF9)
|
||||
Serial.println(F("TP"));
|
||||
else if (mapper == 0x07)
|
||||
Serial.println(F("X07"));
|
||||
else
|
||||
Serial.println(mapper, HEX);
|
||||
#endif
|
||||
}
|
||||
|
||||
void checkStatus_2600() {
|
||||
EEPROM_readAnything(7, a2600mapper);
|
||||
EEPROM_readAnything(8, a2600size);
|
||||
if (a2600size > 6) {
|
||||
a2600size = 1; // default 4KB
|
||||
EEPROM_writeAnything(8, a2600size);
|
||||
}
|
||||
|
||||
#if (defined(ENABLE_OLED) || defined(ENABLE_LCD))
|
||||
display_Clear();
|
||||
println_Msg(F("ATARI 2600 READER"));
|
||||
println_Msg(FS(FSTRING_CURRENT_SETTINGS));
|
||||
println_Msg(FS(FSTRING_EMPTY));
|
||||
print_Msg(F("MAPPER: "));
|
||||
println_Mapper2600(a2600mapper);
|
||||
print_Msg(FS(FSTRING_ROM_SIZE));
|
||||
if (a2600mapper == 0xD0)
|
||||
print_Msg(F("10"));
|
||||
else
|
||||
print_Msg(a2600[a2600size]);
|
||||
println_Msg(F("K"));
|
||||
display_Update();
|
||||
wait();
|
||||
#else
|
||||
Serial.print(F("MAPPER: "));
|
||||
println_Mapper2600(a2600mapper);
|
||||
|
||||
Serial.print(FS(FSTRING_ROM_SIZE));
|
||||
if (a2600mapper == 0xD0)
|
||||
Serial.print(F("10"));
|
||||
else
|
||||
Serial.print(a2600[a2600size]);
|
||||
Serial.println(F("K"));
|
||||
Serial.println(FS(FSTRING_EMPTY));
|
||||
#endif
|
||||
}
|
||||
|
||||
//******************************************
|
||||
// SET MAPPER
|
||||
//******************************************
|
||||
|
||||
#if (defined(ENABLE_OLED) || defined(ENABLE_LCD))
|
||||
void printMapperSelection_2600(int index) {
|
||||
display_Clear();
|
||||
print_Msg(FS(FSTRING_MAPPER));
|
||||
a2600index = index * 2;
|
||||
a2600mapselect = pgm_read_byte(a2600mapsize + a2600index);
|
||||
println_Mapper2600(a2600mapselect);
|
||||
}
|
||||
#endif
|
||||
|
||||
void setMapper_2600() {
|
||||
byte new2600mapper;
|
||||
#if (defined(ENABLE_OLED) || defined(ENABLE_LCD))
|
||||
navigateMenu(0, a2600mapcount - 1, &printMapperSelection_2600);
|
||||
new2600mapper = a2600mapselect;
|
||||
|
||||
display.setCursor(0, 56);
|
||||
print_Msg(F("MAPPER "));
|
||||
println_Mapper2600(new2600mapper);
|
||||
println_Msg(F(" SELECTED"));
|
||||
display_Update();
|
||||
delay(1000);
|
||||
#else
|
||||
setmapper:
|
||||
String newmap;
|
||||
Serial.println(F("SUPPORTED MAPPERS:"));
|
||||
Serial.println(F("0 = F4SC [Atari 32K \w RAM]"));
|
||||
Serial.println(F("1 = F6SC [Atari 16K \w RAM]"));
|
||||
Serial.println(F("2 = F8SC [Atari 8K \w RAM]"));
|
||||
Serial.println(F("3 = 2K [Standard 2K]"));
|
||||
Serial.println(F("4 = 3F [Tigervision 8K]"));
|
||||
Serial.println(F("5 = 4K [Standard 4K]"));
|
||||
Serial.println(F("6 = CV [Commavid]"));
|
||||
Serial.println(F("7 = DPC [Pitfall II]"));
|
||||
Serial.println(F("8 = E0 [Parker Bros]"));
|
||||
Serial.println(F("9 = E7 [M-Network]"));
|
||||
Serial.println(F("10 = F0 [Megaboy]"));
|
||||
Serial.println(F("11 = F4 [Atari 32K]"));
|
||||
Serial.println(F("12 = F6 [Atari 16K]"));
|
||||
Serial.println(F("13 = F8 [Atari 8K]"));
|
||||
Serial.println(F("14 = FA [CBS RAM Plus]"));
|
||||
Serial.println(F("15 = FE [Activision]"));
|
||||
Serial.println(F("16 = TP [Time Pilot 8K]"));
|
||||
Serial.println(F("17 = UA [UA Ltd]"));
|
||||
Serial.println(F("18 = 3E [Tigervision 32K \w RAM]"));
|
||||
Serial.println(F("19 = 07 [X07 64K]"));
|
||||
Serial.print(F("Enter Mapper [0-19]: "));
|
||||
while (Serial.available() == 0) {}
|
||||
newmap = Serial.readStringUntil('\n');
|
||||
Serial.println(newmap);
|
||||
a2600index = newmap.toInt() * 2;
|
||||
new2600mapper = pgm_read_byte(a2600mapsize + a2600index);
|
||||
#endif
|
||||
EEPROM_writeAnything(7, new2600mapper);
|
||||
a2600mapper = new2600mapper;
|
||||
|
||||
a2600size = pgm_read_byte(a2600mapsize + a2600index + 1);
|
||||
EEPROM_writeAnything(8, a2600size);
|
||||
}
|
||||
|
||||
//******************************************
|
||||
// CART SELECT CODE
|
||||
//******************************************
|
||||
void readDataLine_2600(FsFile& database, void* gameMapper) {
|
||||
// Read mapper with three ascii character and subtract 48 to convert to decimal
|
||||
(*(byte*)gameMapper) = ((database.read() - 48) * 100) + ((database.read() - 48) * 10) + (database.read() - 48);
|
||||
|
||||
// Skip rest of line
|
||||
database.seekCur(2);
|
||||
}
|
||||
|
||||
void setCart_2600() {
|
||||
//go to root
|
||||
sd.chdir();
|
||||
|
||||
byte gameMapper;
|
||||
|
||||
// Select starting letter
|
||||
byte myLetter = starting_letter();
|
||||
|
||||
// Open database
|
||||
if (myFile.open("2600.txt", O_READ)) {
|
||||
seek_first_letter_in_database(myFile, myLetter);
|
||||
|
||||
if(checkCartSelection(myFile, &readDataLine_2600, &gameMapper)) {
|
||||
EEPROM_writeAnything(7, gameMapper);
|
||||
for (int i = 0; i < a2600mapcount; i++) {
|
||||
a2600index = i * 2;
|
||||
if (gameMapper == pgm_read_byte(a2600mapsize + a2600index)) {
|
||||
a2600size = pgm_read_byte(a2600mapsize + a2600index + 1);
|
||||
EEPROM_writeAnything(8, a2600size);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
print_FatalError(FS(FSTRING_DATABASE_FILE_NOT_FOUND));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
//******************************************
|
||||
// End of File
|
||||
//******************************************
|
510
Cart_Reader/5200.ino
Normal file
510
Cart_Reader/5200.ino
Normal file
|
@ -0,0 +1,510 @@
|
|||
//******************************************
|
||||
// ATARI 5200 MODULE
|
||||
//******************************************
|
||||
#ifdef ENABLE_5200
|
||||
// Atari 5200
|
||||
// Cartridge Pinout
|
||||
// 36P 2.54mm pitch connector
|
||||
//
|
||||
// RIGHT
|
||||
// +-------+
|
||||
// INTERLOCK -| 18 19 |- A0
|
||||
// A2 -| 17 20 |- A1
|
||||
// L A5 -| 16 21 |- A3
|
||||
// A A6 -| 15 22 |- A4 B
|
||||
// B GND -| 14 23 |- GND O
|
||||
// E GND -| 13 24 |- GND T
|
||||
// L GND -| 12 25 |- GND T
|
||||
// N/C -| 11 26 |- +5V O
|
||||
// /ENABLE 4000-7FFF -| 10 27 |- A7 M
|
||||
// /ENABLE 8000-BFFF -| 9 28 |- N/C
|
||||
// D7 -| 8 29 |- A8 S
|
||||
// S D6 -| 7 30 |- AUD I
|
||||
// I D5 -| 6 31 |- A9 D
|
||||
// D D4 -| 5 32 |- A13 E
|
||||
// E D3 -| 4 33 |- A10
|
||||
// D2 -| 3 34 |- A12
|
||||
// D1 -| 2 35 |- A11
|
||||
// D0 -| 1 36 |- INTERLOCK
|
||||
// +-------+
|
||||
// LEFT
|
||||
//
|
||||
// LABEL SIDE
|
||||
//
|
||||
// /EN /EN
|
||||
// D0 D1 D2 D3 D4 D5 D6 D7 80 40 -- GND GND GND A6 A5 A2 INT
|
||||
// +--------------------------------------------------------------------------+
|
||||
// | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
|
||||
// LEFT | | RIGHT
|
||||
// | 36 35 34 33 32 31 30 29 28 27 26 25 24 23 22 21 20 19 |
|
||||
// +--------------------------------------------------------------------------+
|
||||
// INT A11 A12 A10 A13 A9 AUD A8 -- A7 +5V GND GND GND A4 A3 A1 A0
|
||||
//
|
||||
// BOTTOM SIDE
|
||||
|
||||
// CONTROL PINS:
|
||||
// /4000(PH5) - SNES /WR
|
||||
// /8000(PH6) - SNES /RD
|
||||
|
||||
//******************************************
|
||||
// Defines
|
||||
//******************************************
|
||||
#define DISABLE_4000 PORTH |= (1 << 5) // ROM SELECT 4000-7FFF
|
||||
#define ENABLE_4000 PORTH &= ~(1 << 5)
|
||||
#define DISABLE_8000 PORTH |= (1 << 6) // ROM SELECT 8000-BFFF
|
||||
#define ENABLE_8000 PORTH &= ~(1 << 6)
|
||||
|
||||
//******************************************
|
||||
// Supported Mappers
|
||||
//******************************************
|
||||
// Supported Mapper Array
|
||||
// Format = {mapper,romsizelo,romsizehi}
|
||||
static const byte PROGMEM a5200mapsize[] = {
|
||||
0, 0, 3, // Standard 4K/8K/16K/32K
|
||||
1, 2, 2, // Two Chip 16K
|
||||
2, 4, 4, // Bounty Bob Strikes Back 40K [UNTESTED]
|
||||
};
|
||||
|
||||
byte a5200mapcount = 3; // (sizeof(a5200mapsize) / sizeof(a5200mapsize[0])) / 3;
|
||||
byte a5200mapselect;
|
||||
int a5200index;
|
||||
|
||||
byte a5200[] = { 4, 8, 16, 32, 40 };
|
||||
byte a5200lo = 0; // Lowest Entry
|
||||
byte a5200hi = 4; // Highest Entry
|
||||
byte a5200mapper = 0;
|
||||
byte a5200size;
|
||||
|
||||
// EEPROM MAPPING
|
||||
// 07 MAPPER
|
||||
// 08 ROM SIZE
|
||||
|
||||
//******************************************
|
||||
// Menu
|
||||
//******************************************
|
||||
// Base Menu
|
||||
static const char* const menuOptions5200[] PROGMEM = { FSTRING_SELECT_CART, FSTRING_READ_ROM, FSTRING_SET_SIZE, FSTRING_RESET };
|
||||
|
||||
void setup_5200() {
|
||||
// Request 5V
|
||||
setVoltage(VOLTS_SET_5V);
|
||||
|
||||
// Set Address Pins to Output
|
||||
// Atari 5200 uses A0-A13 [A14-A23 UNUSED]
|
||||
//A0-A7
|
||||
DDRF = 0xFF;
|
||||
//A8-A15
|
||||
DDRK = 0xFF;
|
||||
//A16-A23
|
||||
DDRL = 0xFF;
|
||||
|
||||
// Set Control Pins to Output
|
||||
// ---(PH0) ---(PH1) ---(PH3) ---(PH4) /4000(PH5) /8000(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-D7) to Input
|
||||
DDRC = 0x00;
|
||||
|
||||
// Setting Control Pins to HIGH
|
||||
// ---(PH0) ---(PH1) ---(PH3) ---(PH4) /4000(PH5) /8000(PH6)
|
||||
PORTH |= (1 << 0) | (1 << 1) | (1 << 3) | (1 << 4) | (1 << 5) | (1 << 6);
|
||||
|
||||
// Set Unused Data Pins (PA0-PA7) to Output
|
||||
DDRA = 0xFF;
|
||||
|
||||
// Set Unused Pins HIGH
|
||||
PORTA = 0xFF;
|
||||
PORTL = 0xFF; // A16-A23
|
||||
PORTJ |= (1 << 0); // TIME(PJ0)
|
||||
|
||||
checkStatus_5200();
|
||||
strcpy(romName, "ATARI");
|
||||
|
||||
mode = CORE_5200;
|
||||
}
|
||||
|
||||
void a5200Menu() {
|
||||
convertPgm(menuOptions5200, 4);
|
||||
uint8_t mainMenu = question_box(F("ATARI 5200 MENU"), menuOptions, 4, 0);
|
||||
|
||||
switch (mainMenu) {
|
||||
case 0:
|
||||
// Select Cart
|
||||
setCart_5200();
|
||||
setup_5200();
|
||||
break;
|
||||
|
||||
case 1:
|
||||
// Read ROM
|
||||
sd.chdir("/");
|
||||
readROM_5200();
|
||||
sd.chdir("/");
|
||||
break;
|
||||
|
||||
case 2:
|
||||
// Set Mapper + Size
|
||||
setMapper_5200();
|
||||
checkMapperSize_5200();
|
||||
setROMSize_5200();
|
||||
break;
|
||||
|
||||
case 3:
|
||||
// reset
|
||||
resetArduino();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//******************************************
|
||||
// READ CODE
|
||||
//******************************************
|
||||
|
||||
uint8_t readData_5200(uint16_t addr) // Add Input Pullup
|
||||
{
|
||||
PORTF = addr & 0xFF; // A0-A7
|
||||
PORTK = (addr >> 8) & 0xFF; // A8-A13
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
|
||||
// DDRC = 0x00; // Set to Input
|
||||
PORTC = 0xFF; // Input Pullup
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
// Extended Delay for Vanguard
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
|
||||
uint8_t ret = PINC;
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void readSegment_5200(uint16_t startaddr, uint16_t endaddr) {
|
||||
for (uint16_t addr = startaddr; addr < endaddr; addr += 512) {
|
||||
for (int w = 0; w < 512; w++) {
|
||||
uint8_t temp = readData_5200(addr + w);
|
||||
sdBuffer[w] = temp;
|
||||
}
|
||||
myFile.write(sdBuffer, 512);
|
||||
}
|
||||
}
|
||||
|
||||
//******************************************
|
||||
// READ ROM
|
||||
//******************************************
|
||||
|
||||
void readROM_5200() {
|
||||
createFolderAndOpenFile("5200", "ROM", romName, "a52");
|
||||
|
||||
// 5200 A13-A0 = 10 0000 0000 0000
|
||||
switch (a5200mapper) {
|
||||
case 0: // Standard 4KB/8KB/16KB/32KB
|
||||
// Lower Half of 32K is at 0x4000
|
||||
if (a5200size == 3) { // 32K
|
||||
ENABLE_4000;
|
||||
readSegment_5200(0x4000, 0x8000); // +16K = 32K
|
||||
DISABLE_4000;
|
||||
}
|
||||
// 4K/8K/16K + Upper Half of 32K
|
||||
ENABLE_8000;
|
||||
if (a5200size > 1)
|
||||
readSegment_5200(0x8000, 0xA000); // +8K = 16K
|
||||
if (a5200size > 0)
|
||||
readSegment_5200(0xA000, 0xB000); // +4K = 8K
|
||||
// Base 4K
|
||||
readSegment_5200(0xB000, 0xC000); // 4K
|
||||
DISABLE_8000;
|
||||
break;
|
||||
|
||||
case 1: // Two Chip 16KB
|
||||
ENABLE_4000;
|
||||
readSegment_5200(0x4000, 0x6000); // 8K
|
||||
DISABLE_4000;
|
||||
ENABLE_8000;
|
||||
readSegment_5200(0x8000, 0xA000); // +8K = 16K
|
||||
DISABLE_8000;
|
||||
break;
|
||||
|
||||
case 2: // Bounty Bob Strikes Back 40KB [UNTESTED]
|
||||
ENABLE_4000;
|
||||
// First 16KB (4KB x 4)
|
||||
for (int w = 0; w < 4; w++) {
|
||||
readData_5200(0x4FF6 + w);
|
||||
readSegment_5200(0x4000, 0x4E00);
|
||||
// Split Read of Last 0x200 bytes
|
||||
for (int x = 0; x < 0x1F6; x++) {
|
||||
sdBuffer[x] = readData_5200(0x4E00 + x);
|
||||
}
|
||||
myFile.write(sdBuffer, 502);
|
||||
// Bank Registers 0x4FF6-0x4FF9
|
||||
for (int y = 0; y < 4; y++) {
|
||||
readData_5200(0x4FFF); // Reset Bank
|
||||
sdBuffer[y] = readData_5200(0x4FF6 + y);
|
||||
}
|
||||
// End of Bank 0x4FFA-0x4FFF
|
||||
readData_5200(0x4FFF); // Reset Bank
|
||||
readData_5200(0x4FF6 + w); // Set Bank
|
||||
for (int z = 4; z < 10; z++) {
|
||||
sdBuffer[z] = readData_5200(0x4FF6 + z); // 0x4FFA-0x4FFF
|
||||
}
|
||||
myFile.write(sdBuffer, 10);
|
||||
}
|
||||
readData_5200(0x4FFF); // Reset Bank
|
||||
// Second 16KB (4KB x 4)
|
||||
for (int w = 0; w < 4; w++) {
|
||||
readData_5200(0x5FF6 + w);
|
||||
readSegment_5200(0x5000, 0x5E00);
|
||||
// Split Read of Last 0x200 bytes
|
||||
for (int x = 0; x < 0x1F6; x++) {
|
||||
sdBuffer[x] = readData_5200(0x5E00 + x);
|
||||
}
|
||||
myFile.write(sdBuffer, 502);
|
||||
// Bank Registers 0x5FF6-0x5FF9
|
||||
for (int y = 0; y < 4; y++) {
|
||||
readData_5200(0x5FFF); // Reset Bank
|
||||
sdBuffer[y] = readData_5200(0x5FF6 + y);
|
||||
}
|
||||
// End of Bank 0x5FFA-0x5FFF
|
||||
readData_5200(0x5FFF); // Reset Bank
|
||||
readData_5200(0x5FF6 + w); // Set Bank
|
||||
for (int z = 4; z < 10; z++) {
|
||||
sdBuffer[z] = readData_5200(0x5FF6 + z); // 0x5FFA-0x5FFF
|
||||
}
|
||||
myFile.write(sdBuffer, 10);
|
||||
}
|
||||
readData_5200(0x5FFF); // Reset Bank
|
||||
DISABLE_4000;
|
||||
ENABLE_8000;
|
||||
readSegment_5200(0x8000, 0xA000); // +8K = 40K
|
||||
DISABLE_8000;
|
||||
break;
|
||||
}
|
||||
myFile.close();
|
||||
|
||||
printCRC(fileName, NULL, 0);
|
||||
|
||||
println_Msg(FS(FSTRING_EMPTY));
|
||||
// Prints string out of the common strings array either with or without newline
|
||||
print_STR(press_button_STR, 1);
|
||||
display_Update();
|
||||
wait();
|
||||
}
|
||||
|
||||
//******************************************
|
||||
// ROM SIZE
|
||||
//******************************************
|
||||
|
||||
void println_Mapper5200(byte mapper) {
|
||||
#if (defined(ENABLE_OLED) || defined(ENABLE_LCD))
|
||||
if (mapper == 0)
|
||||
println_Msg(F("STANDARD"));
|
||||
else if (mapper == 1)
|
||||
println_Msg(F("TWO CHIP"));
|
||||
else if (mapper == 2)
|
||||
println_Msg(F("BOUNTY BOB"));
|
||||
#else
|
||||
if (mapper == 0)
|
||||
Serial.println(F("STANDARD"));
|
||||
else if (mapper == 1)
|
||||
Serial.println(F("TWO CHIP"));
|
||||
else if (mapper == 2)
|
||||
Serial.println(F("BOUNTY BOB"));
|
||||
#endif
|
||||
}
|
||||
|
||||
void checkMapperSize_5200() {
|
||||
for (int i = 0; i < a5200mapcount; i++) {
|
||||
a5200index = i * 3;
|
||||
byte mapcheck = pgm_read_byte(a5200mapsize + a5200index);
|
||||
if (mapcheck == a5200mapper) {
|
||||
a5200lo = pgm_read_byte(a5200mapsize + a5200index + 1);
|
||||
a5200hi = pgm_read_byte(a5200mapsize + a5200index + 2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if (defined(ENABLE_OLED) || defined(ENABLE_LCD))
|
||||
void printRomSize_5200(int index) {
|
||||
display_Clear();
|
||||
print_Msg(F("ROM Size: "));
|
||||
println_Msg(a5200[index]);
|
||||
}
|
||||
#endif
|
||||
|
||||
void setROMSize_5200() {
|
||||
byte new5200size;
|
||||
#if (defined(ENABLE_OLED) || defined(ENABLE_LCD))
|
||||
display_Clear();
|
||||
if (a5200lo == a5200hi)
|
||||
new5200size = a5200lo;
|
||||
else {
|
||||
new5200size = navigateMenu(a5200lo, a5200hi, &printRomSize_5200);
|
||||
|
||||
display.setCursor(0, 56); // Display selection at bottom
|
||||
}
|
||||
print_Msg(FS(FSTRING_ROM_SIZE));
|
||||
print_Msg(a5200[new5200size]);
|
||||
println_Msg(F("K"));
|
||||
display_Update();
|
||||
delay(1000);
|
||||
#else
|
||||
if (a5200lo == a5200hi)
|
||||
new5200size = a5200lo;
|
||||
else {
|
||||
setrom:
|
||||
String sizeROM;
|
||||
for (int i = 0; i < (a5200hi - a5200lo + 1); i++) {
|
||||
Serial.print(F("Select ROM Size: "));
|
||||
Serial.print(i);
|
||||
Serial.print(F(" = "));
|
||||
Serial.print(a5200[i + a5200lo]);
|
||||
Serial.println(F("K"));
|
||||
}
|
||||
Serial.print(F("Enter ROM Size: "));
|
||||
while (Serial.available() == 0) {}
|
||||
sizeROM = Serial.readStringUntil('\n');
|
||||
Serial.println(sizeROM);
|
||||
new5200size = sizeROM.toInt() + a5200lo;
|
||||
if (new5200size > a5200hi) {
|
||||
Serial.println(F("SIZE NOT SUPPORTED"));
|
||||
Serial.println(FS(FSTRING_EMPTY));
|
||||
goto setrom;
|
||||
}
|
||||
}
|
||||
Serial.print(F("ROM Size = "));
|
||||
Serial.print(a5200[new5200size]);
|
||||
Serial.println(F("K"));
|
||||
#endif
|
||||
EEPROM_writeAnything(8, new5200size);
|
||||
a5200size = new5200size;
|
||||
}
|
||||
|
||||
void checkStatus_5200() {
|
||||
EEPROM_readAnything(7, a5200mapper);
|
||||
EEPROM_readAnything(8, a5200size);
|
||||
if (a5200mapper > 2) {
|
||||
a5200mapper = 0; // default STANDARD
|
||||
EEPROM_writeAnything(7, a5200mapper);
|
||||
}
|
||||
if (a5200size > 4) {
|
||||
a5200size = 1; // default 8K
|
||||
EEPROM_writeAnything(8, a5200size);
|
||||
}
|
||||
|
||||
#if (defined(ENABLE_OLED) || defined(ENABLE_LCD))
|
||||
display_Clear();
|
||||
println_Msg(F("ATARI 5200 READER"));
|
||||
println_Msg(FS(FSTRING_CURRENT_SETTINGS));
|
||||
println_Msg(FS(FSTRING_EMPTY));
|
||||
print_Msg(F("MAPPER: "));
|
||||
println_Msg(a5200mapper);
|
||||
println_Mapper5200(a5200mapper);
|
||||
print_Msg(FS(FSTRING_ROM_SIZE));
|
||||
print_Msg(a5200[a5200size]);
|
||||
println_Msg(F("K"));
|
||||
display_Update();
|
||||
wait();
|
||||
#else
|
||||
Serial.print(F("MAPPER: "));
|
||||
Serial.println(a5200mapper);
|
||||
println_Mapper5200(a5200mapper);
|
||||
Serial.print(FS(FSTRING_ROM_SIZE));
|
||||
Serial.print(a5200[a5200size]);
|
||||
Serial.println(F("K"));
|
||||
Serial.println(FS(FSTRING_EMPTY));
|
||||
#endif
|
||||
}
|
||||
|
||||
//******************************************
|
||||
// SET MAPPER
|
||||
//******************************************
|
||||
|
||||
#if (defined(ENABLE_OLED) || defined(ENABLE_LCD))
|
||||
void printMapperSelection_5200(int index) {
|
||||
display_Clear();
|
||||
print_Msg(FS(FSTRING_MAPPER));
|
||||
a5200index = index * 3;
|
||||
a5200mapselect = pgm_read_byte(a5200mapsize + a5200index);
|
||||
println_Msg(a5200mapselect);
|
||||
println_Mapper5200(a5200mapselect);
|
||||
}
|
||||
#endif
|
||||
|
||||
void setMapper_5200() {
|
||||
byte new5200mapper;
|
||||
#if (defined(ENABLE_OLED) || defined(ENABLE_LCD))
|
||||
navigateMenu(0, a5200mapcount - 1, &printMapperSelection_5200);
|
||||
new5200mapper = a5200mapselect;
|
||||
|
||||
display.setCursor(0, 56);
|
||||
print_Msg(F("MAPPER "));
|
||||
print_Msg(new5200mapper);
|
||||
println_Msg(F(" SELECTED"));
|
||||
display_Update();
|
||||
delay(1000);
|
||||
#else
|
||||
setmapper:
|
||||
String newmap;
|
||||
Serial.println(F("SUPPORTED MAPPERS:"));
|
||||
Serial.println(F("0 = Standard 4K/8K/16K/32K"));
|
||||
Serial.println(F("1 = Two Chip 16K"));
|
||||
Serial.println(F("2 = Bounty Bob Strikes Back 40K"));
|
||||
Serial.print(F("Enter Mapper [0-2]: "));
|
||||
while (Serial.available() == 0) {}
|
||||
newmap = Serial.readStringUntil('\n');
|
||||
Serial.println(newmap);
|
||||
a5200index = newmap.toInt() * 3;
|
||||
new5200mapper = pgm_read_byte(a5200mapsize + a5200index);
|
||||
#endif
|
||||
EEPROM_writeAnything(7, new5200mapper);
|
||||
a5200mapper = new5200mapper;
|
||||
}
|
||||
|
||||
//******************************************
|
||||
// CART SELECT CODE
|
||||
//******************************************
|
||||
void setCart_5200() {
|
||||
//go to root
|
||||
sd.chdir();
|
||||
|
||||
struct database_entry_mapper_size entry;
|
||||
|
||||
// Select starting letter
|
||||
byte myLetter = starting_letter();
|
||||
|
||||
// Open database
|
||||
if (myFile.open("5200.txt", O_READ)) {
|
||||
seek_first_letter_in_database(myFile, myLetter);
|
||||
|
||||
if(checkCartSelection(myFile, &readDataLineMapperSize, &entry)) {
|
||||
EEPROM_writeAnything(7, entry.gameMapper);
|
||||
EEPROM_writeAnything(8, entry.gameSize);
|
||||
}
|
||||
} else {
|
||||
print_FatalError(FS(FSTRING_DATABASE_FILE_NOT_FOUND));
|
||||
}
|
||||
}
|
||||
#endif
|
664
Cart_Reader/7800.ino
Normal file
664
Cart_Reader/7800.ino
Normal file
|
@ -0,0 +1,664 @@
|
|||
//******************************************
|
||||
// ATARI 7800 MODULE
|
||||
//******************************************
|
||||
#ifdef ENABLE_7800
|
||||
// Atari 7800
|
||||
// Cartridge Pinout
|
||||
// 32P 2.54mm pitch (USE 36P CONNECTOR)
|
||||
//
|
||||
// RIGHT
|
||||
// +-------+
|
||||
// R/W -| 1 32 |- CLK
|
||||
// HALT -| 2 31 |- IRQ
|
||||
// |-------|
|
||||
// D3 -| 3 30 |- GND
|
||||
// L D4 -| 4 29 |- D2 B
|
||||
// A D5 -| 5 28 |- D1 O
|
||||
// B D6 -| 6 27 |- D0 T
|
||||
// E D7 -| 7 26 |- A0 T
|
||||
// L A12 -| 8 25 |- A1 O
|
||||
// A10 -| 9 24 |- A2 M
|
||||
// S A11 -| 10 23 |- A3
|
||||
// I A9 -| 11 22 |- A4 S
|
||||
// D A8 -| 12 21 |- A5 I
|
||||
// E +5V -| 13 20 |- A6 D
|
||||
// GND -| 14 19 |- A7 E
|
||||
// |-------|
|
||||
// A13 -| 15 18 |- AUD
|
||||
// A14 -| 16 17 |- A15
|
||||
// +-------+
|
||||
// LEFT
|
||||
//
|
||||
// LABEL SIDE
|
||||
//
|
||||
// A14 A13 GND +5V A8 A9 A11 A10 A12 D7 D6 D5 D4 D3 HLT R/W
|
||||
// +--------------------------------------------------------------------+
|
||||
// | 16 15 | 14 13 12 11 10 9 8 7 6 5 4 3 | 2 1 |
|
||||
// LEFT | | | | RIGHT
|
||||
// | 17 18 | 19 20 21 22 23 24 25 26 27 28 29 30 | 31 32 |
|
||||
// +--------------------------------------------------------------------+
|
||||
// A15 AUD A7 A6 A5 A4 A3 A2 A1 A0 D0 D1 D2 GND IRQ CLK
|
||||
//
|
||||
// BOTTOM SIDE
|
||||
|
||||
// CONTROL PINS:
|
||||
// CLK(PH1) - SNES CPUCLK
|
||||
// R/W(PH6) - SNES /RD
|
||||
// HALT(PH0) - SNES /RESET
|
||||
|
||||
//******************************************
|
||||
// Supported Mappers
|
||||
//******************************************
|
||||
// Supported Mapper Array
|
||||
// Format = {mapper,romsizelo,romsizehi}
|
||||
static const byte PROGMEM a7800mapsize[] = {
|
||||
0, 0, 2, // Standard 16K/32K/48K [7816/7832/7848]
|
||||
1, 4, 4, // SuperGame 128K [78SG]
|
||||
2, 5, 5, // SuperGame - Alien Brigade/Crossbow 144K [78S9]
|
||||
3, 3, 3, // F-18 Hornet 64K [78AB]
|
||||
4, 4, 4, // Double Dragon/Rampage 128K [78AC]
|
||||
5, 3, 3, // Realsports Baseball/Tank Command/Tower Toppler/Waterski 64K [78S4]
|
||||
6, 3, 3, // Karateka (PAL) 64K [78S4 Variant]
|
||||
7, 1, 4, // Bankset switching
|
||||
};
|
||||
|
||||
byte a7800mapcount = 8; // (sizeof(a7800mapsize) / sizeof(a7800mapsize[0])) / 3;
|
||||
byte a7800mapselect;
|
||||
int a7800index;
|
||||
|
||||
byte a7800[] = { 16, 32, 48, 64, 128, 144 };
|
||||
byte a7800lo = 0; // Lowest Entry
|
||||
byte a7800hi = 5; // Highest Entry
|
||||
byte a7800mapper = 0;
|
||||
byte a7800size;
|
||||
|
||||
// EEPROM MAPPING
|
||||
// 07 MAPPER
|
||||
// 08 ROM SIZE
|
||||
|
||||
//******************************************
|
||||
// Menu
|
||||
//******************************************
|
||||
// Base Menu
|
||||
static const char* const menuOptions7800[] PROGMEM = { FSTRING_SELECT_CART, FSTRING_READ_ROM, FSTRING_SET_SIZE, FSTRING_RESET };
|
||||
|
||||
void setup_7800() {
|
||||
// Request 5V
|
||||
setVoltage(VOLTS_SET_5V);
|
||||
|
||||
// Set Address Pins to Output
|
||||
// Atari 7800 uses A0-A15 [A16-A23 UNUSED]
|
||||
//A0-A7
|
||||
DDRF = 0xFF;
|
||||
//A8-A15
|
||||
DDRK = 0xFF;
|
||||
//A16-A23
|
||||
DDRL = 0xFF;
|
||||
|
||||
// Set Control Pins to Output
|
||||
// HALT(PH0) ---(PH3) ---(PH4) ---(PH5) R/W(PH6)
|
||||
DDRH |= (1 << 0) | (1 << 3) | (1 << 4) | (1 << 5) | (1 << 6);
|
||||
|
||||
// Set TIME(PJ0) to Output (UNUSED)
|
||||
DDRJ |= (1 << 0);
|
||||
|
||||
// Set Pins (D0-D7) to Input
|
||||
DDRC = 0x00;
|
||||
|
||||
// Setting Control Pins to HIGH
|
||||
// HALT(PH0) ---(PH3) ---(PH4) ---(PH5) R/W(PH6)
|
||||
PORTH |= (1 << 0) | (1 << 3) | (1 << 4) | (1 << 5) | (1 << 6);
|
||||
|
||||
// Set Unused Data Pins (PA0-PA7) to Output
|
||||
DDRA = 0xFF;
|
||||
|
||||
// Set Unused Pins HIGH
|
||||
PORTA = 0xFF;
|
||||
PORTL = 0xFF; // A16-A23
|
||||
PORTJ |= (1 << 0); // TIME(PJ0)
|
||||
|
||||
#ifdef ENABLE_CLOCKGEN
|
||||
// Adafruit Clock Generator
|
||||
|
||||
initializeClockOffset();
|
||||
|
||||
if (!i2c_found) {
|
||||
display_Clear();
|
||||
print_FatalError(F("Clock Generator not found"));
|
||||
}
|
||||
|
||||
// Set Eeprom clock to 1Mhz
|
||||
clockgen.set_freq(200000000ULL, SI5351_CLK1);
|
||||
|
||||
// Start outputting Eeprom clock
|
||||
clockgen.output_enable(SI5351_CLK1, 1); // Eeprom clock
|
||||
|
||||
// Wait for clock generator
|
||||
clockgen.update_status();
|
||||
|
||||
#else
|
||||
// Set CLK(PH1) to Output
|
||||
DDRH |= (1 << 1);
|
||||
// Output a high signal CLK(PH1)
|
||||
PORTH |= (1 << 1);
|
||||
#endif
|
||||
|
||||
checkStatus_7800();
|
||||
strcpy(romName, "ATARI");
|
||||
|
||||
mode = CORE_7800;
|
||||
}
|
||||
|
||||
void a7800Menu() {
|
||||
convertPgm(menuOptions7800, 4);
|
||||
uint8_t mainMenu = question_box(F("ATARI 7800 MENU"), menuOptions, 4, 0);
|
||||
|
||||
switch (mainMenu) {
|
||||
case 0:
|
||||
// Select Cart
|
||||
setCart_7800();
|
||||
setup_7800();
|
||||
break;
|
||||
|
||||
case 1:
|
||||
// Read ROM
|
||||
sd.chdir("/");
|
||||
readROM_7800();
|
||||
sd.chdir("/");
|
||||
break;
|
||||
|
||||
case 2:
|
||||
// Set Mapper + Size
|
||||
setMapper_7800();
|
||||
checkMapperSize_7800();
|
||||
setROMSize_7800();
|
||||
break;
|
||||
|
||||
case 3:
|
||||
// reset
|
||||
resetArduino();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//******************************************
|
||||
// READ CODE
|
||||
//******************************************
|
||||
|
||||
uint8_t readData_7800(uint16_t addr) // Add Input Pullup
|
||||
{
|
||||
PORTF = addr & 0xFF; // A0-A7
|
||||
PORTK = (addr >> 8) & 0xFF; // A8-A15
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
|
||||
// DDRC = 0x00; // Set to Input
|
||||
PORTC = 0xFF; // Input Pullup
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
|
||||
uint8_t ret = PINC;
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void readSegment_7800(uint16_t startaddr, uint32_t endaddr) {
|
||||
for (uint32_t addr = startaddr; addr < endaddr; addr += 512) {
|
||||
for (int w = 0; w < 512; w++) {
|
||||
uint8_t temp = readData_7800(addr + w);
|
||||
sdBuffer[w] = temp;
|
||||
}
|
||||
myFile.write(sdBuffer, 512);
|
||||
}
|
||||
}
|
||||
|
||||
void readSegmentBank_7800(uint8_t startbank, uint8_t endbank) {
|
||||
for (uint8_t x = startbank; x < endbank; x++) {
|
||||
writeData_7800(0x8000, x);
|
||||
readSegment_7800(0x8000, 0xC000);
|
||||
}
|
||||
}
|
||||
|
||||
void readStandard_7800() {
|
||||
if (a7800size > 1)
|
||||
readSegment_7800(0x4000, 0x8000); // +16K = 48K
|
||||
if (a7800size > 0)
|
||||
readSegment_7800(0x8000, 0xC000); // +16K = 32K
|
||||
// Base 16K
|
||||
readSegment_7800(0xC000, 0x10000); // 16K
|
||||
}
|
||||
|
||||
void readSupergame_7800() {
|
||||
readSegmentBank_7800(0, 7); // Bank 0-6 16K * 7 = 112K
|
||||
readSegment_7800(0xC000, 0x10000); // Bank 7 +16K = 128K
|
||||
}
|
||||
|
||||
|
||||
void writeData_7800(uint16_t addr, uint8_t data) {
|
||||
PORTF = addr & 0xFF; // A0-A7
|
||||
PORTK = (addr >> 8) & 0xFF; // A8-A15
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
|
||||
DDRC = 0xFF; // Set to Output
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
|
||||
PORTC = data;
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
|
||||
PORTH &= ~(1 << 6); // R/W(PH6) LOW = WRITE
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
PORTH |= (1 << 6); // R/W(PH6) HIGH = READ
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
|
||||
DDRC = 0x00; // Reset to Input
|
||||
}
|
||||
|
||||
// Activision Bankswitch - Double Dragon/Rampage 128K
|
||||
void bankSwitch_7800(uint16_t addr) {
|
||||
PORTF = addr & 0xFF; // A0-A7
|
||||
PORTK = (addr >> 8) & 0xFF; // A8-A15
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
|
||||
PORTH &= ~(1 << 6); // R/W(PH6) LOW = WRITE
|
||||
for (int y = 0; y < 8; y++) { // Pulse Clock to latch data into PAL16 Chip
|
||||
PORTH &= ~(1 << 1); // CLK(PH1) LOW
|
||||
NOP;
|
||||
PORTH |= (1 << 1); // CLK(PH1) HIGH
|
||||
NOP;
|
||||
}
|
||||
|
||||
PORTH |= (1 << 6); // R/W(PH6) HIGH = READ
|
||||
|
||||
DDRC = 0x00; // Reset to Input
|
||||
}
|
||||
|
||||
//******************************************
|
||||
// READ ROM
|
||||
//******************************************
|
||||
|
||||
void readROM_7800() {
|
||||
createFolderAndOpenFile("7800", "ROM", romName, "a78");
|
||||
|
||||
switch (a7800mapper) {
|
||||
case 0: // Standard 16K/32K/48K [7816/7832/7848]
|
||||
readStandard_7800();
|
||||
break;
|
||||
|
||||
case 1: // SuperGame 128K [78SG]
|
||||
readSupergame_7800();
|
||||
break;
|
||||
|
||||
case 2: // SuperGame - Alien Brigade/Crossbow 144K [78S9]
|
||||
readSegment_7800(0x4000, 0x8000); // 16K
|
||||
readSegmentBank_7800(0, 8); // 16K * 8 = +128K = 144K
|
||||
break;
|
||||
|
||||
case 3: // F-18 Hornet 64K [78AB]
|
||||
for (int x = 1; x >= 0; x--) { // Bank Order Inverted = Bank 1 then Bank 0
|
||||
writeData_7800(0x8000, x); // Banks 0-1
|
||||
readSegment_7800(0x4000, 0x8000); // 16K * 2 = 32K
|
||||
}
|
||||
readSegment_7800(0x8000, 0x10000); // +32K = 64K
|
||||
break;
|
||||
|
||||
case 4: // Double Dragon/Rampage 128K [78AC]
|
||||
/*
|
||||
// THIS CODE OUTPUTS ROMS THAT SHOULD MATCH THE CURRENT NO-INTRO DATABASE
|
||||
// BUT THE ROMS INCLUDED IN THE NO-INTRO DATABASE WERE DONE INCORRECTLY
|
||||
// THE UPPER AND LOWER HALVES OF EACH 16K BANK ARE IN THE WRONG ORDER
|
||||
// THE OLD BANKSWITCH INFORMATION IS INCORRECT/INCOMPLETE
|
||||
// Double Dragon (NTSC) = CRC32 AA265865 BAD
|
||||
// Double Dragon (PAL) = CRC32 F29ABDB2 BAD
|
||||
// Rampage (NTSC) = CRC32 39A316AA BAD
|
||||
for (int x = 0; x < 8; x++) {
|
||||
bankSwitch_7800(0xFF80 + x); // Activision Bankswitch
|
||||
readSegment_7800(0xA000, 0xE000); // 16K * 8 = 128K
|
||||
}
|
||||
*/
|
||||
// THIS CODE OUTPUTS PROPER ROMS THAT SHOULD MATCH MAME
|
||||
// THE UPPER AND LOWER HALVES OF EACH 16K BANK ARE IN THE CORRECT ORDER
|
||||
// Double Dragon (NTSC) = CRC32 F20773D5
|
||||
// Double Dragon (PAL) = CRC32 4D634BF5
|
||||
// Rampage (NTSC) = CRC32 D2876EE2
|
||||
for (int x = 0; x < 8; x++) {
|
||||
bankSwitch_7800(0xFF80 + x); // Activision Bankswitch
|
||||
readSegment_7800(0xC000, 0xE000); // 8K * 8 = 64K
|
||||
readSegment_7800(0xA000, 0xC000); // 8K * 8 = +64K = 128K
|
||||
}
|
||||
break;
|
||||
|
||||
case 5: // Realsports Baseball/Tank Command/Tower Toppler/Waterski 64K [78S4]
|
||||
readSegmentBank_7800(0, 4); // 16K * 4 = 64K
|
||||
break;
|
||||
|
||||
case 6: // Karateka (PAL) 64K [78S4 Variant]
|
||||
readSegmentBank_7800(4, 8); // 16K * 4 = 64K
|
||||
break;
|
||||
|
||||
case 7: // Bankset switching
|
||||
if (a7800size > 3) {
|
||||
setHalt_7800(1);
|
||||
readSupergame_7800();
|
||||
setHalt_7800(0);
|
||||
readSupergame_7800();
|
||||
} else {
|
||||
setHalt_7800(1);
|
||||
readStandard_7800();
|
||||
setHalt_7800(0);
|
||||
readStandard_7800();
|
||||
}
|
||||
break;
|
||||
}
|
||||
myFile.close();
|
||||
|
||||
printCRC(fileName, NULL, 0);
|
||||
|
||||
println_Msg(FS(FSTRING_EMPTY));
|
||||
// Prints string out of the common strings array either with or without newline
|
||||
print_STR(press_button_STR, 1);
|
||||
display_Update();
|
||||
wait();
|
||||
}
|
||||
|
||||
void setHalt_7800(byte on) {
|
||||
if(on == 1) {
|
||||
PORTH |= (1 << 0); // HALT(PH0) HIGH = SALLY
|
||||
} else {
|
||||
PORTH &= ~(1 << 0); // HALT(PH0) LOW = MARIA
|
||||
}
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
}
|
||||
|
||||
//******************************************
|
||||
// ROM SIZE
|
||||
//******************************************
|
||||
|
||||
void checkMapperSize_7800() {
|
||||
for (int i = 0; i < a7800mapcount; i++) {
|
||||
a7800index = i * 3;
|
||||
byte mapcheck = pgm_read_byte(a7800mapsize + a7800index);
|
||||
if (mapcheck == a7800mapper) {
|
||||
a7800lo = pgm_read_byte(a7800mapsize + a7800index + 1);
|
||||
a7800hi = pgm_read_byte(a7800mapsize + a7800index + 2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if (defined(ENABLE_OLED) || defined(ENABLE_LCD))
|
||||
void println_Mapper7800(byte mapper) {
|
||||
if (mapper == 0)
|
||||
println_Msg(F("STANDARD"));
|
||||
else if (mapper == 1)
|
||||
println_Msg(F("SUPERGAME 128K[78SG]"));
|
||||
else if (mapper == 2)
|
||||
println_Msg(F("SUPERGAME 144K[78S9]"));
|
||||
else if (mapper == 3)
|
||||
println_Msg(F("F-18 HORNET [78AB]"));
|
||||
else if (mapper == 4)
|
||||
println_Msg(F("DBLDRGN/RMPG [78AC]"));
|
||||
else if (mapper == 5)
|
||||
println_Msg(F("BASEBALL/ETC [78S4]"));
|
||||
else if (mapper == 6)
|
||||
println_Msg(F("KARATEKA(PAL) [78S4]"));
|
||||
else if (mapper == 7)
|
||||
println_Msg(F("BANKSET"));
|
||||
}
|
||||
|
||||
void printRomSize_7800(int index) {
|
||||
display_Clear();
|
||||
print_Msg(F("ROM Size: "));
|
||||
println_Msg(a7800[index]);
|
||||
}
|
||||
#endif
|
||||
|
||||
void setROMSize_7800() {
|
||||
byte new7800size;
|
||||
#if (defined(ENABLE_OLED) || defined(ENABLE_LCD))
|
||||
display_Clear();
|
||||
if (a7800lo == a7800hi)
|
||||
new7800size = a7800lo;
|
||||
else {
|
||||
display_Clear();
|
||||
|
||||
new7800size = navigateMenu(a7800lo, a7800hi, &printRomSize_7800);
|
||||
display.setCursor(0, 56); // Display selection at bottom
|
||||
}
|
||||
print_Msg(FS(FSTRING_ROM_SIZE));
|
||||
print_Msg(a7800[new7800size]);
|
||||
println_Msg(F("K"));
|
||||
display_Update();
|
||||
delay(1000);
|
||||
#else
|
||||
if (a7800lo == a7800hi)
|
||||
new7800size = a7800lo;
|
||||
else {
|
||||
setrom:
|
||||
String sizeROM;
|
||||
for (int i = 0; i < (a7800hi - a7800lo + 1); i++) {
|
||||
Serial.print(F("Select ROM Size: "));
|
||||
Serial.print(i);
|
||||
Serial.print(F(" = "));
|
||||
Serial.print(a7800[i + a7800lo]);
|
||||
Serial.println(F("K"));
|
||||
}
|
||||
Serial.print(F("Enter ROM Size: "));
|
||||
while (Serial.available() == 0) {}
|
||||
sizeROM = Serial.readStringUntil('\n');
|
||||
Serial.println(sizeROM);
|
||||
new7800size = sizeROM.toInt() + a7800lo;
|
||||
if (new7800size > a7800hi) {
|
||||
Serial.println(F("SIZE NOT SUPPORTED"));
|
||||
Serial.println(FS(FSTRING_EMPTY));
|
||||
goto setrom;
|
||||
}
|
||||
}
|
||||
Serial.print(F("ROM Size = "));
|
||||
Serial.print(a7800[new7800size]);
|
||||
Serial.println(F("K"));
|
||||
#endif
|
||||
EEPROM_writeAnything(8, new7800size);
|
||||
a7800size = new7800size;
|
||||
}
|
||||
|
||||
void checkStatus_7800() {
|
||||
EEPROM_readAnything(7, a7800mapper);
|
||||
EEPROM_readAnything(8, a7800size);
|
||||
if (a7800mapper > 7) {
|
||||
a7800mapper = 0; // default
|
||||
EEPROM_writeAnything(7, a7800mapper);
|
||||
}
|
||||
if (a7800size > 5) {
|
||||
a7800size = 0; // default 16KB
|
||||
EEPROM_writeAnything(8, a7800size);
|
||||
}
|
||||
|
||||
#if (defined(ENABLE_OLED) || defined(ENABLE_LCD))
|
||||
display_Clear();
|
||||
println_Msg(F("ATARI 7800 READER"));
|
||||
println_Msg(FS(FSTRING_CURRENT_SETTINGS));
|
||||
println_Msg(FS(FSTRING_EMPTY));
|
||||
print_Msg(F("MAPPER: "));
|
||||
println_Msg(a7800mapper);
|
||||
println_Mapper7800(a7800mapper);
|
||||
print_Msg(FS(FSTRING_ROM_SIZE));
|
||||
print_Msg(a7800[a7800size]);
|
||||
println_Msg(F("K"));
|
||||
display_Update();
|
||||
wait();
|
||||
#else
|
||||
Serial.print(F("MAPPER: "));
|
||||
Serial.println(a7800mapper);
|
||||
if (a7800mapper == 0)
|
||||
Serial.println(F("Standard [7816/7832/7848]"));
|
||||
else if (a7800mapper == 1)
|
||||
Serial.println(F("SuperGame 128K [78SG]"));
|
||||
else if (a7800mapper == 2)
|
||||
Serial.println(F("SuperGame 144K [78S9] - Alien Brigade/Crossbow"));
|
||||
else if (a7800mapper == 3)
|
||||
Serial.println(F("F-18 Hornet 64K [78AB]"));
|
||||
else if (a7800mapper == 4)
|
||||
Serial.println(F("Double Dragon/Rampage [78AC]"));
|
||||
else if (a7800mapper == 5)
|
||||
Serial.println(F("Realsports Baseball/Tank Command/Tower Toppler/Waterski [78S4]"));
|
||||
else if (a7800mapper == 6)
|
||||
Serial.println(F("Karateka (PAL) [78S4 Variant]"));
|
||||
else if (a7800mapper == 7)
|
||||
Serial.println(F("Bankset"));
|
||||
Serial.print(FS(FSTRING_ROM_SIZE));
|
||||
Serial.print(A7800[a7800size]);
|
||||
Serial.println(F("K"));
|
||||
Serial.println(FS(FSTRING_EMPTY));
|
||||
#endif
|
||||
}
|
||||
|
||||
//******************************************
|
||||
// SET MAPPER
|
||||
//******************************************
|
||||
|
||||
#if (defined(ENABLE_OLED) || defined(ENABLE_LCD))
|
||||
void printMapperSelection_7800(int index) {
|
||||
display_Clear();
|
||||
print_Msg(FS(FSTRING_MAPPER));
|
||||
a7800index = index * 3;
|
||||
a7800mapselect = pgm_read_byte(a7800mapsize + a7800index);
|
||||
println_Msg(a7800mapselect);
|
||||
println_Mapper7800(a7800mapselect);
|
||||
}
|
||||
#endif
|
||||
|
||||
void setMapper_7800() {
|
||||
byte new7800mapper = 0;
|
||||
#if (defined(ENABLE_OLED) || defined(ENABLE_LCD))
|
||||
navigateMenu(0, a7800mapcount - 1, &printMapperSelection_7800);
|
||||
new7800mapper = a7800mapselect;
|
||||
|
||||
display.setCursor(0, 56);
|
||||
print_Msg(F("MAPPER "));
|
||||
print_Msg(new7800mapper);
|
||||
println_Msg(F(" SELECTED"));
|
||||
display_Update();
|
||||
delay(1000);
|
||||
#else
|
||||
setmapper:
|
||||
String newmap;
|
||||
Serial.println(F("SUPPORTED MAPPERS:"));
|
||||
Serial.println(F("0 = Standard [7816/7832/7848]"));
|
||||
Serial.println(F("1 = SuperGame 128K [78SG]"));
|
||||
Serial.println(F("2 = SuperGame 144K [78S9] - Alien Brigade/Crossbow"));
|
||||
Serial.println(F("3 = F-18 Hornet 64K [78AB]"));
|
||||
Serial.println(F("4 = Double Dragon/Rampage [78AC]"));
|
||||
Serial.println(F("5 = Realsports Baseball/Tank Command/Tower Toppler/Waterski [78S4]"));
|
||||
Serial.println(F("6 = Karateka (PAL) [78S4 Variant]"));
|
||||
Serial.println(F("7 = Bankset"));
|
||||
Serial.print(F("Enter Mapper [0-7]: "));
|
||||
while (Serial.available() == 0) {}
|
||||
newmap = Serial.readStringUntil('\n');
|
||||
Serial.println(newmap);
|
||||
a7800index = newmap.toInt() * 3;
|
||||
new7800mapper = pgm_read_byte(a7800mapsize + a7800index);
|
||||
#endif
|
||||
EEPROM_writeAnything(7, new7800mapper);
|
||||
a7800mapper = new7800mapper;
|
||||
|
||||
a7800size = pgm_read_byte(a7800mapsize + a7800index + 1);
|
||||
EEPROM_writeAnything(8, a7800size);
|
||||
}
|
||||
|
||||
//******************************************
|
||||
// CART SELECT CODE
|
||||
//******************************************
|
||||
|
||||
void setCart_7800() {
|
||||
//go to root
|
||||
sd.chdir();
|
||||
|
||||
struct database_entry_mapper_size entry;
|
||||
|
||||
// Select starting letter
|
||||
byte myLetter = starting_letter();
|
||||
|
||||
// Open database
|
||||
if (myFile.open("7800.txt", O_READ)) {
|
||||
seek_first_letter_in_database(myFile, myLetter);
|
||||
|
||||
if(checkCartSelection(myFile, &readDataLineMapperSize, &entry)) {
|
||||
EEPROM_writeAnything(7, entry.gameMapper);
|
||||
EEPROM_writeAnything(8, entry.gameSize);
|
||||
}
|
||||
} else {
|
||||
print_FatalError(FS(FSTRING_DATABASE_FILE_NOT_FOUND));
|
||||
}
|
||||
}
|
||||
#endif
|
|
@ -1,7 +1,7 @@
|
|||
//******************************************
|
||||
// EMERSON ARCADIA 2001 MODULE
|
||||
//******************************************
|
||||
#if defined(enable_ARC)
|
||||
#if defined(ENABLE_ARC)
|
||||
// Emerson Arcadia 2001
|
||||
// Cartridge Pinout
|
||||
// 30P 2.54mm pitch connector
|
||||
|
@ -40,7 +40,6 @@ byte arclo = 0; // Lowest Entry
|
|||
byte archi = 3; // Highest Entry
|
||||
|
||||
byte arcsize;
|
||||
byte newarcsize;
|
||||
|
||||
// EEPROM MAPPING
|
||||
// 08 ROM SIZE
|
||||
|
@ -49,11 +48,7 @@ byte newarcsize;
|
|||
// Menu
|
||||
//******************************************
|
||||
// Base Menu
|
||||
static const char arcMenuItem1[] PROGMEM = "Select Cart";
|
||||
static const char arcMenuItem2[] PROGMEM = "Read ROM";
|
||||
static const char arcMenuItem3[] PROGMEM = "Set Size";
|
||||
static const char arcMenuItem4[] PROGMEM = "Reset";
|
||||
static const char* const menuOptionsARC[] PROGMEM = { arcMenuItem1, arcMenuItem2, arcMenuItem3, arcMenuItem4 };
|
||||
static const char* const menuOptionsARC[] PROGMEM = { FSTRING_SELECT_CART, FSTRING_READ_ROM, FSTRING_SET_SIZE, FSTRING_RESET };
|
||||
|
||||
void setup_ARC() {
|
||||
// Request 5V
|
||||
|
@ -93,7 +88,7 @@ void setup_ARC() {
|
|||
checkStatus_ARC();
|
||||
strcpy(romName, "ARCADIA");
|
||||
|
||||
mode = mode_ARC;
|
||||
mode = CORE_ARC;
|
||||
}
|
||||
|
||||
void arcMenu() {
|
||||
|
@ -104,7 +99,6 @@ void arcMenu() {
|
|||
case 0:
|
||||
// Select Cart
|
||||
setCart_ARC();
|
||||
wait();
|
||||
setup_ARC();
|
||||
break;
|
||||
|
||||
|
@ -156,28 +150,7 @@ void readSegment_ARC(uint16_t startaddr, uint16_t endaddr) {
|
|||
}
|
||||
|
||||
void readROM_ARC() {
|
||||
strcpy(fileName, romName);
|
||||
strcat(fileName, ".bin");
|
||||
|
||||
// create a new folder for storing rom file
|
||||
EEPROM_readAnything(0, foldern);
|
||||
sprintf(folder, "ARC/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_FatalError(create_file_STR);
|
||||
}
|
||||
// write new folder number back to EEPROM
|
||||
foldern++;
|
||||
EEPROM_writeAnything(0, foldern);
|
||||
createFolderAndOpenFile("ARC", "ROM", romName, "bin");
|
||||
|
||||
readSegment_ARC(0x0000, 0x0800); // 2K
|
||||
if (arcsize > 0) {
|
||||
|
@ -191,10 +164,9 @@ void readROM_ARC() {
|
|||
}
|
||||
myFile.close();
|
||||
|
||||
unsigned long crcsize = ARC[arcsize] * 0x400;
|
||||
calcCRC(fileName, crcsize, NULL, 0);
|
||||
printCRC(fileName, NULL, 0);
|
||||
|
||||
println_Msg(F(""));
|
||||
println_Msg(FS(FSTRING_EMPTY));
|
||||
print_STR(press_button_STR, 1);
|
||||
display_Update();
|
||||
wait();
|
||||
|
@ -204,78 +176,26 @@ void readROM_ARC() {
|
|||
// ROM SIZE
|
||||
//******************************************
|
||||
|
||||
#if (defined(ENABLE_OLED) || defined(ENABLE_LCD))
|
||||
void printRomSize_ARC(int index) {
|
||||
display_Clear();
|
||||
print_Msg(F("ROM Size: "));
|
||||
println_Msg(ARC[index]);
|
||||
}
|
||||
#endif
|
||||
|
||||
void setROMSize_ARC() {
|
||||
#if (defined(enable_OLED) || defined(enable_LCD))
|
||||
byte newarcsize;
|
||||
#if (defined(ENABLE_OLED) || defined(ENABLE_LCD))
|
||||
display_Clear();
|
||||
if (arclo == archi)
|
||||
newarcsize = arclo;
|
||||
else {
|
||||
int b = 0;
|
||||
int i = arclo;
|
||||
newarcsize = navigateMenu(arclo, archi, &printRomSize_ARC);
|
||||
|
||||
display_Clear();
|
||||
print_Msg(F("ROM Size: "));
|
||||
println_Msg(ARC[i]);
|
||||
println_Msg(F(""));
|
||||
#if defined(enable_OLED)
|
||||
print_STR(press_to_change_STR, 1);
|
||||
print_STR(right_to_select_STR, 1);
|
||||
#elif defined(enable_LCD)
|
||||
print_STR(rotate_to_change_STR, 1);
|
||||
print_STR(press_to_select_STR, 1);
|
||||
#endif
|
||||
display_Update();
|
||||
|
||||
while (1) {
|
||||
b = checkButton();
|
||||
if (b == 2) { // Previous (doubleclick)
|
||||
if (i == arclo)
|
||||
i = archi;
|
||||
else
|
||||
i--;
|
||||
|
||||
// Only update display after input because of slow LCD library
|
||||
display_Clear();
|
||||
print_Msg(F("ROM Size: "));
|
||||
println_Msg(ARC[i]);
|
||||
println_Msg(F(""));
|
||||
#if defined(enable_OLED)
|
||||
print_STR(press_to_change_STR, 1);
|
||||
print_STR(right_to_select_STR, 1);
|
||||
#elif defined(enable_LCD)
|
||||
print_STR(rotate_to_change_STR, 1);
|
||||
print_STR(press_to_select_STR, 1);
|
||||
#endif
|
||||
display_Update();
|
||||
}
|
||||
if (b == 1) { // Next (press)
|
||||
if (i == archi)
|
||||
i = arclo;
|
||||
else
|
||||
i++;
|
||||
|
||||
// Only update display after input because of slow LCD library
|
||||
display_Clear();
|
||||
print_Msg(F("ROM Size: "));
|
||||
println_Msg(ARC[i]);
|
||||
println_Msg(F(""));
|
||||
#if defined(enable_OLED)
|
||||
print_STR(press_to_change_STR, 1);
|
||||
print_STR(right_to_select_STR, 1);
|
||||
#elif defined(enable_LCD)
|
||||
print_STR(rotate_to_change_STR, 1);
|
||||
print_STR(press_to_select_STR, 1);
|
||||
#endif
|
||||
display_Update();
|
||||
}
|
||||
if (b == 3) { // Long Press - Execute (hold)
|
||||
newarcsize = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
display.setCursor(0, 56); // Display selection at bottom
|
||||
}
|
||||
print_Msg(F("ROM SIZE "));
|
||||
print_Msg(FS(FSTRING_ROM_SIZE));
|
||||
print_Msg(ARC[newarcsize]);
|
||||
println_Msg(F("K"));
|
||||
display_Update();
|
||||
|
@ -300,7 +220,7 @@ setrom:
|
|||
newarcsize = sizeROM.toInt() + arclo;
|
||||
if (newarcsize > archi) {
|
||||
Serial.println(F("SIZE NOT SUPPORTED"));
|
||||
Serial.println(F(""));
|
||||
Serial.println(FS(FSTRING_EMPTY));
|
||||
goto setrom;
|
||||
}
|
||||
}
|
||||
|
@ -319,12 +239,12 @@ void checkStatus_ARC() {
|
|||
EEPROM_writeAnything(8, arcsize);
|
||||
}
|
||||
|
||||
#if (defined(enable_OLED) || defined(enable_LCD))
|
||||
#if (defined(ENABLE_OLED) || defined(ENABLE_LCD))
|
||||
display_Clear();
|
||||
println_Msg(F("ARCADIA 2001 READER"));
|
||||
println_Msg(F("CURRENT SETTINGS"));
|
||||
println_Msg(F(""));
|
||||
print_Msg(F("ROM SIZE: "));
|
||||
println_Msg(FS(FSTRING_CURRENT_SETTINGS));
|
||||
println_Msg(FS(FSTRING_EMPTY));
|
||||
print_Msg(FS(FSTRING_ROM_SIZE));
|
||||
print_Msg(ARC[arcsize]);
|
||||
println_Msg(F("K"));
|
||||
display_Update();
|
||||
|
@ -333,248 +253,34 @@ void checkStatus_ARC() {
|
|||
Serial.print(F("CURRENT ROM SIZE: "));
|
||||
Serial.print(ARC[arcsize]);
|
||||
Serial.println(F("K"));
|
||||
Serial.println(F(""));
|
||||
Serial.println(FS(FSTRING_EMPTY));
|
||||
#endif
|
||||
}
|
||||
|
||||
//******************************************
|
||||
// CART SELECT CODE
|
||||
//******************************************
|
||||
|
||||
FsFile arccsvFile;
|
||||
char arcgame[20]; // title
|
||||
char arcrr[3]; // romsize
|
||||
char arcll[4]; // linelength (previous line)
|
||||
unsigned long arccsvpos; // CSV File Position
|
||||
char arccartCSV[] = "arccart.txt"; // CSV List
|
||||
char arccsvEND[] = "EOF"; // CSV End Marker for scrolling
|
||||
|
||||
bool readLine_ARC(FsFile& f, char* line, size_t maxLen) {
|
||||
for (size_t n = 0; n < maxLen; n++) {
|
||||
int c = f.read();
|
||||
if (c < 0 && n == 0) return false; // EOF
|
||||
if (c < 0 || c == '\n') {
|
||||
line[n] = 0;
|
||||
return true;
|
||||
}
|
||||
line[n] = c;
|
||||
}
|
||||
return false; // line too long
|
||||
}
|
||||
|
||||
bool readVals_ARC(char* arcgame, char* arcrr, char* arcll) {
|
||||
char line[26];
|
||||
arccsvpos = arccsvFile.position();
|
||||
if (!readLine_ARC(arccsvFile, line, sizeof(line))) {
|
||||
return false; // EOF or too long
|
||||
}
|
||||
char* comma = strtok(line, ",");
|
||||
int x = 0;
|
||||
while (comma != NULL) {
|
||||
if (x == 0)
|
||||
strcpy(arcgame, comma);
|
||||
else if (x == 1)
|
||||
strcpy(arcrr, comma);
|
||||
else if (x == 2)
|
||||
strcpy(arcll, comma);
|
||||
comma = strtok(NULL, ",");
|
||||
x += 1;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool getCartListInfo_ARC() {
|
||||
bool buttonreleased = 0;
|
||||
bool cartselected = 0;
|
||||
#if (defined(enable_OLED) || defined(enable_LCD))
|
||||
display_Clear();
|
||||
println_Msg(F(" HOLD TO FAST CYCLE"));
|
||||
display_Update();
|
||||
#else
|
||||
Serial.println(F("HOLD BUTTON TO FAST CYCLE"));
|
||||
#endif
|
||||
delay(2000);
|
||||
#if defined(enable_OLED)
|
||||
buttonVal1 = (PIND & (1 << 7)); // PD7
|
||||
#elif defined(enable_LCD)
|
||||
boolean buttonVal1 = (PING & (1 << 2)); //PG2
|
||||
#endif
|
||||
if (buttonVal1 == LOW) { // Button Held - Fast Cycle
|
||||
while (1) { // Scroll Game List
|
||||
while (readVals_ARC(arcgame, arcrr, arcll)) {
|
||||
if (strcmp(arccsvEND, arcgame) == 0) {
|
||||
arccsvFile.seek(0); // Restart
|
||||
} else {
|
||||
#if (defined(enable_OLED) || defined(enable_LCD))
|
||||
display_Clear();
|
||||
println_Msg(F("CART TITLE:"));
|
||||
println_Msg(F(""));
|
||||
println_Msg(arcgame);
|
||||
display_Update();
|
||||
#else
|
||||
Serial.print(F("CART TITLE:"));
|
||||
Serial.println(arcgame);
|
||||
#endif
|
||||
#if defined(enable_OLED)
|
||||
buttonVal1 = (PIND & (1 << 7)); // PD7
|
||||
#elif defined(enable_LCD)
|
||||
buttonVal1 = (PING & (1 << 2)); //PG2
|
||||
#endif
|
||||
if (buttonVal1 == HIGH) { // Button Released
|
||||
buttonreleased = 1;
|
||||
break;
|
||||
}
|
||||
if (buttonreleased) {
|
||||
buttonreleased = 0; // Reset Flag
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#if defined(enable_OLED)
|
||||
buttonVal1 = (PIND & (1 << 7)); // PD7
|
||||
#elif defined(enable_LCD)
|
||||
buttonVal1 = (PING & (1 << 2)); //PG2
|
||||
#endif
|
||||
if (buttonVal1 == HIGH) // Button Released
|
||||
break;
|
||||
}
|
||||
}
|
||||
#if (defined(enable_OLED) || defined(enable_LCD))
|
||||
display.setCursor(0, 56);
|
||||
println_Msg(F("FAST CYCLE OFF"));
|
||||
display_Update();
|
||||
#else
|
||||
Serial.println(F(""));
|
||||
Serial.println(F("FAST CYCLE OFF"));
|
||||
Serial.println(F("PRESS BUTTON TO STEP FORWARD"));
|
||||
Serial.println(F("DOUBLE CLICK TO STEP BACK"));
|
||||
Serial.println(F("HOLD TO SELECT"));
|
||||
Serial.println(F(""));
|
||||
#endif
|
||||
while (readVals_ARC(arcgame, arcrr, arcll)) {
|
||||
if (strcmp(arccsvEND, arcgame) == 0) {
|
||||
arccsvFile.seek(0); // Restart
|
||||
} else {
|
||||
#if (defined(enable_OLED) || defined(enable_LCD))
|
||||
display_Clear();
|
||||
println_Msg(F("CART TITLE:"));
|
||||
println_Msg(F(""));
|
||||
println_Msg(arcgame);
|
||||
display.setCursor(0, 48);
|
||||
#if defined(enable_OLED)
|
||||
print_STR(press_to_change_STR, 1);
|
||||
print_STR(right_to_select_STR, 1);
|
||||
#elif defined(enable_LCD)
|
||||
print_STR(rotate_to_change_STR, 1);
|
||||
print_STR(press_to_select_STR, 1);
|
||||
#endif
|
||||
display_Update();
|
||||
#else
|
||||
Serial.print(F("CART TITLE:"));
|
||||
Serial.println(arcgame);
|
||||
#endif
|
||||
while (1) { // Single Step
|
||||
int b = checkButton();
|
||||
if (b == 1) { // Continue (press)
|
||||
break;
|
||||
}
|
||||
if (b == 2) { // Reset to Start of List (doubleclick)
|
||||
byte prevline = strtol(arcll, NULL, 10);
|
||||
arccsvpos -= prevline;
|
||||
arccsvFile.seek(arccsvpos);
|
||||
break;
|
||||
}
|
||||
if (b == 3) { // Long Press - Select Cart (hold)
|
||||
newarcsize = strtol(arcrr, NULL, 10);
|
||||
EEPROM_writeAnything(8, newarcsize);
|
||||
cartselected = 1; // SELECTION MADE
|
||||
#if (defined(enable_OLED) || defined(enable_LCD))
|
||||
println_Msg(F("SELECTION MADE"));
|
||||
display_Update();
|
||||
#else
|
||||
Serial.println(F("SELECTION MADE"));
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (cartselected) {
|
||||
cartselected = 0; // Reset Flag
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
#if (defined(enable_OLED) || defined(enable_LCD))
|
||||
println_Msg(F(""));
|
||||
println_Msg(F("END OF FILE"));
|
||||
display_Update();
|
||||
#else
|
||||
Serial.println(F("END OF FILE"));
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void checkCSV_ARC() {
|
||||
if (getCartListInfo_ARC()) {
|
||||
#if (defined(enable_OLED) || defined(enable_LCD))
|
||||
display_Clear();
|
||||
println_Msg(F("CART SELECTED"));
|
||||
println_Msg(F(""));
|
||||
println_Msg(arcgame);
|
||||
display_Update();
|
||||
// Display Settings
|
||||
display.setCursor(0, 56);
|
||||
print_Msg(F("CODE: R"));
|
||||
println_Msg(newarcsize);
|
||||
display_Update();
|
||||
#else
|
||||
Serial.println(F(""));
|
||||
Serial.println(F("CART SELECTED"));
|
||||
Serial.println(arcgame);
|
||||
// Display Settings
|
||||
Serial.print(F("CODE: R"));
|
||||
Serial.println(newarcsize);
|
||||
Serial.println(F(""));
|
||||
#endif
|
||||
} else {
|
||||
#ifdef enable_OLED
|
||||
display.setCursor(0, 56);
|
||||
println_Msg(F("NO SELECTION"));
|
||||
display_Update();
|
||||
#else
|
||||
Serial.println(F("NO SELECTION"));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void setCart_ARC() {
|
||||
#if (defined(enable_OLED) || defined(enable_LCD))
|
||||
display_Clear();
|
||||
println_Msg(arccartCSV);
|
||||
display_Update();
|
||||
#endif
|
||||
//go to root
|
||||
sd.chdir();
|
||||
sprintf(folder, "ARC/CSV");
|
||||
sd.chdir(folder); // Switch Folder
|
||||
arccsvFile = sd.open(arccartCSV, O_READ);
|
||||
if (!arccsvFile) {
|
||||
#if (defined(enable_OLED) || defined(enable_LCD))
|
||||
display_Clear();
|
||||
println_Msg(F("CSV FILE NOT FOUND!"));
|
||||
display_Update();
|
||||
#else
|
||||
Serial.println(F("CSV FILE NOT FOUND!"));
|
||||
#endif
|
||||
while (1) {
|
||||
if (checkButton() != 0)
|
||||
setup_ARC();
|
||||
}
|
||||
}
|
||||
checkCSV_ARC();
|
||||
|
||||
arccsvFile.close();
|
||||
byte gameSize;
|
||||
|
||||
// Select starting letter
|
||||
//byte myLetter = starting_letter();
|
||||
|
||||
// Open database
|
||||
if (myFile.open("arccart.txt", O_READ)) {
|
||||
// seek_first_letter_in_database(myFile, myLetter);
|
||||
|
||||
if(checkCartSelection(myFile, &readDataLineSingleDigit, &gameSize)) {
|
||||
EEPROM_writeAnything(8, gameSize);
|
||||
}
|
||||
} else {
|
||||
print_FatalError(FS(FSTRING_DATABASE_FILE_NOT_FOUND));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
//******************************************
|
||||
// End of File
|
||||
//******************************************
|
||||
//******************************************
|
||||
|
|
File diff suppressed because it is too large
Load Diff
844
Cart_Reader/C64.ino
Normal file
844
Cart_Reader/C64.ino
Normal file
|
@ -0,0 +1,844 @@
|
|||
//******************************************
|
||||
// COMMODORE 64 MODULE
|
||||
//******************************************
|
||||
#ifdef ENABLE_C64
|
||||
// Commodore 64
|
||||
// Cartridge Pinout
|
||||
// 44P 2.54mm pitch connector
|
||||
//
|
||||
// FRONT BACK
|
||||
// SIDE SIDE
|
||||
// +-------+
|
||||
// GND -| 1 A |- GND
|
||||
// +5VDC -| 2 B |- /ROMH
|
||||
// +5VDC -| 3 C |- /RESET
|
||||
// /IRQ -| 4 D |- /NMI
|
||||
// R/W -| 5 E |- PHI2
|
||||
// DOTCLK -| 6 F |- A15
|
||||
// /IO1 -| 7 H |- A14
|
||||
// /GAME -| 8 J |- A13
|
||||
// /EXROM -| 9 K |- A12
|
||||
// /IO2 -| 10 L |- A11
|
||||
// /ROML -| 11 M |- A10
|
||||
// BA -| 12 N |- A9
|
||||
// /DMA -| 13 P |- A8
|
||||
// D7 -| 14 R |- A7
|
||||
// D6 -| 15 S |- A6
|
||||
// D5 -| 16 T |- A5
|
||||
// D4 -| 17 U |- A4
|
||||
// D3 -| 18 V |- A3
|
||||
// D2 -| 19 W |- A2
|
||||
// D1 -| 20 X |- A1
|
||||
// D0 -| 21 Y |- A0
|
||||
// GND -| 22 Z |- GND
|
||||
// +-------+
|
||||
//
|
||||
// TOP
|
||||
// +---------------------------------------------------------------------------------------+
|
||||
// | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
|
||||
// LEFT | | RIGHT
|
||||
// | A B C D E F H J K L M N P R S T U V W X Y Z |
|
||||
// +---------------------------------------------------------------------------------------+
|
||||
// BOTTOM
|
||||
//
|
||||
// CONTROL PINS:
|
||||
// /RESET(PH0) - SNES RESET
|
||||
// PHI2(PH1) - SNES CPUCLK
|
||||
// /GAME(PH3) - SNES /CS
|
||||
// /EXROM(PH4) - SNES /IRQ
|
||||
// R/W(PH6) - SNES /RD
|
||||
// /ROML(PL0) - SNES A16
|
||||
// /ROMH(PL1) - SNES A17
|
||||
// /IO1(PL2) - SNES A18
|
||||
// /IO2(PL3) - SNES A19
|
||||
|
||||
//******************************************
|
||||
// Defines
|
||||
//******************************************
|
||||
#define PHI2_ENABLE PORTH |= (1 << 1)
|
||||
#define PHI2_DISABLE PORTH &= ~(1 << 1)
|
||||
#define ROML_DISABLE PORTL |= (1 << 0)
|
||||
#define ROML_ENABLE PORTL &= ~(1 << 0)
|
||||
#define ROMH_DISABLE PORTL |= (1 << 1)
|
||||
#define ROMH_ENABLE PORTL &= ~(1 << 1)
|
||||
#define IO1_DISABLE PORTL |= (1 << 2)
|
||||
#define IO1_ENABLE PORTL &= ~(1 << 2)
|
||||
#define IO2_DISABLE PORTL |= (1 << 3)
|
||||
#define IO2_ENABLE PORTL &= ~(1 << 3)
|
||||
|
||||
//******************************************
|
||||
// Supported Mappers
|
||||
//******************************************
|
||||
// Supported Mapper Array
|
||||
// Format = {c64mapper,c64lo,c64hi}
|
||||
static const byte PROGMEM c64mapsize[] = {
|
||||
0, 0, 3, // Normal 4K/8K/16K + Ultimax 8K/16K
|
||||
1, 5, 5, // Action Replay 32K [UNTESTED]
|
||||
2, 3, 3, // KCS Power Cartridge 16K [UNTESTED]
|
||||
3, 6, 6, // Final Cartridge III 64K [UNTESTED]
|
||||
4, 3, 3, // Simons Basic 16K [UNTESTED]
|
||||
5, 7, 9, // Ocean 128K/256K/512K
|
||||
6, 2, 2, // Expert Cartridge 8K [UNTESTED]
|
||||
7, 7, 7, // Fun Play, Power Play 128K [UNTESTED]
|
||||
8, 6, 6, // Super Games 64K [UNTESTED]
|
||||
9, 5, 5, // Atomic Power 32K [UNTESTED]
|
||||
10, 2, 2, // Epyx Fastload 8K [UNTESTED]
|
||||
11, 3, 3, // Westermann Learning 16K [UNTESTED]
|
||||
12, 1, 1, // Rex Utility 8K [UNTESTED]
|
||||
13, 3, 3, // Final Cartridge I 16K [UNTESTED]
|
||||
14, 6, 6, // Magic Formel 64K [UNTESTED]
|
||||
15, 9, 9, // C64 Game System, System 3 512K [UNTESTED]
|
||||
16, 3, 3, // WarpSpeed 16K [UNTESTED]
|
||||
17, 7, 7, // Dinamic 128K [UNTESTED]
|
||||
18, 4, 4, // Zaxxon, Super Zaxxon (SEGA) 20K [UNTESTED]
|
||||
19, 5, 7, // Magic Desk, Domark, HES Australia 32K/64K/128K [UNTESTED]
|
||||
20, 6, 6, // Super Snapshot 5 64K [UNTESTED]
|
||||
21, 6, 6, // Comal-80 64K [UNTESTED]
|
||||
};
|
||||
|
||||
int C64[] = { 4, 8, 12, 16, 20, 32, 64, 128, 256, 512 };
|
||||
byte c64lo = 0; // Lowest Entry
|
||||
byte c64hi = 9; // Highest Entry
|
||||
|
||||
byte c64mapcount = 22; // (sizeof(mapsize)/sizeof(mapsize[0])) / 3;
|
||||
byte c64mapselect;
|
||||
int c64index;
|
||||
|
||||
byte c64mapper;
|
||||
byte c64size;
|
||||
uint8_t c64banks;
|
||||
byte c64port; // exrom+game
|
||||
|
||||
// EEPROM MAPPING
|
||||
// 07 MAPPER
|
||||
// 08 ROM SIZE
|
||||
|
||||
//******************************************
|
||||
// MENU
|
||||
//******************************************
|
||||
// Base Menu
|
||||
static const char* const menuOptionsC64[] PROGMEM = { FSTRING_SELECT_CART, FSTRING_READ_ROM, FSTRING_SET_SIZE, FSTRING_RESET };
|
||||
|
||||
void c64Menu() {
|
||||
convertPgm(menuOptionsC64, 4);
|
||||
uint8_t mainMenu = question_box(F("C64 MENU"), menuOptions, 4, 0);
|
||||
|
||||
switch (mainMenu) {
|
||||
case 0:
|
||||
// Select Cart
|
||||
setCart_C64();
|
||||
setup_C64();
|
||||
break;
|
||||
|
||||
case 1:
|
||||
// Read ROM
|
||||
sd.chdir("/");
|
||||
readROM_C64();
|
||||
sd.chdir("/");
|
||||
break;
|
||||
|
||||
case 2:
|
||||
// Set Mapper + Size
|
||||
setMapper_C64();
|
||||
checkMapperSize_C64();
|
||||
setROMSize_C64();
|
||||
break;
|
||||
|
||||
case 3:
|
||||
// reset
|
||||
resetArduino();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//******************************************
|
||||
// SETUP
|
||||
//******************************************
|
||||
void setup_C64() {
|
||||
// Request 5V
|
||||
setVoltage(VOLTS_SET_5V);
|
||||
|
||||
// Set Address Pins to Output
|
||||
// C64 uses A0-A15
|
||||
//A0-A7
|
||||
DDRF = 0xFF;
|
||||
//A8-A15
|
||||
DDRK = 0xFF;
|
||||
//A16-A23 - Use A16-A19 for /ROML, /ROMH, /IO1, /IO2
|
||||
DDRL = 0xFF;
|
||||
|
||||
// Set Control Pins to Output
|
||||
// /RST(PH0) ---(PH5) R/W(PH6)
|
||||
DDRH |= (1 << 0) | (1 << 5) | (1 << 6);
|
||||
|
||||
// Set Port Pins to Input
|
||||
// /GAME(PH3) /EXROM(PH4)
|
||||
DDRH &= ~((1 << 3) | (1 << 4));
|
||||
|
||||
// Set TIME(PJ0) to Output (UNUSED)
|
||||
DDRJ |= (1 << 0);
|
||||
|
||||
// Set Pins (D0-D7) to Input
|
||||
DDRC = 0x00;
|
||||
|
||||
// Setting Control Pins to HIGH
|
||||
// /RST(PH0) ---(PH5) R/W(PH6)
|
||||
PORTH |= (1 << 0) | (1 << 5) | (1 << 6);
|
||||
|
||||
// Set /ROML, /ROMH, /IO1, /IO2 to HIGH
|
||||
PORTL = 0xFF; // A16-A23 (A16 = /ROML, A17 = /ROMH, A18 = /IO1, A19 = /IO2)
|
||||
|
||||
// Set Unused Data Pins (PA0-PA7) to Output
|
||||
DDRA = 0xFF;
|
||||
|
||||
// Set Unused Pins HIGH
|
||||
PORTA = 0xFF;
|
||||
PORTJ |= (1 << 0); // TIME(PJ0)
|
||||
|
||||
#ifdef ENABLE_CLOCKGEN
|
||||
// Adafruit Clock Generator
|
||||
|
||||
initializeClockOffset();
|
||||
|
||||
if (!i2c_found) {
|
||||
display_Clear();
|
||||
print_FatalError(F("Clock Generator not found"));
|
||||
}
|
||||
|
||||
// Set Eeprom clock to 1Mhz
|
||||
clockgen.set_freq(100000000ULL, SI5351_CLK1);
|
||||
|
||||
// Start outputting Eeprom clock
|
||||
clockgen.output_enable(SI5351_CLK1, 1); // Eeprom clock
|
||||
|
||||
// Wait for clock generator
|
||||
clockgen.update_status();
|
||||
|
||||
#else
|
||||
// Set PHI2(PH1 to Output
|
||||
DDRH |= (1 << 1);
|
||||
// Setting Control Pins to HIGH for PHI2(PH1)
|
||||
PHI2_ENABLE;
|
||||
#endif
|
||||
|
||||
checkStatus_C64();
|
||||
strcpy(romName, "C64");
|
||||
|
||||
mode = CORE_C64;
|
||||
}
|
||||
|
||||
//******************************************
|
||||
// READ DATA
|
||||
//******************************************
|
||||
uint8_t readData_C64(uint16_t addr) {
|
||||
PORTF = addr & 0xFF; // A0-A7
|
||||
PORTK = (addr >> 8) & 0xFF; // A8-A15
|
||||
NOP;
|
||||
NOP;
|
||||
|
||||
// Set R/W(PH6) to HIGH
|
||||
PORTH |= (1 << 6); // R/W HIGH (READ)
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
|
||||
uint8_t ret = PINC;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void readSegment_C64(uint16_t startaddr, uint32_t endaddr, uint16_t size = 512) {
|
||||
for (uint32_t addr = startaddr; addr < endaddr; addr += size) {
|
||||
for (uint16_t w = 0; w < size; w++) {
|
||||
uint8_t temp = readData_C64(addr + w);
|
||||
sdBuffer[w] = temp;
|
||||
}
|
||||
myFile.write(sdBuffer, size);
|
||||
}
|
||||
}
|
||||
|
||||
void readSegmentEnableDisable_C64(uint16_t startaddr, uint32_t endaddr, byte romLow, uint16_t size = 512) {
|
||||
PORTL &= ~(1 << romLow); // enable ROML or ROMH
|
||||
readSegment_C64(startaddr, endaddr, size);
|
||||
PORTL |= (1 << romLow); // disable ROML or ROMH
|
||||
}
|
||||
|
||||
void readSegment16k_C64() {
|
||||
readSegmentEnableDisable_C64(0x8000, 0xA000, 0); // 8K
|
||||
readSegmentEnableDisable_C64(0xA000, 0xC000, 1); // +8K = 16K
|
||||
}
|
||||
|
||||
void readSegmentBankD0D5_C64(uint16_t banks, uint16_t address, byte romLow) {
|
||||
PORTL &= ~(1 << romLow); // enable ROML or ROMH
|
||||
uint32_t endAddress = address + 0x2000;
|
||||
for (uint16_t x = 0; x < banks; x++) {
|
||||
bankSwitch_C64(0xDE00, x); // Switch Bank using D0-D5
|
||||
readSegment_C64(address, endAddress);
|
||||
}
|
||||
PORTL |= (1 << romLow); // disable ROML or ROMH
|
||||
}
|
||||
|
||||
void readSegmentBankA0A4_C64(uint16_t banks) {
|
||||
ROML_ENABLE;
|
||||
for (uint16_t x = 0; x < banks; x++) {
|
||||
bankSwitch_C64(0xDE00 + x, 0); // Switch Bank using address lines
|
||||
readSegment_C64(0x8000, 0xA000); // 8K per bank
|
||||
}
|
||||
ROML_DISABLE;
|
||||
}
|
||||
|
||||
//******************************************
|
||||
// WRITE DATA
|
||||
//******************************************
|
||||
void writeData_C64(uint16_t addr, uint8_t data) {
|
||||
PORTF = addr & 0xFF; // A0-A7
|
||||
PORTK = (addr >> 8) & 0xFF; // A8-A15
|
||||
NOP;
|
||||
NOP;
|
||||
|
||||
DDRC = 0xFF; // Set to Output
|
||||
PORTC = data;
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
|
||||
// Set R/W(PH6) to LOW
|
||||
PORTH &= ~(1 << 6); // R/W LOW (WRITE)
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
|
||||
// Set R/W(PH6) to HIGH
|
||||
PORTH |= (1 << 6);
|
||||
NOP;
|
||||
NOP;
|
||||
|
||||
DDRC = 0x00; // Reset to Input
|
||||
}
|
||||
|
||||
void bankSwitch_C64(uint16_t addr, uint8_t data) {
|
||||
PORTF = addr & 0xFF; // A0-A7
|
||||
PORTK = (addr >> 8) & 0xFF; // A8-A15
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
|
||||
DDRC = 0xFF; // Set to Output
|
||||
PORTC = data;
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
|
||||
// Latch Bank Data
|
||||
PHI2_DISABLE; // PHI2 LOW
|
||||
if (((addr >> 8) & 0xFF) == 0xDF) // 0xDFxx
|
||||
IO2_ENABLE;
|
||||
else if (((addr >> 8) & 0xFF) == 0xDE) // 0xDExx
|
||||
IO1_ENABLE;
|
||||
PORTH &= ~(1 << 6); // R/W LOW (WRITE)
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
PORTH |= (1 << 6); // R/W HIGH (READ)
|
||||
PHI2_ENABLE; // PHI2 HIGH
|
||||
IO2_DISABLE;
|
||||
IO1_DISABLE;
|
||||
|
||||
DDRC = 0x00; // Reset to Input
|
||||
}
|
||||
|
||||
//******************************************
|
||||
// READ PORT STATE
|
||||
//******************************************
|
||||
void readPorts_C64() {
|
||||
c64port = (PINH >> 3) & 0x3;
|
||||
}
|
||||
|
||||
//******************************************
|
||||
// READ ROM
|
||||
//******************************************
|
||||
// ADDRESS RANGES
|
||||
// $8000-$9FFF/$A0000-$BFFF/$E000-$FFFF
|
||||
// NORMAL (EXROM LOW/GAME LOW): ROML = $8000, ROMH = $A000
|
||||
// ULTIMAX (EXROM HIGH/GAME LOW/): ROML = $8000, ROMH = $E000
|
||||
// GAME HIGH/EXROM LOW: ROML = $8000
|
||||
|
||||
void readROM_C64() {
|
||||
createFolderAndOpenFile("C64", "ROM", romName, "bin");
|
||||
|
||||
switch (c64mapper) {
|
||||
case 0: // Normal (4K/8K/16K) & Ultimax (8K/16K)
|
||||
readPorts_C64();
|
||||
// ULTIMAX CARTS
|
||||
if (c64port == 2) { // 2 = 10 = EXROM HIGH/GAME LOW
|
||||
if (c64size > 1) { // 16K [NO ROML FOR 8K]
|
||||
readSegmentEnableDisable_C64(0x8000, 0xA000, 0); // 8K
|
||||
}
|
||||
readSegmentEnableDisable_C64(0xE000, 0x10000, 1); // +8K = 8K/16K
|
||||
} else { // NORMAL CARTS
|
||||
if (c64size > 0) {
|
||||
readSegmentEnableDisable_C64(0x8000, 0xA000, 0); // 8K
|
||||
if (c64size > 1)
|
||||
readSegmentEnableDisable_C64(0xA000, 0xC000, 1); // +8K = 16K
|
||||
}
|
||||
else
|
||||
readSegmentEnableDisable_C64(0x9000, 0xA000, 0); // 4K
|
||||
}
|
||||
break;
|
||||
|
||||
case 1: // Action Replay (32K)
|
||||
case 9: // Atomic Power (32K)
|
||||
ROML_ENABLE;
|
||||
for (int x = 0; x < 4; x++) {
|
||||
bankSwitch_C64(0xDE00, x << 3); // Switch Bank using D3-D4
|
||||
readSegment_C64(0x8000, 0xA000); // 8K *4 = 32K
|
||||
}
|
||||
ROML_DISABLE;
|
||||
break;
|
||||
|
||||
case 2: // KCS Power Cartridge (16K)
|
||||
case 11: // Westermann Learning (16K)
|
||||
case 16: // WarpSpeed (16K)
|
||||
readSegment16k_C64();
|
||||
break;
|
||||
|
||||
case 3: // Final Cartridge III (64K)
|
||||
for (int x = 0; x < 4; x++) {
|
||||
bankSwitch_C64(0xDFFF, 0x40 + x); // Switch Bank using $DFFF
|
||||
readSegment16k_C64();
|
||||
}
|
||||
break;
|
||||
|
||||
case 4: // Simons Basic (16K)
|
||||
readSegmentEnableDisable_C64(0x8000, 0xA000, 0); // 8K
|
||||
ROMH_ENABLE;
|
||||
bankSwitch_C64(0xDE00, 0x1); // Switch Bank to ROM
|
||||
readSegment_C64(0xA000, 0xC000); // +8K = 16K
|
||||
ROMH_DISABLE;
|
||||
break;
|
||||
|
||||
// Ocean Bank 1/B (Single Chip) Selection Notes (Luigi Di Fraia):
|
||||
// 128 KiB cartridges (all known titles): bits 0-3 at $DE00 and /ROML (single 128 KiB chip with A16 on pin 22, rather than the /OE signal)
|
||||
// 256 KiB cartridges (just "Chase H.Q. II"): bits 0-4 at $DE00 and /ROML (single 256 KiB chip)
|
||||
// 512 KiB cartridges (just "Terminator 2"): bits 0-5 at $DE00 and /ROML (single 512 KiB chip)
|
||||
|
||||
// Ocean 256K ROM Start Data
|
||||
// Single Chip:
|
||||
// Chase HQ II 09 80 63 80 C3 C2 CD 38 30 4C 63 80 4C C8 80 80
|
||||
// Space Gun 09 80 09 80 C3 C2 CD 38 30 78 A2 FF 9A A9 E7 85
|
||||
// Two Chip:
|
||||
// Robocop 2 09 80 75 80 C3 C2 CD 38 30 4C 75 80 4C FA 80 80
|
||||
// Shadow of the Beast 09 80 83 81 C3 C2 CD 38 30 4C 83 81 4C 76 82 80
|
||||
// Read 0x8002 to determine whether Single Chip or Two Chip
|
||||
// IF 0x75 OR 0x83, THEN Two Chip ELSE Single Chip
|
||||
|
||||
case 5: { // Ocean 128K/256K/512K
|
||||
ROML_ENABLE;
|
||||
bankSwitch_C64(0xDE00, 0); // Reset Bank 0
|
||||
uint8_t checkOcean = readData_C64(0x8002);
|
||||
ROML_DISABLE;
|
||||
if ((c64size == 8) && ((checkOcean == 0x75) || (checkOcean == 0x83))) { // Two Chip 256K
|
||||
// Robocop 2 + Shadow of the Beast
|
||||
println_Msg(F("TWO CHIP"));
|
||||
display_Update();
|
||||
readSegmentBankD0D5_C64(16, 0x8000, 0); // 8K * 16 = 128K
|
||||
readSegmentBankD0D5_C64(16, 0xA000, 1); // 8K * 16 = +128K = 256K
|
||||
} else { // Single Chip 128K/256K/512K
|
||||
println_Msg(F("SINGLE CHIP"));
|
||||
display_Update();
|
||||
c64banks = C64[c64size] / 8;
|
||||
readSegmentBankD0D5_C64(c64banks, 0x8000, 0); // 8K * Banks = 128K/256K/512K
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 6: // Expert Cartridge (8K)
|
||||
readSegmentEnableDisable_C64(0x8000, 0xA000, 0);
|
||||
break;
|
||||
|
||||
case 7: // Fun Play, Power Play (128K)
|
||||
ROML_ENABLE;
|
||||
for (int x = 0; x < 8; x++) {
|
||||
bankSwitch_C64(0xDE00, x * 8); // Switch Bank 0-8
|
||||
readSegment_C64(0x8000, 0xA000); // 8K * 8 = 64K
|
||||
}
|
||||
ROML_DISABLE;
|
||||
ROMH_ENABLE;
|
||||
for (int x = 0; x < 8; x++) {
|
||||
bankSwitch_C64(0xDE00, (x * 8) + 1); // Switch Bank 9-15
|
||||
readSegment_C64(0x8000, 0xA000); // 8K * 8 = +64K = 128K
|
||||
}
|
||||
ROMH_DISABLE;
|
||||
bankSwitch_C64(0xDE00, 0x86); // Reset ROM
|
||||
break;
|
||||
|
||||
case 8: // Super Games (64K)
|
||||
for (int x = 0; x < 4; x++) {
|
||||
bankSwitch_C64(0xDF00, x); // Switch Bank
|
||||
readSegment16k_C64();
|
||||
}
|
||||
break;
|
||||
|
||||
case 10: // Epyx Fastload (8K)
|
||||
ROML_ENABLE;
|
||||
bankSwitch_C64(0xDE00, 0); // Read IO1 - Trigger Access
|
||||
readSegment_C64(0x8000, 0x9E00); // 7680 Bytes
|
||||
readSegment_C64(0x9E00, 0x9F00, 256); // +256 Bytes = 7936 Bytes
|
||||
bankSwitch_C64(0xDF00, 0); // Read IO2 - Access Last 256 Bytes
|
||||
readSegment_C64(0x9F00, 0xA000, 256); // +256 Bytes = 8K
|
||||
ROML_DISABLE;
|
||||
break;
|
||||
|
||||
case 12: // Rex Utility (8K)
|
||||
ROML_ENABLE;
|
||||
bankSwitch_C64(0xDFC0, 0); // Enable ROM
|
||||
readSegment_C64(0x8000, 0xA000); // 8K
|
||||
ROML_DISABLE;
|
||||
break;
|
||||
|
||||
case 13: // Final Cartridge I (16K)
|
||||
bankSwitch_C64(0xDF00, 0); // Enable ROM
|
||||
readSegment16k_C64();
|
||||
break;
|
||||
|
||||
case 14: // Magic Formel (64K)
|
||||
ROMH_ENABLE;
|
||||
for (int x = 0; x < 8; x++) {
|
||||
bankSwitch_C64(0xDF00 + x, 0); // Switch Bank using A0-A2
|
||||
readSegment_C64(0xE000, 0x10000); // 8K * 8 = 64K
|
||||
}
|
||||
ROMH_DISABLE;
|
||||
break;
|
||||
|
||||
case 15: // C64 Game System, System 3 (512K)
|
||||
readSegmentBankA0A4_C64(64);
|
||||
break;
|
||||
|
||||
case 17: // Dinamic (128K)
|
||||
readSegmentBankA0A4_C64(16);
|
||||
break;
|
||||
|
||||
case 18: // Zaxxon, Super Zaxxon (SEGA) (20K)
|
||||
readSegmentEnableDisable_C64(0x8000, 0x9000, 0); // 4K
|
||||
readSegmentEnableDisable_C64(0xA000, 0xC000, 1); // +8K = 12K
|
||||
// Switch Bank
|
||||
readData_C64(0x9000);
|
||||
readSegmentEnableDisable_C64(0xA000, 0xC000, 1); // +8K = 20K
|
||||
break;
|
||||
|
||||
case 19: // Magic Desk, Domark, HES Australia (32K/64K/128K)
|
||||
c64banks = C64[c64size] / 8;
|
||||
readSegmentBankD0D5_C64(c64banks, 0x8000, 0);
|
||||
break;
|
||||
|
||||
case 20: // Super Snapshot 5 (64K)
|
||||
for (int x = 0; x < 4; x++) {
|
||||
int bank = (((x & 2) << 3) | (0 << 3) | ((x & 1) << 2));
|
||||
bankSwitch_C64(0xDE00, bank); // Switch Bank using D2-D4 (D3 == 0 Enable ROM)
|
||||
readSegment16k_C64();
|
||||
}
|
||||
break;
|
||||
|
||||
case 21: // Comal-80 (64K)
|
||||
for (int x = 0; x < 4; x++) {
|
||||
bankSwitch_C64(0xDE00, x + 0x80); // Switch Bank
|
||||
readSegment16k_C64();
|
||||
}
|
||||
}
|
||||
myFile.close();
|
||||
|
||||
printCRC(fileName, NULL, 0);
|
||||
|
||||
println_Msg(FS(FSTRING_EMPTY));
|
||||
// Prints string out of the common strings array either with or without newline
|
||||
print_STR(press_button_STR, 1);
|
||||
display_Update();
|
||||
wait();
|
||||
}
|
||||
|
||||
//******************************************
|
||||
// MAPPER CODE
|
||||
//******************************************
|
||||
|
||||
#if (defined(ENABLE_OLED) || defined(ENABLE_LCD))
|
||||
void printMapperSelection_C64(int index) {
|
||||
display_Clear();
|
||||
print_Msg(FS(FSTRING_MAPPER));
|
||||
c64index = index * 3;
|
||||
c64mapselect = pgm_read_byte(c64mapsize + c64index);
|
||||
println_Msg(c64mapselect);
|
||||
printMapper_C64(c64mapselect);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
void setMapper_C64() {
|
||||
byte newc64mapper;
|
||||
#if (defined(ENABLE_OLED) || defined(ENABLE_LCD))
|
||||
navigateMenu(0, c64mapcount - 1, &printMapperSelection_C64);
|
||||
newc64mapper = c64mapselect;
|
||||
|
||||
display.setCursor(0, 56);
|
||||
print_Msg(F("MAPPER "));
|
||||
print_Msg(newc64mapper);
|
||||
println_Msg(F(" SELECTED"));
|
||||
display_Update();
|
||||
delay(1000);
|
||||
#else
|
||||
setmapper:
|
||||
String newmap;
|
||||
boolean c64mapfound = false;
|
||||
printMapper_C64(0);
|
||||
Serial.print(F("Enter Mapper [0-22]: "));
|
||||
while (Serial.available() == 0) {}
|
||||
newmap = Serial.readStringUntil('\n');
|
||||
Serial.println(newmap);
|
||||
newc64mapper = newmap.toInt();
|
||||
for (int i = 0; i < c64mapcount; i++) {
|
||||
c64index = i * 3;
|
||||
c64mapselect = pgm_read_byte(c64mapsize + c64index);
|
||||
if (newc64mapper == c64mapselect)
|
||||
c64mapfound = true;
|
||||
}
|
||||
if (c64mapfound == false) {
|
||||
Serial.println(F("MAPPER NOT SUPPORTED!"));
|
||||
Serial.println(FS(FSTRING_EMPTY));
|
||||
newc64mapper = 0;
|
||||
goto setmapper;
|
||||
}
|
||||
#endif
|
||||
EEPROM_writeAnything(7, newc64mapper);
|
||||
c64mapper = newc64mapper;
|
||||
}
|
||||
|
||||
void checkMapperSize_C64() {
|
||||
for (int i = 0; i < c64mapcount; i++) {
|
||||
c64index = i * 3;
|
||||
byte mapcheck = pgm_read_byte(c64mapsize + c64index);
|
||||
if (mapcheck == c64mapper) {
|
||||
c64lo = pgm_read_byte(c64mapsize + c64index + 1);
|
||||
c64hi = pgm_read_byte(c64mapsize + c64index + 2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//******************************************
|
||||
// SET ROM SIZE
|
||||
//******************************************
|
||||
|
||||
#if (defined(ENABLE_OLED) || defined(ENABLE_LCD))
|
||||
void printRomSize_C64(int index) {
|
||||
display_Clear();
|
||||
print_Msg(F("ROM Size: "));
|
||||
println_Msg(C64[index]);
|
||||
}
|
||||
#endif
|
||||
|
||||
void setROMSize_C64() {
|
||||
byte newc64size;
|
||||
#if (defined(ENABLE_OLED) || defined(ENABLE_LCD))
|
||||
display_Clear();
|
||||
if (c64lo == c64hi)
|
||||
newc64size = c64lo;
|
||||
else {
|
||||
newc64size = navigateMenu(c64lo, c64hi, &printRomSize_C64);
|
||||
|
||||
display.setCursor(0, 56); // Display selection at bottom
|
||||
}
|
||||
print_Msg(FS(FSTRING_ROM_SIZE));
|
||||
print_Msg(C64[newc64size]);
|
||||
println_Msg(F("K"));
|
||||
display_Update();
|
||||
delay(1000);
|
||||
#else
|
||||
if (c64lo == c64hi)
|
||||
newc64size = c64lo;
|
||||
else {
|
||||
setrom:
|
||||
String sizeROM;
|
||||
for (int i = 0; i < (c64hi - c64lo + 1); i++) {
|
||||
Serial.print(F("Select ROM Size: "));
|
||||
Serial.print(i);
|
||||
Serial.print(F(" = "));
|
||||
Serial.print(C64[i + c64lo]);
|
||||
Serial.println(F("K"));
|
||||
}
|
||||
Serial.print(F("Enter ROM Size: "));
|
||||
while (Serial.available() == 0) {}
|
||||
sizeROM = Serial.readStringUntil('\n');
|
||||
Serial.println(sizeROM);
|
||||
newc64size = sizeROM.toInt() + c64lo;
|
||||
if (newc64size > c64hi) {
|
||||
Serial.println(F("SIZE NOT SUPPORTED"));
|
||||
Serial.println(FS(FSTRING_EMPTY));
|
||||
goto setrom;
|
||||
}
|
||||
}
|
||||
Serial.print(F("ROM Size = "));
|
||||
Serial.print(C64[newc64size]);
|
||||
Serial.println(F("K"));
|
||||
#endif
|
||||
EEPROM_writeAnything(8, newc64size);
|
||||
c64size = newc64size;
|
||||
}
|
||||
|
||||
//******************************************
|
||||
// CHECK STATUS
|
||||
//******************************************
|
||||
void checkStatus_C64() {
|
||||
EEPROM_readAnything(7, c64mapper);
|
||||
EEPROM_readAnything(8, c64size);
|
||||
if (c64mapper > 21) {
|
||||
c64mapper = 0;
|
||||
EEPROM_writeAnything(7, c64mapper);
|
||||
}
|
||||
if (c64size > 9) {
|
||||
c64size = 0;
|
||||
EEPROM_writeAnything(8, c64size);
|
||||
}
|
||||
|
||||
#if (defined(ENABLE_OLED) || defined(ENABLE_LCD))
|
||||
display_Clear();
|
||||
println_Msg(F("C64 READER"));
|
||||
println_Msg(FS(FSTRING_CURRENT_SETTINGS));
|
||||
println_Msg(FS(FSTRING_EMPTY));
|
||||
print_Msg(F("MAPPER: "));
|
||||
println_Msg(c64mapper);
|
||||
printMapper_C64(c64mapper);
|
||||
print_Msg(F("ROM SIZE: "));
|
||||
print_Msg(C64[c64size]);
|
||||
println_Msg(F("K"));
|
||||
display_Update();
|
||||
wait();
|
||||
#else
|
||||
Serial.print(F("CURRENT MAPPER: "));
|
||||
Serial.println(c64mapper);
|
||||
Serial.print(F("CURRENT ROM SIZE: "));
|
||||
Serial.print(C64[c64size]);
|
||||
Serial.println(F("K"));
|
||||
Serial.println(FS(FSTRING_EMPTY));
|
||||
#endif
|
||||
}
|
||||
|
||||
void printMapper_C64(byte c64maplabel) {
|
||||
#if (defined(ENABLE_OLED) || defined(ENABLE_LCD))
|
||||
switch (c64maplabel) {
|
||||
case 0:
|
||||
println_Msg(F("NORMAL/ULTIMAX"));
|
||||
break;
|
||||
case 1:
|
||||
println_Msg(F("ACTION REPLAY"));
|
||||
break;
|
||||
case 2:
|
||||
println_Msg(F("KCS POWER CARTRIDGE"));
|
||||
break;
|
||||
case 3:
|
||||
println_Msg(F("FINAL CARTRIDGE III"));
|
||||
break;
|
||||
case 4:
|
||||
println_Msg(F("SIMONS BASIC"));
|
||||
break;
|
||||
case 5:
|
||||
println_Msg(F("OCEAN"));
|
||||
break;
|
||||
case 6:
|
||||
println_Msg(F("EXPERT CARTRIDGE"));
|
||||
break;
|
||||
case 7:
|
||||
println_Msg(F("FUN PLAY/POWER PLAY"));
|
||||
break;
|
||||
case 8:
|
||||
println_Msg(F("SUPER GAMES"));
|
||||
break;
|
||||
case 9:
|
||||
println_Msg(F("ATOMIC POWER"));
|
||||
break;
|
||||
case 10:
|
||||
println_Msg(F("EPYX FASTLOAD"));
|
||||
break;
|
||||
case 11:
|
||||
println_Msg(F("WESTERMANN LEARNING"));
|
||||
break;
|
||||
case 12:
|
||||
println_Msg(F("REX UTILITY"));
|
||||
break;
|
||||
case 13:
|
||||
println_Msg(F("FINAL CARTRIDGE I"));
|
||||
break;
|
||||
case 14:
|
||||
println_Msg(F("MAGIC FORMEL"));
|
||||
break;
|
||||
case 15:
|
||||
println_Msg(F("C64 GAME SYSTEM"));
|
||||
break;
|
||||
case 16:
|
||||
println_Msg(F("WARPSPEED"));
|
||||
break;
|
||||
case 17:
|
||||
println_Msg(F("DINAMIC"));
|
||||
break;
|
||||
case 18:
|
||||
println_Msg(F("ZAXXON/SUPER ZAXXON"));
|
||||
break;
|
||||
case 19:
|
||||
println_Msg(F("MAGIC DESK/DOMARK"));
|
||||
break;
|
||||
case 20:
|
||||
println_Msg(F("SUPER SNAPSHOT"));
|
||||
break;
|
||||
case 21:
|
||||
println_Msg(F("COMAL-80"));
|
||||
break;
|
||||
}
|
||||
#else
|
||||
Serial.println(F("0 = NORMAL/ULTIMAX"));
|
||||
Serial.println(F("1 = ACTION REPLAY"));
|
||||
Serial.println(F("2 = KCS POWER CARTRIDGE"));
|
||||
Serial.println(F("3 = FINAL CARTRIDGE III"));
|
||||
Serial.println(F("4 = SIMONS BASIC"));
|
||||
Serial.println(F("5 = OCEAN"));
|
||||
Serial.println(F("6 = EXPERT CARTRIDGE"));
|
||||
Serial.println(F("7 = FUN PLAY/POWER PLAY"));
|
||||
Serial.println(F("8 = SUPER GAMES"));
|
||||
Serial.println(F("9 = ATOMIC POWER"));
|
||||
Serial.println(F("10 = EPYX FASTLOAD"));
|
||||
Serial.println(F("11 = WESTERMANN LEARNING"));
|
||||
Serial.println(F("12 = REX UTILITY"));
|
||||
Serial.println(F("13 = FINAL CARTRIDGE I"));
|
||||
Serial.println(F("14 = MAGIC FORMEL"));
|
||||
Serial.println(F("15 = C64 GAME SYSTEM"));
|
||||
Serial.println(F("16 = WARPSPEED"));
|
||||
Serial.println(F("17 = DINAMIC"));
|
||||
Serial.println(F("18 = ZAXXON/SUPER ZAXXON"));
|
||||
Serial.println(F("19 = MAGIC DESK/DOMARK/HES AUSTRALIA"));
|
||||
Serial.println(F("20 = SUPER SNAPSHOT"));
|
||||
Serial.println(F("21 = COMAL-80"));
|
||||
#endif
|
||||
}
|
||||
|
||||
//******************************************
|
||||
// CART SELECT CODE
|
||||
//******************************************
|
||||
|
||||
void setCart_C64() {
|
||||
//go to root
|
||||
sd.chdir();
|
||||
|
||||
struct database_entry_mapper_size entry;
|
||||
|
||||
// Select starting letter
|
||||
byte myLetter = starting_letter();
|
||||
|
||||
// Open database
|
||||
if (myFile.open("c64cart.txt", O_READ)) {
|
||||
seek_first_letter_in_database(myFile, myLetter);
|
||||
|
||||
if(checkCartSelection(myFile, &readDataLineMapperSize, &entry)) {
|
||||
EEPROM_writeAnything(7, entry.gameMapper);
|
||||
EEPROM_writeAnything(8, entry.gameSize);
|
||||
}
|
||||
} else {
|
||||
print_FatalError(FS(FSTRING_DATABASE_FILE_NOT_FOUND));
|
||||
}
|
||||
}
|
||||
#endif
|
|
@ -1,7 +1,7 @@
|
|||
//******************************************
|
||||
// COLECOVISION MODULE
|
||||
//******************************************
|
||||
#ifdef enable_COLV
|
||||
#ifdef ENABLE_COLV
|
||||
|
||||
// Coleco Colecovision
|
||||
// Cartridge Pinout
|
||||
|
@ -39,7 +39,6 @@ byte collo = 0; // Lowest Entry
|
|||
byte colhi = 5; // Highest Entry
|
||||
|
||||
byte colsize;
|
||||
byte newcolsize;
|
||||
|
||||
// EEPROM MAPPING
|
||||
// 08 ROM SIZE
|
||||
|
@ -48,11 +47,7 @@ byte newcolsize;
|
|||
// Menu
|
||||
//******************************************
|
||||
// Base Menu
|
||||
static const char colMenuItem1[] PROGMEM = "Select Cart";
|
||||
static const char colMenuItem2[] PROGMEM = "Read ROM";
|
||||
static const char colMenuItem3[] PROGMEM = "Set Size";
|
||||
//static const char colMenuItem4[] PROGMEM = "Reset"; (stored in common strings array)
|
||||
static const char* const menuOptionsCOL[] PROGMEM = { colMenuItem1, colMenuItem2, colMenuItem3, string_reset2 };
|
||||
static const char* const menuOptionsCOL[] PROGMEM = { FSTRING_SELECT_CART, FSTRING_READ_ROM, FSTRING_SET_SIZE, FSTRING_RESET };
|
||||
|
||||
void setup_COL() {
|
||||
// Request 5V
|
||||
|
@ -92,7 +87,7 @@ void setup_COL() {
|
|||
checkStatus_COL();
|
||||
strcpy(romName, "COLECO");
|
||||
|
||||
mode = mode_COL;
|
||||
mode = CORE_COL;
|
||||
}
|
||||
|
||||
void colMenu() {
|
||||
|
@ -167,29 +162,7 @@ void readSegment_COL(uint32_t startaddr, uint32_t endaddr) {
|
|||
}
|
||||
|
||||
void readROM_COL() {
|
||||
strcpy(fileName, romName);
|
||||
strcat(fileName, ".col");
|
||||
|
||||
// create a new folder for storing rom file
|
||||
EEPROM_readAnything(0, foldern);
|
||||
// sprintf(folder, "COL/ROM/%s/%d", romName, foldern);
|
||||
sprintf(folder, "COL/ROM/%d", foldern);
|
||||
sd.mkdir(folder, true);
|
||||
sd.chdir(folder);
|
||||
|
||||
display_Clear();
|
||||
print_STR(saving_to_STR, 0);
|
||||
print_Msg(folder);
|
||||
println_Msg(F("/..."));
|
||||
display_Update();
|
||||
|
||||
// open file on sdcard
|
||||
if (!myFile.open(fileName, O_RDWR | O_CREAT))
|
||||
print_FatalError(create_file_STR);
|
||||
|
||||
// write new folder number back to EEPROM
|
||||
foldern++;
|
||||
EEPROM_writeAnything(0, foldern);
|
||||
createFolderAndOpenFile("COL", "ROM", romName, "col");
|
||||
|
||||
// RESET ALL CS PINS HIGH (DISABLE)
|
||||
PORTH |= (1 << 3) | (1 << 4) | (1 << 5) | (1 << 6);
|
||||
|
@ -218,7 +191,7 @@ void readROM_COL() {
|
|||
// Compare CRC32 to database and rename ROM if found
|
||||
compareCRC("colv.txt", 0, 1, 0);
|
||||
|
||||
println_Msg(F(""));
|
||||
println_Msg(FS(FSTRING_EMPTY));
|
||||
// Prints string out of the common strings array either with or without newline
|
||||
print_STR(press_button_STR, 1);
|
||||
display_Update();
|
||||
|
@ -229,78 +202,27 @@ void readROM_COL() {
|
|||
// ROM SIZE
|
||||
//******************************************
|
||||
|
||||
#if (defined(ENABLE_OLED) || defined(ENABLE_LCD))
|
||||
void printRomSize_COL(int index) {
|
||||
display_Clear();
|
||||
print_Msg(F("ROM Size: "));
|
||||
println_Msg(pgm_read_byte(&(COL[index])));
|
||||
}
|
||||
#endif
|
||||
|
||||
void setROMSize_COL() {
|
||||
#if (defined(enable_OLED) || defined(enable_LCD))
|
||||
byte newcolsize;
|
||||
#if (defined(ENABLE_OLED) || defined(ENABLE_LCD))
|
||||
display_Clear();
|
||||
if (collo == colhi)
|
||||
newcolsize = collo;
|
||||
else {
|
||||
int b = 0;
|
||||
int i = collo;
|
||||
|
||||
display_Clear();
|
||||
print_Msg(F("ROM Size: "));
|
||||
println_Msg(pgm_read_byte(&(COL[i])));
|
||||
println_Msg(F(""));
|
||||
#if defined(enable_OLED)
|
||||
print_STR(press_to_change_STR, 1);
|
||||
print_STR(right_to_select_STR, 1);
|
||||
#elif defined(enable_LCD)
|
||||
print_STR(rotate_to_change_STR, 1);
|
||||
print_STR(press_to_select_STR, 1);
|
||||
#endif
|
||||
display_Update();
|
||||
|
||||
while (1) {
|
||||
b = checkButton();
|
||||
if (b == 2) { // Previous (doubleclick)
|
||||
if (i == collo)
|
||||
i = colhi;
|
||||
else
|
||||
i--;
|
||||
|
||||
// Only update display after input because of slow LCD library
|
||||
display_Clear();
|
||||
print_Msg(F("ROM Size: "));
|
||||
println_Msg(pgm_read_byte(&(COL[i])));
|
||||
println_Msg(F(""));
|
||||
#if defined(enable_OLED)
|
||||
print_STR(press_to_change_STR, 1);
|
||||
print_STR(right_to_select_STR, 1);
|
||||
#elif defined(enable_LCD)
|
||||
print_STR(rotate_to_change_STR, 1);
|
||||
print_STR(press_to_select_STR, 1);
|
||||
#endif
|
||||
display_Update();
|
||||
}
|
||||
if (b == 1) { // Next (press)
|
||||
if (i == colhi)
|
||||
i = collo;
|
||||
else
|
||||
i++;
|
||||
|
||||
// Only update display after input because of slow LCD library
|
||||
display_Clear();
|
||||
print_Msg(F("ROM Size: "));
|
||||
println_Msg(pgm_read_byte(&(COL[i])));
|
||||
println_Msg(F(""));
|
||||
#if defined(enable_OLED)
|
||||
print_STR(press_to_change_STR, 1);
|
||||
print_STR(right_to_select_STR, 1);
|
||||
#elif defined(enable_LCD)
|
||||
print_STR(rotate_to_change_STR, 1);
|
||||
print_STR(press_to_select_STR, 1);
|
||||
#endif
|
||||
display_Update();
|
||||
}
|
||||
if (b == 3) { // Long Press - Execute (hold)
|
||||
newcolsize = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
newcolsize = navigateMenu(collo, colhi, &printRomSize_COL);
|
||||
|
||||
display.setCursor(0, 56); // Display selection at bottom
|
||||
}
|
||||
print_Msg(F("ROM SIZE "));
|
||||
|
||||
print_Msg(FS(FSTRING_ROM_SIZE));
|
||||
print_Msg(pgm_read_byte(&(COL[newcolsize])));
|
||||
println_Msg(F("K"));
|
||||
display_Update();
|
||||
|
@ -325,7 +247,7 @@ setrom:
|
|||
newcolsize = sizeROM.toInt() + collo;
|
||||
if (newcolsize > colhi) {
|
||||
Serial.println(F("SIZE NOT SUPPORTED"));
|
||||
Serial.println(F(""));
|
||||
Serial.println(FS(FSTRING_EMPTY));
|
||||
goto setrom;
|
||||
}
|
||||
}
|
||||
|
@ -344,15 +266,15 @@ void checkStatus_COL() {
|
|||
EEPROM_writeAnything(8, colsize);
|
||||
}
|
||||
|
||||
#if (defined(enable_OLED) || defined(enable_LCD))
|
||||
#if (defined(ENABLE_OLED) || defined(ENABLE_LCD))
|
||||
display_Clear();
|
||||
println_Msg(F("COLECOVISION READER"));
|
||||
println_Msg(F("CURRENT SETTINGS"));
|
||||
println_Msg(F(""));
|
||||
print_Msg(F("ROM SIZE: "));
|
||||
println_Msg(FS(FSTRING_CURRENT_SETTINGS));
|
||||
println_Msg(FS(FSTRING_EMPTY));
|
||||
print_Msg(FS(FSTRING_ROM_SIZE));
|
||||
print_Msg(pgm_read_byte(&(COL[colsize])));
|
||||
println_Msg(F("K"));
|
||||
println_Msg(F(""));
|
||||
println_Msg(FS(FSTRING_EMPTY));
|
||||
// Prints string out of the common strings array either with or without newline
|
||||
print_STR(press_button_STR, 1);
|
||||
display_Update();
|
||||
|
@ -361,164 +283,101 @@ void checkStatus_COL() {
|
|||
Serial.print(F("CURRENT ROM SIZE: "));
|
||||
Serial.print(pgm_read_byte(&(COL[colsize])));
|
||||
Serial.println(F("K"));
|
||||
Serial.println(F(""));
|
||||
Serial.println(FS(FSTRING_EMPTY));
|
||||
#endif
|
||||
}
|
||||
|
||||
//******************************************
|
||||
// CART SELECT CODE
|
||||
//******************************************
|
||||
void setCart_COL() {
|
||||
char gamename[100];
|
||||
char tempStr2[2];
|
||||
struct database_entry_COL {
|
||||
char crc_search[9];
|
||||
byte gameSize;
|
||||
};
|
||||
|
||||
void readDataLine_COL(FsFile& database, void* entry) {
|
||||
struct database_entry_COL* castEntry = (database_entry_COL*)entry;
|
||||
|
||||
// Read CRC32 checksum
|
||||
for (byte i = 0; i < 8; i++) {
|
||||
checksumStr[i] = char(database.read());
|
||||
}
|
||||
|
||||
// Skip over semicolon
|
||||
database.seekCur(1);
|
||||
|
||||
// Read CRC32 of first 512 bytes
|
||||
for (byte i = 0; i < 8; i++) {
|
||||
castEntry->crc_search[i] = char(database.read());
|
||||
}
|
||||
|
||||
// Skip over semicolon
|
||||
database.seekCur(1);
|
||||
|
||||
// Read rom size
|
||||
// Read the next ascii character and subtract 48 to convert to decimal
|
||||
castEntry->gameSize = ((database.read() - 48) * 10) + (database.read() - 48);
|
||||
|
||||
// Skip rest of line
|
||||
database.seekCur(2);
|
||||
}
|
||||
|
||||
void printDataLine_COL(void* entry) {
|
||||
struct database_entry_COL* castEntry = (database_entry_COL*)entry;
|
||||
|
||||
print_Msg(FS(FSTRING_SIZE));
|
||||
print_Msg(castEntry->gameSize);
|
||||
println_Msg(F("KB"));
|
||||
}
|
||||
|
||||
void setCart_COL() {
|
||||
//go to root
|
||||
sd.chdir();
|
||||
|
||||
struct database_entry_COL entry;
|
||||
|
||||
// Select starting letter
|
||||
byte myLetter = starting_letter();
|
||||
|
||||
// Open database
|
||||
if (myFile.open("colv.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);
|
||||
seek_first_letter_in_database(myFile, myLetter);
|
||||
|
||||
// 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;
|
||||
}
|
||||
if(checkCartSelection(myFile, &readDataLine_COL, &entry, &printDataLine_COL)) {
|
||||
//byte COL[] = {8, 12, 16, 20, 24, 32};
|
||||
switch (entry.gameSize) {
|
||||
case 8:
|
||||
colsize = 0;
|
||||
break;
|
||||
|
||||
// Rewind one line
|
||||
rewind_line(myFile);
|
||||
}
|
||||
case 12:
|
||||
colsize = 1;
|
||||
break;
|
||||
|
||||
// Display database
|
||||
while (myFile.available()) {
|
||||
display_Clear();
|
||||
case 16:
|
||||
colsize = 2;
|
||||
break;
|
||||
|
||||
// Read game name
|
||||
get_line(gamename, &myFile, 96);
|
||||
case 20:
|
||||
colsize = 3;
|
||||
break;
|
||||
|
||||
// Read CRC32 checksum
|
||||
sprintf(checksumStr, "%c", myFile.read());
|
||||
for (byte i = 0; i < 7; i++) {
|
||||
sprintf(tempStr2, "%c", myFile.read());
|
||||
strcat(checksumStr, tempStr2);
|
||||
}
|
||||
case 24:
|
||||
colsize = 4;
|
||||
break;
|
||||
|
||||
// Skip over semicolon
|
||||
myFile.seekCur(1);
|
||||
case 32:
|
||||
colsize = 5;
|
||||
break;
|
||||
|
||||
// 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.seekCur(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.seekCur(2);
|
||||
|
||||
// Skip every 3rd line
|
||||
skip_line(&myFile);
|
||||
|
||||
println_Msg(F("Select your cartridge"));
|
||||
println_Msg(F(""));
|
||||
println_Msg(gamename);
|
||||
print_Msg(F("Size: "));
|
||||
print_Msg(cartSize);
|
||||
println_Msg(F("KB"));
|
||||
println_Msg(F(""));
|
||||
#if defined(enable_OLED)
|
||||
print_STR(press_to_change_STR, 1);
|
||||
print_STR(right_to_select_STR, 1);
|
||||
#elif defined(enable_LCD)
|
||||
print_STR(rotate_to_change_STR, 1);
|
||||
print_STR(press_to_select_STR, 1);
|
||||
#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) {
|
||||
default:
|
||||
colsize = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
// Previous
|
||||
else if (b == 2) {
|
||||
rewind_line(myFile, 6);
|
||||
break;
|
||||
}
|
||||
|
||||
// Selection
|
||||
else if (b == 3) {
|
||||
//byte COL[] = {8, 12, 16, 20, 24, 32};
|
||||
switch (cartSize) {
|
||||
case 8:
|
||||
colsize = 0;
|
||||
break;
|
||||
|
||||
case 12:
|
||||
colsize = 1;
|
||||
break;
|
||||
|
||||
case 16:
|
||||
colsize = 2;
|
||||
break;
|
||||
|
||||
case 20:
|
||||
colsize = 3;
|
||||
break;
|
||||
|
||||
case 24:
|
||||
colsize = 4;
|
||||
break;
|
||||
|
||||
case 32:
|
||||
colsize = 5;
|
||||
break;
|
||||
|
||||
default:
|
||||
colsize = 0;
|
||||
break;
|
||||
}
|
||||
EEPROM_writeAnything(8, colsize);
|
||||
myFile.close();
|
||||
break;
|
||||
}
|
||||
}
|
||||
EEPROM_writeAnything(8, colsize);
|
||||
}
|
||||
} else {
|
||||
print_FatalError(F("Database file not found"));
|
||||
print_FatalError(FS(FSTRING_DATABASE_FILE_NOT_FOUND));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -77,7 +77,7 @@ void DynamicClockSerial::begin(unsigned long baud, byte config, unsigned long sc
|
|||
}
|
||||
|
||||
// ClockedSerial setup
|
||||
#if !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_SERIAL) && !defined(enable_serial) && defined(ENABLE_UPDATER)
|
||||
#if !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_SERIAL) && !defined(ENABLE_SERIAL) && defined(ENABLE_UPDATER)
|
||||
#if defined(UBRRH) && defined(UBRRL)
|
||||
DynamicClockSerial ClockedSerial(&UBRRH, &UBRRL, &UCSRA, &UCSRB, &UCSRC, &UDR);
|
||||
#else
|
||||
|
|
|
@ -1,32 +1,32 @@
|
|||
/********************************************************************
|
||||
* Open Source Cartridge Reader *
|
||||
Open Source Cartridge Reader
|
||||
********************************************************************/
|
||||
|
||||
#ifndef CONFIG_H_
|
||||
#define CONFIG_H_
|
||||
|
||||
/***** FIRMWARE CONFIGURATION **************************************
|
||||
*
|
||||
* Add or remove the "//" in front of items to toggle them.
|
||||
*
|
||||
* Disabled:
|
||||
* //#define HW5
|
||||
*
|
||||
* Enabled:
|
||||
* #define HW5
|
||||
*
|
||||
* Things in ** blocks like this are comments. Changing them doesn't
|
||||
* affect the firmware that is flashed to your OSCR.
|
||||
*
|
||||
* If you only get a blank screen or "Press Button" message after
|
||||
* flashing you have enabled too many modules.
|
||||
*
|
||||
|
||||
Add or remove the "//" in front of items to toggle them.
|
||||
|
||||
Disabled:
|
||||
//#define HW5
|
||||
|
||||
Enabled:
|
||||
#define HW5
|
||||
|
||||
Things in ** blocks like this are comments. Changing them doesn't
|
||||
affect the firmware that is flashed to your OSCR.
|
||||
|
||||
If you only get a blank screen or "Press Button" message after
|
||||
flashing you have enabled too many modules.
|
||||
|
||||
********************************************************************/
|
||||
|
||||
/*==== HARDWARE VERSION ===========================================*/
|
||||
|
||||
/*
|
||||
* Choose your hardware version:
|
||||
Choose your hardware version:
|
||||
*/
|
||||
|
||||
//#define HW5
|
||||
|
@ -41,7 +41,7 @@
|
|||
/*==== HARDWARE MODULES ===========================================*/
|
||||
|
||||
/* [ Automatic Voltage Selection ---------------------------------- ]
|
||||
* Enable this if you have the VSELECT module.
|
||||
Enable this if you have the VSELECT module.
|
||||
*/
|
||||
|
||||
//#define ENABLE_VSELECT
|
||||
|
@ -49,18 +49,20 @@
|
|||
/****/
|
||||
|
||||
/* [ Clock Generator ---------------------------------------------- ]
|
||||
* Enable this if you have the clock generator module.
|
||||
Enable this if you have the clock generator module. This will
|
||||
automatically be enabled if you selected HW2 or newer above.
|
||||
*/
|
||||
|
||||
//#define clockgen_installed
|
||||
//#define ENABLE_CLOCKGEN
|
||||
|
||||
/****/
|
||||
|
||||
/* [ Real Time Clock ---------------------------------------------- ]
|
||||
* Enable this if you have the RTC module.
|
||||
Enable this if you have the RTC module. You can configure the
|
||||
type later in this file.
|
||||
*/
|
||||
|
||||
//#define RTC_installed
|
||||
//#define ENABLE_RTC
|
||||
|
||||
/****/
|
||||
|
||||
|
@ -69,199 +71,262 @@
|
|||
/* [ Atari 2600 --------------------------------------------------- ]
|
||||
*/
|
||||
|
||||
//#define enable_ATARI
|
||||
//#define ENABLE_2600
|
||||
|
||||
/****/
|
||||
|
||||
/* [ Atari 5200 --------------------------------------------------- ]
|
||||
*/
|
||||
|
||||
//#define ENABLE_5200
|
||||
|
||||
/****/
|
||||
|
||||
/* [ Atari 7800 --------------------------------------------------- ]
|
||||
*/
|
||||
|
||||
//#define ENABLE_7800
|
||||
|
||||
/****/
|
||||
|
||||
/* [ Benesse Pocket Challenge W ----------------------------------- ]
|
||||
*/
|
||||
|
||||
//#define enable_PCW
|
||||
//#define ENABLE_PCW
|
||||
|
||||
/****/
|
||||
|
||||
/* [ C64 --------------------------------------------------- ]
|
||||
*/
|
||||
|
||||
//#define ENABLE_C64
|
||||
|
||||
/****/
|
||||
|
||||
/* [ ColecoVision ------------------------------------------------- ]
|
||||
*/
|
||||
|
||||
//#define enable_COLV
|
||||
//#define ENABLE_COLV
|
||||
|
||||
/****/
|
||||
|
||||
/* [ Emerson Arcadia 2001 ----------------------------------------- ]
|
||||
*/
|
||||
|
||||
//#define enable_ARC
|
||||
//#define ENABLE_ARC
|
||||
|
||||
/****/
|
||||
|
||||
/* [ Fairchild Channel F ------------------------------------------ ]
|
||||
*/
|
||||
|
||||
//#define enable_FAIRCHILD
|
||||
//#define ENABLE_FAIRCHILD
|
||||
|
||||
/****/
|
||||
|
||||
/* [ Flashrom Programmer for SNES repros -------------------------- ]
|
||||
*/
|
||||
|
||||
#define enable_FLASH
|
||||
//#define enable_FLASH16
|
||||
//#define ENABLE_FLASH
|
||||
//#define ENABLE_FLASH16
|
||||
|
||||
/****/
|
||||
|
||||
/* [ Game Boy (Color) and Advance --------------------------------- ]
|
||||
*/
|
||||
|
||||
#define enable_GBX
|
||||
#define ENABLE_GBX
|
||||
|
||||
/****/
|
||||
|
||||
/* [ Intellivision ------------------------------------------------ ]
|
||||
*/
|
||||
|
||||
//#define enable_INTV
|
||||
//#define ENABLE_INTV
|
||||
|
||||
/****/
|
||||
|
||||
/* [ Neo Geo Pocket ----------------------------------------------- ]
|
||||
*/
|
||||
|
||||
//#define enable_NGP
|
||||
//#define ENABLE_NGP
|
||||
|
||||
/****/
|
||||
|
||||
/* [ Nintendo 64 -------------------------------------------------- ]
|
||||
*/
|
||||
|
||||
#define enable_N64
|
||||
#define ENABLE_N64
|
||||
|
||||
/****/
|
||||
|
||||
/* [ Nintendo Entertainment System/Family Computer ---------------- ]
|
||||
*/
|
||||
|
||||
#define enable_NES
|
||||
#define ENABLE_NES
|
||||
|
||||
/****/
|
||||
|
||||
/* [ Magnavox Odyssey 2 ------------------------------------------- ]
|
||||
*/
|
||||
|
||||
//#define enable_ODY2
|
||||
//#define ENABLE_ODY2
|
||||
|
||||
/****/
|
||||
|
||||
/* [ MSX ------------------------------------------- ]
|
||||
*/
|
||||
|
||||
//#define enable_MSX
|
||||
//#define ENABLE_MSX
|
||||
|
||||
/****/
|
||||
|
||||
/* [ PC Engine/TurboGrafx 16 -------------------------------------- ]
|
||||
*/
|
||||
|
||||
//#define enable_PCE
|
||||
//#define ENABLE_PCE
|
||||
|
||||
/****/
|
||||
|
||||
/* [ Pokemon Mini -------------------------------------- ]
|
||||
*/
|
||||
|
||||
//#define enable_POKE
|
||||
//#define ENABLE_POKE
|
||||
|
||||
/****/
|
||||
|
||||
/* [ Sega Master System/Mark III/Game Gear/SG-1000 ---------------- ]
|
||||
*/
|
||||
|
||||
#define enable_SMS
|
||||
#define ENABLE_SMS
|
||||
|
||||
/****/
|
||||
|
||||
/* [ Sega Mega Drive/Genesis -------------------------------------- ]
|
||||
*/
|
||||
|
||||
#define enable_MD
|
||||
#define ENABLE_MD
|
||||
|
||||
/****/
|
||||
|
||||
/* [ Super Famicom SF Memory Cassette ----------------------------- ]
|
||||
*/
|
||||
|
||||
#define enable_SFM
|
||||
//#define ENABLE_SFM
|
||||
|
||||
/****/
|
||||
|
||||
/* [ Super Famicom Satellaview ------------------------------------ ]
|
||||
*/
|
||||
|
||||
#define enable_SV
|
||||
//#define ENABLE_SV
|
||||
|
||||
/****/
|
||||
|
||||
/* [ Super Famicom Sufami Turbo ----------------------------------- ]
|
||||
*/
|
||||
|
||||
//#define ENABLE_ST
|
||||
|
||||
/****/
|
||||
|
||||
/* [ Super Famicom Game Processor RAM Cassette -------------------- ]
|
||||
*/
|
||||
|
||||
//#define ENABLE_GPC
|
||||
|
||||
/****/
|
||||
|
||||
/* [ Super Nintendo ----------------------------------------------- ]
|
||||
*/
|
||||
|
||||
#define enable_SNES
|
||||
#define ENABLE_SNES
|
||||
|
||||
/****/
|
||||
|
||||
/* [ Vectrex --------------------------------------------------- ]
|
||||
*/
|
||||
|
||||
//#define ENABLE_VECTREX
|
||||
|
||||
/****/
|
||||
|
||||
/* [ Virtual Boy -------------------------------------------------- ]
|
||||
*/
|
||||
|
||||
//#define enable_VBOY
|
||||
//#define ENABLE_VBOY
|
||||
|
||||
/****/
|
||||
|
||||
/* [ Watara Supervision ------------------------------------------- ]
|
||||
/* [ Watara Supervision ------------------------------------------- ]
|
||||
*/
|
||||
|
||||
//#define enable_WSV
|
||||
//#define ENABLE_WSV
|
||||
|
||||
/****/
|
||||
|
||||
/* [ WonderSwan and Benesse Pocket Challenge v2 ------------------- ]
|
||||
*/
|
||||
|
||||
//#define enable_WS
|
||||
//#define ENABLE_WS
|
||||
|
||||
/****/
|
||||
|
||||
/* [ Super A'can -------------------------------------------------- ]
|
||||
*/
|
||||
|
||||
//#define enable_SUPRACAN
|
||||
//#define ENABLE_SUPRACAN
|
||||
|
||||
/****/
|
||||
|
||||
/* [ Casio Loopy -------------------------------------------------- ]
|
||||
*/
|
||||
|
||||
//#define enable_LOOPY
|
||||
//#define ENABLE_LOOPY
|
||||
|
||||
/****/
|
||||
|
||||
/*==== FIRMWARE OPTIONS ===========================================*/
|
||||
|
||||
/* [ LCD: Background Color ---------------------------------------- ]
|
||||
* Set the backlight color of the LCD if you have one.
|
||||
*
|
||||
* PARAMETERS:
|
||||
* Green, Red, Blue
|
||||
/* [ Config File -------------------------------------------------- ]
|
||||
Allow changing some configuration values via a config file. You
|
||||
generally can only use the config to set options or disable
|
||||
certain featuress. It cannot be used to toggle firmware options
|
||||
on, only off.
|
||||
|
||||
Note For Developers: See OSCR.* for info.
|
||||
|
||||
Filename: config.txt
|
||||
*/
|
||||
|
||||
#define background_color 100, 0, 0
|
||||
//#define ENABLE_CONFIG
|
||||
|
||||
/****/
|
||||
|
||||
/* [ LCD: Background Color ---------------------------------------- ]
|
||||
Set the backlight color of the LCD if you have one.
|
||||
|
||||
Can be set using config:
|
||||
lcd.confColor=1
|
||||
lcd.red=0
|
||||
lcd.green=0
|
||||
lcd.blue=0
|
||||
|
||||
PARAMETERS:
|
||||
Green, Red, Blue
|
||||
*/
|
||||
|
||||
#define OPTION_LCD_BG_COLOR 100, 0, 0
|
||||
|
||||
/****/
|
||||
|
||||
/* [ 3.3V Stability Fix (3V3FIX) ---------------------------------- ]
|
||||
* Enable this if you are having stability issues when using 3.3V,
|
||||
* works best with VSELECT.
|
||||
*
|
||||
* If not using VSELECT, always turn the cart reader on with the
|
||||
* voltage switch set to 5V and switch to 5V before selecting a
|
||||
* cartridge from the menu.
|
||||
Enable this if you are having stability issues when using 3.3V,
|
||||
works best with VSELECT.
|
||||
|
||||
If not using VSELECT, always turn the cart reader on with the
|
||||
voltage switch set to 5V and switch to 5V before selecting a
|
||||
cartridge from the menu.
|
||||
*/
|
||||
|
||||
//#define ENABLE_3V3FIX
|
||||
|
@ -269,119 +334,154 @@
|
|||
/****/
|
||||
|
||||
/* [ Updater ------------------------------------------------------ ]
|
||||
* Disable this if you don't plan to/want to use the firmware
|
||||
* updater utility. This setting is ignored on hardware versions
|
||||
* other than HW5 and HW3.
|
||||
Disable this if you don't plan to/want to use the firmware
|
||||
updater utility. This setting is ignored on hardware versions
|
||||
other than HW5 and HW3.
|
||||
*/
|
||||
|
||||
//#define ENABLE_UPDATER
|
||||
#define ENABLE_UPDATER
|
||||
|
||||
/****/
|
||||
|
||||
/* [ Self Test ---------------------------------------------------- ]
|
||||
* Tests for shorts and other issues in your OSCR build.
|
||||
Tests for shorts and other issues in your OSCR build.
|
||||
*/
|
||||
|
||||
#define enable_selftest
|
||||
#define ENABLE_SELFTEST
|
||||
|
||||
/****/
|
||||
|
||||
/* [ Logging ------------------------------------------------------ ]
|
||||
* Write all info to OSCR_LOG.txt in root dir
|
||||
Write all info to OSCR_LOG.txt in root dir
|
||||
|
||||
Can be toggled off using config:
|
||||
oscr.logging=0
|
||||
*/
|
||||
|
||||
#define global_log
|
||||
#define ENABLE_GLOBAL_LOG
|
||||
|
||||
/****/
|
||||
|
||||
/* [ RTC: IC Type ------------------------------------------------- ]
|
||||
When the RTC module is installed, choose the type here. This
|
||||
setting is ignored if the RTC option is not enabled.
|
||||
*/
|
||||
|
||||
#define DS3231
|
||||
//#define DS1307
|
||||
|
||||
/****/
|
||||
|
||||
/* [ SNES Core/CLOCKGEN: Read Clock Generator Calibration Data ---- ]
|
||||
* Toggle to use calibration data from snes_clk.txt
|
||||
Toggle clock calibration menu and whether or not to use calibration data from snes_clk.txt
|
||||
*/
|
||||
|
||||
//#define clockgen_calibration
|
||||
//#define OPTION_CLOCKGEN_CALIBRATION
|
||||
//#define OPTION_CLOCKGEN_USE_CALIBRATION
|
||||
|
||||
/****/
|
||||
|
||||
/* [ MegaDrive/Genesis Core: Compatibility Settings --------------- ]
|
||||
* Allows you to create a text file on the SD card called
|
||||
* "mdconf.txt" which you should place the following into:
|
||||
*
|
||||
* [segaSram16bit] N
|
||||
*
|
||||
* Where N is:
|
||||
* 0: Output each byte once. Not supported by emulators. (default)
|
||||
* 1: Duplicate each byte. Usable by Kega Fusion.
|
||||
* 2: Same as 1 + pad with 0xFF so that the file size is 64KB.
|
||||
Allows you to create a text file on the SD card called
|
||||
"mdconf.txt" which you should place the following into:
|
||||
|
||||
[segaSram16bit] N
|
||||
|
||||
Where N is:
|
||||
0: Output each byte once. Not supported by emulators. (default)
|
||||
1: Duplicate each byte. Usable by Kega Fusion.
|
||||
2: Same as 1 + pad with 0xFF so that the file size is 64KB.
|
||||
|
||||
**
|
||||
** DEPRECATED: Use the config file instead. See below.
|
||||
**
|
||||
*/
|
||||
|
||||
//#define use_md_conf
|
||||
|
||||
/*
|
||||
* Alternatively, define it here by uncommenting and changing the
|
||||
* following line. Setting both allows you to change the default.
|
||||
Configure how the MD core saves are formatted.
|
||||
|
||||
Can be set using config:
|
||||
md.saveType=0
|
||||
|
||||
If config is enabled, this option does nothing -- use the config.
|
||||
|
||||
Options:
|
||||
0: Output each byte once. Not supported by emulators. (default)
|
||||
1: Duplicate each byte. Usable by Kega Fusion.
|
||||
2: Same as 1 + pad with 0xFF so that the file size is 64KB.
|
||||
*/
|
||||
|
||||
//#define DEFAULT_VALUE_segaSram16bit 0
|
||||
//#define OPTION_MD_DEFAULT_SAVE_TYPE 0
|
||||
|
||||
/****/
|
||||
|
||||
/* [ N64 Core: Fast CRC ------------------------------------------- ]
|
||||
* Toggle so the CRC for N64 Roms will be calculated during dumping
|
||||
* from memory instead of after dumping from SD card, not compatible
|
||||
* with all Cart Readers
|
||||
Toggle so the CRC for N64 Roms will be calculated during dumping
|
||||
from memory instead of after dumping from SD card, not compatible
|
||||
with all Cart Readers
|
||||
*/
|
||||
|
||||
//#define fastcrc
|
||||
//#define OPTION_N64_FASTCRC
|
||||
|
||||
/****/
|
||||
|
||||
/* [ N64 Core: Log Summary ---------------------------------------- ]
|
||||
* Enable to save a n64log.txt file with rom info in /N64/ROM
|
||||
Enable to save a n64log.txt file with rom info in /N64/ROM
|
||||
*/
|
||||
|
||||
//#define savesummarytotxt
|
||||
//#define OPTION_N64_SAVESUMMARY
|
||||
|
||||
/****/
|
||||
|
||||
/*==== PROCESSING =================================================*/
|
||||
|
||||
/*
|
||||
* You probably shouldn't change this stuff!
|
||||
You probably shouldn't change this stuff!
|
||||
*/
|
||||
|
||||
#if defined(ENABLE_CONFIG)
|
||||
# define CONFIG_FILE "config.txt"
|
||||
// Define the max length of the key=value pairs
|
||||
// Do your best not to have to increase these.
|
||||
# define CONFIG_KEY_MAX 32
|
||||
# define CONFIG_VALUE_MAX 32
|
||||
#endif
|
||||
|
||||
#if (defined(HW4) || defined(HW5))
|
||||
#define enable_LCD
|
||||
#define enable_neopixel
|
||||
#define enable_rotary
|
||||
//#define rotate_counter_clockwise
|
||||
#define clockgen_installed
|
||||
#define fastcrc
|
||||
#define ws_adapter_v2
|
||||
# define ENABLE_LCD
|
||||
# define ENABLE_NEOPIXEL
|
||||
# define ENABLE_ROTARY
|
||||
//# define rotate_counter_clockwise
|
||||
# define ENABLE_CLOCKGEN
|
||||
# define OPTION_N64_FASTCRC
|
||||
# define OPTION_WS_ADAPTER_V2
|
||||
#endif
|
||||
|
||||
#if (defined(HW2) || defined(HW3))
|
||||
#define enable_OLED
|
||||
#define enable_Button2
|
||||
#define clockgen_installed
|
||||
#define CA_LED
|
||||
#define fastcrc
|
||||
# define ENABLE_OLED
|
||||
# define ENABLE_BUTTON2
|
||||
# define ENABLE_CLOCKGEN
|
||||
# define ENABLE_CA_LED
|
||||
# define OPTION_N64_FASTCRC
|
||||
#endif
|
||||
|
||||
#if defined(HW1)
|
||||
#define enable_OLED
|
||||
//#define clockgen_installed
|
||||
//#define fastcrc
|
||||
# define ENABLE_OLED
|
||||
//#define ENABLE_CLOCKGEN
|
||||
//#define OPTION_N64_FASTCRC
|
||||
#endif
|
||||
|
||||
#if defined(SERIAL_MONITOR)
|
||||
#define enable_serial
|
||||
//#define clockgen_installed
|
||||
//#define fastcrc
|
||||
# define ENABLE_SERIAL
|
||||
//#define ENABLE_CLOCKGEN
|
||||
//#define OPTION_N64_FASTCRC
|
||||
#endif
|
||||
|
||||
/* Firmware updater only works with HW3 and HW5 */
|
||||
#if !(defined(HW5) || defined(HW3))
|
||||
#undef ENABLE_UPDATER
|
||||
# undef ENABLE_UPDATER
|
||||
#endif
|
||||
|
||||
/* End of settings */
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
//******************************************
|
||||
// FAIRCHILD CHANNEL F MODULE
|
||||
//******************************************
|
||||
#if defined(enable_FAIRCHILD)
|
||||
#if defined(ENABLE_FAIRCHILD)
|
||||
// Fairchild Channel F
|
||||
// Cartridge Pinout
|
||||
// 22P (27P Width) 2.54mm pitch connector
|
||||
|
@ -70,7 +70,6 @@ byte fairchildlo = 0; // Lowest Entry
|
|||
byte fairchildhi = 3; // Highest Entry
|
||||
|
||||
byte fairchildsize;
|
||||
byte newfairchildsize;
|
||||
|
||||
// EEPROM MAPPING
|
||||
// 08 ROM SIZE
|
||||
|
@ -79,12 +78,8 @@ byte newfairchildsize;
|
|||
// Menu
|
||||
//******************************************
|
||||
// Base Menu
|
||||
static const char fairchildMenuItem1[] PROGMEM = "Select Cart";
|
||||
static const char fairchildMenuItem2[] PROGMEM = "Read ROM";
|
||||
static const char fairchildMenuItem3[] PROGMEM = "Set Size";
|
||||
static const char fairchildMenuItem4[] PROGMEM = "Read 16K";
|
||||
static const char fairchildMenuItem5[] PROGMEM = "Reset";
|
||||
static const char* const menuOptionsFAIRCHILD[] PROGMEM = { fairchildMenuItem1, fairchildMenuItem2, fairchildMenuItem3, fairchildMenuItem4, fairchildMenuItem5 };
|
||||
static const char* const menuOptionsFAIRCHILD[] PROGMEM = { FSTRING_SELECT_CART, FSTRING_READ_ROM, FSTRING_SET_SIZE, fairchildMenuItem4, FSTRING_RESET };
|
||||
|
||||
void setup_FAIRCHILD() {
|
||||
// Request 5V
|
||||
|
@ -125,7 +120,7 @@ void setup_FAIRCHILD() {
|
|||
checkStatus_FAIRCHILD();
|
||||
strcpy(romName, "FAIRCHILD");
|
||||
|
||||
mode = mode_FAIRCHILD;
|
||||
mode = CORE_FAIRCHILD;
|
||||
}
|
||||
|
||||
void fairchildMenu() {
|
||||
|
@ -397,29 +392,7 @@ uint8_t readData_FAIRCHILD() {
|
|||
}
|
||||
|
||||
void readROM_FAIRCHILD() {
|
||||
strcpy(fileName, romName);
|
||||
strcat(fileName, ".bin");
|
||||
|
||||
// create a new folder for storing rom file
|
||||
EEPROM_readAnything(0, foldern);
|
||||
sprintf(folder, "FAIRCHILD/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_FatalError(create_file_STR);
|
||||
}
|
||||
|
||||
// write new folder number back to EEPROM
|
||||
foldern++;
|
||||
EEPROM_writeAnything(0, foldern);
|
||||
createFolderAndOpenFile("FAIRCHILD", "ROM", romName, "bin");
|
||||
|
||||
unsigned long cartsize = FAIRCHILD[fairchildsize] * 0x400;
|
||||
uint8_t blocks = cartsize / 0x200;
|
||||
|
@ -431,7 +404,7 @@ void readROM_FAIRCHILD() {
|
|||
// 0x55,0x2B - most carts
|
||||
// 0x55,0xAA - alien invasion (4K)
|
||||
// 0x55,0xBB - video whizball (3K)
|
||||
for (int y = 0; y < 0x4800; y++) {
|
||||
for (uint16_t y = 0; y < 0x4800; y++) {
|
||||
uint8_t startbyte = readData_FAIRCHILD();
|
||||
if (startbyte == 0x55) { // Start Byte
|
||||
sdBuffer[0] = startbyte;
|
||||
|
@ -456,12 +429,10 @@ void readROM_FAIRCHILD() {
|
|||
}
|
||||
}
|
||||
} else if (cartsize == 0x1000) { // 4K
|
||||
// Skip BIOS/Blocks Code for 4K Carts - Tested with Pro Football 4K
|
||||
// Pro Football uses a DM74LS02N (Quad 2-Input NOR Gate) with two 2K ROM Chips
|
||||
setROMC_FAIRCHILD(0x8); // Clear PC0
|
||||
setREAD_FAIRCHILD();
|
||||
// Skip BIOS/Blocks Code for 4K Carts - Tested with Alien Invasion/Pro Football
|
||||
// Alien Invasion/Pro Football both use a DM74LS02N (Quad 2-Input NOR Gate) with two 2K ROM Chips
|
||||
uint16_t offset = z * 0x200;
|
||||
for (int x = 0; x < 0x800 + offset; x++) { // Skip BIOS/Previous Blocks
|
||||
for (uint16_t x = 0; x < 0x800 + offset; x++) { // Skip BIOS/Previous Blocks
|
||||
readData_FAIRCHILD();
|
||||
}
|
||||
}
|
||||
|
@ -478,27 +449,19 @@ void readROM_FAIRCHILD() {
|
|||
}
|
||||
myFile.close();
|
||||
|
||||
calcCRC(fileName, cartsize, NULL, 0);
|
||||
printCRC(fileName, NULL, 0);
|
||||
|
||||
println_Msg(F(""));
|
||||
println_Msg(FS(FSTRING_EMPTY));
|
||||
print_STR(press_button_STR, 1);
|
||||
display_Update();
|
||||
wait();
|
||||
}
|
||||
|
||||
void read16K_FAIRCHILD() // Read 16K Bytes
|
||||
{
|
||||
strcpy(fileName, romName);
|
||||
strcat(fileName, ".bin");
|
||||
|
||||
// create a new folder for storing rom file
|
||||
EEPROM_readAnything(0, foldern);
|
||||
sprintf(folder, "FAIRCHILD/ROM/%d", foldern);
|
||||
sd.mkdir(folder, true);
|
||||
sd.chdir(folder);
|
||||
void read16K_FAIRCHILD() { // Read 16K Bytes
|
||||
createFolder("FAIRCHILD", "ROM", romName, "bin");
|
||||
|
||||
display_Clear();
|
||||
print_Msg(F("Saving to "));
|
||||
print_STR(saving_to_STR, 0);
|
||||
print_Msg(folder);
|
||||
println_Msg(F("/..."));
|
||||
display_Update();
|
||||
|
@ -513,16 +476,14 @@ void read16K_FAIRCHILD() // Read 16K Bytes
|
|||
EEPROM_writeAnything(0, foldern);
|
||||
|
||||
unsigned long cartsize = FAIRCHILD[fairchildsize] * 0x400;
|
||||
for (int y = 0; y < 0x20; y++) {
|
||||
for (uint16_t y = 0; y < 0x20; y++) {
|
||||
if (cartsize == 0x1000) { // 4K
|
||||
// Skip BIOS/Blocks Code for 4K Carts - Tested with Pro Football 4K
|
||||
// Pro Football uses a DM74LS02N (Quad 2-Input NOR Gate) with two 2K ROM Chips
|
||||
// IF OTHER 4K CARTS DO NOT DUMP PROPERLY USING READROM
|
||||
// Skip BIOS/Blocks Code for 4K Carts - Tested with Alien Invasion/Pro Football
|
||||
// Alien Invasion/Pro Football both use a DM74LS02N (Quad 2-Input NOR Gate) with two 2K ROM Chips
|
||||
// IF CASINO POKER DOES NOT DUMP PROPERLY USING READROM
|
||||
// TEST BY SETTING ROM SIZE TO 2K AND 4K THEN COMPARE 16K DUMPS
|
||||
setROMC_FAIRCHILD(0x8); // Clear PC0
|
||||
setREAD_FAIRCHILD();
|
||||
uint16_t offset = y * 0x200;
|
||||
for (int x = 0; x < 0x800 + offset; x++) { // Skip BIOS/Previous Blocks
|
||||
for (uint16_t x = 0; x < 0x800 + offset; x++) { // Skip BIOS/Previous Blocks
|
||||
readData_FAIRCHILD();
|
||||
}
|
||||
}
|
||||
|
@ -535,9 +496,9 @@ void read16K_FAIRCHILD() // Read 16K Bytes
|
|||
}
|
||||
myFile.close();
|
||||
|
||||
calcCRC(fileName, 0x4000, NULL, 0);
|
||||
printCRC(fileName, NULL, 0);
|
||||
|
||||
println_Msg(F(""));
|
||||
println_Msg(FS(FSTRING_EMPTY));
|
||||
print_STR(press_button_STR, 1);
|
||||
display_Update();
|
||||
wait();
|
||||
|
@ -547,75 +508,26 @@ void read16K_FAIRCHILD() // Read 16K Bytes
|
|||
// ROM SIZE
|
||||
//******************************************
|
||||
|
||||
#if (defined(ENABLE_OLED) || defined(ENABLE_LCD))
|
||||
void printRomSize_FAIRCHILD(int index) {
|
||||
display_Clear();
|
||||
print_Msg(F("ROM Size: "));
|
||||
println_Msg(FAIRCHILD[index]);
|
||||
}
|
||||
#endif
|
||||
|
||||
void setROMSize_FAIRCHILD() {
|
||||
#if (defined(enable_OLED) || defined(enable_LCD))
|
||||
byte newfairchildsize;
|
||||
#if (defined(ENABLE_OLED) || defined(ENABLE_LCD))
|
||||
display_Clear();
|
||||
if (fairchildlo == fairchildhi)
|
||||
newfairchildsize = fairchildlo;
|
||||
else {
|
||||
int b = 0;
|
||||
int i = fairchildlo;
|
||||
display_Clear();
|
||||
print_Msg(F("ROM Size: "));
|
||||
println_Msg(FAIRCHILD[i]);
|
||||
println_Msg(F(""));
|
||||
#if defined(enable_OLED)
|
||||
print_STR(press_to_change_STR, 1);
|
||||
print_STR(right_to_select_STR, 1);
|
||||
#elif defined(enable_LCD)
|
||||
print_STR(rotate_to_change_STR, 1);
|
||||
print_STR(press_to_select_STR, 1);
|
||||
#endif
|
||||
display_Update();
|
||||
while (1) {
|
||||
b = checkButton();
|
||||
if (b == 2) { // Previous (doubleclick)
|
||||
if (i == fairchildlo)
|
||||
i = fairchildhi;
|
||||
else
|
||||
i--;
|
||||
newfairchildsize = navigateMenu(fairchildlo, fairchildhi, &printRomSize_FAIRCHILD);
|
||||
|
||||
// Only update display after input because of slow LCD library
|
||||
display_Clear();
|
||||
print_Msg(F("ROM Size: "));
|
||||
println_Msg(FAIRCHILD[i]);
|
||||
println_Msg(F(""));
|
||||
#if defined(enable_OLED)
|
||||
print_STR(press_to_change_STR, 1);
|
||||
print_STR(right_to_select_STR, 1);
|
||||
#elif defined(enable_LCD)
|
||||
print_STR(rotate_to_change_STR, 1);
|
||||
print_STR(press_to_select_STR, 1);
|
||||
#endif
|
||||
display_Update();
|
||||
}
|
||||
if (b == 1) { // Next (press)
|
||||
if (i == fairchildhi)
|
||||
i = fairchildlo;
|
||||
else
|
||||
i++;
|
||||
// Only update display after input because of slow LCD library
|
||||
display_Clear();
|
||||
print_Msg(F("ROM Size: "));
|
||||
println_Msg(FAIRCHILD[i]);
|
||||
println_Msg(F(""));
|
||||
#if defined(enable_OLED)
|
||||
print_STR(press_to_change_STR, 1);
|
||||
print_STR(right_to_select_STR, 1);
|
||||
#elif defined(enable_LCD)
|
||||
print_STR(rotate_to_change_STR, 1);
|
||||
print_STR(press_to_select_STR, 1);
|
||||
#endif
|
||||
display_Update();
|
||||
}
|
||||
if (b == 3) { // Long Press - Execute (hold)
|
||||
newfairchildsize = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
display.setCursor(0, 56); // Display selection at bottom
|
||||
}
|
||||
print_Msg(F("ROM SIZE "));
|
||||
print_Msg(FS(FSTRING_ROM_SIZE));
|
||||
print_Msg(FAIRCHILD[newfairchildsize]);
|
||||
println_Msg(F("K"));
|
||||
display_Update();
|
||||
|
@ -640,7 +552,7 @@ setrom:
|
|||
newfairchildsize = sizeROM.toInt() + fairchildlo;
|
||||
if (newfairchildsize > fairchildhi) {
|
||||
Serial.println(F("SIZE NOT SUPPORTED"));
|
||||
Serial.println(F(""));
|
||||
Serial.println(FS(FSTRING_EMPTY));
|
||||
goto setrom;
|
||||
}
|
||||
}
|
||||
|
@ -659,12 +571,12 @@ void checkStatus_FAIRCHILD() {
|
|||
EEPROM_writeAnything(8, fairchildsize);
|
||||
}
|
||||
|
||||
#if (defined(enable_OLED) || defined(enable_LCD))
|
||||
#if (defined(ENABLE_OLED) || defined(ENABLE_LCD))
|
||||
display_Clear();
|
||||
println_Msg(F("CHANNEL F READER"));
|
||||
println_Msg(F("CURRENT SETTINGS"));
|
||||
println_Msg(F(""));
|
||||
print_Msg(F("ROM SIZE: "));
|
||||
println_Msg(FS(FSTRING_CURRENT_SETTINGS));
|
||||
println_Msg(FS(FSTRING_EMPTY));
|
||||
print_Msg(FS(FSTRING_ROM_SIZE));
|
||||
print_Msg(FAIRCHILD[fairchildsize]);
|
||||
println_Msg(F("K"));
|
||||
display_Update();
|
||||
|
@ -673,248 +585,34 @@ void checkStatus_FAIRCHILD() {
|
|||
Serial.print(F("CURRENT ROM SIZE: "));
|
||||
Serial.print(FAIRCHILD[fairchildsize]);
|
||||
Serial.println(F("K"));
|
||||
Serial.println(F(""));
|
||||
Serial.println(FS(FSTRING_EMPTY));
|
||||
#endif
|
||||
}
|
||||
|
||||
//******************************************
|
||||
// CART SELECT CODE
|
||||
//******************************************
|
||||
|
||||
FsFile fairchildcsvFile;
|
||||
char fairchildgame[33]; // title
|
||||
char fairchildrr[3]; // romsize
|
||||
char fairchildll[4]; // linelength (previous line)
|
||||
unsigned long fairchildcsvpos; // CSV File Position
|
||||
char fairchildcartCSV[] = "fairchildcart.txt"; // CSV List
|
||||
char fairchildcsvEND[] = "EOF"; // CSV End Marker for scrolling
|
||||
|
||||
bool readLine_FAIRCHILD(FsFile& f, char* line, size_t maxLen) {
|
||||
for (size_t n = 0; n < maxLen; n++) {
|
||||
int c = f.read();
|
||||
if (c < 0 && n == 0) return false; // EOF
|
||||
if (c < 0 || c == '\n') {
|
||||
line[n] = 0;
|
||||
return true;
|
||||
}
|
||||
line[n] = c;
|
||||
}
|
||||
return false; // line too long
|
||||
}
|
||||
|
||||
bool readVals_FAIRCHILD(char* fairchildgame, char* fairchildrr, char* fairchildll) {
|
||||
char line[39];
|
||||
fairchildcsvpos = fairchildcsvFile.position();
|
||||
if (!readLine_FAIRCHILD(fairchildcsvFile, line, sizeof(line))) {
|
||||
return false; // EOF or too long
|
||||
}
|
||||
char* comma = strtok(line, ",");
|
||||
int x = 0;
|
||||
while (comma != NULL) {
|
||||
if (x == 0)
|
||||
strcpy(fairchildgame, comma);
|
||||
else if (x == 1)
|
||||
strcpy(fairchildrr, comma);
|
||||
else if (x == 2)
|
||||
strcpy(fairchildll, comma);
|
||||
comma = strtok(NULL, ",");
|
||||
x += 1;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool getCartListInfo_FAIRCHILD() {
|
||||
bool buttonreleased = 0;
|
||||
bool cartselected = 0;
|
||||
#if (defined(enable_OLED) || defined(enable_LCD))
|
||||
display_Clear();
|
||||
println_Msg(F(" HOLD TO FAST CYCLE"));
|
||||
display_Update();
|
||||
#else
|
||||
Serial.println(F("HOLD BUTTON TO FAST CYCLE"));
|
||||
#endif
|
||||
delay(2000);
|
||||
#if defined(enable_OLED)
|
||||
buttonVal1 = (PIND & (1 << 7)); // PD7
|
||||
#elif defined(enable_LCD)
|
||||
boolean buttonVal1 = (PING & (1 << 2)); //PG2
|
||||
#endif
|
||||
if (buttonVal1 == LOW) { // Button Held - Fast Cycle
|
||||
while (1) { // Scroll Game List
|
||||
while (readVals_FAIRCHILD(fairchildgame, fairchildrr, fairchildll)) {
|
||||
if (strcmp(fairchildcsvEND, fairchildgame) == 0) {
|
||||
fairchildcsvFile.seek(0); // Restart
|
||||
} else {
|
||||
#if (defined(enable_OLED) || defined(enable_LCD))
|
||||
display_Clear();
|
||||
println_Msg(F("CART TITLE:"));
|
||||
println_Msg(F(""));
|
||||
println_Msg(fairchildgame);
|
||||
display_Update();
|
||||
#else
|
||||
Serial.print(F("CART TITLE:"));
|
||||
Serial.println(fairchildgame);
|
||||
#endif
|
||||
#if defined(enable_OLED)
|
||||
buttonVal1 = (PIND & (1 << 7)); // PD7
|
||||
#elif defined(enable_LCD)
|
||||
buttonVal1 = (PING & (1 << 2)); //PG2
|
||||
#endif
|
||||
if (buttonVal1 == HIGH) { // Button Released
|
||||
buttonreleased = 1;
|
||||
break;
|
||||
}
|
||||
if (buttonreleased) {
|
||||
buttonreleased = 0; // Reset Flag
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#if defined(enable_OLED)
|
||||
buttonVal1 = (PIND & (1 << 7)); // PD7
|
||||
#elif defined(enable_LCD)
|
||||
buttonVal1 = (PING & (1 << 2)); //PG2
|
||||
#endif
|
||||
if (buttonVal1 == HIGH) // Button Released
|
||||
break;
|
||||
}
|
||||
}
|
||||
#if (defined(enable_OLED) || defined(enable_LCD))
|
||||
display.setCursor(0, 56);
|
||||
println_Msg(F("FAST CYCLE OFF"));
|
||||
display_Update();
|
||||
#else
|
||||
Serial.println(F(""));
|
||||
Serial.println(F("FAST CYCLE OFF"));
|
||||
Serial.println(F("PRESS BUTTON TO STEP FORWARD"));
|
||||
Serial.println(F("DOUBLE CLICK TO STEP BACK"));
|
||||
Serial.println(F("HOLD TO SELECT"));
|
||||
Serial.println(F(""));
|
||||
#endif
|
||||
while (readVals_FAIRCHILD(fairchildgame, fairchildrr, fairchildll)) {
|
||||
if (strcmp(fairchildcsvEND, fairchildgame) == 0) {
|
||||
fairchildcsvFile.seek(0); // Restart
|
||||
} else {
|
||||
#if (defined(enable_OLED) || defined(enable_LCD))
|
||||
display_Clear();
|
||||
println_Msg(F("CART TITLE:"));
|
||||
println_Msg(F(""));
|
||||
println_Msg(fairchildgame);
|
||||
display.setCursor(0, 48);
|
||||
#if defined(enable_OLED)
|
||||
print_STR(press_to_change_STR, 1);
|
||||
print_STR(right_to_select_STR, 1);
|
||||
#elif defined(enable_LCD)
|
||||
print_STR(rotate_to_change_STR, 1);
|
||||
print_STR(press_to_select_STR, 1);
|
||||
#endif
|
||||
display_Update();
|
||||
#else
|
||||
Serial.print(F("CART TITLE:"));
|
||||
Serial.println(fairchildgame);
|
||||
#endif
|
||||
while (1) { // Single Step
|
||||
int b = checkButton();
|
||||
if (b == 1) { // Continue (press)
|
||||
break;
|
||||
}
|
||||
if (b == 2) { // Reset to Start of List (doubleclick)
|
||||
byte prevline = strtol(fairchildll, NULL, 10);
|
||||
fairchildcsvpos -= prevline;
|
||||
fairchildcsvFile.seek(fairchildcsvpos);
|
||||
break;
|
||||
}
|
||||
if (b == 3) { // Long Press - Select Cart (hold)
|
||||
newfairchildsize = strtol(fairchildrr, NULL, 10);
|
||||
EEPROM_writeAnything(8, newfairchildsize);
|
||||
cartselected = 1; // SELECTION MADE
|
||||
#if (defined(enable_OLED) || defined(enable_LCD))
|
||||
println_Msg(F("SELECTION MADE"));
|
||||
display_Update();
|
||||
#else
|
||||
Serial.println(F("SELECTION MADE"));
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (cartselected) {
|
||||
cartselected = 0; // Reset Flag
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
#if (defined(enable_OLED) || defined(enable_LCD))
|
||||
println_Msg(F(""));
|
||||
println_Msg(F("END OF FILE"));
|
||||
display_Update();
|
||||
#else
|
||||
Serial.println(F("END OF FILE"));
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void checkCSV_FAIRCHILD() {
|
||||
if (getCartListInfo_FAIRCHILD()) {
|
||||
#if (defined(enable_OLED) || defined(enable_LCD))
|
||||
display_Clear();
|
||||
println_Msg(F("CART SELECTED"));
|
||||
println_Msg(F(""));
|
||||
println_Msg(fairchildgame);
|
||||
display_Update();
|
||||
// Display Settings
|
||||
display.setCursor(0, 56);
|
||||
print_Msg(F("CODE: R"));
|
||||
println_Msg(newfairchildsize);
|
||||
display_Update();
|
||||
#else
|
||||
Serial.println(F(""));
|
||||
Serial.println(F("CART SELECTED"));
|
||||
Serial.println(fairchildgame);
|
||||
// Display Settings
|
||||
Serial.print(F("CODE: R"));
|
||||
Serial.println(newfairchildsize);
|
||||
Serial.println(F(""));
|
||||
#endif
|
||||
} else {
|
||||
#if (defined(enable_OLED) || defined(enable_LCD))
|
||||
display.setCursor(0, 56);
|
||||
println_Msg(F("NO SELECTION"));
|
||||
display_Update();
|
||||
#else
|
||||
Serial.println(F("NO SELECTION"));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void setCart_FAIRCHILD() {
|
||||
#if (defined(enable_OLED) || defined(enable_LCD))
|
||||
display_Clear();
|
||||
println_Msg(fairchildcartCSV);
|
||||
display_Update();
|
||||
#endif
|
||||
//go to root
|
||||
sd.chdir();
|
||||
sprintf(folder, "FAIRCHILD/CSV");
|
||||
sd.chdir(folder); // Switch Folder
|
||||
fairchildcsvFile = sd.open(fairchildcartCSV, O_READ);
|
||||
if (!fairchildcsvFile) {
|
||||
#if (defined(enable_OLED) || defined(enable_LCD))
|
||||
display_Clear();
|
||||
println_Msg(F("CSV FILE NOT FOUND!"));
|
||||
display_Update();
|
||||
#else
|
||||
Serial.println(F("CSV FILE NOT FOUND!"));
|
||||
#endif
|
||||
while (1) {
|
||||
if (checkButton() != 0)
|
||||
setup_FAIRCHILD();
|
||||
}
|
||||
}
|
||||
checkCSV_FAIRCHILD();
|
||||
|
||||
fairchildcsvFile.close();
|
||||
byte gameSize;
|
||||
|
||||
// Select starting letter
|
||||
//byte myLetter = starting_letter();
|
||||
|
||||
// Open database
|
||||
if (myFile.open("fairchildcart.txt", O_READ)) {
|
||||
// seek_first_letter_in_database(myFile, myLetter);
|
||||
|
||||
if(checkCartSelection(myFile, &readDataLineSingleDigit, &gameSize)) {
|
||||
EEPROM_writeAnything(8, gameSize);
|
||||
}
|
||||
} else {
|
||||
print_FatalError(FS(FSTRING_DATABASE_FILE_NOT_FOUND));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
//******************************************
|
||||
// End of File
|
||||
//******************************************
|
||||
//******************************************
|
||||
|
|
File diff suppressed because it is too large
Load Diff
1765
Cart_Reader/GB.ino
1765
Cart_Reader/GB.ino
File diff suppressed because it is too large
Load Diff
|
@ -1,19 +1,15 @@
|
|||
//******************************************
|
||||
// GAME BOY ADVANCE MODULE
|
||||
//******************************************
|
||||
#ifdef enable_GBX
|
||||
#ifdef ENABLE_GBX
|
||||
|
||||
/******************************************
|
||||
Menu
|
||||
*****************************************/
|
||||
// GBA menu items
|
||||
static const char GBAMenuItem1[] PROGMEM = "Read ROM";
|
||||
static const char GBAMenuItem2[] PROGMEM = "Read Save";
|
||||
static const char GBAMenuItem3[] PROGMEM = "Write Save";
|
||||
static const char GBAMenuItem4[] PROGMEM = "Force Savetype";
|
||||
static const char GBAMenuItem5[] PROGMEM = "Flash Repro";
|
||||
//static const char GBAMenuItem6[] PROGMEM = "Reset"; (stored in common strings array)
|
||||
static const char* const menuOptionsGBA[] PROGMEM = { GBAMenuItem1, GBAMenuItem2, GBAMenuItem3, GBAMenuItem4, GBAMenuItem5, string_reset2 };
|
||||
static const char* const menuOptionsGBA[] PROGMEM = { FSTRING_READ_ROM, FSTRING_READ_SAVE, FSTRING_WRITE_SAVE, GBAMenuItem4, GBAMenuItem5, FSTRING_RESET };
|
||||
|
||||
// Rom menu
|
||||
static const char GBARomItem1[] PROGMEM = "1 MB";
|
||||
|
@ -66,7 +62,7 @@ void gbaMenu() {
|
|||
compare_checksum_GBA();
|
||||
// CRC32
|
||||
compareCRC("gba.txt", 0, 1, 0);
|
||||
#ifdef global_log
|
||||
#ifdef ENABLE_GLOBAL_LOG
|
||||
save_log();
|
||||
#endif
|
||||
// Prints string out of the common strings array either with or without newline
|
||||
|
@ -116,7 +112,7 @@ void gbaMenu() {
|
|||
break;
|
||||
}
|
||||
setROM_GBA();
|
||||
println_Msg(F(""));
|
||||
println_Msg(FS(FSTRING_EMPTY));
|
||||
// Prints string out of the common strings array either with or without newline
|
||||
print_STR(press_button_STR, 1);
|
||||
display_Update();
|
||||
|
@ -162,7 +158,7 @@ void gbaMenu() {
|
|||
printFlashTypeAndWait(F("Panasonic MN63F805MNP"));
|
||||
} else {
|
||||
printFlashTypeAndWait(F("Unknown"));
|
||||
//print_FatalError(F(""));
|
||||
//print_FatalError(FSTRING_EMPTY);
|
||||
}
|
||||
|
||||
if (flashid == 0x1F3D) { // Atmel
|
||||
|
@ -188,7 +184,7 @@ void gbaMenu() {
|
|||
printFlashTypeAndWait(F("SANYO LE26FV10N1TS"));
|
||||
} else {
|
||||
printFlashTypeAndWait(F("Unknown"));
|
||||
//print_FatalError(F(""));
|
||||
//print_FatalError(FSTRING_EMPTY);
|
||||
}
|
||||
|
||||
eraseFLASH_GBA();
|
||||
|
@ -211,7 +207,7 @@ void gbaMenu() {
|
|||
break;
|
||||
}
|
||||
setROM_GBA();
|
||||
println_Msg(F(""));
|
||||
println_Msg(FS(FSTRING_EMPTY));
|
||||
// Prints string out of the common strings array either with or without newline
|
||||
print_STR(press_button_STR, 1);
|
||||
display_Update();
|
||||
|
@ -228,7 +224,7 @@ void gbaMenu() {
|
|||
case 4:
|
||||
display_Clear();
|
||||
flashRepro_GBA();
|
||||
println_Msg(F(""));
|
||||
println_Msg(FS(FSTRING_EMPTY));
|
||||
// Prints string out of the common strings array either with or without newline
|
||||
print_STR(press_button_STR, 1);
|
||||
display_Update();
|
||||
|
@ -256,7 +252,7 @@ void setup_GBA() {
|
|||
display_Clear();
|
||||
|
||||
// Print start page
|
||||
print_Msg(F("Title: "));
|
||||
print_Msg(FS(FSTRING_NAME));
|
||||
println_Msg(romName);
|
||||
print_Msg(F("Serial: "));
|
||||
println_Msg(cartID);
|
||||
|
@ -326,10 +322,10 @@ static byte getSaveType() {
|
|||
static void printFlashTypeAndWait(const __FlashStringHelper* caption) {
|
||||
print_Msg(F("FLASH ID: "));
|
||||
println_Msg(flashid_str);
|
||||
println_Msg(F(""));
|
||||
println_Msg(FS(FSTRING_EMPTY));
|
||||
println_Msg(F("FLASH Type: "));
|
||||
println_Msg(caption);
|
||||
println_Msg(F(""));
|
||||
println_Msg(FS(FSTRING_EMPTY));
|
||||
// Prints string out of the common strings array either with or without newline
|
||||
print_STR(press_button_STR, 1);
|
||||
display_Update();
|
||||
|
@ -471,7 +467,7 @@ void writeWord_GAB(unsigned long myAddress, word myWord) {
|
|||
writeWord_GBA(myAddress, swapBits(myWord, 0, 1));
|
||||
}
|
||||
|
||||
byte readByte_GBA(unsigned long myAddress) {
|
||||
byte readByte_GBA(uint16_t myAddress) {
|
||||
// Set address ports to output
|
||||
DDRF = 0xFF;
|
||||
DDRK = 0xFF;
|
||||
|
@ -508,7 +504,7 @@ byte readByte_GBA(unsigned long myAddress) {
|
|||
return tempByte;
|
||||
}
|
||||
|
||||
void writeByte_GBA(unsigned long myAddress, byte myData) {
|
||||
void writeByte_GBA(uint16_t myAddress, byte myData) {
|
||||
// Set address ports to output
|
||||
DDRF = 0xFF;
|
||||
DDRK = 0xFF;
|
||||
|
@ -599,17 +595,17 @@ void getCartInfo_GBA() {
|
|||
display_Clear();
|
||||
print_Error(F("CARTRIDGE ERROR"));
|
||||
strcpy(romName, "ERROR");
|
||||
println_Msg(F(""));
|
||||
println_Msg(F(""));
|
||||
println_Msg(F(""));
|
||||
println_Msg(FS(FSTRING_EMPTY));
|
||||
println_Msg(FS(FSTRING_EMPTY));
|
||||
println_Msg(FS(FSTRING_EMPTY));
|
||||
println_Msg(F("Press Button to"));
|
||||
println_Msg(F("ignore or powercycle"));
|
||||
println_Msg(F("to try again"));
|
||||
display_Update();
|
||||
wait();
|
||||
} else {
|
||||
char tempStr2[2];
|
||||
char tempStr[5];
|
||||
tempStr[4] = 0;
|
||||
|
||||
// cart not in list
|
||||
cartSize = 0;
|
||||
|
@ -630,7 +626,7 @@ void getCartInfo_GBA() {
|
|||
if (myFile.open("gba.txt", O_READ)) {
|
||||
char gamename[100];
|
||||
|
||||
#ifdef global_log
|
||||
#ifdef ENABLE_GLOBAL_LOG
|
||||
// Disable log to prevent unnecessary logging
|
||||
dont_log = true;
|
||||
#endif
|
||||
|
@ -644,10 +640,8 @@ void getCartInfo_GBA() {
|
|||
myFile.seekCur(9);
|
||||
|
||||
// Read 4 bytes into String, do it one at a time so byte order doesn't get mixed up
|
||||
sprintf(tempStr, "%c", myFile.read());
|
||||
for (byte i = 0; i < 3; i++) {
|
||||
sprintf(tempStr2, "%c", myFile.read());
|
||||
strcat(tempStr, tempStr2);
|
||||
for (byte i = 0; i < 4; i++) {
|
||||
tempStr[i] = char(myFile.read());
|
||||
}
|
||||
|
||||
// Check if string is a match
|
||||
|
@ -666,23 +660,15 @@ void getCartInfo_GBA() {
|
|||
myFile.seekCur(9);
|
||||
|
||||
// Read 4 bytes into String, do it one at a time so byte order doesn't get mixed up
|
||||
sprintf(tempStr, "%c", myFile.read());
|
||||
for (byte i = 0; i < 3; i++) {
|
||||
sprintf(tempStr2, "%c", myFile.read());
|
||||
strcat(tempStr, tempStr2);
|
||||
for (byte i = 0; i < 4; i++) {
|
||||
tempStr[i] = char(myFile.read());
|
||||
}
|
||||
|
||||
// Skip the , in the file
|
||||
myFile.seekCur(1);
|
||||
|
||||
// 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;
|
||||
}
|
||||
cartSize = ((myFile.read() - 48) * 10) + (myFile.read() - 48);
|
||||
|
||||
// Skip the , in the file
|
||||
myFile.seekCur(1);
|
||||
|
@ -703,21 +689,9 @@ void getCartInfo_GBA() {
|
|||
print_Msg(F("Save Lib: "));
|
||||
println_Msg(saveTypeStr);
|
||||
|
||||
#if defined(enable_OLED)
|
||||
print_STR(press_to_change_STR, 1);
|
||||
print_STR(right_to_select_STR, 1);
|
||||
#elif defined(enable_LCD)
|
||||
println_Msg(F(""));
|
||||
print_STR(rotate_to_change_STR, 1);
|
||||
print_STR(press_to_select_STR, 1);
|
||||
#elif defined(SERIAL_MONITOR)
|
||||
println_Msg(F(""));
|
||||
println_Msg(F("U/D to Change"));
|
||||
println_Msg(F("Space to Select"));
|
||||
#endif
|
||||
display_Update();
|
||||
printInstructions();
|
||||
|
||||
int b = 0;
|
||||
uint8_t b = 0;
|
||||
while (1) {
|
||||
// Check button input
|
||||
b = checkButton();
|
||||
|
@ -754,7 +728,7 @@ void getCartInfo_GBA() {
|
|||
// Close the file:
|
||||
myFile.close();
|
||||
|
||||
#ifdef global_log
|
||||
#ifdef ENABLE_GLOBAL_LOG
|
||||
// Enable log again
|
||||
dont_log = false;
|
||||
#endif
|
||||
|
@ -785,7 +759,7 @@ void getCartInfo_GBA() {
|
|||
sprintf(calcChecksumStr, "%02X", calcChecksum);
|
||||
println_Msg(calcChecksumStr);
|
||||
print_Error(F("Checksum Error"));
|
||||
println_Msg(F(""));
|
||||
println_Msg(FS(FSTRING_EMPTY));
|
||||
// Prints string out of the common strings array either with or without newline
|
||||
print_STR(press_button_STR, 1);
|
||||
display_Update();
|
||||
|
@ -847,30 +821,7 @@ void getCartInfo_GBA() {
|
|||
// Dump ROM
|
||||
void readROM_GBA() {
|
||||
// Get name, add extension and convert to char array for sd lib
|
||||
strcpy(fileName, romName);
|
||||
strcat(fileName, ".gba");
|
||||
|
||||
// create a new folder for the rom file
|
||||
EEPROM_readAnything(0, foldern);
|
||||
sprintf(folder, "GBA/ROM/%s/%d", romName, foldern);
|
||||
sd.mkdir(folder, true);
|
||||
sd.chdir(folder);
|
||||
|
||||
//clear the screen
|
||||
display_Clear();
|
||||
print_STR(saving_to_STR, 0);
|
||||
print_Msg(folder);
|
||||
println_Msg(F("/..."));
|
||||
display_Update();
|
||||
|
||||
// write new folder number back to eeprom
|
||||
foldern = foldern + 1;
|
||||
EEPROM_writeAnything(0, foldern);
|
||||
|
||||
//open file on sd card
|
||||
if (!myFile.open(fileName, O_RDWR | O_CREAT)) {
|
||||
print_FatalError(create_file_STR);
|
||||
}
|
||||
createFolderAndOpenFile("GBA", "ROM", romName, "gba");
|
||||
|
||||
//Initialize progress bar
|
||||
uint32_t processedProgressBar = 0;
|
||||
|
@ -914,7 +865,7 @@ void readROM_GBA() {
|
|||
|
||||
// Calculate the checksum of the dumped rom
|
||||
boolean compare_checksum_GBA() {
|
||||
print_Msg(F("Checksum: "));
|
||||
print_Msg(FS(FSTRING_CHECKSUM));
|
||||
display_Update();
|
||||
|
||||
strcpy(fileName, romName);
|
||||
|
@ -958,26 +909,11 @@ boolean compare_checksum_GBA() {
|
|||
/******************************************
|
||||
GBA SRAM SAVE Functions
|
||||
*****************************************/
|
||||
void readSRAM_GBA(boolean browseFile, unsigned long sramSize, uint32_t pos) {
|
||||
void readSRAM_GBA(boolean browseFile, uint32_t sramSize, uint32_t pos) {
|
||||
if (browseFile) {
|
||||
// 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(0, foldern);
|
||||
sprintf(folder, "GBA/SAVE/%s/%d", romName, foldern);
|
||||
sd.mkdir(folder, true);
|
||||
sd.chdir(folder);
|
||||
|
||||
// Save location
|
||||
print_STR(saving_to_STR, 0);
|
||||
print_Msg(folder);
|
||||
println_Msg(F("/..."));
|
||||
display_Update();
|
||||
// write new folder number back to eeprom
|
||||
foldern = foldern + 1;
|
||||
EEPROM_writeAnything(0, foldern);
|
||||
createFolder("GBA", "SAVE", romName, "srm");
|
||||
printAndIncrementFolder();
|
||||
}
|
||||
|
||||
//open file on sd card
|
||||
|
@ -989,7 +925,7 @@ void readSRAM_GBA(boolean browseFile, unsigned long sramSize, uint32_t pos) {
|
|||
if (pos != 0)
|
||||
myFile.seekCur(pos);
|
||||
|
||||
for (unsigned long currAddress = 0; currAddress < sramSize; currAddress += 512) {
|
||||
for (uint32_t currAddress = 0; currAddress < sramSize; currAddress += 512) {
|
||||
for (int c = 0; c < 512; c++) {
|
||||
// Read byte
|
||||
sdBuffer[c] = readByte_GBA(currAddress + c);
|
||||
|
@ -1006,7 +942,7 @@ void readSRAM_GBA(boolean browseFile, unsigned long sramSize, uint32_t pos) {
|
|||
display_Update();
|
||||
}
|
||||
|
||||
void writeSRAM_GBA(boolean browseFile, unsigned long sramSize, uint32_t pos) {
|
||||
void writeSRAM_GBA(boolean browseFile, uint32_t sramSize, uint32_t pos) {
|
||||
if (browseFile) {
|
||||
filePath[0] = '\0';
|
||||
sd.chdir("/");
|
||||
|
@ -1023,7 +959,7 @@ void writeSRAM_GBA(boolean browseFile, unsigned long sramSize, uint32_t pos) {
|
|||
if (pos != 0)
|
||||
myFile.seekCur(pos);
|
||||
|
||||
for (unsigned long currAddress = 0; currAddress < sramSize; currAddress += 512) {
|
||||
for (uint32_t currAddress = 0; currAddress < sramSize; currAddress += 512) {
|
||||
//fill sdBuffer
|
||||
myFile.read(sdBuffer, 512);
|
||||
|
||||
|
@ -1038,7 +974,7 @@ void writeSRAM_GBA(boolean browseFile, unsigned long sramSize, uint32_t pos) {
|
|||
display_Update();
|
||||
|
||||
} else {
|
||||
print_Error(F("File doesnt exist"));
|
||||
print_Error(FS(FSTRING_FILE_DOESNT_EXIST));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1102,28 +1038,8 @@ void readFRAM_GBA(unsigned long framSize) {
|
|||
PORTH &= ~((1 << 0) | (1 << 6));
|
||||
|
||||
// Get name, add extension and convert to char array for sd lib
|
||||
strcpy(fileName, romName);
|
||||
strcat(fileName, ".srm");
|
||||
createFolderAndOpenFile("GBA", "SAVE", romName, "srm");
|
||||
|
||||
// create a new folder for the save file
|
||||
EEPROM_readAnything(0, foldern);
|
||||
sprintf(folder, "GBA/SAVE/%s/%d", romName, foldern);
|
||||
sd.mkdir(folder, true);
|
||||
sd.chdir(folder);
|
||||
|
||||
// Save location
|
||||
print_STR(saving_to_STR, 0);
|
||||
print_Msg(folder);
|
||||
println_Msg(F("/..."));
|
||||
display_Update();
|
||||
// write new folder number back to eeprom
|
||||
foldern = foldern + 1;
|
||||
EEPROM_writeAnything(0, foldern);
|
||||
|
||||
//open file on sd card
|
||||
if (!myFile.open(fileName, O_RDWR | O_CREAT)) {
|
||||
print_FatalError(sd_error_STR);
|
||||
}
|
||||
for (unsigned long currAddress = 0; currAddress < framSize; currAddress += 512) {
|
||||
for (int c = 0; c < 512; c++) {
|
||||
// Pull OE_SRAM(PH6) HIGH
|
||||
|
@ -1225,7 +1141,7 @@ void writeFRAM_GBA(boolean browseFile, unsigned long framSize) {
|
|||
display_Update();
|
||||
|
||||
} else {
|
||||
print_Error(F("File doesnt exist"));
|
||||
print_Error(FS(FSTRING_FILE_DOESNT_EXIST));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1294,8 +1210,7 @@ unsigned long verifyFRAM_GBA(unsigned long framSize) {
|
|||
/******************************************
|
||||
GBA FLASH SAVE Functions
|
||||
*****************************************/
|
||||
// SST 39VF512 Flashrom
|
||||
void idFlash_GBA() {
|
||||
void initOutputFlash_GBA() {
|
||||
// Output a HIGH signal on CS_ROM(PH3) WE_FLASH(PH5) and OE_FLASH(PH6)
|
||||
PORTH |= (1 << 3) | (1 << 5) | (1 << 6);
|
||||
|
||||
|
@ -1307,6 +1222,11 @@ void idFlash_GBA() {
|
|||
|
||||
// Output a LOW signal on CE_FLASH(PH0)
|
||||
PORTH &= ~(1 << 0);
|
||||
}
|
||||
|
||||
// SST 39VF512 Flashrom
|
||||
void idFlash_GBA() {
|
||||
initOutputFlash_GBA();
|
||||
|
||||
// ID command sequence
|
||||
writeByteFlash_GBA(0x5555, 0xaa);
|
||||
|
@ -1336,17 +1256,7 @@ void idFlash_GBA() {
|
|||
|
||||
// Reset FLASH
|
||||
void resetFLASH_GBA() {
|
||||
// Output a HIGH signal on CS_ROM(PH3) WE_FLASH(PH5) and OE_FLASH(PH6)
|
||||
PORTH |= (1 << 3) | (1 << 5) | (1 << 6);
|
||||
|
||||
// Set address ports to output
|
||||
DDRF = 0xFF;
|
||||
DDRK = 0xFF;
|
||||
// Set data pins to output
|
||||
DDRC = 0xFF;
|
||||
|
||||
// Output a LOW signal on CE_FLASH(PH0)
|
||||
PORTH &= ~(1 << 0);
|
||||
initOutputFlash_GBA();
|
||||
|
||||
// Reset command sequence
|
||||
writeByteFlash_GBA(0x5555, 0xAA);
|
||||
|
@ -1361,7 +1271,7 @@ void resetFLASH_GBA() {
|
|||
delay(100);
|
||||
}
|
||||
|
||||
byte readByteFlash_GBA(unsigned long myAddress) {
|
||||
byte readByteFlash_GBA(uint16_t myAddress) {
|
||||
// Set address
|
||||
PORTF = myAddress & 0xFF;
|
||||
PORTK = (myAddress >> 8) & 0xFF;
|
||||
|
@ -1384,7 +1294,7 @@ byte readByteFlash_GBA(unsigned long myAddress) {
|
|||
return tempByte;
|
||||
}
|
||||
|
||||
void writeByteFlash_GBA(unsigned long myAddress, byte myData) {
|
||||
void writeByteFlash_GBA(uint16_t myAddress, byte myData) {
|
||||
PORTF = myAddress & 0xFF;
|
||||
PORTK = (myAddress >> 8) & 0xFF;
|
||||
PORTC = myData;
|
||||
|
@ -1417,17 +1327,7 @@ void writeByteFlash_GBA(unsigned long myAddress, byte myData) {
|
|||
|
||||
// Erase FLASH
|
||||
void eraseFLASH_GBA() {
|
||||
// Output a HIGH signal on CS_ROM(PH3) WE_FLASH(PH5) and OE_FLASH(PH6)
|
||||
PORTH |= (1 << 3) | (1 << 5) | (1 << 6);
|
||||
|
||||
// Set address ports to output
|
||||
DDRF = 0xFF;
|
||||
DDRK = 0xFF;
|
||||
// Set data pins to output
|
||||
DDRC = 0xFF;
|
||||
|
||||
// Output a LOW signal on CE_FLASH(PH0)
|
||||
PORTH &= ~(1 << 0);
|
||||
initOutputFlash_GBA();
|
||||
|
||||
// Erase command sequence
|
||||
writeByteFlash_GBA(0x5555, 0xaa);
|
||||
|
@ -1444,7 +1344,7 @@ void eraseFLASH_GBA() {
|
|||
delay(500);
|
||||
}
|
||||
|
||||
boolean blankcheckFLASH_GBA(unsigned long flashSize) {
|
||||
boolean blankcheckFLASH_GBA(uint32_t flashSize) {
|
||||
// Output a HIGH signal on CS_ROM(PH3) WE_FLASH(PH5)
|
||||
PORTH |= (1 << 3) | (1 << 5);
|
||||
|
||||
|
@ -1468,14 +1368,14 @@ boolean blankcheckFLASH_GBA(unsigned long flashSize) {
|
|||
// Output a LOW signal on OE_FLASH(PH6)
|
||||
PORTH &= ~(1 << 6);
|
||||
|
||||
for (unsigned long currAddress = 0; currAddress < flashSize; currAddress += 512) {
|
||||
for (uint32_t currAddress = 0; currAddress < flashSize; currAddress += 512) {
|
||||
// Fill buffer
|
||||
for (int c = 0; c < 512; c++) {
|
||||
// Read byte
|
||||
sdBuffer[c] = readByteFlash_GBA(currAddress + c);
|
||||
}
|
||||
// Check buffer
|
||||
for (unsigned long currByte = 0; currByte < 512; currByte++) {
|
||||
for (uint32_t currByte = 0; currByte < 512; currByte++) {
|
||||
if (sdBuffer[currByte] != 0xFF) {
|
||||
print_Error(F("Erase failed"));
|
||||
currByte = 512;
|
||||
|
@ -1494,17 +1394,7 @@ boolean blankcheckFLASH_GBA(unsigned long flashSize) {
|
|||
// each sector is 4096 bytes, there are 32 sectors total
|
||||
// therefore the bank size is 65536 bytes, so we have two banks in total
|
||||
void switchBank_GBA(byte bankNum) {
|
||||
// Output a HIGH signal on CS_ROM(PH3) WE_FLASH(PH5) and OE_FLASH(PH6)
|
||||
PORTH |= (1 << 3) | (1 << 5) | (1 << 6);
|
||||
|
||||
// Set address ports to output
|
||||
DDRF = 0xFF;
|
||||
DDRK = 0xFF;
|
||||
// Set data pins to output
|
||||
DDRC = 0xFF;
|
||||
|
||||
// Output a LOW signal on CE_FLASH(PH0)
|
||||
PORTH &= ~(1 << 0);
|
||||
initOutputFlash_GBA();
|
||||
|
||||
// Switch bank command sequence
|
||||
writeByte_GBA(0x5555, 0xAA);
|
||||
|
@ -1516,7 +1406,7 @@ void switchBank_GBA(byte bankNum) {
|
|||
PORTH |= (1 << 0);
|
||||
}
|
||||
|
||||
void readFLASH_GBA(boolean browseFile, unsigned long flashSize, uint32_t pos) {
|
||||
void readFLASH_GBA(boolean browseFile, uint32_t flashSize, uint32_t pos) {
|
||||
// Output a HIGH signal on CS_ROM(PH3) WE_FLASH(PH5)
|
||||
PORTH |= (1 << 3) | (1 << 5);
|
||||
|
||||
|
@ -1532,25 +1422,9 @@ void readFLASH_GBA(boolean browseFile, unsigned long flashSize, uint32_t pos) {
|
|||
|
||||
if (browseFile) {
|
||||
// Get name, add extension and convert to char array for sd lib
|
||||
strcpy(fileName, romName);
|
||||
strcat(fileName, ".fla");
|
||||
createFolder("GBA", "SAVE", romName, "fla");
|
||||
|
||||
// create a new folder for the save file
|
||||
EEPROM_readAnything(0, foldern);
|
||||
|
||||
sprintf(folder, "GBA/SAVE/%s/%d", romName, foldern);
|
||||
sd.mkdir(folder, true);
|
||||
sd.chdir(folder);
|
||||
|
||||
// Save location
|
||||
print_STR(saving_to_STR, 0);
|
||||
print_Msg(folder);
|
||||
println_Msg(F("/..."));
|
||||
display_Update();
|
||||
|
||||
// write new folder number back to eeprom
|
||||
foldern = foldern + 1;
|
||||
EEPROM_writeAnything(0, foldern);
|
||||
printAndIncrementFolder();
|
||||
}
|
||||
|
||||
//open file on sd card
|
||||
|
@ -1568,7 +1442,7 @@ void readFLASH_GBA(boolean browseFile, unsigned long flashSize, uint32_t pos) {
|
|||
// Output a LOW signal on OE_FLASH(PH6)
|
||||
PORTH &= ~(1 << 6);
|
||||
|
||||
for (unsigned long currAddress = 0; currAddress < flashSize; currAddress += 512) {
|
||||
for (uint32_t currAddress = 0; currAddress < flashSize; currAddress += 512) {
|
||||
for (int c = 0; c < 512; c++) {
|
||||
// Read byte
|
||||
sdBuffer[c] = readByteFlash_GBA(currAddress + c);
|
||||
|
@ -1586,7 +1460,7 @@ void readFLASH_GBA(boolean browseFile, unsigned long flashSize, uint32_t pos) {
|
|||
display_Update();
|
||||
}
|
||||
|
||||
void busyCheck_GBA(int currByte) {
|
||||
void busyCheck_GBA(uint16_t currByte) {
|
||||
// Set data pins to input
|
||||
DDRC = 0x00;
|
||||
// Output a LOW signal on OE_FLASH(PH6)
|
||||
|
@ -1599,7 +1473,7 @@ void busyCheck_GBA(int currByte) {
|
|||
DDRC = 0xFF;
|
||||
}
|
||||
|
||||
void writeFLASH_GBA(boolean browseFile, unsigned long flashSize, uint32_t pos, boolean isAtmel) {
|
||||
void writeFLASH_GBA(boolean browseFile, uint32_t flashSize, uint32_t pos, boolean isAtmel) {
|
||||
// Output a HIGH signal on CS_ROM(PH3) WE_FLASH(PH5) and OE_FLASH(PH6)
|
||||
PORTH |= (1 << 3) | (1 << 5) | (1 << 6);
|
||||
|
||||
|
@ -1632,7 +1506,7 @@ void writeFLASH_GBA(boolean browseFile, unsigned long flashSize, uint32_t pos, b
|
|||
PORTH &= ~(1 << 0);
|
||||
|
||||
if (!isAtmel) {
|
||||
for (unsigned long currAddress = 0; currAddress < flashSize; currAddress += 512) {
|
||||
for (uint32_t currAddress = 0; currAddress < flashSize; currAddress += 512) {
|
||||
//fill sdBuffer
|
||||
myFile.read(sdBuffer, 512);
|
||||
|
||||
|
@ -1649,7 +1523,7 @@ void writeFLASH_GBA(boolean browseFile, unsigned long flashSize, uint32_t pos, b
|
|||
}
|
||||
}
|
||||
} else {
|
||||
for (unsigned long currAddress = 0; currAddress < flashSize; currAddress += 128) {
|
||||
for (uint32_t currAddress = 0; currAddress < flashSize; currAddress += 128) {
|
||||
//fill sdBuffer
|
||||
myFile.read(sdBuffer, 128);
|
||||
|
||||
|
@ -1673,12 +1547,12 @@ void writeFLASH_GBA(boolean browseFile, unsigned long flashSize, uint32_t pos, b
|
|||
|
||||
} else {
|
||||
println_Msg(F("Error"));
|
||||
print_Error(F("File doesnt exist"));
|
||||
print_Error(FS(FSTRING_FILE_DOESNT_EXIST));
|
||||
}
|
||||
}
|
||||
|
||||
// Check if the Flashrom was written without any error
|
||||
unsigned long verifyFLASH_GBA(unsigned long flashSize, uint32_t pos) {
|
||||
unsigned long verifyFLASH_GBA(uint32_t flashSize, uint32_t pos) {
|
||||
// Output a HIGH signal on CS_ROM(PH3) WE_FLASH(PH5)
|
||||
PORTH |= (1 << 3) | (1 << 5);
|
||||
|
||||
|
@ -1723,7 +1597,7 @@ unsigned long verifyFLASH_GBA(unsigned long flashSize, uint32_t pos) {
|
|||
PORTH |= (1 << 0);
|
||||
|
||||
if (wrError == 0) {
|
||||
println_Msg(F("OK"));
|
||||
println_Msg(FS(FSTRING_OK));
|
||||
} else {
|
||||
print_Msg(wrError);
|
||||
print_Error(F(" Errors"));
|
||||
|
@ -1769,32 +1643,16 @@ void writeEeprom_GBA(word eepSize) {
|
|||
display_Update();
|
||||
} else {
|
||||
println_Msg(F("Error"));
|
||||
print_Error(F("File doesnt exist"));
|
||||
print_Error(FS(FSTRING_FILE_DOESNT_EXIST));
|
||||
}
|
||||
}
|
||||
|
||||
// Read eeprom to file
|
||||
void readEeprom_GBA(word eepSize) {
|
||||
// Get name, add extension and convert to char array for sd lib
|
||||
strcpy(fileName, romName);
|
||||
strcat(fileName, ".eep");
|
||||
createFolder("GBA", "SAVE", romName, "eep");
|
||||
|
||||
// create a new folder for the save file
|
||||
EEPROM_readAnything(0, foldern);
|
||||
|
||||
sprintf(folder, "GBA/SAVE/%s/%d", romName, foldern);
|
||||
sd.mkdir(folder, true);
|
||||
sd.chdir(folder);
|
||||
|
||||
// Save location
|
||||
print_STR(saving_to_STR, 0);
|
||||
print_Msg(folder);
|
||||
println_Msg(F("/..."));
|
||||
display_Update();
|
||||
|
||||
// write new folder number back to eeprom
|
||||
foldern = foldern + 1;
|
||||
EEPROM_writeAnything(0, foldern);
|
||||
printAndIncrementFolder();
|
||||
|
||||
//open file on sd card
|
||||
if (!myFile.open(fileName, O_RDWR | O_CREAT)) {
|
||||
|
@ -2145,11 +2003,11 @@ void idFlashrom_GBA() {
|
|||
resetMX29GL128E_GBA();
|
||||
} else {
|
||||
println_Msg(F("Error"));
|
||||
println_Msg(F(""));
|
||||
println_Msg(FS(FSTRING_EMPTY));
|
||||
println_Msg(F("Unknown Flash"));
|
||||
print_Msg(F("Flash ID: "));
|
||||
println_Msg(flashid_str);
|
||||
println_Msg(F(""));
|
||||
println_Msg(FS(FSTRING_EMPTY));
|
||||
print_FatalError(F("Check voltage"));
|
||||
}
|
||||
}
|
||||
|
@ -2591,7 +2449,7 @@ void flashRepro_GBA() {
|
|||
println_Msg("");
|
||||
println_Msg(F("This will erase your"));
|
||||
println_Msg(F("Repro Cartridge."));
|
||||
println_Msg(F(""));
|
||||
println_Msg(FS(FSTRING_EMPTY));
|
||||
println_Msg("");
|
||||
// Prints string out of the common strings array either with or without newline
|
||||
print_STR(press_button_STR, 1);
|
||||
|
@ -2649,7 +2507,7 @@ void flashRepro_GBA() {
|
|||
print_Msg(F("Blankcheck..."));
|
||||
display_Update();
|
||||
if (blankcheckFlashrom_GBA()) {
|
||||
println_Msg(F("OK"));
|
||||
println_Msg(FS(FSTRING_OK));
|
||||
*/
|
||||
|
||||
//Write flashrom
|
||||
|
@ -2693,7 +2551,7 @@ void flashRepro_GBA() {
|
|||
delay(1000);
|
||||
}
|
||||
if (verifyFlashrom_GBA() == 1) {
|
||||
println_Msg(F("OK"));
|
||||
println_Msg(FS(FSTRING_OK));
|
||||
display_Update();
|
||||
} else {
|
||||
print_FatalError(F("ERROR"));
|
||||
|
@ -2709,11 +2567,11 @@ void flashRepro_GBA() {
|
|||
}
|
||||
} else {
|
||||
println_Msg(F("Error"));
|
||||
println_Msg(F(""));
|
||||
println_Msg(FS(FSTRING_EMPTY));
|
||||
println_Msg(F("Unknown Flash"));
|
||||
print_Msg(F("Flash ID: "));
|
||||
println_Msg(flashid_str);
|
||||
println_Msg(F(""));
|
||||
println_Msg(FS(FSTRING_EMPTY));
|
||||
print_FatalError(F("Check voltage"));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
//******************************************
|
||||
// GB MEMORY MODULE
|
||||
//******************************************
|
||||
#ifdef enable_GBX
|
||||
#ifdef ENABLE_GBX
|
||||
|
||||
/******************************************
|
||||
Menu
|
||||
|
@ -86,7 +86,7 @@ void gbmMenu() {
|
|||
// Clear screen
|
||||
display_Clear();
|
||||
if (blankcheckFlash_GBM()) {
|
||||
println_Msg(F("OK"));
|
||||
println_Msg(FS(FSTRING_OK));
|
||||
display_Update();
|
||||
} else {
|
||||
println_Msg(F("ERROR"));
|
||||
|
@ -162,7 +162,7 @@ void gbmMenu() {
|
|||
// Erase mapping
|
||||
eraseMapping_GBM();
|
||||
if (blankcheckMapping_GBM()) {
|
||||
println_Msg(F("OK"));
|
||||
println_Msg(FS(FSTRING_OK));
|
||||
display_Update();
|
||||
} else {
|
||||
print_Error(F("Erasing failed"));
|
||||
|
@ -173,7 +173,7 @@ void gbmMenu() {
|
|||
writeMapping_GBM();
|
||||
break;
|
||||
}
|
||||
println_Msg(F(""));
|
||||
println_Msg(FS(FSTRING_EMPTY));
|
||||
// Prints string out of the common strings array either with or without newline
|
||||
print_STR(press_button_STR, 1);
|
||||
display_Update();
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
// GB SMART MODULE
|
||||
// Supports 32M cart with LH28F016SUT flash
|
||||
//******************************************
|
||||
#ifdef enable_GBX
|
||||
#ifdef ENABLE_GBX
|
||||
#define GB_SMART_GAMES_PER_PAGE 6
|
||||
|
||||
/******************************************
|
||||
|
@ -11,8 +11,7 @@
|
|||
// GB Smart menu items
|
||||
static const char gbSmartMenuItem1[] PROGMEM = "Game Menu";
|
||||
static const char gbSmartMenuItem2[] PROGMEM = "Flash Menu";
|
||||
//static const char gbSmartMenuItem3[] PROGMEM = "Reset"; (stored in common strings array)
|
||||
static const char *const menuOptionsGBSmart[] PROGMEM = { gbSmartMenuItem1, gbSmartMenuItem2, string_reset2 };
|
||||
static const char *const menuOptionsGBSmart[] PROGMEM = { gbSmartMenuItem1, gbSmartMenuItem2, FSTRING_RESET };
|
||||
|
||||
static const char gbSmartFlashMenuItem1[] PROGMEM = "Read Flash";
|
||||
static const char gbSmartFlashMenuItem2[] PROGMEM = "Write Flash";
|
||||
|
@ -20,11 +19,8 @@ static const char gbSmartFlashMenuItem3[] PROGMEM = "Back";
|
|||
static const char *const menuOptionsGBSmartFlash[] PROGMEM = { gbSmartFlashMenuItem1, gbSmartFlashMenuItem2, gbSmartFlashMenuItem3 };
|
||||
|
||||
static const char gbSmartGameMenuItem1[] PROGMEM = "Read Game";
|
||||
static const char gbSmartGameMenuItem2[] PROGMEM = "Read SRAM";
|
||||
static const char gbSmartGameMenuItem3[] PROGMEM = "Write SRAM";
|
||||
static const char gbSmartGameMenuItem4[] PROGMEM = "Switch Game";
|
||||
//static const char gbSmartGameMenuItem5[] PROGMEM = "Reset"; (stored in common strings array)
|
||||
static const char *const menuOptionsGBSmartGame[] PROGMEM = { gbSmartGameMenuItem1, gbSmartGameMenuItem2, gbSmartGameMenuItem3, gbSmartGameMenuItem4, string_reset2 };
|
||||
static const char *const menuOptionsGBSmartGame[] PROGMEM = { gbSmartGameMenuItem1, FSTRING_READ_SAVE, FSTRING_WRITE_SAVE, gbSmartGameMenuItem4, FSTRING_RESET };
|
||||
|
||||
struct GBSmartGameInfo {
|
||||
uint8_t start_bank;
|
||||
|
@ -163,7 +159,7 @@ void gbSmartMenu() {
|
|||
}
|
||||
case 1:
|
||||
{
|
||||
mode = mode_GB_GBSmart_Flash;
|
||||
mode = CORE_GB_GBSMART_FLASH;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
@ -227,7 +223,7 @@ void gbSmartGameOptions() {
|
|||
}
|
||||
|
||||
if (gameSubMenu != 3) {
|
||||
println_Msg(F(""));
|
||||
println_Msg(FS(FSTRING_EMPTY));
|
||||
// Prints string out of the common strings array either with or without newline
|
||||
print_STR(press_button_STR, 1);
|
||||
display_Update();
|
||||
|
@ -269,7 +265,7 @@ gb_smart_load_more_games:
|
|||
getCartInfo_GB();
|
||||
showCartInfo_GB();
|
||||
|
||||
mode = mode_GB_GBSmart_Game;
|
||||
mode = CORE_GB_GBSMART_GAME;
|
||||
}
|
||||
|
||||
void gbSmartFlashMenu() {
|
||||
|
@ -303,7 +299,7 @@ void gbSmartFlashMenu() {
|
|||
println_Msg(F("Attention"));
|
||||
println_Msg(F("This will erase your"));
|
||||
println_Msg(F("GB Smart Cartridge."));
|
||||
println_Msg(F(""));
|
||||
println_Msg(FS(FSTRING_EMPTY));
|
||||
// Prints string out of the common strings array either with or without newline
|
||||
print_STR(press_button_STR, 1);
|
||||
display_Update();
|
||||
|
@ -320,12 +316,12 @@ void gbSmartFlashMenu() {
|
|||
}
|
||||
default:
|
||||
{
|
||||
mode = mode_GB_GBSmart;
|
||||
mode = CORE_GB_GBSMART;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
println_Msg(F(""));
|
||||
println_Msg(FS(FSTRING_EMPTY));
|
||||
// Prints string out of the common strings array either with or without newline
|
||||
print_STR(press_button_STR, 1);
|
||||
display_Update();
|
||||
|
@ -476,7 +472,7 @@ void gbSmartWriteFlash() {
|
|||
|
||||
writeErrors = gbSmartVerifyFlash();
|
||||
if (writeErrors == 0) {
|
||||
println_Msg(F("OK"));
|
||||
println_Msg(FS(FSTRING_OK));
|
||||
display_Update();
|
||||
} else {
|
||||
print_STR(error_STR, 0);
|
||||
|
|
398
Cart_Reader/GPC.ino
Normal file
398
Cart_Reader/GPC.ino
Normal file
|
@ -0,0 +1,398 @@
|
|||
//******************************************
|
||||
// SNES Game Processor RAM Cassette code by LuigiBlood
|
||||
// Revision 1.0.0 February 2024
|
||||
//******************************************
|
||||
#ifdef ENABLE_GPC
|
||||
|
||||
/******************************************
|
||||
Game Processor RAM Cassette
|
||||
******************************************/
|
||||
/******************************************
|
||||
Prototype Declarations
|
||||
*****************************************/
|
||||
/* Hoping that sanni will use this progressbar function */
|
||||
extern void draw_progressbar(uint32_t processedsize, uint32_t totalsize);
|
||||
|
||||
//void gpcMenu();
|
||||
void readRAM_GPC();
|
||||
//void setup_GPC();
|
||||
void writeRAM_GPC(void);
|
||||
|
||||
/******************************************
|
||||
Variables
|
||||
*****************************************/
|
||||
//No global variables
|
||||
|
||||
/******************************************
|
||||
Menu
|
||||
*****************************************/
|
||||
// GPC flash menu items
|
||||
static const char gpcFlashMenuItem1[] PROGMEM = "Read RAM";
|
||||
static const char gpcFlashMenuItem2[] PROGMEM = "Write RAM";
|
||||
static const char* const menuOptionsGPCFlash[] PROGMEM = { gpcFlashMenuItem1, gpcFlashMenuItem2, FSTRING_RESET };
|
||||
|
||||
|
||||
void gpcMenu() {
|
||||
// create menu with title and 3 options to choose from
|
||||
unsigned char mainMenu;
|
||||
// Copy menuOptions out of progmem
|
||||
convertPgm(menuOptionsGPCFlash, 3);
|
||||
mainMenu = question_box(F("Game Processor RAM"), menuOptions, 3, 0);
|
||||
|
||||
// wait for user choice to come back from the question box menu
|
||||
switch (mainMenu) {
|
||||
// Read ram
|
||||
case 0:
|
||||
// Change working dir to root
|
||||
sd.chdir("/");
|
||||
readRAM_GPC();
|
||||
break;
|
||||
|
||||
// Write ram
|
||||
case 1:
|
||||
// Change working dir to root
|
||||
sd.chdir("/");
|
||||
writeRAM_GPC();
|
||||
unsigned long wrErrors;
|
||||
wrErrors = verifyRAM_GPC();
|
||||
if (wrErrors == 0) {
|
||||
println_Msg(F("Verified OK"));
|
||||
display_Update();
|
||||
} else {
|
||||
print_STR(error_STR, 0);
|
||||
print_Msg(wrErrors);
|
||||
print_STR(_bytes_STR, 1);
|
||||
print_Error(did_not_verify_STR);
|
||||
}
|
||||
wait();
|
||||
break;
|
||||
|
||||
// Reset
|
||||
case 2:
|
||||
resetArduino();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************
|
||||
Setup
|
||||
*****************************************/
|
||||
void setup_GPC() {
|
||||
// Request 5V
|
||||
setVoltage(VOLTS_SET_5V);
|
||||
|
||||
// Set cicrstPin(PG1) to Output
|
||||
DDRG |= (1 << 1);
|
||||
// Output a high signal until we're ready to start
|
||||
PORTG |= (1 << 1);
|
||||
// Set cichstPin(PG0) to Input
|
||||
DDRG &= ~(1 << 0);
|
||||
|
||||
// Adafruit Clock Generator
|
||||
i2c_found = clockgen.init(SI5351_CRYSTAL_LOAD_8PF, 0, 0);
|
||||
if (i2c_found) {
|
||||
clockgen.set_pll(SI5351_PLL_FIXED, SI5351_PLLA);
|
||||
clockgen.set_pll(SI5351_PLL_FIXED, SI5351_PLLB);
|
||||
clockgen.set_freq(2147727200ULL, SI5351_CLK0);
|
||||
clockgen.set_freq(307200000ULL, SI5351_CLK2);
|
||||
clockgen.output_enable(SI5351_CLK0, 1);
|
||||
clockgen.output_enable(SI5351_CLK1, 0);
|
||||
clockgen.output_enable(SI5351_CLK2, 1);
|
||||
}
|
||||
#ifdef ENABLE_CLOCKGEN
|
||||
else {
|
||||
display_Clear();
|
||||
print_FatalError(F("Clock Generator not found"));
|
||||
}
|
||||
#endif
|
||||
|
||||
// Set Address Pins to Output
|
||||
//A0-A7
|
||||
DDRF = 0xFF;
|
||||
//A8-A15
|
||||
DDRK = 0xFF;
|
||||
//BA0-BA7
|
||||
DDRL = 0xFF;
|
||||
//PA0-PA7
|
||||
DDRA = 0xFF;
|
||||
|
||||
// Set Control Pins to Output RST(PH0) CS(PH3) WR(PH5) RD(PH6)
|
||||
DDRH |= (1 << 0) | (1 << 3) | (1 << 5) | (1 << 6);
|
||||
// Switch RST(PH0) and WR(PH5) to HIGH
|
||||
PORTH |= (1 << 0) | (1 << 5);
|
||||
// Switch CS(PH3) and RD(PH6) to LOW
|
||||
PORTH &= ~((1 << 3) | (1 << 6));
|
||||
|
||||
// Set Refresh(PE5) to Output
|
||||
DDRE |= (1 << 5);
|
||||
// Switch Refresh(PE5) to LOW (needed for SA-1)
|
||||
PORTE &= ~(1 << 5);
|
||||
|
||||
// Set CPU Clock(PH1) to Output
|
||||
DDRH |= (1 << 1);
|
||||
//PORTH &= ~(1 << 1);
|
||||
|
||||
// Set IRQ(PH4) to Input
|
||||
DDRH &= ~(1 << 4);
|
||||
// Activate Internal Pullup Resistors
|
||||
//PORTH |= (1 << 4);
|
||||
|
||||
// Set expand(PG5) to output
|
||||
DDRG |= (1 << 5);
|
||||
// Output High
|
||||
PORTG |= (1 << 5);
|
||||
|
||||
// Set Data Pins (D0-D7) to Input
|
||||
DDRC = 0x00;
|
||||
// Enable Internal Pullups
|
||||
//PORTC = 0xFF;
|
||||
|
||||
// Unused pins
|
||||
// Set wram(PE4) to Output
|
||||
DDRE |= (1 << 4);
|
||||
//PORTE &= ~(1 << 4);
|
||||
// Set pawr(PJ1) to Output
|
||||
DDRJ |= (1 << 1);
|
||||
//PORTJ &= ~(1 << 1);
|
||||
// Set pard(PJ0) to Output
|
||||
DDRJ |= (1 << 0);
|
||||
//PORTJ &= ~(1 << 0);
|
||||
|
||||
// Start CIC by outputting a low signal to cicrstPin(PG1)
|
||||
PORTG &= ~(1 << 1);
|
||||
|
||||
// Wait for CIC reset
|
||||
delay(1000);
|
||||
}
|
||||
|
||||
/******************************************
|
||||
Low level functions
|
||||
*****************************************/
|
||||
// Write one byte of data to a location specified by bank and address, 00:0000
|
||||
void writeBank_GPC(byte myBank, word myAddress, byte myData) {
|
||||
PORTL = myBank;
|
||||
PORTF = myAddress & 0xFF;
|
||||
PORTK = (myAddress >> 8) & 0xFF;
|
||||
PORTC = myData;
|
||||
|
||||
// Arduino running at 16Mhz -> one nop = 62.5ns
|
||||
// Wait till output is stable
|
||||
__asm__("nop\n\t"
|
||||
"nop\n\t"
|
||||
"nop\n\t"
|
||||
"nop\n\t"
|
||||
"nop\n\t"
|
||||
"nop\n\t"
|
||||
"nop\n\t"
|
||||
"nop\n\t");
|
||||
|
||||
// Switch WR(PH5) to LOW
|
||||
PORTH &= ~(1 << 5);
|
||||
|
||||
// Leave WR low for at least 60ns
|
||||
__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"
|
||||
"nop\n\t"
|
||||
"nop\n\t"
|
||||
"nop\n\t"
|
||||
"nop\n\t");
|
||||
|
||||
// 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"
|
||||
"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 one byte of data from a location specified by bank and address, 00:0000
|
||||
byte readBank_GPC(byte myBank, word myAddress) {
|
||||
PORTL = myBank;
|
||||
PORTF = myAddress & 0xFF;
|
||||
PORTK = (myAddress >> 8) & 0xFF;
|
||||
|
||||
// Arduino running at 16Mhz -> one nop = 62.5ns -> 1000ns total
|
||||
__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"
|
||||
"nop\n\t"
|
||||
"nop\n\t"
|
||||
"nop\n\t"
|
||||
"nop\n\t");
|
||||
|
||||
// Read
|
||||
byte tempByte = PINC;
|
||||
return tempByte;
|
||||
}
|
||||
|
||||
/******************************************
|
||||
Game Processor RAM Cassette functions
|
||||
*****************************************/
|
||||
// Read RAM cassette to SD card
|
||||
void readRAM_GPC() {
|
||||
// Set control
|
||||
dataIn();
|
||||
controlIn_SNES();
|
||||
|
||||
// Get name, add extension and convert to char array for sd lib
|
||||
createFolderAndOpenFile("SNES", "ROM", "GPC4M", "sfc");
|
||||
|
||||
// Read Banks
|
||||
for (int currBank = 0xC0; currBank < 0xC8; currBank++) {
|
||||
// Dump the bytes to SD 512B at a time
|
||||
for (long currByte = 0; currByte < 65536; currByte += 512) {
|
||||
draw_progressbar((currBank - 0xC0) * 0x10000 + currByte, 0x80000);
|
||||
for (int c = 0; c < 512; c++) {
|
||||
sdBuffer[c] = readBank_GPC(currBank, currByte + c);
|
||||
}
|
||||
myFile.write(sdBuffer, 512);
|
||||
}
|
||||
}
|
||||
draw_progressbar(0x80000, 0x80000); //Finish drawing progress bar
|
||||
|
||||
// Close the file:
|
||||
myFile.close();
|
||||
println_Msg(F("Read ram completed"));
|
||||
display_Update();
|
||||
wait();
|
||||
}
|
||||
|
||||
void writeRAM_GPC(void) {
|
||||
//Display file Browser and wait user to select a file. Size must be 512KB.
|
||||
filePath[0] = '\0';
|
||||
sd.chdir("/");
|
||||
fileBrowser(F("Select SFC file"));
|
||||
// Create filepath
|
||||
sprintf(filePath, "%s/%s", filePath, fileName);
|
||||
display_Clear();
|
||||
|
||||
//open file on sd card
|
||||
if (myFile.open(filePath, O_READ)) {
|
||||
|
||||
fileSize = myFile.fileSize();
|
||||
if (fileSize != 0x80000) {
|
||||
println_Msg(F("File must be 512KB"));
|
||||
display_Update();
|
||||
myFile.close();
|
||||
wait();
|
||||
return;
|
||||
}
|
||||
|
||||
//Disable ram cassette write protection
|
||||
dataOut();
|
||||
controlOut_SNES();
|
||||
for (int countProtect = 0; countProtect < 15; countProtect++) {
|
||||
writeBank_GPC(0x20, 0x6000, 0x00);
|
||||
}
|
||||
|
||||
//Write ram
|
||||
dataOut();
|
||||
controlOut_SNES();
|
||||
println_Msg(F("Writing ram..."));
|
||||
display_Update();
|
||||
for (int currBank = 0xC0; currBank < 0xC8; currBank++) {
|
||||
//startAddr = 0x0000
|
||||
for (long currByte = 0x0000; currByte < 0x10000; currByte += 512) {
|
||||
myFile.read(sdBuffer, 512);
|
||||
for (unsigned long c = 0; c < 512; c++) {
|
||||
//startBank = 0x10; CS low
|
||||
writeBank_GPC(currBank, currByte + c, sdBuffer[c]);
|
||||
}
|
||||
}
|
||||
draw_progressbar(((currBank - 0xC0) * 0x10000), 0x80000);
|
||||
}
|
||||
|
||||
//reenable write protection
|
||||
dataIn();
|
||||
controlIn_SNES();
|
||||
byte keepByte = readBank_GPC(0x20, 0x6000);
|
||||
delay(100);
|
||||
dataOut();
|
||||
controlOut_SNES();
|
||||
writeBank_GPC(0x20, 0x6000, keepByte);
|
||||
|
||||
draw_progressbar(0x80000, 0x80000);
|
||||
delay(100);
|
||||
// Set pins to input
|
||||
dataIn();
|
||||
|
||||
// Close the file:
|
||||
myFile.close();
|
||||
println_Msg("");
|
||||
println_Msg(F("RAM writing finished"));
|
||||
display_Update();
|
||||
} else {
|
||||
print_Error(FS(FSTRING_FILE_DOESNT_EXIST));
|
||||
}
|
||||
}
|
||||
|
||||
// Check if the RAM was written without any error
|
||||
unsigned long verifyRAM_GPC() {
|
||||
//open file on sd card
|
||||
if (myFile.open(filePath, O_READ)) {
|
||||
// Variable for errors
|
||||
writeErrors = 0;
|
||||
|
||||
// Set control
|
||||
controlIn_SNES();
|
||||
|
||||
//startBank = 0xC0; endBank = 0xC7; CS low
|
||||
for (byte currBank = 0xC0; currBank < 0xC8; currBank++) {
|
||||
//startAddr = 0x0000
|
||||
for (long currByte = 0x0000; currByte < 0x10000; currByte += 512) {
|
||||
//fill sdBuffer
|
||||
myFile.read(sdBuffer, 512);
|
||||
for (unsigned long c = 0; c < 512; c++) {
|
||||
if ((readBank_GPC(currBank, currByte + c)) != sdBuffer[c]) {
|
||||
writeErrors++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Close the file:
|
||||
myFile.close();
|
||||
return writeErrors;
|
||||
} else {
|
||||
print_Error(F("Can't open file"));
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
//******************************************
|
||||
// End of File
|
||||
//******************************************
|
|
@ -1,7 +1,7 @@
|
|||
//******************************************
|
||||
// INTELLIVISION MODULE
|
||||
//******************************************
|
||||
#ifdef enable_INTV
|
||||
#ifdef ENABLE_INTV
|
||||
|
||||
// Mattel Intellivision
|
||||
// Cartridge Pinout
|
||||
|
@ -58,16 +58,16 @@
|
|||
// Cart Configurations
|
||||
// Format = {mapper,romlo,romhi,ramsize}
|
||||
static const byte PROGMEM intvmapsize[] = {
|
||||
0, 0, 2, 0, // default mattel up to 32K (8K/16K/24K/32K)
|
||||
1, 1, 3, 0, // demo cart 16K, championship tennis 32K, wsml baseball 48K
|
||||
2, 1, 3, 0, // up to 48K (16K/32K/48K)
|
||||
3, 4, 4, 0, // tower of doom 48K
|
||||
4, 0, 1, 1, // uscf chess 16K + RAM 1K
|
||||
5, 2, 3, 0, // congo bongo/defender/pac-man 24K, dig dug 32K
|
||||
6, 1, 1, 0, // centipede 16K
|
||||
7, 1, 1, 0, // imagic carts 16K
|
||||
8, 1, 1, 0, // mte-201 test cart 16K
|
||||
9, 3, 3, 2, // triple challenge 32K + RAM 2K
|
||||
0, 0, 3, 0, // default mattel up to 32K (8K/12K/16K/24K/32K)
|
||||
1, 2, 4, 0, // demo cart 16K, championship tennis 32K, wsml baseball 48K
|
||||
2, 2, 4, 0, // up to 48K (16K/32K/48K)
|
||||
3, 5, 5, 0, // tower of doom 48K
|
||||
4, 2, 2, 1, // uscf chess 16K + RAM 1K
|
||||
5, 3, 4, 0, // congo bongo/defender/pac-man 24K, dig dug 32K
|
||||
6, 2, 2, 0, // centipede 16K
|
||||
7, 2, 2, 0, // imagic carts 16K
|
||||
8, 2, 2, 0, // mte-201 test cart 16K
|
||||
9, 4, 4, 2, // triple challenge 32K + RAM 2K
|
||||
};
|
||||
|
||||
byte intvmapcount = 10; // (sizeof(mapsize)/sizeof(mapsize[0])) / 4;
|
||||
|
@ -75,14 +75,12 @@ boolean intvmapfound = false;
|
|||
byte intvmapselect;
|
||||
int intvindex;
|
||||
|
||||
const byte INTV[] PROGMEM = { 8, 16, 24, 32, 48 };
|
||||
const byte INTV[] PROGMEM = { 8, 12, 16, 24, 32, 48 };
|
||||
byte intvlo = 0; // Lowest Entry
|
||||
byte intvhi = 4; // Highest Entry
|
||||
byte intvhi = 5; // Highest Entry
|
||||
|
||||
byte intvmapper;
|
||||
byte newintvmapper;
|
||||
byte intvsize;
|
||||
byte newintvsize;
|
||||
|
||||
// EEPROM MAPPING
|
||||
// 07 MAPPER
|
||||
|
@ -92,11 +90,7 @@ byte newintvsize;
|
|||
// Menu
|
||||
//******************************************
|
||||
// Base Menu
|
||||
static const char intvMenuItem1[] PROGMEM = "Select Cart";
|
||||
static const char intvMenuItem2[] PROGMEM = "Read ROM";
|
||||
static const char intvMenuItem3[] PROGMEM = "Set Mapper + Size";
|
||||
//static const char intvMenuItem4[] PROGMEM = "Reset"; (stored in common strings array)
|
||||
static const char* const menuOptionsINTV[] PROGMEM = { intvMenuItem1, intvMenuItem2, intvMenuItem3, string_reset2 };
|
||||
static const char* const menuOptionsINTV[] PROGMEM = { FSTRING_SELECT_CART, FSTRING_READ_ROM, FSTRING_SET_SIZE, FSTRING_RESET };
|
||||
|
||||
void setup_INTV() {
|
||||
// Request 5V
|
||||
|
@ -134,7 +128,7 @@ void setup_INTV() {
|
|||
checkStatus_INTV();
|
||||
strcpy(romName, "INTV");
|
||||
|
||||
mode = mode_INTV;
|
||||
mode = CORE_INTV;
|
||||
}
|
||||
|
||||
void intvMenu() {
|
||||
|
@ -309,49 +303,31 @@ void readSegment_INTV(uint32_t startaddr, uint32_t endaddr) {
|
|||
|
||||
// MODIFIED READ ROUTINE FOR ALL 10 MAPPERS
|
||||
void readROM_INTV() {
|
||||
strcpy(fileName, romName);
|
||||
strcat(fileName, ".int");
|
||||
|
||||
// create a new folder for storing rom file
|
||||
EEPROM_readAnything(0, foldern);
|
||||
sprintf(folder, "INTV/ROM/%d", foldern);
|
||||
sd.mkdir(folder, true);
|
||||
sd.chdir(folder);
|
||||
|
||||
display_Clear();
|
||||
print_STR(saving_to_STR, 0);
|
||||
print_Msg(folder);
|
||||
println_Msg(F("/..."));
|
||||
display_Update();
|
||||
|
||||
// open file on sdcard
|
||||
if (!myFile.open(fileName, O_RDWR | O_CREAT))
|
||||
print_FatalError(create_file_STR);
|
||||
|
||||
// write new folder number back to EEPROM
|
||||
foldern++;
|
||||
EEPROM_writeAnything(0, foldern);
|
||||
createFolderAndOpenFile("INTV", "ROM", romName, "int");
|
||||
|
||||
switch (intvmapper) {
|
||||
case 0: //default mattel up to 32K (8K/16K/24K/32K)
|
||||
case 0: //default mattel up to 32K (8K/12K/16K/24K/32K)
|
||||
readSegment_INTV(0x5000, 0x6000); // 8K
|
||||
if (intvsize > 0) {
|
||||
readSegment_INTV(0x6000, 0x7000); // +8K = 16K
|
||||
readSegment_INTV(0x6000, 0x6800); // +4K = 12K
|
||||
if (intvsize > 1) {
|
||||
readSegment_INTV(0xD000, 0xE000); // +8K = 24K
|
||||
if (intvsize > 2)
|
||||
readSegment_INTV(0xF000, 0x10000); // +8K = 32K
|
||||
readSegment_INTV(0x6800, 0x7000); // +4K = 16K
|
||||
if (intvsize > 2) {
|
||||
readSegment_INTV(0xD000, 0xE000); // +8K = 24K
|
||||
if (intvsize > 3)
|
||||
readSegment_INTV(0xF000, 0x10000); // +8K = 32K
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 1: // demo cart/championship tennis/wsml baseball
|
||||
readSegment_INTV(0x5000, 0x7000); // 16K Demo Cart
|
||||
if (intvsize > 1) {
|
||||
if (intvsize > 2) {
|
||||
readSegment_INTV(0xD000, 0xE000); // +8K = 24K [NONE]
|
||||
if (intvsize > 2) {
|
||||
if (intvsize > 3) {
|
||||
readSegment_INTV(0xE000, 0xF000); // +8K = 32K Championship Tennis
|
||||
if (intvsize > 3) {
|
||||
if (intvsize > 4) {
|
||||
readSegment_INTV(0xF000, 0x10000); // +8K = 40K WSML Baseball [MISSING 8K ECS BANK]
|
||||
// ecs bank switch
|
||||
ecsBank(0xFFFF, 0x1); // switch ecs page 1 to 0xF000
|
||||
|
@ -364,11 +340,11 @@ void readROM_INTV() {
|
|||
|
||||
case 2: // up to 48K (16K/32K/48K)
|
||||
readSegment_INTV(0x5000, 0x7000); // 16K
|
||||
if (intvsize > 1) {
|
||||
if (intvsize > 2) {
|
||||
readSegment_INTV(0x9000, 0xA000); // +8K = 24K [NONE]
|
||||
if (intvsize > 2) {
|
||||
if (intvsize > 3) {
|
||||
readSegment_INTV(0xA000, 0xB000); // +8K = 32K
|
||||
if (intvsize > 3) {
|
||||
if (intvsize > 4) {
|
||||
readSegment_INTV(0xB000, 0xC000); // +8K = 40K
|
||||
readSegment_INTV(0xD000, 0xE000); // +8K = 48K
|
||||
}
|
||||
|
@ -393,7 +369,7 @@ void readROM_INTV() {
|
|||
case 5: // congo bongo/defender/pac-man/dig dug
|
||||
readSegment_INTV(0x5000, 0x7000); // 16K
|
||||
readSegment_INTV(0x7000, 0x8000); // +8K = 24K Congo Bongo/Defender/Pac-Man
|
||||
if (intvsize > 2) {
|
||||
if (intvsize > 3) {
|
||||
readSegment_INTV(0x9000, 0xA000); // +8K = 32K Dig Dug
|
||||
//readSegment_INTV(0xA000,0xC000); // +16K = 48K [UNUSED]
|
||||
}
|
||||
|
@ -425,7 +401,7 @@ void readROM_INTV() {
|
|||
// Compare CRC32 to database and rename ROM if found
|
||||
compareCRC("intv.txt", 0, 1, 0);
|
||||
|
||||
println_Msg(F(""));
|
||||
println_Msg(FS(FSTRING_EMPTY));
|
||||
// Prints string out of the common strings array either with or without newline
|
||||
print_STR(press_button_STR, 1);
|
||||
display_Update();
|
||||
|
@ -485,113 +461,22 @@ void ecsBank(uint32_t addr, uint8_t bank) {
|
|||
//******************************************
|
||||
// MAPPER CODE
|
||||
//******************************************
|
||||
|
||||
void setMapper_INTV() {
|
||||
#if (defined(enable_OLED) || defined(enable_LCD))
|
||||
int b = 0;
|
||||
int i = 0;
|
||||
// Check Button Status
|
||||
#if defined(enable_OLED)
|
||||
buttonVal1 = (PIND & (1 << 7)); // PD7
|
||||
#elif defined(enable_LCD)
|
||||
boolean buttonVal1 = (PING & (1 << 2)); // PG2
|
||||
#endif
|
||||
if (buttonVal1 == LOW) { // Button Pressed
|
||||
while (1) { // Scroll Mapper List
|
||||
#if defined(enable_OLED)
|
||||
buttonVal1 = (PIND & (1 << 7)); // PD7
|
||||
#elif defined(enable_LCD)
|
||||
boolean buttonVal1 = (PING & (1 << 2)); // PG2
|
||||
#endif
|
||||
if (buttonVal1 == HIGH) { // Button Released
|
||||
// Correct Overshoot
|
||||
if (i == 0)
|
||||
i = intvmapcount - 1;
|
||||
else
|
||||
i--;
|
||||
break;
|
||||
}
|
||||
display_Clear();
|
||||
print_Msg(F("Mapper: "));
|
||||
intvindex = i * 4;
|
||||
intvmapselect = pgm_read_byte(intvmapsize + intvindex);
|
||||
println_Msg(intvmapselect);
|
||||
display_Update();
|
||||
if (i == (intvmapcount - 1))
|
||||
i = 0;
|
||||
else
|
||||
i++;
|
||||
delay(250);
|
||||
}
|
||||
}
|
||||
|
||||
#if (defined(ENABLE_OLED) || defined(ENABLE_LCD))
|
||||
void printMapperSelection_INTV(int index) {
|
||||
display_Clear();
|
||||
print_Msg(F("Mapper: "));
|
||||
intvindex = i * 4;
|
||||
print_Msg(FS(FSTRING_MAPPER));
|
||||
intvindex = index * 4;
|
||||
intvmapselect = pgm_read_byte(intvmapsize + intvindex);
|
||||
println_Msg(intvmapselect);
|
||||
println_Msg(F(""));
|
||||
#if defined(enable_OLED)
|
||||
print_STR(press_to_change_STR, 1);
|
||||
print_STR(right_to_select_STR, 1);
|
||||
#elif defined(enable_LCD)
|
||||
print_STR(rotate_to_change_STR, 1);
|
||||
print_STR(press_to_select_STR, 1);
|
||||
}
|
||||
#endif
|
||||
display_Update();
|
||||
|
||||
while (1) {
|
||||
b = checkButton();
|
||||
|
||||
if (b == 2) { // Previous Mapper (doubleclick)
|
||||
if (i == 0)
|
||||
i = intvmapcount - 1;
|
||||
else
|
||||
i--;
|
||||
|
||||
// Only update display after input because of slow LCD library
|
||||
display_Clear();
|
||||
print_Msg(F("Mapper: "));
|
||||
intvindex = i * 4;
|
||||
intvmapselect = pgm_read_byte(intvmapsize + intvindex);
|
||||
println_Msg(intvmapselect);
|
||||
println_Msg(F(""));
|
||||
#if defined(enable_OLED)
|
||||
print_STR(press_to_change_STR, 1);
|
||||
print_STR(right_to_select_STR, 1);
|
||||
#elif defined(enable_LCD)
|
||||
print_STR(rotate_to_change_STR, 1);
|
||||
print_STR(press_to_select_STR, 1);
|
||||
#endif
|
||||
display_Update();
|
||||
}
|
||||
if (b == 1) { // Next Mapper (press)
|
||||
if (i == (intvmapcount - 1))
|
||||
i = 0;
|
||||
else
|
||||
i++;
|
||||
|
||||
// Only update display after input because of slow LCD library
|
||||
display_Clear();
|
||||
print_Msg(F("Mapper: "));
|
||||
intvindex = i * 4;
|
||||
intvmapselect = pgm_read_byte(intvmapsize + intvindex);
|
||||
println_Msg(intvmapselect);
|
||||
println_Msg(F(""));
|
||||
#if defined(enable_OLED)
|
||||
print_STR(press_to_change_STR, 1);
|
||||
print_STR(right_to_select_STR, 1);
|
||||
#elif defined(enable_LCD)
|
||||
print_STR(rotate_to_change_STR, 1);
|
||||
print_STR(press_to_select_STR, 1);
|
||||
#endif
|
||||
display_Update();
|
||||
}
|
||||
if (b == 3) { // Long Press - Execute (hold)
|
||||
newintvmapper = intvmapselect;
|
||||
break;
|
||||
}
|
||||
}
|
||||
void setMapper_INTV() {
|
||||
byte newintvmapper;
|
||||
#if (defined(ENABLE_OLED) || defined(ENABLE_LCD))
|
||||
navigateMenu(0, intvmapcount - 1, &printMapperSelection_INTV);
|
||||
newintvmapper = intvmapselect;
|
||||
|
||||
display.setCursor(0, 56);
|
||||
print_Msg(F("MAPPER "));
|
||||
print_Msg(newintvmapper);
|
||||
|
@ -615,7 +500,7 @@ setmapper:
|
|||
}
|
||||
if (intvmapfound == false) {
|
||||
Serial.println(F("MAPPER NOT SUPPORTED!"));
|
||||
Serial.println(F(""));
|
||||
Serial.println(FS(FSTRING_EMPTY));
|
||||
newintvmapper = 0;
|
||||
goto setmapper;
|
||||
}
|
||||
|
@ -636,78 +521,26 @@ void checkMapperSize_INTV() {
|
|||
}
|
||||
}
|
||||
|
||||
#if (defined(ENABLE_OLED) || defined(ENABLE_LCD))
|
||||
void printRomSize_INTV(int index) {
|
||||
display_Clear();
|
||||
print_Msg(F("ROM Size: "));
|
||||
println_Msg(pgm_read_byte(&(INTV[index])));
|
||||
}
|
||||
#endif
|
||||
|
||||
void setROMSize_INTV() {
|
||||
#if (defined(enable_OLED) || defined(enable_LCD))
|
||||
byte newintvsize;
|
||||
#if (defined(ENABLE_OLED) || defined(ENABLE_LCD))
|
||||
display_Clear();
|
||||
if (intvlo == intvhi)
|
||||
newintvsize = intvlo;
|
||||
else {
|
||||
int b = 0;
|
||||
int i = intvlo;
|
||||
newintvsize = navigateMenu(intvlo, intvhi, &printRomSize_INTV);
|
||||
|
||||
// Only update display after input because of slow LCD library
|
||||
display_Clear();
|
||||
print_Msg(F("ROM Size: "));
|
||||
println_Msg(pgm_read_byte(&(INTV[i])));
|
||||
println_Msg(F(""));
|
||||
#if defined(enable_OLED)
|
||||
print_STR(press_to_change_STR, 1);
|
||||
print_STR(right_to_select_STR, 1);
|
||||
#elif defined(enable_LCD)
|
||||
print_STR(rotate_to_change_STR, 1);
|
||||
print_STR(press_to_select_STR, 1);
|
||||
#endif
|
||||
display_Update();
|
||||
|
||||
while (1) {
|
||||
b = checkButton();
|
||||
if (b == 2) { // Previous (doubleclick)
|
||||
if (i == intvlo)
|
||||
i = intvhi;
|
||||
else
|
||||
i--;
|
||||
|
||||
// Only update display after input because of slow LCD library
|
||||
display_Clear();
|
||||
print_Msg(F("ROM Size: "));
|
||||
println_Msg(pgm_read_byte(&(INTV[i])));
|
||||
println_Msg(F(""));
|
||||
#if defined(enable_OLED)
|
||||
print_STR(press_to_change_STR, 1);
|
||||
print_STR(right_to_select_STR, 1);
|
||||
#elif defined(enable_LCD)
|
||||
print_STR(rotate_to_change_STR, 1);
|
||||
print_STR(press_to_select_STR, 1);
|
||||
#endif
|
||||
display_Update();
|
||||
}
|
||||
if (b == 1) { // Next (press)
|
||||
if (i == intvhi)
|
||||
i = intvlo;
|
||||
else
|
||||
i++;
|
||||
|
||||
display_Clear();
|
||||
print_Msg(F("ROM Size: "));
|
||||
println_Msg(pgm_read_byte(&(INTV[i])));
|
||||
println_Msg(F(""));
|
||||
#if defined(enable_OLED)
|
||||
print_STR(press_to_change_STR, 1);
|
||||
print_STR(right_to_select_STR, 1);
|
||||
#elif defined(enable_LCD)
|
||||
print_STR(rotate_to_change_STR, 1);
|
||||
print_STR(press_to_select_STR, 1);
|
||||
#endif
|
||||
display_Update();
|
||||
}
|
||||
if (b == 3) { // Long Press - Execute (hold)
|
||||
newintvsize = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
display.setCursor(0, 56); // Display selection at bottom
|
||||
}
|
||||
print_Msg(F("ROM SIZE "));
|
||||
print_Msg(FS(FSTRING_ROM_SIZE));
|
||||
print_Msg(pgm_read_byte(&(INTV[newintvsize])));
|
||||
println_Msg(F("K"));
|
||||
display_Update();
|
||||
|
@ -732,7 +565,7 @@ setrom:
|
|||
newintvsize = sizeROM.toInt() + intvlo;
|
||||
if (newintvsize > intvhi) {
|
||||
Serial.println(F("SIZE NOT SUPPORTED"));
|
||||
Serial.println(F(""));
|
||||
Serial.println(FS(FSTRING_EMPTY));
|
||||
goto setrom;
|
||||
}
|
||||
}
|
||||
|
@ -751,19 +584,19 @@ void checkStatus_INTV() {
|
|||
intvmapper = 0;
|
||||
EEPROM_writeAnything(7, intvmapper);
|
||||
}
|
||||
if (intvsize > 4) {
|
||||
if (intvsize > 5) {
|
||||
intvsize = 0;
|
||||
EEPROM_writeAnything(8, intvsize);
|
||||
}
|
||||
|
||||
#if (defined(enable_OLED) || defined(enable_LCD))
|
||||
#if (defined(ENABLE_OLED) || defined(ENABLE_LCD))
|
||||
display_Clear();
|
||||
println_Msg(F("INTELLIVISION READER"));
|
||||
println_Msg(F("CURRENT SETTINGS"));
|
||||
println_Msg(F(""));
|
||||
println_Msg(FS(FSTRING_CURRENT_SETTINGS));
|
||||
println_Msg(FS(FSTRING_EMPTY));
|
||||
print_Msg(F("MAPPER: "));
|
||||
println_Msg(intvmapper);
|
||||
print_Msg(F("ROM SIZE: "));
|
||||
print_Msg(FS(FSTRING_ROM_SIZE));
|
||||
print_Msg(pgm_read_byte(&(INTV[intvsize])));
|
||||
println_Msg(F("K"));
|
||||
display_Update();
|
||||
|
@ -774,174 +607,115 @@ void checkStatus_INTV() {
|
|||
Serial.print(F("CURRENT ROM SIZE: "));
|
||||
Serial.print(pgm_read_byte(&(INTV[intvsize])));
|
||||
Serial.println(F("K"));
|
||||
Serial.println(F(""));
|
||||
Serial.println(FS(FSTRING_EMPTY));
|
||||
#endif
|
||||
}
|
||||
|
||||
//******************************************
|
||||
// CART SELECT CODE
|
||||
//******************************************
|
||||
void setCart_INTV() {
|
||||
char gamename[100];
|
||||
char tempStr2[2];
|
||||
struct database_entry_INTV {
|
||||
char crc_search[9];
|
||||
byte gameMapper;
|
||||
byte gameSize;
|
||||
};
|
||||
|
||||
void readDataLine_INTV(FsFile& database, void* entry) {
|
||||
struct database_entry_INTV* castEntry = (database_entry_INTV*)entry;
|
||||
// Read CRC32 checksum
|
||||
for (byte i = 0; i < 8; i++) {
|
||||
checksumStr[i] = char(database.read());
|
||||
}
|
||||
|
||||
// Skip over semicolon
|
||||
database.seekCur(1);
|
||||
|
||||
// Read CRC32 of first 512 bytes
|
||||
for (byte i = 0; i < 8; i++) {
|
||||
castEntry->crc_search[i] = char(database.read());
|
||||
}
|
||||
|
||||
// Skip over semicolon
|
||||
database.seekCur(1);
|
||||
|
||||
// Read mapper
|
||||
castEntry->gameMapper = database.read() - 48;
|
||||
|
||||
// Skip over semicolon
|
||||
database.seekCur(1);
|
||||
|
||||
// Read rom size
|
||||
// Read the next ascii character and subtract 48 to convert to decimal
|
||||
castEntry->gameSize = ((database.read() - 48) * 10) + (database.read() - 48);
|
||||
|
||||
// Skip over semicolon
|
||||
database.seekCur(1);
|
||||
|
||||
// Read SRAM size
|
||||
byte sramSize __attribute__((unused)) = database.read() - 48;
|
||||
|
||||
// Skip rest of line
|
||||
database.seekCur(2);
|
||||
}
|
||||
|
||||
void printDataLine_INTV(void* entry) {
|
||||
struct database_entry_INTV* castEntry = (database_entry_INTV*)entry;
|
||||
print_Msg(FS(FSTRING_SIZE));
|
||||
print_Msg(castEntry->gameSize);
|
||||
println_Msg(F("KB"));
|
||||
print_Msg(FS(FSTRING_MAPPER));
|
||||
println_Msg(castEntry->gameMapper);
|
||||
}
|
||||
|
||||
void setCart_INTV() {
|
||||
//go to root
|
||||
sd.chdir();
|
||||
|
||||
struct database_entry_INTV entry;
|
||||
|
||||
// Select starting letter
|
||||
byte myLetter = starting_letter();
|
||||
|
||||
// Open database
|
||||
if (myFile.open("intv.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);
|
||||
seek_first_letter_in_database(myFile, myLetter);
|
||||
|
||||
// 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
|
||||
rewind_line(myFile);
|
||||
}
|
||||
|
||||
// Display database
|
||||
while (myFile.available()) {
|
||||
display_Clear();
|
||||
|
||||
// Read game name
|
||||
get_line(gamename, &myFile, 96);
|
||||
|
||||
// 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.seekCur(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.seekCur(1);
|
||||
|
||||
// Read mapper
|
||||
intvmapper = myFile.read() - 48;
|
||||
|
||||
// Skip over semicolon
|
||||
myFile.seekCur(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 over semicolon
|
||||
myFile.seekCur(1);
|
||||
|
||||
// Read SRAM size
|
||||
byte sramSize __attribute__((unused)) = myFile.read() - 48;
|
||||
|
||||
// Skip rest of line
|
||||
myFile.seekCur(2);
|
||||
|
||||
// Skip every 3rd line
|
||||
skip_line(&myFile);
|
||||
|
||||
println_Msg(F("Select your cartridge"));
|
||||
println_Msg(F(""));
|
||||
println_Msg(gamename);
|
||||
print_Msg(F("Size: "));
|
||||
print_Msg(cartSize);
|
||||
println_Msg(F("KB"));
|
||||
print_Msg(F("Mapper: "));
|
||||
println_Msg(intvmapper);
|
||||
#if defined(enable_OLED)
|
||||
print_STR(press_to_change_STR, 1);
|
||||
print_STR(right_to_select_STR, 1);
|
||||
#elif defined(enable_LCD)
|
||||
print_STR(rotate_to_change_STR, 1);
|
||||
print_STR(press_to_select_STR, 1);
|
||||
#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) {
|
||||
if(checkCartSelection(myFile, &readDataLine_INTV, &entry, &printDataLine_INTV)) {
|
||||
//byte INTV[] = {8, 12, 16, 24, 32, 48};
|
||||
switch (entry.gameSize) {
|
||||
case 8:
|
||||
intvsize = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
// Previous
|
||||
else if (b == 2) {
|
||||
rewind_line(myFile, 6);
|
||||
case 12:
|
||||
intvsize = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
// Selection
|
||||
else if (b == 3) {
|
||||
//byte INTV[] = {8, 16, 24, 32, 48};
|
||||
switch (cartSize) {
|
||||
case 8:
|
||||
intvsize = 0;
|
||||
break;
|
||||
|
||||
case 16:
|
||||
intvsize = 1;
|
||||
break;
|
||||
|
||||
case 24:
|
||||
intvsize = 2;
|
||||
break;
|
||||
|
||||
case 32:
|
||||
intvsize = 3;
|
||||
break;
|
||||
|
||||
case 48:
|
||||
intvsize = 4;
|
||||
break;
|
||||
|
||||
default:
|
||||
intvsize = 0;
|
||||
break;
|
||||
}
|
||||
EEPROM_writeAnything(7, intvmapper);
|
||||
EEPROM_writeAnything(8, intvsize);
|
||||
myFile.close();
|
||||
case 16:
|
||||
intvsize = 2;
|
||||
break;
|
||||
|
||||
case 24:
|
||||
intvsize = 3;
|
||||
break;
|
||||
|
||||
case 32:
|
||||
intvsize = 4;
|
||||
break;
|
||||
|
||||
case 48:
|
||||
intvsize = 5;
|
||||
break;
|
||||
|
||||
default:
|
||||
intvsize = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
EEPROM_writeAnything(7, entry.gameMapper);
|
||||
EEPROM_writeAnything(8, intvsize);
|
||||
}
|
||||
} else {
|
||||
print_FatalError(F("Database file not found"));
|
||||
print_FatalError(FS(FSTRING_DATABASE_FILE_NOT_FOUND));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -59,7 +59,7 @@
|
|||
//
|
||||
// By @partlyhuman
|
||||
// Special thanks to @kasamikona
|
||||
#ifdef enable_LOOPY
|
||||
#ifdef ENABLE_LOOPY
|
||||
|
||||
// SH-1 memory map locations, ROM starts here
|
||||
const uint32_t LOOPY_MAP_ROM_ZERO = 0x0E000000;
|
||||
|
@ -109,7 +109,7 @@ void setup_LOOPY() {
|
|||
|
||||
getCartInfo_LOOPY();
|
||||
|
||||
mode = mode_LOOPY;
|
||||
mode = CORE_LOOPY;
|
||||
}
|
||||
|
||||
//******************************************
|
||||
|
@ -117,12 +117,8 @@ void setup_LOOPY() {
|
|||
//******************************************
|
||||
|
||||
// Base Menu
|
||||
static const char loopyMenuItem0[] PROGMEM = "Refresh Cart";
|
||||
static const char loopyMenuItem1[] PROGMEM = "Read ROM";
|
||||
static const char loopyMenuItem2[] PROGMEM = "Backup SRAM";
|
||||
static const char loopyMenuItem3[] PROGMEM = "Restore SRAM";
|
||||
static const char loopyMenuItem4[] PROGMEM = "Format SRAM";
|
||||
static const char* const menuOptionsLOOPY[] PROGMEM = { loopyMenuItem0, loopyMenuItem1, loopyMenuItem2, loopyMenuItem3, loopyMenuItem4, string_reset2 };
|
||||
static const char* const menuOptionsLOOPY[] PROGMEM = { FSTRING_REFRESH_CART, FSTRING_READ_ROM, FSTRING_READ_SAVE, FSTRING_WRITE_SAVE, loopyMenuItem4, FSTRING_RESET };
|
||||
|
||||
void loopyMenu() {
|
||||
convertPgm(menuOptionsLOOPY, 5);
|
||||
|
@ -188,10 +184,10 @@ void loopyMenu() {
|
|||
break;
|
||||
}
|
||||
|
||||
#if (defined(enable_OLED) || defined(enable_LCD))
|
||||
#if (defined(ENABLE_OLED) || defined(ENABLE_LCD))
|
||||
if (waitForInput) {
|
||||
// Wait for user input
|
||||
println_Msg(F(""));
|
||||
println_Msg(FS(FSTRING_EMPTY));
|
||||
// Prints string out of the common strings array either with or without newline
|
||||
print_STR(press_button_STR, 1);
|
||||
display_Update();
|
||||
|
@ -497,20 +493,20 @@ void getCartInfo_LOOPY() {
|
|||
setRomName_LOOPY("loopy.txt", checksumStr);
|
||||
|
||||
println_Msg(F("Cart Info"));
|
||||
println_Msg(F(" "));
|
||||
print_Msg(F("Name: "));
|
||||
println_Msg(FS(FSTRING_SPACE));
|
||||
print_Msg(FS(FSTRING_NAME));
|
||||
println_Msg(loopyRomNameLong);
|
||||
print_Msg(F("Checksum: "));
|
||||
print_Msg(FS(FSTRING_CHECKSUM));
|
||||
println_Msg(checksumStr);
|
||||
print_Msg(F("Size: "));
|
||||
print_Msg(FS(FSTRING_SIZE));
|
||||
print_Msg(cartSize * 8 / 1024 / 1024);
|
||||
println_Msg(F(" MBit"));
|
||||
print_Msg(F("Sram: "));
|
||||
print_Msg(sramSize * 8 / 1024);
|
||||
println_Msg(F(" KBit"));
|
||||
println_Msg(F(" "));
|
||||
println_Msg(FS(FSTRING_SPACE));
|
||||
|
||||
#if (defined(enable_OLED) || defined(enable_LCD))
|
||||
#if (defined(ENABLE_OLED) || defined(ENABLE_LCD))
|
||||
// Wait for user input
|
||||
// Prints string out of the common strings array either with or without newline
|
||||
print_STR(press_button_STR, 1);
|
||||
|
@ -526,25 +522,7 @@ void getCartInfo_LOOPY() {
|
|||
void readROM_LOOPY() {
|
||||
dataIn_LOOPY();
|
||||
|
||||
sprintf(fileName, "%s.bin", romName);
|
||||
|
||||
EEPROM_readAnything(0, foldern);
|
||||
sprintf(folder, "LOOPY/ROM/%d", foldern);
|
||||
sd.mkdir(folder, true);
|
||||
sd.chdir(folder);
|
||||
|
||||
display_Clear();
|
||||
print_STR(saving_to_STR, 0);
|
||||
print_Msg(folder);
|
||||
println_Msg(F("/..."));
|
||||
display_Update();
|
||||
|
||||
foldern = foldern + 1;
|
||||
EEPROM_writeAnything(0, foldern);
|
||||
|
||||
if (!myFile.open(fileName, O_RDWR | O_CREAT)) {
|
||||
print_FatalError(sd_error_STR);
|
||||
}
|
||||
createFolderAndOpenFile("LOOPY", "ROM", romName, "bin");
|
||||
|
||||
draw_progressbar(0, cartSize);
|
||||
|
||||
|
@ -661,12 +639,7 @@ void formatSRAM_LOOPY() {
|
|||
void readSRAM_LOOPY() {
|
||||
dataIn_LOOPY();
|
||||
|
||||
sprintf(fileName, "%s.sav", romName);
|
||||
|
||||
EEPROM_readAnything(0, foldern);
|
||||
sprintf(folder, "LOOPY/SAVE/%s/%d", romName, foldern);
|
||||
sd.mkdir(folder, true);
|
||||
sd.chdir(folder);
|
||||
createFolder("LOOPY", "SAVE", romName, "sav");
|
||||
|
||||
foldern = foldern + 1;
|
||||
EEPROM_writeAnything(0, foldern);
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
// SEGA MEGA DRIVE MODULE
|
||||
//******************************************
|
||||
// Writes to Sega CD Backup RAM Cart require an extra wire from MRES (B02) to VRES (B27)
|
||||
#ifdef enable_MD
|
||||
#ifdef ENABLE_MD
|
||||
|
||||
/******************************************
|
||||
Variables
|
||||
|
@ -63,6 +63,7 @@ static const word PROGMEM eepid[] = {
|
|||
// EA
|
||||
0x8512, 0x84, // Bill Walsh College Football (UE) [BAD HEADER SAVE DATA]
|
||||
0xA107, 0x84, // John Madden Football '93 (UE) [NO HEADER SAVE DATA]
|
||||
0x246A, 0x84, // John Madden Football '93 (U) (EA Sports) [NO HEADER SAVE DATA]
|
||||
0x5807, 0x84, // John Madden Football '93 Championship Edition (U) [NO HEADER SAVE DATA]
|
||||
0x2799, 0x84, // NHLPA Hockey '93 (UE) (Rev 0) [NO HEADER SAVE DATA]
|
||||
0xFA57, 0x84, // NHLPA Hockey '93 (UE) (Rev 1) [NO HEADER SAVE DATA]
|
||||
|
@ -86,10 +87,19 @@ unsigned long bramSize = 0;
|
|||
// REALTEC MAPPER
|
||||
boolean realtec = 0;
|
||||
|
||||
#ifndef DEFAULT_VALUE_segaSram16bit
|
||||
#define DEFAULT_VALUE_segaSram16bit 0
|
||||
#endif
|
||||
int segaSram16bit = DEFAULT_VALUE_segaSram16bit;
|
||||
#if defined(ENABLED_CONFIG)
|
||||
|
||||
int segaSram16bit = 0;
|
||||
|
||||
#else /* !ENABLED_CONFIG */
|
||||
|
||||
# ifndef OPTION_MD_DEFAULT_SAVE_TYPE
|
||||
# define OPTION_MD_DEFAULT_SAVE_TYPE 0
|
||||
# endif /* !OPTION_MD_DEFAULT_SAVE_TYPE */
|
||||
|
||||
int segaSram16bit = OPTION_MD_DEFAULT_SAVE_TYPE;
|
||||
|
||||
#endif /* ENABLED_CONFIG */
|
||||
|
||||
//*****************************************
|
||||
// SONIC & KNUCKLES LOCK-ON MODE VARIABLES
|
||||
|
@ -110,12 +120,15 @@ static word chksumSonic2 = 0x0635;
|
|||
/******************************************
|
||||
Configuration
|
||||
*****************************************/
|
||||
#ifdef use_md_conf
|
||||
#if defined(use_md_conf) && !defined(ENABLE_CONFIG)
|
||||
|
||||
#warning "DEPRECATED: use_md_conf is deprecated. You should use ENABLE_CONFIG instead."
|
||||
|
||||
void mdLoadConf() {
|
||||
if (myFile.open("mdconf.txt", O_READ)) {
|
||||
char line[64];
|
||||
int n;
|
||||
int i;
|
||||
unsigned int n;
|
||||
unsigned int i;
|
||||
while ((n = myFile.fgets(line, sizeof(line) - 1)) > 0) {
|
||||
// preprocess
|
||||
for (i = 0; i < n; i++) {
|
||||
|
@ -172,7 +185,7 @@ void mdLoadConf() {
|
|||
// 2: Duplicate each byte. Pad with 0xFF so that the file size is 64KB.
|
||||
segaSram16bit = atoi(value);
|
||||
if (segaSram16bit != 0 && segaSram16bit != 1 && segaSram16bit != 2) {
|
||||
segaSram16bit = DEFAULT_VALUE_segaSram16bit;
|
||||
segaSram16bit = DEFAULT_VALUE_SAVE_TYPE;
|
||||
}
|
||||
print_Msg(F("segaSram16bit: "));
|
||||
println_Msg(segaSram16bit);
|
||||
|
@ -196,24 +209,17 @@ void pulse_clock(int n) {
|
|||
static const char MDMenuItem1[] PROGMEM = "Game Cartridge";
|
||||
static const char MDMenuItem2[] PROGMEM = "SegaCD RamCart";
|
||||
static const char MDMenuItem3[] PROGMEM = "Flash Repro";
|
||||
//static const char MDMenuItem4[] PROGMEM = "Reset"; (stored in common strings array)
|
||||
static const char* const menuOptionsMD[] PROGMEM = { MDMenuItem1, MDMenuItem2, MDMenuItem3, string_reset2 };
|
||||
static const char* const menuOptionsMD[] PROGMEM = { MDMenuItem1, MDMenuItem2, MDMenuItem3, FSTRING_RESET };
|
||||
|
||||
// Cart menu items
|
||||
static const char MDCartMenuItem1[] PROGMEM = "Read Rom";
|
||||
static const char MDCartMenuItem2[] PROGMEM = "Read Sram";
|
||||
static const char MDCartMenuItem3[] PROGMEM = "Write Sram";
|
||||
static const char MDCartMenuItem4[] PROGMEM = "Read EEPROM";
|
||||
static const char MDCartMenuItem5[] PROGMEM = "Write EEPROM";
|
||||
static const char MDCartMenuItem6[] PROGMEM = "Cycle cart";
|
||||
//static const char MDCartMenuItem7[] PROGMEM = "Reset"; (stored in common strings array)
|
||||
static const char* const menuOptionsMDCart[] PROGMEM = { MDCartMenuItem1, MDCartMenuItem2, MDCartMenuItem3, MDCartMenuItem4, MDCartMenuItem5, MDCartMenuItem6, string_reset2 };
|
||||
static const char* const menuOptionsMDCart[] PROGMEM = { FSTRING_READ_ROM, FSTRING_READ_SAVE, FSTRING_WRITE_SAVE, MDCartMenuItem4, MDCartMenuItem5, FSTRING_REFRESH_CART, FSTRING_RESET };
|
||||
|
||||
// Sega CD Ram Backup Cartridge menu items
|
||||
static const char SCDMenuItem1[] PROGMEM = "Read Backup RAM";
|
||||
static const char SCDMenuItem2[] PROGMEM = "Write Backup RAM";
|
||||
//static const char SCDMenuItem3[] PROGMEM = "Reset"; (stored in common strings array)
|
||||
static const char* const menuOptionsSCD[] PROGMEM = { SCDMenuItem1, SCDMenuItem2, string_reset2 };
|
||||
static const char* const menuOptionsSCD[] PROGMEM = { SCDMenuItem1, SCDMenuItem2, FSTRING_RESET };
|
||||
|
||||
// Sega start menu
|
||||
void mdMenu() {
|
||||
|
@ -229,22 +235,22 @@ void mdMenu() {
|
|||
display_Clear();
|
||||
display_Update();
|
||||
setup_MD();
|
||||
mode = mode_MD_Cart;
|
||||
mode = CORE_MD_CART;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
display_Clear();
|
||||
display_Update();
|
||||
setup_MD();
|
||||
mode = mode_SEGA_CD;
|
||||
mode = CORE_SEGA_CD;
|
||||
break;
|
||||
|
||||
#ifdef enable_FLASH
|
||||
#ifdef ENABLE_FLASH
|
||||
case 2:
|
||||
display_Clear();
|
||||
display_Update();
|
||||
setup_MD();
|
||||
mode = mode_MD_Cart;
|
||||
mode = CORE_MD_CART;
|
||||
// Change working dir to root
|
||||
filePath[0] = '\0';
|
||||
sd.chdir("/");
|
||||
|
@ -278,7 +284,7 @@ void mdMenu() {
|
|||
verifyFlash_MD();
|
||||
// Set CS(PH3) HIGH
|
||||
PORTH |= (1 << 3);
|
||||
println_Msg(F(""));
|
||||
println_Msg(FS(FSTRING_EMPTY));
|
||||
// Prints string out of the common strings array either with or without newline
|
||||
print_STR(press_button_STR, 1);
|
||||
display_Update();
|
||||
|
@ -323,7 +329,7 @@ void mdCartMenu() {
|
|||
} else {
|
||||
print_Error(F("Cart has no ROM"));
|
||||
}
|
||||
#ifdef global_log
|
||||
#ifdef ENABLE_GLOBAL_LOG
|
||||
save_log();
|
||||
#endif
|
||||
break;
|
||||
|
@ -452,7 +458,7 @@ void segaCDMenu() {
|
|||
asm volatile(" jmp 0");
|
||||
break;
|
||||
}
|
||||
println_Msg(F(""));
|
||||
println_Msg(FS(FSTRING_EMPTY));
|
||||
// Prints string out of the common strings array either with or without newline
|
||||
print_STR(press_button_STR, 1);
|
||||
display_Update();
|
||||
|
@ -466,9 +472,11 @@ void setup_MD() {
|
|||
// Request 5V
|
||||
setVoltage(VOLTS_SET_5V);
|
||||
|
||||
#ifdef use_md_conf
|
||||
#if defined(ENABLE_CONFIG)
|
||||
segaSram16bit = configGetLong(F("md.saveType"));
|
||||
#elif defined(use_md_conf)
|
||||
mdLoadConf();
|
||||
#endif
|
||||
#endif /*ENABLE_CONFIG*/
|
||||
|
||||
// Set Address Pins to Output
|
||||
//A0-A7
|
||||
|
@ -744,7 +752,7 @@ void getCartInfo_MD() {
|
|||
id[c + 1] = loByte;
|
||||
}
|
||||
|
||||
//Identify games using SVP chip
|
||||
// Identify games using SVP chip
|
||||
if (!strncmp("GM MK-1229 ", id, 11) || !strncmp("GM G-7001 ", id, 11)) // Virtua Racing (E/U/J)
|
||||
isSVP = 1;
|
||||
else
|
||||
|
@ -769,45 +777,48 @@ void getCartInfo_MD() {
|
|||
}
|
||||
if (cartSize == 0x300000) {
|
||||
switch (chksum) {
|
||||
case 0xBC5F: //Batman Forever (World)
|
||||
case 0x3CDD: //Donald in Maui Mallard (Brazil) (En)
|
||||
case 0x44AD: //Donald in Maui Mallard (Europe) (Rev A)
|
||||
case 0x2D9A: //Foreman for Real (World)
|
||||
case 0x5648: //Justice League Task Force (World)
|
||||
case 0x0A29: //Mega 6 Vol. 3 (Europe)
|
||||
case 0x7651: //NFL Quarterback Club (World)
|
||||
case 0x74CA: //WWF RAW (World)
|
||||
case 0xBC5F: // Batman Forever (World)
|
||||
case 0x3CDD: // Donald in Maui Mallard (Brazil) (En)
|
||||
case 0x44AD: // Donald in Maui Mallard (Europe) (Rev A)
|
||||
case 0x2D9A: // Foreman for Real (World)
|
||||
case 0x5648: // Justice League Task Force (World)
|
||||
case 0x0A29: // Mega 6 Vol. 3 (Europe)
|
||||
case 0x7651: // NFL Quarterback Club (World)
|
||||
case 0x74CA: // WWF RAW (World)
|
||||
cartSize = 0x400000;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (cartSize == 0x200000) {
|
||||
switch (chksum) {
|
||||
case 0xAE95: //Winter Olympic Games (USA)
|
||||
case 0x2078: // Dynamite Headdy (USA, Europe)
|
||||
chksum = 0x9877;
|
||||
break;
|
||||
case 0xAE95: // Winter Olympic Games (USA)
|
||||
chksum = 0x56A0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (cartSize == 0x180000) {
|
||||
switch (chksum) {
|
||||
case 0xFFE2: //Cannon Fodder (Europe)
|
||||
case 0xF418: //Chaos Engine, The (Europe)
|
||||
case 0xF71D: //Fatal Fury (Europe, Korea) (En)
|
||||
case 0xA884: //Flashback (Europe) (En,Fr)
|
||||
case 0x7D68: //Flashback - The Quest for Identity (USA) (En,Fr)
|
||||
case 0x030D: //Shining Force (Europe)
|
||||
case 0xE975: //Shining Force (USA)
|
||||
case 0xFFE2: // Cannon Fodder (Europe)
|
||||
case 0xF418: // Chaos Engine, The (Europe)
|
||||
case 0xF71D: // Fatal Fury (Europe, Korea) (En)
|
||||
case 0xA884: // Flashback (Europe) (En,Fr)
|
||||
case 0x7D68: // Flashback - The Quest for Identity (USA) (En,Fr)
|
||||
case 0x030D: // Shining Force (Europe)
|
||||
case 0xE975: // Shining Force (USA)
|
||||
cartSize = 0x200000;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (cartSize == 0x100000) {
|
||||
switch (chksum) {
|
||||
case 0xCDF5: //Life on Mars (Aftermarket)
|
||||
case 0xCDF5: // Life on Mars (Aftermarket)
|
||||
cartSize = 0x400000;
|
||||
chksum = 0x603A;
|
||||
break;
|
||||
case 0xF85F: //Metal Dragon (Aftermarket)
|
||||
case 0xF85F: // Metal Dragon (Aftermarket)
|
||||
cartSize = 0x200000;
|
||||
chksum = 0x6965;
|
||||
break;
|
||||
|
@ -815,45 +826,59 @@ void getCartInfo_MD() {
|
|||
}
|
||||
if (cartSize == 0xC0000) {
|
||||
switch (chksum) {
|
||||
case 0x9D79: //Wonder Boy in Monster World (USA, Europe)
|
||||
case 0x9D79: // Wonder Boy in Monster World (USA, Europe)
|
||||
cartSize = 0x100000;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (cartSize == 0x80000) {
|
||||
switch (chksum) {
|
||||
case 0xD07D: //Zero Wing (Japan)
|
||||
case 0x06C1: // Madden NFL 98 (USA)
|
||||
cartSize = 0x200000;
|
||||
chksum = 0x8473;
|
||||
break;
|
||||
case 0x5B3A: // NHL 98 (USA)
|
||||
cartSize = 0x200000;
|
||||
chksum = 0x5613;
|
||||
break;
|
||||
case 0xD07D: // Zero Wing (Japan)
|
||||
cartSize = 0x100000;
|
||||
chksum = 0xF204;
|
||||
break;
|
||||
case 0x95C9: //Zero Wing (Europe)
|
||||
case 0x9144: //Zoop (Europe)
|
||||
case 0xB8D4: //Zoop (USA)
|
||||
case 0x95C9: // Zero Wing (Europe)
|
||||
case 0x9144: // Zoop (Europe)
|
||||
case 0xB8D4: // Zoop (USA)
|
||||
cartSize = 0x100000;
|
||||
break;
|
||||
case 0xC422: //Jeopardy! (USA)
|
||||
case 0xC422: // Jeopardy! (USA)
|
||||
chksum = 0xC751;
|
||||
break;
|
||||
case 0x0C6A: //Monopoly (USA)
|
||||
case 0x0C6A: // Monopoly (USA)
|
||||
chksum = 0xE1AA;
|
||||
break;
|
||||
case 0xA760: // Gain Ground (USA)
|
||||
chksum = 0x97CD;
|
||||
break;
|
||||
case 0x1404: // Wonder Boy III - Monster Lair (Japan, Europe) (En)
|
||||
chksum = 0x53B9;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (cartSize == 0x40000) {
|
||||
switch (chksum) {
|
||||
case 0x8BC6: //Pac-Attack (USA)
|
||||
case 0xB344: //Pac-Panic (Europe)
|
||||
case 0x8BC6: // Pac-Attack (USA)
|
||||
case 0xB344: // Pac-Panic (Europe)
|
||||
cartSize = 0x100000;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (cartSize == 0x20000) {
|
||||
switch (chksum) {
|
||||
case 0x7E50: //Micro Machines 2 - Turbo Tournament (Europe)
|
||||
case 0x7E50: // Micro Machines 2 - Turbo Tournament (Europe)
|
||||
cartSize = 0x100000;
|
||||
chksum = 0xD074;
|
||||
break;
|
||||
case 0x168B: //Micro Machines - Military (Europe)
|
||||
case 0x168B: // Micro Machines - Military (Europe)
|
||||
cartSize = 0x100000;
|
||||
chksum = 0xCEE0;
|
||||
break;
|
||||
|
@ -876,41 +901,93 @@ void getCartInfo_MD() {
|
|||
chksum = 0x45C6;
|
||||
}
|
||||
|
||||
//YM2612 Instrument Editor (Aftermarket)
|
||||
// YM2612 Instrument Editor (Aftermarket)
|
||||
if (!strncmp("GM 10101010", id, 11) && (chksum == 0xC439)) {
|
||||
chksum = 0x21B0;
|
||||
cartSize = 0x100000;
|
||||
}
|
||||
|
||||
//Technoptimistic (Aftermarket)
|
||||
// Technoptimistic (Aftermarket)
|
||||
if (!strncmp("MU REMUTE01", id, 11) && (chksum == 0x0000)) {
|
||||
chksum = 0xB55C;
|
||||
cartSize = 0x400000;
|
||||
}
|
||||
|
||||
//Decoder (Aftermarket)
|
||||
// Decoder (Aftermarket)
|
||||
if (!strncmp("GM REMUTE02", id, 11) && (chksum == 0x0000)) {
|
||||
chksum = 0x5426;
|
||||
cartSize = 0x400000;
|
||||
}
|
||||
|
||||
//Handy Harvy (Aftermarket)
|
||||
// Handy Harvy (Aftermarket)
|
||||
if (!strncmp("GM HHARVYSG", id, 11) && (chksum == 0x0000)) {
|
||||
chksum = 0xD9D2;
|
||||
cartSize = 0x100000;
|
||||
}
|
||||
|
||||
//Jim Power - The Lost Dimension in 3D (Aftermarket)
|
||||
// Jim Power - The Lost Dimension in 3D (Aftermarket)
|
||||
if (!strncmp("GM T-107036", id, 11) && (chksum == 0x0000)) {
|
||||
chksum = 0xAA28;
|
||||
}
|
||||
|
||||
//mikeyeldey95 (Aftermarket)
|
||||
// mikeyeldey95 (Aftermarket)
|
||||
if (!strncmp("GM 00000000-43", id, 14) && (chksum == 0x0000)) {
|
||||
chksum = 0x921B;
|
||||
cartSize = 0x400000;
|
||||
}
|
||||
|
||||
// Enryuu Seiken Xiao-Mei (Aftermarket)
|
||||
if (!strncmp("GM 00000000-00", id, 14) && (chksum == 0x1E0C)) {
|
||||
chksum = 0xE7E5;
|
||||
cartSize = 0x400000;
|
||||
}
|
||||
|
||||
// Life on Earth - Reimagined (Aftermarket)
|
||||
if (!strncmp("GM 00000000-00", id, 14) && (chksum == 0x6BD5)) {
|
||||
chksum = 0x1FEA;
|
||||
cartSize = 0x400000;
|
||||
}
|
||||
|
||||
// Sasha Darko's Sacred Line I (Aftermarket)
|
||||
if (!strncmp("GM 00000005-00", id, 14) && (chksum == 0x9F34)) {
|
||||
chksum = 0xA094;
|
||||
cartSize = 0x400000;
|
||||
}
|
||||
|
||||
// Sasha Darko's Sacred Line II (Aftermarket)
|
||||
if (!strncmp("GM 00000005-00", id, 14) && (chksum == 0x0E9B)) {
|
||||
chksum = 0x6B4B;
|
||||
cartSize = 0x400000;
|
||||
}
|
||||
|
||||
// Sasha Darko's Sacred Line (Watermelon Release) (Aftermarket)
|
||||
if (!strncmp("GM T-574323-00", id, 14) && (chksum == 0xAEDD)) {
|
||||
cartSize = 0x400000;
|
||||
}
|
||||
|
||||
// Kromasphere (Aftermarket)
|
||||
if (!strncmp("GM MK-0000 -00", id, 14) && (chksum == 0xC536)) {
|
||||
chksum = 0xFAB1;
|
||||
cartSize = 0x200000;
|
||||
}
|
||||
|
||||
// YM2017 (Aftermarket)
|
||||
if (!strncmp("GM CSET0001-02", id, 14) && (chksum == 0x0000)) {
|
||||
chksum = 0xE3A9;
|
||||
}
|
||||
|
||||
// The Curse of Illmore Bay (Aftermarket)
|
||||
if (!strncmp("1774 ", id, 14) && (chksum == 0x0000)) {
|
||||
chksum = 0x6E34;
|
||||
cartSize = 0x400000;
|
||||
}
|
||||
|
||||
// Coffee Crisis (Aftermarket)
|
||||
if (!strncmp("JN-20160131-03", id, 14) && (chksum == 0x0000)) {
|
||||
chksum = 0x8040;
|
||||
cartSize = 0x400000;
|
||||
}
|
||||
|
||||
// Sonic & Knuckles Check
|
||||
SnKmode = 0;
|
||||
if (chksum == 0xDFB3) {
|
||||
|
@ -1059,13 +1136,13 @@ void getCartInfo_MD() {
|
|||
} else {
|
||||
print_Msg(("sramType: "));
|
||||
print_Msg_PaddedHex16(sramType);
|
||||
println_Msg(F(""));
|
||||
println_Msg(FS(FSTRING_EMPTY));
|
||||
print_Msg(("sramBase: "));
|
||||
print_Msg_PaddedHex32(sramBase);
|
||||
println_Msg(F(""));
|
||||
println_Msg(FS(FSTRING_EMPTY));
|
||||
print_Msg(("sramEnd: "));
|
||||
print_Msg_PaddedHex32(sramEnd);
|
||||
println_Msg(F(""));
|
||||
println_Msg(FS(FSTRING_EMPTY));
|
||||
print_FatalError(F("Unknown Sram Base"));
|
||||
}
|
||||
} else if (sramType == 0xE020) { // SRAM BOTH BYTES
|
||||
|
@ -1081,16 +1158,19 @@ void getCartInfo_MD() {
|
|||
saveType = 3; // BOTH
|
||||
sramSize = sramEnd - sramBase + 1;
|
||||
sramBase = sramBase >> 1;
|
||||
} else {
|
||||
} else if (sramBase == 0x3FFC00) {
|
||||
// Used for some aftermarket carts without sram
|
||||
saveType = 0;
|
||||
}else {
|
||||
print_Msg(("sramType: "));
|
||||
print_Msg_PaddedHex16(sramType);
|
||||
println_Msg(F(""));
|
||||
println_Msg(FS(FSTRING_EMPTY));
|
||||
print_Msg(("sramBase: "));
|
||||
print_Msg_PaddedHex32(sramBase);
|
||||
println_Msg(F(""));
|
||||
println_Msg(FS(FSTRING_EMPTY));
|
||||
print_Msg(("sramEnd: "));
|
||||
print_Msg_PaddedHex32(sramEnd);
|
||||
println_Msg(F(""));
|
||||
println_Msg(FS(FSTRING_EMPTY));
|
||||
print_FatalError(F("Unknown Sram Base"));
|
||||
}
|
||||
}
|
||||
|
@ -1159,6 +1239,12 @@ void getCartInfo_MD() {
|
|||
}
|
||||
romName[copyToRomName_MD(romName, sdBuffer, sizeof(romName) - 1)] = 0;
|
||||
|
||||
//Check for Slaughter Sport
|
||||
if (!strncmp("GMT5604600jJ", romName, 12) && (chksum == 0xFFFF)) {
|
||||
strcpy(romName, "SLAUGHTERSPORT");
|
||||
chksum = 0x6BAE;
|
||||
}
|
||||
|
||||
//Get Lock-on cart name
|
||||
if (SnKmode >= 2) {
|
||||
char romNameLockon[12];
|
||||
|
@ -1208,19 +1294,19 @@ void getCartInfo_MD() {
|
|||
|
||||
display_Clear();
|
||||
println_Msg(F("Cart Info"));
|
||||
println_Msg(F(" "));
|
||||
print_Msg(F("Name: "));
|
||||
println_Msg(FS(FSTRING_SPACE));
|
||||
print_Msg(FS(FSTRING_NAME));
|
||||
println_Msg(romName);
|
||||
if (bramCheck != 0x00FF) {
|
||||
print_Msg(F("bramCheck: "));
|
||||
print_Msg_PaddedHex16(bramCheck);
|
||||
println_Msg(F(""));
|
||||
println_Msg(FS(FSTRING_EMPTY));
|
||||
}
|
||||
if (bramSize > 0) {
|
||||
print_Msg(F("bramSize(KB): "));
|
||||
println_Msg(bramSize >> 10);
|
||||
}
|
||||
print_Msg(F("Size: "));
|
||||
print_Msg(FS(FSTRING_SIZE));
|
||||
print_Msg(cartSize * 8 / 1024 / 1024);
|
||||
switch (SnKmode) {
|
||||
case 2:
|
||||
|
@ -1257,7 +1343,7 @@ void getCartInfo_MD() {
|
|||
print_Msg_PaddedHexByte((chksumSonic2 & 0x00ff));
|
||||
break;
|
||||
}
|
||||
println_Msg(F(""));
|
||||
println_Msg(FS(FSTRING_EMPTY));
|
||||
if (saveType == 4) {
|
||||
print_Msg(F("Serial EEPROM: "));
|
||||
print_Msg(eepSize * 8 / 1024);
|
||||
|
@ -1270,10 +1356,10 @@ void getCartInfo_MD() {
|
|||
} else
|
||||
println_Msg(F("None"));
|
||||
}
|
||||
println_Msg(F(" "));
|
||||
println_Msg(FS(FSTRING_SPACE));
|
||||
|
||||
// Wait for user input
|
||||
#if (defined(enable_LCD) || defined(enable_OLED))
|
||||
#if (defined(ENABLE_LCD) || defined(ENABLE_OLED))
|
||||
// Prints string out of the common strings array either with or without newline
|
||||
print_STR(press_button_STR, 1);
|
||||
display_Update();
|
||||
|
@ -1338,29 +1424,7 @@ void readROM_MD() {
|
|||
dataIn_MD();
|
||||
|
||||
// Get name, add extension and convert to char array for sd lib
|
||||
strcpy(fileName, romName);
|
||||
strcat(fileName, ".BIN");
|
||||
|
||||
// create a new folder
|
||||
EEPROM_readAnything(0, foldern);
|
||||
sprintf(folder, "MD/ROM/%s/%d", romName, foldern);
|
||||
sd.mkdir(folder, true);
|
||||
sd.chdir(folder);
|
||||
|
||||
display_Clear();
|
||||
print_STR(saving_to_STR, 0);
|
||||
print_Msg(folder);
|
||||
println_Msg(F("/..."));
|
||||
display_Update();
|
||||
|
||||
// write new folder number back to eeprom
|
||||
foldern = foldern + 1;
|
||||
EEPROM_writeAnything(0, foldern);
|
||||
|
||||
// Open file on sd card
|
||||
if (!myFile.open(fileName, O_RDWR | O_CREAT)) {
|
||||
print_FatalError(sd_error_STR);
|
||||
}
|
||||
createFolderAndOpenFile("MD", "ROM", romName, "BIN");
|
||||
|
||||
byte buffer[1024] = { 0 };
|
||||
|
||||
|
@ -1636,14 +1700,14 @@ void readROM_MD() {
|
|||
print_Msg(F("Internal checksum..."));
|
||||
display_Update();
|
||||
if (chksum == calcCKS) {
|
||||
println_Msg(F("OK"));
|
||||
println_Msg(FS(FSTRING_OK));
|
||||
display_Update();
|
||||
} else {
|
||||
println_Msg(F("Error"));
|
||||
char calcsumStr[5];
|
||||
sprintf(calcsumStr, "%04X", calcCKS);
|
||||
println_Msg(calcsumStr);
|
||||
print_Error(F(""));
|
||||
print_Error(FS(FSTRING_EMPTY));
|
||||
display_Update();
|
||||
}
|
||||
|
||||
|
@ -1651,28 +1715,28 @@ void readROM_MD() {
|
|||
if (SnKmode >= 2) {
|
||||
print_Msg(F("Lock-on checksum..."));
|
||||
if (chksumLockon == calcCKSLockon) {
|
||||
println_Msg(F("OK"));
|
||||
println_Msg(FS(FSTRING_OK));
|
||||
display_Update();
|
||||
} else {
|
||||
print_Msg(F("Error"));
|
||||
char calcsumStr[5];
|
||||
sprintf(calcsumStr, "%04X", calcCKSLockon);
|
||||
println_Msg(calcsumStr);
|
||||
print_Error(F(""));
|
||||
print_Error(FS(FSTRING_EMPTY));
|
||||
display_Update();
|
||||
}
|
||||
}
|
||||
if (SnKmode == 3) {
|
||||
print_Msg(F("Adittional checksum..."));
|
||||
if (chksumSonic2 == calcCKSSonic2) {
|
||||
println_Msg(F("OK"));
|
||||
println_Msg(FS(FSTRING_OK));
|
||||
display_Update();
|
||||
} else {
|
||||
print_Msg(F("Error"));
|
||||
char calcsumStr[5];
|
||||
sprintf(calcsumStr, "%04X", calcCKSSonic2);
|
||||
println_Msg(calcsumStr);
|
||||
print_Error(F(""));
|
||||
print_Error(FS(FSTRING_EMPTY));
|
||||
display_Update();
|
||||
}
|
||||
}
|
||||
|
@ -1767,14 +1831,7 @@ 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(0, foldern);
|
||||
sprintf(folder, "MD/SAVE/%s/%d", romName, foldern);
|
||||
sd.mkdir(folder, true);
|
||||
sd.chdir(folder);
|
||||
createFolder("MD", "SAVE", romName, "srm");
|
||||
|
||||
// write new folder number back to eeprom
|
||||
foldern = foldern + 1;
|
||||
|
@ -1882,7 +1939,7 @@ unsigned long verifySram_MD() {
|
|||
return writeErrors;
|
||||
}
|
||||
|
||||
#ifdef enable_FLASH
|
||||
#ifdef ENABLE_FLASH
|
||||
//******************************************
|
||||
// Flashrom Functions
|
||||
//******************************************
|
||||
|
@ -2628,15 +2685,7 @@ void readEEP_MD() {
|
|||
dataIn_MD();
|
||||
|
||||
// Get name, add extension and convert to char array for sd lib
|
||||
strcpy(fileName, romName);
|
||||
strcat(fileName, ".eep");
|
||||
|
||||
// create a new folder for the save file
|
||||
EEPROM_readAnything(0, foldern);
|
||||
sd.chdir();
|
||||
sprintf(folder, "MD/SAVE/%s/%d", romName, foldern);
|
||||
sd.mkdir(folder, true);
|
||||
sd.chdir(folder);
|
||||
createFolder("MD", "SAVE", romName, "eep");
|
||||
|
||||
// write new folder number back to eeprom
|
||||
foldern = foldern + 1;
|
||||
|
@ -2670,7 +2719,7 @@ void readEEP_MD() {
|
|||
}
|
||||
// Close the file:
|
||||
myFile.close();
|
||||
println_Msg(F(""));
|
||||
println_Msg(FS(FSTRING_EMPTY));
|
||||
display_Clear();
|
||||
print_Msg(F("Saved to "));
|
||||
print_Msg(folder);
|
||||
|
@ -2705,13 +2754,13 @@ void writeEEP_MD() {
|
|||
writeEepromByte(currByte);
|
||||
print_Msg(F("."));
|
||||
if ((currByte != 0) && ((currByte + 1) % 64 == 0))
|
||||
println_Msg(F(""));
|
||||
println_Msg(FS(FSTRING_EMPTY));
|
||||
display_Update(); // ON SERIAL = delay(100)
|
||||
}
|
||||
}
|
||||
// Close the file:
|
||||
myFile.close();
|
||||
println_Msg(F(""));
|
||||
println_Msg(FS(FSTRING_EMPTY));
|
||||
display_Clear();
|
||||
print_STR(done_STR, 1);
|
||||
display_Update();
|
||||
|
@ -2728,14 +2777,7 @@ void readBram_MD() {
|
|||
dataIn_MD();
|
||||
|
||||
// Get name, add extension and convert to char array for sd lib
|
||||
strcpy(fileName, "Cart.brm");
|
||||
|
||||
// create a new folder for the save file
|
||||
EEPROM_readAnything(0, foldern);
|
||||
sd.chdir();
|
||||
sprintf(folder, "MD/RAM/%d", foldern);
|
||||
sd.mkdir(folder, true);
|
||||
sd.chdir(folder);
|
||||
createFolder("MD", "RAM", "Cart", "brm");
|
||||
|
||||
// write new folder number back to eeprom
|
||||
foldern = foldern + 1;
|
||||
|
@ -2758,7 +2800,7 @@ void readBram_MD() {
|
|||
|
||||
// Close the file:
|
||||
myFile.close();
|
||||
println_Msg(F(""));
|
||||
println_Msg(FS(FSTRING_EMPTY));
|
||||
display_Clear();
|
||||
print_Msg(F("Saved to "));
|
||||
print_Msg(folder);
|
||||
|
@ -2790,7 +2832,7 @@ void writeBram_MD() {
|
|||
writeWord_MD(0x380000, 0); // Disable BRAM Writes
|
||||
// Close the file:
|
||||
myFile.close();
|
||||
println_Msg(F(""));
|
||||
println_Msg(FS(FSTRING_EMPTY));
|
||||
display_Clear();
|
||||
print_STR(done_STR, 1);
|
||||
display_Update();
|
||||
|
@ -2823,29 +2865,7 @@ void readRealtec_MD() {
|
|||
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(0, foldern);
|
||||
sprintf(folder, "MD/ROM/%s/%d", romName, foldern);
|
||||
sd.mkdir(folder, true);
|
||||
sd.chdir(folder);
|
||||
|
||||
display_Clear();
|
||||
print_STR(saving_to_STR, 0);
|
||||
print_Msg(folder);
|
||||
println_Msg(F("/..."));
|
||||
display_Update();
|
||||
|
||||
// write new folder number back to eeprom
|
||||
foldern = foldern + 1;
|
||||
EEPROM_writeAnything(0, foldern);
|
||||
|
||||
// Open file on sd card
|
||||
if (!myFile.open(fileName, O_RDWR | O_CREAT)) {
|
||||
print_FatalError(sd_error_STR);
|
||||
}
|
||||
createFolderAndOpenFile("MD", "ROM", romName, "MD");
|
||||
|
||||
// Realtec Registers
|
||||
writeWord_MD(0x201000, 4); // Number of 128K Blocks 0x402000 (0x201000)
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
//******************************************
|
||||
// MSX COMPUTER MODULE
|
||||
//******************************************
|
||||
#ifdef enable_MSX
|
||||
#ifdef ENABLE_MSX
|
||||
// MSX
|
||||
// Cartridge Pinout
|
||||
// 50P 2.54mm pitch connector
|
||||
|
@ -105,11 +105,8 @@ byte msxmapselect;
|
|||
int msxindex;
|
||||
|
||||
byte msxmapper;
|
||||
byte newmsxmapper;
|
||||
byte msxsize;
|
||||
byte newmsxsize;
|
||||
byte msxramsize;
|
||||
byte newmsxramsize;
|
||||
uint8_t msxbanks;
|
||||
byte chipselect;
|
||||
|
||||
|
@ -126,11 +123,10 @@ boolean srambit7 = false;
|
|||
// MENU
|
||||
//******************************************
|
||||
// Base Menu
|
||||
static const char msxMenuItem1[] PROGMEM = "Select Cart";
|
||||
static const char msxMenuItem2[] PROGMEM = "Read Cart";
|
||||
static const char msxMenuItem3[] PROGMEM = "Set Mapper + Size";
|
||||
static const char msxMenuItem4[] PROGMEM = "Write SRAM";
|
||||
static const char* const menuOptionsMSX[] PROGMEM = { msxMenuItem1, msxMenuItem2, msxMenuItem3, msxMenuItem4, string_reset2 };
|
||||
static const char* const menuOptionsMSX[] PROGMEM = { FSTRING_SELECT_CART, msxMenuItem2, msxMenuItem3, msxMenuItem4, FSTRING_RESET };
|
||||
|
||||
void msxMenu() {
|
||||
convertPgm(menuOptionsMSX, 5);
|
||||
|
@ -140,7 +136,6 @@ void msxMenu() {
|
|||
case 0:
|
||||
// Select Cart
|
||||
setCart_MSX();
|
||||
wait();
|
||||
setup_MSX();
|
||||
break;
|
||||
|
||||
|
@ -163,7 +158,7 @@ void msxMenu() {
|
|||
case 3:
|
||||
// Write RAM
|
||||
writeRAM_MSX();
|
||||
println_Msg(F(""));
|
||||
println_Msg(FS(FSTRING_EMPTY));
|
||||
// Prints string out of the common strings array either with or without newline
|
||||
print_STR(press_button_STR, 1);
|
||||
display_Update();
|
||||
|
@ -223,7 +218,7 @@ void setup_MSX() {
|
|||
checkStatus_MSX();
|
||||
strcpy(romName, "MSX");
|
||||
|
||||
mode = mode_MSX;
|
||||
mode = CORE_MSX;
|
||||
}
|
||||
|
||||
//******************************************
|
||||
|
@ -295,23 +290,6 @@ void writeData_MSX(uint16_t addr, uint8_t data) {
|
|||
DDRC = 0x00; // Reset to Input
|
||||
}
|
||||
|
||||
//******************************************
|
||||
// POWER
|
||||
//******************************************
|
||||
#ifndef enable_NES
|
||||
int int_pow(int base, int exp) // Power for int
|
||||
{
|
||||
int result = 1;
|
||||
while (exp) {
|
||||
if (exp & 1)
|
||||
result *= base;
|
||||
exp /= 2;
|
||||
base *= base;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
//******************************************
|
||||
// CS CODE
|
||||
//******************************************
|
||||
|
@ -365,28 +343,7 @@ void readROM_MSX() {
|
|||
println_Msg(F("ROM SIZE 0K"));
|
||||
display_Update();
|
||||
} else {
|
||||
strcpy(fileName, romName);
|
||||
strcat(fileName, ".bin");
|
||||
|
||||
// create a new folder for storing rom file
|
||||
EEPROM_readAnything(0, foldern);
|
||||
sprintf(folder, "MSX/ROM/%d", foldern);
|
||||
sd.mkdir(folder, true);
|
||||
sd.chdir(folder);
|
||||
|
||||
display_Clear();
|
||||
print_STR(saving_to_STR, 0);
|
||||
print_Msg(folder);
|
||||
println_Msg(F("/..."));
|
||||
display_Update();
|
||||
|
||||
// open file on sdcard
|
||||
if (!myFile.open(fileName, O_RDWR | O_CREAT))
|
||||
print_FatalError(sd_error_STR);
|
||||
|
||||
// write new folder number back to EEPROM
|
||||
foldern++;
|
||||
EEPROM_writeAnything(0, foldern);
|
||||
createFolderAndOpenFile("MSX", "ROM", romName, "bin");
|
||||
|
||||
switch (msxmapper) {
|
||||
case 0: // No Mapper
|
||||
|
@ -560,10 +517,9 @@ void readROM_MSX() {
|
|||
}
|
||||
myFile.close();
|
||||
|
||||
unsigned long crcsize = MSX[msxsize] * 0x400;
|
||||
calcCRC(fileName, crcsize, NULL, 0);
|
||||
printCRC(fileName, NULL, 0);
|
||||
|
||||
println_Msg(F(""));
|
||||
println_Msg(FS(FSTRING_EMPTY));
|
||||
// Prints string out of the common strings array either with or without newline
|
||||
print_STR(press_button_STR, 1);
|
||||
display_Update();
|
||||
|
@ -720,10 +676,9 @@ void readRAM_MSX() {
|
|||
}
|
||||
myFile.close();
|
||||
|
||||
unsigned long crcsize = MSX[msxramsize] * 0x400;
|
||||
calcCRC(fileName, crcsize, NULL, 0);
|
||||
printCRC(fileName, NULL, 0);
|
||||
|
||||
println_Msg(F(""));
|
||||
println_Msg(FS(FSTRING_EMPTY));
|
||||
// Prints string out of the common strings array either with or without newline
|
||||
print_STR(press_button_STR, 1);
|
||||
display_Update();
|
||||
|
@ -847,7 +802,7 @@ void writeRAM_MSX() {
|
|||
}
|
||||
myFile.close();
|
||||
|
||||
println_Msg(F(""));
|
||||
println_Msg(FS(FSTRING_EMPTY));
|
||||
println_Msg(F("RAM FILE WRITTEN!"));
|
||||
display_Update();
|
||||
|
||||
|
@ -862,115 +817,24 @@ void writeRAM_MSX() {
|
|||
//******************************************
|
||||
// MAPPER CODE
|
||||
//******************************************
|
||||
void setMapper_MSX() {
|
||||
#if (defined(enable_OLED) || defined(enable_LCD))
|
||||
int b = 0;
|
||||
int i = 0;
|
||||
// Check Button Status
|
||||
#if defined(enable_OLED)
|
||||
buttonVal1 = (PIND & (1 << 7)); // PD7
|
||||
#elif defined(enable_LCD)
|
||||
boolean buttonVal1 = (PING & (1 << 2)); //PG2
|
||||
#endif
|
||||
if (buttonVal1 == LOW) { // Button Pressed
|
||||
while (1) { // Scroll Mapper List
|
||||
#if defined(enable_OLED)
|
||||
buttonVal1 = (PIND & (1 << 7)); // PD7
|
||||
#elif defined(enable_LCD)
|
||||
buttonVal1 = (PING & (1 << 2)); //PG2
|
||||
#endif
|
||||
if (buttonVal1 == HIGH) { // Button Released
|
||||
// Correct Overshoot
|
||||
if (i == 0)
|
||||
i = msxmapcount - 1;
|
||||
else
|
||||
i--;
|
||||
break;
|
||||
}
|
||||
display_Clear();
|
||||
print_Msg(F("Mapper: "));
|
||||
msxindex = i * 5;
|
||||
msxmapselect = pgm_read_byte(msxmapsize + msxindex);
|
||||
println_Msg(msxmapselect);
|
||||
printMapper(msxmapselect);
|
||||
display_Update();
|
||||
if (i == (msxmapcount - 1))
|
||||
i = 0;
|
||||
else
|
||||
i++;
|
||||
delay(250);
|
||||
}
|
||||
}
|
||||
|
||||
#if (defined(ENABLE_OLED) || defined(ENABLE_LCD))
|
||||
void printMapperSelection_MSX(int index) {
|
||||
display_Clear();
|
||||
print_Msg(F("Mapper: "));
|
||||
msxindex = i * 5;
|
||||
print_Msg(FS(FSTRING_MAPPER));
|
||||
msxindex = index * 5;
|
||||
msxmapselect = pgm_read_byte(msxmapsize + msxindex);
|
||||
println_Msg(msxmapselect);
|
||||
printMapper(msxmapselect);
|
||||
println_Msg(F(""));
|
||||
#if defined(enable_OLED)
|
||||
print_STR(press_to_change_STR, 1);
|
||||
print_STR(right_to_select_STR, 1);
|
||||
#elif defined(enable_LCD)
|
||||
print_STR(rotate_to_change_STR, 1);
|
||||
print_STR(press_to_select_STR, 1);
|
||||
}
|
||||
#endif
|
||||
display_Update();
|
||||
|
||||
while (1) {
|
||||
b = checkButton();
|
||||
if (b == 2) { // Previous Mapper (doubleclick)
|
||||
if (i == 0)
|
||||
i = msxmapcount - 1;
|
||||
else
|
||||
i--;
|
||||
|
||||
// Only update display after input because of slow LCD library
|
||||
display_Clear();
|
||||
print_Msg(F("Mapper: "));
|
||||
msxindex = i * 5;
|
||||
msxmapselect = pgm_read_byte(msxmapsize + msxindex);
|
||||
println_Msg(msxmapselect);
|
||||
printMapper(msxmapselect);
|
||||
println_Msg(F(""));
|
||||
#if defined(enable_OLED)
|
||||
print_STR(press_to_change_STR, 1);
|
||||
print_STR(right_to_select_STR, 1);
|
||||
#elif defined(enable_LCD)
|
||||
print_STR(rotate_to_change_STR, 1);
|
||||
print_STR(press_to_select_STR, 1);
|
||||
#endif
|
||||
display_Update();
|
||||
}
|
||||
if (b == 1) { // Next Mapper (press)
|
||||
if (i == (msxmapcount - 1))
|
||||
i = 0;
|
||||
else
|
||||
i++;
|
||||
|
||||
// Only update display after input because of slow LCD library
|
||||
display_Clear();
|
||||
print_Msg(F("Mapper: "));
|
||||
msxindex = i * 5;
|
||||
msxmapselect = pgm_read_byte(msxmapsize + msxindex);
|
||||
println_Msg(msxmapselect);
|
||||
printMapper(msxmapselect);
|
||||
println_Msg(F(""));
|
||||
#if defined(enable_OLED)
|
||||
print_STR(press_to_change_STR, 1);
|
||||
print_STR(right_to_select_STR, 1);
|
||||
#elif defined(enable_LCD)
|
||||
print_STR(rotate_to_change_STR, 1);
|
||||
print_STR(press_to_select_STR, 1);
|
||||
#endif
|
||||
display_Update();
|
||||
}
|
||||
if (b == 3) { // Long Press - Execute (hold)
|
||||
newmsxmapper = msxmapselect;
|
||||
break;
|
||||
}
|
||||
}
|
||||
void setMapper_MSX() {
|
||||
byte newmsxmapper;
|
||||
#if (defined(ENABLE_OLED) || defined(ENABLE_LCD))
|
||||
navigateMenu(0, msxmapcount - 1, &printMapperSelection_MSX);
|
||||
newmsxmapper = msxmapselect;
|
||||
|
||||
display.setCursor(0, 56);
|
||||
print_Msg(F("MAPPER "));
|
||||
print_Msg(newmsxmapper);
|
||||
|
@ -995,7 +859,7 @@ setmapper:
|
|||
}
|
||||
if (msxmapfound == false) {
|
||||
Serial.println(F("MAPPER NOT SUPPORTED!"));
|
||||
Serial.println(F(""));
|
||||
Serial.println(FS(FSTRING_EMPTY));
|
||||
newmsxmapper = 0;
|
||||
goto setmapper;
|
||||
}
|
||||
|
@ -1021,27 +885,27 @@ void checkMapperSize_MSX() {
|
|||
//******************************************
|
||||
// SET ROM SIZE
|
||||
//******************************************
|
||||
|
||||
#if (defined(ENABLE_OLED) || defined(ENABLE_LCD))
|
||||
void printRomSize_MSX(uint8_t index) {
|
||||
display_Clear();
|
||||
print_Msg(F("ROM Size: "));
|
||||
println_Msg(MSX[index]);
|
||||
}
|
||||
#endif
|
||||
|
||||
void setROMSize_MSX() {
|
||||
#if (defined(enable_OLED) || defined(enable_LCD))
|
||||
byte newmsxsize;
|
||||
#if (defined(ENABLE_OLED) || defined(ENABLE_LCD))
|
||||
display_Clear();
|
||||
if (msxlo == msxhi)
|
||||
newmsxsize = msxlo;
|
||||
else {
|
||||
int b = 0;
|
||||
uint8_t b = 0;
|
||||
int i = msxlo;
|
||||
|
||||
display_Clear();
|
||||
print_Msg(F("ROM Size: "));
|
||||
println_Msg(MSX[i]);
|
||||
println_Msg(F(""));
|
||||
#if defined(enable_OLED)
|
||||
print_STR(press_to_change_STR, 1);
|
||||
print_STR(right_to_select_STR, 1);
|
||||
#elif defined(enable_LCD)
|
||||
print_STR(rotate_to_change_STR, 1);
|
||||
print_STR(press_to_select_STR, 1);
|
||||
#endif
|
||||
display_Update();
|
||||
printRomSize_MSX(i);
|
||||
printInstructions();
|
||||
|
||||
while (1) {
|
||||
b = checkButton();
|
||||
|
@ -1058,18 +922,8 @@ void setROMSize_MSX() {
|
|||
i--;
|
||||
|
||||
// Only update display after input because of slow LCD library
|
||||
display_Clear();
|
||||
print_Msg(F("ROM Size: "));
|
||||
println_Msg(MSX[i]);
|
||||
println_Msg(F(""));
|
||||
#if defined(enable_OLED)
|
||||
print_STR(press_to_change_STR, 1);
|
||||
print_STR(right_to_select_STR, 1);
|
||||
#elif defined(enable_LCD)
|
||||
print_STR(rotate_to_change_STR, 1);
|
||||
print_STR(press_to_select_STR, 1);
|
||||
#endif
|
||||
display_Update();
|
||||
printRomSize_MSX(i);
|
||||
printInstructions();
|
||||
}
|
||||
}
|
||||
if (b == 1) { // Next (press)
|
||||
|
@ -1085,18 +939,8 @@ void setROMSize_MSX() {
|
|||
i++;
|
||||
|
||||
// Only update display after input because of slow LCD library
|
||||
display_Clear();
|
||||
print_Msg(F("ROM Size: "));
|
||||
println_Msg(MSX[i]);
|
||||
println_Msg(F(""));
|
||||
#if defined(enable_OLED)
|
||||
print_STR(press_to_change_STR, 1);
|
||||
print_STR(right_to_select_STR, 1);
|
||||
#elif defined(enable_LCD)
|
||||
print_STR(rotate_to_change_STR, 1);
|
||||
print_STR(press_to_select_STR, 1);
|
||||
#endif
|
||||
display_Update();
|
||||
printRomSize_MSX(i);
|
||||
printInstructions();
|
||||
}
|
||||
}
|
||||
if (b == 3) { // Long Press - Execute (hold)
|
||||
|
@ -1106,7 +950,7 @@ void setROMSize_MSX() {
|
|||
}
|
||||
display.setCursor(0, 56); // Display selection at bottom
|
||||
}
|
||||
print_Msg(F("ROM SIZE "));
|
||||
print_Msg(FS(FSTRING_ROM_SIZE));
|
||||
if (msxmapper == 12) // R-Type
|
||||
print_Msg(F("384"));
|
||||
else
|
||||
|
@ -1138,13 +982,13 @@ setrom:
|
|||
if (msxmapper == 11) { // PAC/FM-PAC 0K/64K
|
||||
if ((newmsxromsize > 0) && (newmsxromsize < 4)) {
|
||||
Serial.println(F("SIZE NOT SUPPORTED"));
|
||||
Serial.println(F(""));
|
||||
Serial.println(FS(FSTRING_EMPTY));
|
||||
goto setrom;
|
||||
}
|
||||
}
|
||||
if (newmsxsize > msxhi) {
|
||||
Serial.println(F("SIZE NOT SUPPORTED"));
|
||||
Serial.println(F(""));
|
||||
Serial.println(FS(FSTRING_EMPTY));
|
||||
goto setrom;
|
||||
}
|
||||
}
|
||||
|
@ -1162,27 +1006,27 @@ setrom:
|
|||
//******************************************
|
||||
// SET RAM SIZE
|
||||
//******************************************
|
||||
|
||||
#if (defined(ENABLE_OLED) || defined(ENABLE_LCD))
|
||||
void printRamSize_MSX(uint8_t index) {
|
||||
display_Clear();
|
||||
print_Msg(F("RAM Size: "));
|
||||
println_Msg(MSXRAM[index]);
|
||||
}
|
||||
#endif
|
||||
|
||||
void setRAMSize_MSX() {
|
||||
#if (defined(enable_OLED) || defined(enable_LCD))
|
||||
byte newmsxramsize;
|
||||
#if (defined(ENABLE_OLED) || defined(ENABLE_LCD))
|
||||
display_Clear();
|
||||
if (msxramlo == msxramhi)
|
||||
newmsxramsize = msxramlo;
|
||||
else {
|
||||
int b = 0;
|
||||
uint8_t b = 0;
|
||||
int i = msxramlo;
|
||||
|
||||
display_Clear();
|
||||
print_Msg(F("RAM Size: "));
|
||||
println_Msg(MSXRAM[i]);
|
||||
println_Msg(F(""));
|
||||
#if defined(enable_OLED)
|
||||
print_STR(press_to_change_STR, 1);
|
||||
print_STR(right_to_select_STR, 1);
|
||||
#elif defined(enable_LCD)
|
||||
print_STR(rotate_to_change_STR, 1);
|
||||
print_STR(press_to_select_STR, 1);
|
||||
#endif
|
||||
display_Update();
|
||||
printRamSize_MSX(i);
|
||||
printInstructions();
|
||||
|
||||
while (1) {
|
||||
b = checkButton();
|
||||
|
@ -1199,18 +1043,8 @@ void setRAMSize_MSX() {
|
|||
i--;
|
||||
|
||||
// Only update display after input because of slow LCD library
|
||||
display_Clear();
|
||||
print_Msg(F("RAM Size: "));
|
||||
println_Msg(MSXRAM[i]);
|
||||
println_Msg(F(""));
|
||||
#if defined(enable_OLED)
|
||||
print_STR(press_to_change_STR, 1);
|
||||
print_STR(right_to_select_STR, 1);
|
||||
#elif defined(enable_LCD)
|
||||
print_STR(rotate_to_change_STR, 1);
|
||||
print_STR(press_to_select_STR, 1);
|
||||
#endif
|
||||
display_Update();
|
||||
printRamSize_MSX(i);
|
||||
printInstructions();
|
||||
}
|
||||
}
|
||||
if (b == 1) { // Next (press)
|
||||
|
@ -1226,18 +1060,8 @@ void setRAMSize_MSX() {
|
|||
i++;
|
||||
|
||||
// Only update display after input because of slow LCD library
|
||||
display_Clear();
|
||||
print_Msg(F("RAM Size: "));
|
||||
println_Msg(MSXRAM[i]);
|
||||
println_Msg(F(""));
|
||||
#if defined(enable_OLED)
|
||||
print_STR(press_to_change_STR, 1);
|
||||
print_STR(right_to_select_STR, 1);
|
||||
#elif defined(enable_LCD)
|
||||
print_STR(rotate_to_change_STR, 1);
|
||||
print_STR(press_to_select_STR, 1);
|
||||
#endif
|
||||
display_Update();
|
||||
printRamSize_MSX(i);
|
||||
printInstructions();
|
||||
}
|
||||
}
|
||||
if (b == 3) { // Long Press - Execute (hold)
|
||||
|
@ -1273,13 +1097,13 @@ setram:
|
|||
if (msxmapper == 7) { // Koei 8K/32K
|
||||
if (newmsxramsize == 3) { // 16K
|
||||
Serial.println(F("SIZE NOT SUPPORTED"));
|
||||
Serial.println(F(""));
|
||||
Serial.println(FS(FSTRING_EMPTY));
|
||||
goto setram;
|
||||
}
|
||||
}
|
||||
if (newmsxramsize > msxramhi) {
|
||||
Serial.println(F("SIZE NOT SUPPORTED"));
|
||||
Serial.println(F(""));
|
||||
Serial.println(FS(FSTRING_EMPTY));
|
||||
goto setram;
|
||||
}
|
||||
}
|
||||
|
@ -1311,15 +1135,15 @@ void checkStatus_MSX() {
|
|||
EEPROM_writeAnything(10, msxramsize);
|
||||
}
|
||||
|
||||
#if (defined(enable_OLED) || defined(enable_LCD))
|
||||
#if (defined(ENABLE_OLED) || defined(ENABLE_LCD))
|
||||
display_Clear();
|
||||
println_Msg(F("MSX READER"));
|
||||
println_Msg(F("CURRENT SETTINGS"));
|
||||
println_Msg(F(""));
|
||||
println_Msg(FS(FSTRING_CURRENT_SETTINGS));
|
||||
println_Msg(FS(FSTRING_EMPTY));
|
||||
print_Msg(F("MAPPER: "));
|
||||
println_Msg(msxmapper);
|
||||
printMapper(msxmapper);
|
||||
print_Msg(F("ROM SIZE: "));
|
||||
print_Msg(FS(FSTRING_ROM_SIZE));
|
||||
if (msxmapper == 12) // R-Type
|
||||
print_Msg(F("384"));
|
||||
else
|
||||
|
@ -1342,12 +1166,12 @@ void checkStatus_MSX() {
|
|||
Serial.print(F("CURRENT RAM SIZE: "));
|
||||
Serial.print(MSXRAM[msxramsize]);
|
||||
Serial.println(F("K"));
|
||||
Serial.println(F(""));
|
||||
Serial.println(FS(FSTRING_EMPTY));
|
||||
#endif
|
||||
}
|
||||
|
||||
void printMapper(byte msxmaplabel) {
|
||||
#if (defined(enable_OLED) || defined(enable_LCD))
|
||||
#if (defined(ENABLE_OLED) || defined(ENABLE_LCD))
|
||||
switch (msxmaplabel) {
|
||||
case 0:
|
||||
println_Msg(F("NONE"));
|
||||
|
@ -1413,250 +1237,53 @@ void printMapper(byte msxmaplabel) {
|
|||
//******************************************
|
||||
// CART SELECT CODE
|
||||
//******************************************
|
||||
FsFile msxcsvFile;
|
||||
char msxgame[31]; // title
|
||||
char msxmm[3]; // mapper
|
||||
char msxrr[3]; // romsize
|
||||
char msxss[3]; // ramsize
|
||||
char msxll[4]; // linelength (previous line)
|
||||
unsigned long msxcsvpos; // CSV File Position
|
||||
char msxcartCSV[] = "msxcart.txt"; // CSV List
|
||||
char msxcsvEND[] = "EOF"; // CSV End Marker for scrolling
|
||||
struct database_entry_MSX {
|
||||
byte gameMapper;
|
||||
byte gameSize;
|
||||
byte ramSize;
|
||||
};
|
||||
|
||||
bool readLine_MSX(FsFile& f, char* line, size_t maxLen) {
|
||||
for (size_t n = 0; n < maxLen; n++) {
|
||||
int c = f.read();
|
||||
if (c < 0 && n == 0) return false; // EOF
|
||||
if (c < 0 || c == '\n') {
|
||||
line[n] = 0;
|
||||
return true;
|
||||
}
|
||||
line[n] = c;
|
||||
}
|
||||
return false; // line too long
|
||||
}
|
||||
void readDataLine_MSX(FsFile& database, void* entry) {
|
||||
database_entry_MSX* castEntry = (database_entry_MSX*)entry;
|
||||
// Read mapper
|
||||
castEntry->gameMapper = ((database.read() - 48) * 10) + (database.read() - 48);
|
||||
|
||||
bool readVals_MSX(char* msxgame, char* msxmm, char* msxrr, char* msxss, char* msxll) {
|
||||
char line[41];
|
||||
msxcsvpos = msxcsvFile.position();
|
||||
if (!readLine_MSX(msxcsvFile, line, sizeof(line))) {
|
||||
return false; // EOF or too long
|
||||
}
|
||||
char* comma = strtok(line, ",");
|
||||
int x = 0;
|
||||
while (comma != NULL) {
|
||||
if (x == 0)
|
||||
strcpy(msxgame, comma);
|
||||
else if (x == 1)
|
||||
strcpy(msxmm, comma);
|
||||
else if (x == 2)
|
||||
strcpy(msxrr, comma);
|
||||
else if (x == 3)
|
||||
strcpy(msxss, comma);
|
||||
else if (x == 4)
|
||||
strcpy(msxll, comma);
|
||||
comma = strtok(NULL, ",");
|
||||
x += 1;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
// Skip over semicolon
|
||||
database.seekCur(1);
|
||||
|
||||
bool getCartListInfo_MSX() {
|
||||
bool buttonreleased = 0;
|
||||
bool cartselected = 0;
|
||||
#if (defined(enable_OLED) || defined(enable_LCD))
|
||||
display_Clear();
|
||||
println_Msg(F(" HOLD TO FAST CYCLE"));
|
||||
display_Update();
|
||||
#else
|
||||
Serial.println(F("HOLD BUTTON TO FAST CYCLE"));
|
||||
#endif
|
||||
delay(2000);
|
||||
#if defined(enable_OLED)
|
||||
buttonVal1 = (PIND & (1 << 7)); // PD7
|
||||
#elif defined(enable_LCD)
|
||||
boolean buttonVal1 = (PING & (1 << 2)); //PG2
|
||||
#endif
|
||||
if (buttonVal1 == LOW) { // Button Held - Fast Cycle
|
||||
while (1) { // Scroll Game List
|
||||
while (readVals_MSX(msxgame, msxmm, msxrr, msxss, msxll)) {
|
||||
if (strcmp(msxcsvEND, msxgame) == 0) {
|
||||
msxcsvFile.seek(0); // Restart
|
||||
} else {
|
||||
#if (defined(enable_OLED) || defined(enable_LCD))
|
||||
display_Clear();
|
||||
println_Msg(F("CART TITLE:"));
|
||||
println_Msg(F(""));
|
||||
println_Msg(msxgame);
|
||||
display_Update();
|
||||
#else
|
||||
Serial.print(F("CART TITLE:"));
|
||||
Serial.println(msxgame);
|
||||
#endif
|
||||
#if defined(enable_OLED)
|
||||
buttonVal1 = (PIND & (1 << 7)); // PD7
|
||||
#elif defined(enable_LCD)
|
||||
buttonVal1 = (PING & (1 << 2)); //PG2
|
||||
#endif
|
||||
if (buttonVal1 == HIGH) { // Button Released
|
||||
buttonreleased = 1;
|
||||
break;
|
||||
}
|
||||
if (buttonreleased) {
|
||||
buttonreleased = 0; // Reset Flag
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#if defined(enable_OLED)
|
||||
buttonVal1 = (PIND & (1 << 7)); // PD7
|
||||
#elif defined(enable_LCD)
|
||||
buttonVal1 = (PING & (1 << 2)); //PG2
|
||||
#endif
|
||||
if (buttonVal1 == HIGH) // Button Released
|
||||
break;
|
||||
}
|
||||
}
|
||||
#if (defined(enable_OLED) || defined(enable_LCD))
|
||||
display.setCursor(0, 56);
|
||||
println_Msg(F("FAST CYCLE OFF"));
|
||||
display_Update();
|
||||
#else
|
||||
Serial.println(F(""));
|
||||
Serial.println(F("FAST CYCLE OFF"));
|
||||
Serial.println(F("PRESS BUTTON TO STEP FORWARD"));
|
||||
Serial.println(F("DOUBLE CLICK TO STEP BACK"));
|
||||
Serial.println(F("HOLD TO SELECT"));
|
||||
Serial.println(F(""));
|
||||
#endif
|
||||
while (readVals_MSX(msxgame, msxmm, msxrr, msxss, msxll)) {
|
||||
if (strcmp(msxcsvEND, msxgame) == 0) {
|
||||
msxcsvFile.seek(0); // Restart
|
||||
} else {
|
||||
#if (defined(enable_OLED) || defined(enable_LCD))
|
||||
display_Clear();
|
||||
println_Msg(F("CART TITLE:"));
|
||||
println_Msg(F(""));
|
||||
println_Msg(msxgame);
|
||||
display.setCursor(0, 48);
|
||||
println_Msg(F("Press to Change"));
|
||||
println_Msg(F("Hold to Select"));
|
||||
display_Update();
|
||||
#else
|
||||
Serial.print(F("CART TITLE:"));
|
||||
Serial.println(msxgame);
|
||||
#endif
|
||||
while (1) { // Single Step
|
||||
int b = checkButton();
|
||||
if (b == 1) { // Continue (press)
|
||||
break;
|
||||
}
|
||||
if (b == 2) { // Reset to Start of List (doubleclick)
|
||||
byte prevline = strtol(msxll, NULL, 10);
|
||||
msxcsvpos -= prevline;
|
||||
msxcsvFile.seek(msxcsvpos);
|
||||
break;
|
||||
}
|
||||
if (b == 3) { // Long Press - Select Cart (hold)
|
||||
newmsxmapper = strtol(msxmm, NULL, 10);
|
||||
newmsxsize = strtol(msxrr, NULL, 10);
|
||||
newmsxramsize = strtol(msxss, NULL, 10);
|
||||
EEPROM_writeAnything(7, newmsxmapper);
|
||||
EEPROM_writeAnything(8, newmsxsize);
|
||||
EEPROM_writeAnything(10, newmsxramsize);
|
||||
cartselected = 1; // SELECTION MADE
|
||||
#if (defined(enable_OLED) || defined(enable_LCD))
|
||||
println_Msg(F("SELECTION MADE"));
|
||||
display_Update();
|
||||
#else
|
||||
Serial.println(F("SELECTION MADE"));
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (cartselected) {
|
||||
cartselected = 0; // Reset Flag
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
#if (defined(enable_OLED) || defined(enable_LCD))
|
||||
println_Msg(F(""));
|
||||
println_Msg(F("END OF FILE"));
|
||||
display_Update();
|
||||
#else
|
||||
Serial.println(F("END OF FILE"));
|
||||
#endif
|
||||
// Read rom size
|
||||
castEntry->gameSize = database.read() - 48;
|
||||
|
||||
return false;
|
||||
}
|
||||
// Skip over semicolon
|
||||
database.seekCur(1);
|
||||
|
||||
void checkCSV_MSX() {
|
||||
if (getCartListInfo_MSX()) {
|
||||
#if (defined(enable_OLED) || defined(enable_LCD))
|
||||
display_Clear();
|
||||
println_Msg(F("CART SELECTED"));
|
||||
println_Msg(F(""));
|
||||
println_Msg(msxgame);
|
||||
display_Update();
|
||||
// Display Settings
|
||||
display.setCursor(0, 56);
|
||||
print_Msg(F("CODE: M"));
|
||||
print_Msg(newmsxmapper);
|
||||
print_Msg(F("/R"));
|
||||
print_Msg(newmsxsize);
|
||||
print_Msg(F("/S"));
|
||||
println_Msg(newmsxramsize);
|
||||
display_Update();
|
||||
#else
|
||||
Serial.println(F(""));
|
||||
Serial.println(F("CART SELECTED"));
|
||||
Serial.println(msxgame);
|
||||
// Display Settings
|
||||
Serial.print(F("CODE: M"));
|
||||
Serial.print(newmsxmapper);
|
||||
Serial.print(F("/R"));
|
||||
Serial.print(newmsxsize);
|
||||
Serial.print(F("/S"));
|
||||
Serial.println(newmsxramsize);
|
||||
Serial.println(F(""));
|
||||
#endif
|
||||
} else {
|
||||
#if (defined(enable_OLED) || defined(enable_LCD))
|
||||
display.setCursor(0, 56);
|
||||
println_Msg(F("NO SELECTION"));
|
||||
display_Update();
|
||||
#else
|
||||
Serial.println(F("NO SELECTION"));
|
||||
#endif
|
||||
}
|
||||
// Read ram size
|
||||
castEntry->ramSize = database.read() - 48;
|
||||
|
||||
// Skip rest of line
|
||||
database.seekCur(2);
|
||||
}
|
||||
|
||||
void setCart_MSX() {
|
||||
#if (defined(enable_OLED) || defined(enable_LCD))
|
||||
display_Clear();
|
||||
println_Msg(msxcartCSV);
|
||||
display_Update();
|
||||
#endif
|
||||
//go to root
|
||||
sd.chdir();
|
||||
sprintf(folder, "MSX/CSV");
|
||||
sd.chdir(folder); // Switch Folder
|
||||
msxcsvFile = sd.open(msxcartCSV, O_READ);
|
||||
if (!msxcsvFile) {
|
||||
#if (defined(enable_OLED) || defined(enable_LCD))
|
||||
display_Clear();
|
||||
println_Msg(F("CSV FILE NOT FOUND!"));
|
||||
display_Update();
|
||||
#else
|
||||
Serial.println(F("CSV FILE NOT FOUND!"));
|
||||
#endif
|
||||
while (1) {
|
||||
if (checkButton() != 0)
|
||||
setup_MSX();
|
||||
}
|
||||
}
|
||||
checkCSV_MSX();
|
||||
|
||||
msxcsvFile.close();
|
||||
struct database_entry_MSX entry;
|
||||
|
||||
// Select starting letter
|
||||
byte myLetter = starting_letter();
|
||||
|
||||
// Open database
|
||||
if (myFile.open("msxcart.txt", O_READ)) {
|
||||
seek_first_letter_in_database(myFile, myLetter);
|
||||
|
||||
if(checkCartSelection(myFile, &readDataLine_MSX, &entry)) {
|
||||
EEPROM_writeAnything(7, entry.gameMapper);
|
||||
EEPROM_writeAnything(8, entry.gameSize);
|
||||
EEPROM_writeAnything(10, entry.ramSize);
|
||||
}
|
||||
} else {
|
||||
print_FatalError(FS(FSTRING_DATABASE_FILE_NOT_FOUND));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
|
8975
Cart_Reader/N64.ino
8975
Cart_Reader/N64.ino
File diff suppressed because it is too large
Load Diff
2276
Cart_Reader/NES.ino
2276
Cart_Reader/NES.ino
File diff suppressed because it is too large
Load Diff
|
@ -1,13 +1,10 @@
|
|||
//******************************************
|
||||
// NGP MODULE
|
||||
//******************************************
|
||||
#ifdef enable_NGP
|
||||
#ifdef ENABLE_NGP
|
||||
|
||||
static const char ngpMenuItem1[] PROGMEM = "Read ROM";
|
||||
static const char ngpMenuItem2[] PROGMEM = "Read chip info";
|
||||
static const char ngpMenuItem3[] PROGMEM = "Change ROM size";
|
||||
//static const char ngpMenuItemReset[] PROGMEM = "Reset"; (stored in common strings array)
|
||||
static const char* const menuOptionsNGP[] PROGMEM = { ngpMenuItem1, ngpMenuItem2, ngpMenuItem3, string_reset2 };
|
||||
static const char* const menuOptionsNGP[] PROGMEM = { FSTRING_READ_ROM, ngpMenuItem2, FSTRING_SET_SIZE, FSTRING_RESET };
|
||||
|
||||
static const char ngpRomItem1[] PROGMEM = "4 Mbits / 512 KB";
|
||||
static const char ngpRomItem2[] PROGMEM = "8 Mbits / 1 MB";
|
||||
|
@ -80,7 +77,7 @@ void ngpMenu() {
|
|||
break;
|
||||
}
|
||||
|
||||
println_Msg(F(""));
|
||||
println_Msg(FS(FSTRING_EMPTY));
|
||||
// Prints string out of the common strings array either with or without newline
|
||||
print_STR(press_button_STR, 1);
|
||||
display_Update();
|
||||
|
@ -174,7 +171,7 @@ void printCartInfo_NGP() {
|
|||
|
||||
println_Msg(F("NGP Cart Info"));
|
||||
|
||||
print_Msg(F("Name: "));
|
||||
print_Msg(FS(FSTRING_NAME));
|
||||
println_Msg(romName);
|
||||
|
||||
print_Msg(F("App ID: "));
|
||||
|
@ -211,32 +208,18 @@ void readROM_NGP(char* outPathBuf, size_t bufferSize) {
|
|||
changeSize_NGP();
|
||||
|
||||
// generate fullname of rom file
|
||||
snprintf(fileName, FILENAME_LENGTH, "%s.ngp", romName);
|
||||
|
||||
// create a new folder for storing rom file
|
||||
EEPROM_readAnything(0, foldern);
|
||||
snprintf(folder, sizeof(folder), "NGP/ROM/%s/%d", romName, foldern);
|
||||
sd.mkdir(folder, true);
|
||||
sd.chdir(folder);
|
||||
createFolder("NGP", "ROM", romName, "ngp");
|
||||
|
||||
// filling output file path to buffer
|
||||
if (outPathBuf != NULL && bufferSize > 0)
|
||||
snprintf(outPathBuf, bufferSize, "%s/%s", folder, fileName);
|
||||
|
||||
display_Clear();
|
||||
print_STR(saving_to_STR, 0);
|
||||
print_Msg(folder);
|
||||
println_Msg(F("/..."));
|
||||
display_Update();
|
||||
printAndIncrementFolder(true);
|
||||
|
||||
// open file on sdcard
|
||||
if (!myFile.open(fileName, O_RDWR | O_CREAT))
|
||||
print_FatalError(create_file_STR);
|
||||
|
||||
// write new folder number back to EEPROM
|
||||
foldern++;
|
||||
EEPROM_writeAnything(0, foldern);
|
||||
|
||||
// back to read mode
|
||||
dataOut();
|
||||
writeByte_NGP(0x0, 0xf0);
|
||||
|
@ -266,13 +249,7 @@ void scanChip_NGP() {
|
|||
display_Clear();
|
||||
|
||||
// generate name of report file
|
||||
snprintf(fileName, FILENAME_LENGTH, "%s.txt", romName);
|
||||
|
||||
// create a new folder to save report file
|
||||
EEPROM_readAnything(0, foldern);
|
||||
snprintf(folder, sizeof(folder), "NGP/ROM/%s/%d", romName, foldern);
|
||||
sd.mkdir(folder, true);
|
||||
sd.chdir(folder);
|
||||
createFolder("NGP", "ROM", romName, "txt");
|
||||
|
||||
print_Msg(F("Saving chip report to "));
|
||||
print_Msg(folder);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
//******************************************
|
||||
// MAGNAVOX ODYSSEY 2 MODULE
|
||||
//******************************************
|
||||
#if defined(enable_ODY2)
|
||||
#if defined(ENABLE_ODY2)
|
||||
// Magnavox Odyssey 2
|
||||
// Philips Videopac/Videopac+
|
||||
// Cartridge Pinout
|
||||
|
@ -50,9 +50,7 @@ byte ody2lo = 0; // Lowest Entry
|
|||
byte ody2hi = 4; // Highest Entry
|
||||
|
||||
byte ody2mapper;
|
||||
byte newody2mapper;
|
||||
byte ody2size;
|
||||
byte newody2size;
|
||||
|
||||
// EEPROM MAPPING
|
||||
// 07 MAPPER
|
||||
|
@ -62,11 +60,7 @@ byte newody2size;
|
|||
// Menu
|
||||
//******************************************
|
||||
// Base Menu
|
||||
static const char ody2MenuItem1[] PROGMEM = "Select Cart";
|
||||
static const char ody2MenuItem2[] PROGMEM = "Read ROM";
|
||||
static const char ody2MenuItem3[] PROGMEM = "Set Size";
|
||||
static const char ody2MenuItem4[] PROGMEM = "Reset";
|
||||
static const char* const menuOptionsODY2[] PROGMEM = { ody2MenuItem1, ody2MenuItem2, ody2MenuItem3, ody2MenuItem4 };
|
||||
static const char* const menuOptionsODY2[] PROGMEM = { FSTRING_SELECT_CART, FSTRING_READ_ROM, FSTRING_SET_SIZE, FSTRING_RESET };
|
||||
|
||||
void setup_ODY2() {
|
||||
// Request 5V
|
||||
|
@ -109,7 +103,7 @@ void setup_ODY2() {
|
|||
checkStatus_ODY2();
|
||||
strcpy(romName, "ODYSSEY2");
|
||||
|
||||
mode = mode_ODY2;
|
||||
mode = CORE_ODY2;
|
||||
}
|
||||
|
||||
void ody2Menu() {
|
||||
|
@ -120,7 +114,6 @@ void ody2Menu() {
|
|||
case 0:
|
||||
// Select Cart
|
||||
setCart_ODY2();
|
||||
wait();
|
||||
setup_ODY2();
|
||||
break;
|
||||
|
||||
|
@ -219,29 +212,7 @@ void bankSwitch_ODY2(uint16_t addr, uint8_t data) {
|
|||
}
|
||||
|
||||
void readROM_ODY2() {
|
||||
strcpy(fileName, romName);
|
||||
strcat(fileName, ".bin");
|
||||
|
||||
// create a new folder for storing rom file
|
||||
EEPROM_readAnything(0, foldern);
|
||||
sprintf(folder, "ODY2/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_FatalError(create_file_STR);
|
||||
}
|
||||
|
||||
// write new folder number back to EEPROM
|
||||
foldern++;
|
||||
EEPROM_writeAnything(0, foldern);
|
||||
createFolderAndOpenFile("ODY2", "ROM", romName, "bin");
|
||||
|
||||
if (ody2mapper == 1) { // A10 CONNECTED
|
||||
// Videopac 31: Musician
|
||||
|
@ -271,10 +242,9 @@ void readROM_ODY2() {
|
|||
}
|
||||
myFile.close();
|
||||
|
||||
unsigned long crcsize = ODY2[ody2size] * 0x400;
|
||||
calcCRC(fileName, crcsize, NULL, 0);
|
||||
printCRC(fileName, NULL, 0);
|
||||
|
||||
println_Msg(F(""));
|
||||
println_Msg(FS(FSTRING_EMPTY));
|
||||
print_STR(press_button_STR, 1);
|
||||
display_Update();
|
||||
wait();
|
||||
|
@ -284,78 +254,26 @@ void readROM_ODY2() {
|
|||
// ROM SIZE
|
||||
//******************************************
|
||||
|
||||
#if (defined(ENABLE_OLED) || defined(ENABLE_LCD))
|
||||
void printRomSize_ODY2(int index) {
|
||||
display_Clear();
|
||||
print_Msg(F("ROM Size: "));
|
||||
println_Msg(ODY2[index]);
|
||||
}
|
||||
#endif
|
||||
|
||||
void setROMSize_ODY2() {
|
||||
#if (defined(enable_OLED) || defined(enable_LCD))
|
||||
byte newody2size;
|
||||
#if (defined(ENABLE_OLED) || defined(ENABLE_LCD))
|
||||
display_Clear();
|
||||
if (ody2lo == ody2hi)
|
||||
newody2size = ody2lo;
|
||||
else {
|
||||
int b = 0;
|
||||
int i = ody2lo;
|
||||
newody2size = navigateMenu(ody2lo, ody2hi, &printRomSize_ODY2);
|
||||
|
||||
display_Clear();
|
||||
print_Msg(F("ROM Size: "));
|
||||
println_Msg(ODY2[i]);
|
||||
println_Msg(F(""));
|
||||
#if defined(enable_OLED)
|
||||
print_STR(press_to_change_STR, 1);
|
||||
print_STR(right_to_select_STR, 1);
|
||||
#elif defined(enable_LCD)
|
||||
print_STR(rotate_to_change_STR, 1);
|
||||
print_STR(press_to_select_STR, 1);
|
||||
#endif
|
||||
display_Update();
|
||||
|
||||
while (1) {
|
||||
b = checkButton();
|
||||
if (b == 2) { // Previous (doubleclick)
|
||||
if (i == ody2lo)
|
||||
i = ody2hi;
|
||||
else
|
||||
i--;
|
||||
|
||||
// Only update display after input because of slow LCD library
|
||||
display_Clear();
|
||||
print_Msg(F("ROM Size: "));
|
||||
println_Msg(ODY2[i]);
|
||||
println_Msg(F(""));
|
||||
#if defined(enable_OLED)
|
||||
print_STR(press_to_change_STR, 1);
|
||||
print_STR(right_to_select_STR, 1);
|
||||
#elif defined(enable_LCD)
|
||||
print_STR(rotate_to_change_STR, 1);
|
||||
print_STR(press_to_select_STR, 1);
|
||||
#endif
|
||||
display_Update();
|
||||
}
|
||||
if (b == 1) { // Next (press)
|
||||
if (i == ody2hi)
|
||||
i = ody2lo;
|
||||
else
|
||||
i++;
|
||||
|
||||
// Only update display after input because of slow LCD library
|
||||
display_Clear();
|
||||
print_Msg(F("ROM Size: "));
|
||||
println_Msg(ODY2[i]);
|
||||
println_Msg(F(""));
|
||||
#if defined(enable_OLED)
|
||||
print_STR(press_to_change_STR, 1);
|
||||
print_STR(right_to_select_STR, 1);
|
||||
#elif defined(enable_LCD)
|
||||
print_STR(rotate_to_change_STR, 1);
|
||||
print_STR(press_to_select_STR, 1);
|
||||
#endif
|
||||
display_Update();
|
||||
}
|
||||
if (b == 3) { // Long Press - Execute (hold)
|
||||
newody2size = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
display.setCursor(0, 56); // Display selection at bottom
|
||||
}
|
||||
print_Msg(F("ROM SIZE "));
|
||||
print_Msg(FS(FSTRING_ROM_SIZE));
|
||||
print_Msg(ODY2[newody2size]);
|
||||
println_Msg(F("K"));
|
||||
display_Update();
|
||||
|
@ -380,7 +298,7 @@ setrom:
|
|||
newody2size = sizeROM.toInt() + ody2lo;
|
||||
if (newody2size > ody2hi) {
|
||||
Serial.println(F("SIZE NOT SUPPORTED"));
|
||||
Serial.println(F(""));
|
||||
Serial.println(FS(FSTRING_EMPTY));
|
||||
goto setrom;
|
||||
}
|
||||
}
|
||||
|
@ -404,14 +322,14 @@ void checkStatus_ODY2() {
|
|||
EEPROM_writeAnything(8, ody2size);
|
||||
}
|
||||
|
||||
#if (defined(enable_OLED) || defined(enable_LCD))
|
||||
#if (defined(ENABLE_OLED) || defined(ENABLE_LCD))
|
||||
display_Clear();
|
||||
println_Msg(F("ODYSSEY 2 READER"));
|
||||
println_Msg(F("CURRENT SETTINGS"));
|
||||
println_Msg(F(""));
|
||||
println_Msg(FS(FSTRING_CURRENT_SETTINGS));
|
||||
println_Msg(FS(FSTRING_EMPTY));
|
||||
print_Msg(F("MAPPER: "));
|
||||
println_Msg(ody2mapper);
|
||||
print_Msg(F("ROM SIZE: "));
|
||||
print_Msg(FS(FSTRING_ROM_SIZE));
|
||||
print_Msg(ODY2[ody2size]);
|
||||
println_Msg(F("K"));
|
||||
display_Update();
|
||||
|
@ -422,255 +340,33 @@ void checkStatus_ODY2() {
|
|||
Serial.print(F("CURRENT ROM SIZE: "));
|
||||
Serial.print(ODY2[ody2size]);
|
||||
Serial.println(F("K"));
|
||||
Serial.println(F(""));
|
||||
Serial.println(FS(FSTRING_EMPTY));
|
||||
#endif
|
||||
}
|
||||
|
||||
//******************************************
|
||||
// CART SELECT CODE
|
||||
//******************************************
|
||||
|
||||
FsFile ody2csvFile;
|
||||
char ody2game[51]; // title
|
||||
char ody2mm[3]; // mapper (A10)
|
||||
char ody2rr[3]; // romsize
|
||||
char ody2ll[4]; // linelength (previous line)
|
||||
unsigned long ody2csvpos; // CSV File Position
|
||||
char ody2cartCSV[] = "ody2cart.txt"; // CSV List
|
||||
char ody2csvEND[] = "EOF"; // CSV End Marker for scrolling
|
||||
|
||||
bool readLine_ODY2(FsFile& f, char* line, size_t maxLen) {
|
||||
for (size_t n = 0; n < maxLen; n++) {
|
||||
int c = f.read();
|
||||
if (c < 0 && n == 0) return false; // EOF
|
||||
if (c < 0 || c == '\n') {
|
||||
line[n] = 0;
|
||||
return true;
|
||||
}
|
||||
line[n] = c;
|
||||
}
|
||||
return false; // line too long
|
||||
}
|
||||
|
||||
bool readVals_ODY2(char* ody2game, char* ody2mm, char* ody2rr, char* ody2ll) {
|
||||
char line[59];
|
||||
ody2csvpos = ody2csvFile.position();
|
||||
if (!readLine_ODY2(ody2csvFile, line, sizeof(line))) {
|
||||
return false; // EOF or too long
|
||||
}
|
||||
char* comma = strtok(line, ",");
|
||||
int x = 0;
|
||||
while (comma != NULL) {
|
||||
if (x == 0)
|
||||
strcpy(ody2game, comma);
|
||||
else if (x == 1)
|
||||
strcpy(ody2mm, comma);
|
||||
else if (x == 2)
|
||||
strcpy(ody2rr, comma);
|
||||
else if (x == 3)
|
||||
strcpy(ody2ll, comma);
|
||||
comma = strtok(NULL, ",");
|
||||
x += 1;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool getCartListInfo_ODY2() {
|
||||
bool buttonreleased = 0;
|
||||
bool cartselected = 0;
|
||||
#if (defined(enable_OLED) || defined(enable_LCD))
|
||||
display_Clear();
|
||||
println_Msg(F(" HOLD TO FAST CYCLE"));
|
||||
display_Update();
|
||||
#else
|
||||
Serial.println(F("HOLD BUTTON TO FAST CYCLE"));
|
||||
#endif
|
||||
delay(2000);
|
||||
#if defined(enable_OLED)
|
||||
buttonVal1 = (PIND & (1 << 7)); // PD7
|
||||
#elif defined(enable_LCD)
|
||||
boolean buttonVal1 = (PING & (1 << 2)); //PG2
|
||||
#endif
|
||||
if (buttonVal1 == LOW) { // Button Held - Fast Cycle
|
||||
while (1) { // Scroll Game List
|
||||
while (readVals_ODY2(ody2game, ody2mm, ody2rr, ody2ll)) {
|
||||
if (strcmp(ody2csvEND, ody2game) == 0) {
|
||||
ody2csvFile.seek(0); // Restart
|
||||
} else {
|
||||
#if (defined(enable_OLED) || defined(enable_LCD))
|
||||
display_Clear();
|
||||
println_Msg(F("CART TITLE:"));
|
||||
println_Msg(F(""));
|
||||
println_Msg(ody2game);
|
||||
display_Update();
|
||||
#else
|
||||
Serial.print(F("CART TITLE:"));
|
||||
Serial.println(ody2game);
|
||||
#endif
|
||||
#if defined(enable_OLED)
|
||||
buttonVal1 = (PIND & (1 << 7)); // PD7
|
||||
#elif defined(enable_LCD)
|
||||
buttonVal1 = (PING & (1 << 2)); //PG2
|
||||
#endif
|
||||
if (buttonVal1 == HIGH) { // Button Released
|
||||
buttonreleased = 1;
|
||||
break;
|
||||
}
|
||||
if (buttonreleased) {
|
||||
buttonreleased = 0; // Reset Flag
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#if defined(enable_OLED)
|
||||
buttonVal1 = (PIND & (1 << 7)); // PD7
|
||||
#elif defined(enable_LCD)
|
||||
buttonVal1 = (PING & (1 << 2)); //PG2
|
||||
#endif
|
||||
if (buttonVal1 == HIGH) // Button Released
|
||||
break;
|
||||
}
|
||||
}
|
||||
#if (defined(enable_OLED) || defined(enable_LCD))
|
||||
display.setCursor(0, 56);
|
||||
println_Msg(F("FAST CYCLE OFF"));
|
||||
display_Update();
|
||||
#else
|
||||
Serial.println(F(""));
|
||||
Serial.println(F("FAST CYCLE OFF"));
|
||||
Serial.println(F("PRESS BUTTON TO STEP FORWARD"));
|
||||
Serial.println(F("DOUBLE CLICK TO STEP BACK"));
|
||||
Serial.println(F("HOLD TO SELECT"));
|
||||
Serial.println(F(""));
|
||||
#endif
|
||||
while (readVals_ODY2(ody2game, ody2mm, ody2rr, ody2ll)) {
|
||||
if (strcmp(ody2csvEND, ody2game) == 0) {
|
||||
ody2csvFile.seek(0); // Restart
|
||||
} else {
|
||||
#if (defined(enable_OLED) || defined(enable_LCD))
|
||||
display_Clear();
|
||||
println_Msg(F("CART TITLE:"));
|
||||
println_Msg(F(""));
|
||||
println_Msg(ody2game);
|
||||
display.setCursor(0, 48);
|
||||
#if defined(enable_OLED)
|
||||
print_STR(press_to_change_STR, 1);
|
||||
print_STR(right_to_select_STR, 1);
|
||||
#elif defined(enable_LCD)
|
||||
print_STR(rotate_to_change_STR, 1);
|
||||
print_STR(press_to_select_STR, 1);
|
||||
#endif
|
||||
display_Update();
|
||||
#else
|
||||
Serial.print(F("CART TITLE:"));
|
||||
Serial.println(ody2game);
|
||||
#endif
|
||||
while (1) { // Single Step
|
||||
int b = checkButton();
|
||||
if (b == 1) { // Continue (press)
|
||||
break;
|
||||
}
|
||||
if (b == 2) { // Reset to Start of List (doubleclick)
|
||||
byte prevline = strtol(ody2ll, NULL, 10);
|
||||
ody2csvpos -= prevline;
|
||||
ody2csvFile.seek(ody2csvpos);
|
||||
break;
|
||||
}
|
||||
if (b == 3) { // Long Press - Select Cart (hold)
|
||||
newody2mapper = strtol(ody2mm, NULL, 10);
|
||||
newody2size = strtol(ody2rr, NULL, 10);
|
||||
EEPROM_writeAnything(7, newody2mapper);
|
||||
EEPROM_writeAnything(8, newody2size);
|
||||
cartselected = 1; // SELECTION MADE
|
||||
#if (defined(enable_OLED) || defined(enable_LCD))
|
||||
println_Msg(F("SELECTION MADE"));
|
||||
display_Update();
|
||||
#else
|
||||
Serial.println(F("SELECTION MADE"));
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (cartselected) {
|
||||
cartselected = 0; // Reset Flag
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
#if (defined(enable_OLED) || defined(enable_LCD))
|
||||
println_Msg(F(""));
|
||||
println_Msg(F("END OF FILE"));
|
||||
display_Update();
|
||||
#else
|
||||
Serial.println(F("END OF FILE"));
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void checkCSV_ODY2() {
|
||||
if (getCartListInfo_ODY2()) {
|
||||
#if (defined(enable_OLED) || defined(enable_LCD))
|
||||
display_Clear();
|
||||
println_Msg(F("CART SELECTED"));
|
||||
println_Msg(F(""));
|
||||
println_Msg(ody2game);
|
||||
display_Update();
|
||||
// Display Settings
|
||||
display.setCursor(0, 56);
|
||||
print_Msg(F("CODE: M"));
|
||||
print_Msg(newody2mapper);
|
||||
print_Msg(F("/R"));
|
||||
println_Msg(newody2size);
|
||||
display_Update();
|
||||
#else
|
||||
Serial.println(F(""));
|
||||
Serial.println(F("CART SELECTED"));
|
||||
Serial.println(ody2game);
|
||||
// Display Settings
|
||||
Serial.print(F("CODE: M"));
|
||||
Serial.print(newody2mapper);
|
||||
Serial.print(F("/R"));
|
||||
Serial.println(newody2size);
|
||||
Serial.println(F(""));
|
||||
#endif
|
||||
} else {
|
||||
#if (defined(enable_OLED) || defined(enable_LCD))
|
||||
display.setCursor(0, 56);
|
||||
println_Msg(F("NO SELECTION"));
|
||||
display_Update();
|
||||
#else
|
||||
Serial.println(F("NO SELECTION"));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void setCart_ODY2() {
|
||||
#if (defined(enable_OLED) || defined(enable_LCD))
|
||||
display_Clear();
|
||||
println_Msg(ody2cartCSV);
|
||||
display_Update();
|
||||
#endif
|
||||
//go to root
|
||||
sd.chdir();
|
||||
sprintf(folder, "ODY2/CSV");
|
||||
sd.chdir(folder); // Switch Folder
|
||||
ody2csvFile = sd.open(ody2cartCSV, O_READ);
|
||||
if (!ody2csvFile) {
|
||||
#if (defined(enable_OLED) || defined(enable_LCD))
|
||||
display_Clear();
|
||||
println_Msg(F("CSV FILE NOT FOUND!"));
|
||||
display_Update();
|
||||
#else
|
||||
Serial.println(F("CSV FILE NOT FOUND!"));
|
||||
#endif
|
||||
while (1) {
|
||||
if (checkButton() != 0)
|
||||
setup_ODY2();
|
||||
}
|
||||
}
|
||||
checkCSV_ODY2();
|
||||
|
||||
ody2csvFile.close();
|
||||
struct database_entry_mapper_size entry;
|
||||
|
||||
// Select starting letter
|
||||
byte myLetter = starting_letter();
|
||||
|
||||
// Open database
|
||||
if (myFile.open("ody2cart.txt", O_READ)) {
|
||||
seek_first_letter_in_database(myFile, myLetter);
|
||||
|
||||
if(checkCartSelection(myFile, &readDataLineMapperSize, &entry)) {
|
||||
EEPROM_writeAnything(7, entry.gameMapper);
|
||||
EEPROM_writeAnything(8, entry.gameSize);
|
||||
}
|
||||
} else {
|
||||
print_FatalError(FS(FSTRING_DATABASE_FILE_NOT_FOUND));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
//******************************************
|
||||
|
|
|
@ -7,7 +7,10 @@
|
|||
* Contains various enums, variables, etc, for the main program.
|
||||
*
|
||||
* PUBLIC FUNCTIONS :
|
||||
* void setClockScale( VOLTS )
|
||||
* void setClockScale( ClockScale )
|
||||
* VOLTS setVoltage( Voltage )
|
||||
* long configGetLong( Key, OnFailure )
|
||||
* String configGetStr( Key )
|
||||
*
|
||||
* NOTES :
|
||||
* This file is a WIP, I've been moving things into it on my local working
|
||||
|
@ -32,16 +35,52 @@
|
|||
* CHANGES :
|
||||
*
|
||||
* REF NO VERSION DATE WHO DETAIL
|
||||
* 13.2 2024-03-02 Ancyker Add string constants
|
||||
* 13.2 2024-02-29 Ancyker Add config support
|
||||
* 12.5 2023-03-29 Ancyker Initial version
|
||||
*
|
||||
*H*/
|
||||
|
||||
#include "OSCR.h"
|
||||
|
||||
/*==== VARIABLES ==================================================*/
|
||||
/*==== CONSTANTS ==================================================*/
|
||||
|
||||
/**
|
||||
* String Constants
|
||||
**/
|
||||
// Firmware Version
|
||||
char ver[5] = "12.8";
|
||||
constexpr char PROGMEM FSTRING_VERSION[] = "V13.2";
|
||||
|
||||
// Universal
|
||||
constexpr char PROGMEM FSTRING_RESET[] = "Reset";
|
||||
constexpr char PROGMEM FSTRING_OK[] = "OK";
|
||||
constexpr char PROGMEM FSTRING_EMPTY[] = "";
|
||||
constexpr char PROGMEM FSTRING_SPACE[] = " ";
|
||||
constexpr char PROGMEM FSTRING_CURRENT_SETTINGS[] = "CURRENT SETTINGS";
|
||||
|
||||
// Messages
|
||||
constexpr char PROGMEM FSTRING_OSCR[] = "OSCR";
|
||||
constexpr char PROGMEM FSTRING_MODULE_NOT_ENABLED[] = "Module is not enabled.";
|
||||
constexpr char PROGMEM FSTRING_DATABASE_FILE_NOT_FOUND[] = "Database file not found";
|
||||
constexpr char PROGMEM FSTRING_FILE_DOESNT_EXIST[] = "File doesn't exist";
|
||||
|
||||
// Cart
|
||||
constexpr char PROGMEM FSTRING_READ_ROM[] = "Read ROM";
|
||||
constexpr char PROGMEM FSTRING_READ_SAVE[] = "Read Save";
|
||||
constexpr char PROGMEM FSTRING_WRITE_SAVE[] = "Write Save";
|
||||
constexpr char PROGMEM FSTRING_SELECT_CART[] = "Select Cart";
|
||||
constexpr char PROGMEM FSTRING_SELECT_CART_TYPE[] = "Select Cart Type";
|
||||
constexpr char PROGMEM FSTRING_SET_SIZE[] = "Set Size";
|
||||
constexpr char PROGMEM FSTRING_REFRESH_CART[] = "Refresh Cart";
|
||||
constexpr char PROGMEM FSTRING_MAPPER[] = "Mapper: ";
|
||||
constexpr char PROGMEM FSTRING_SIZE[] = "Size: ";
|
||||
constexpr char PROGMEM FSTRING_NAME[] = "Name: ";
|
||||
constexpr char PROGMEM FSTRING_CHECKSUM[] = "Checksum: ";
|
||||
constexpr char PROGMEM FSTRING_ROM_SIZE[] ="ROM SIZE: ";
|
||||
|
||||
/*==== /CONSTANTS =================================================*/
|
||||
|
||||
/*==== VARIABLES ==================================================*/
|
||||
|
||||
// Clock speed
|
||||
unsigned long clock = CS_16MHZ;
|
||||
|
@ -49,6 +88,17 @@ unsigned long clock = CS_16MHZ;
|
|||
// Voltage
|
||||
VOLTS voltage = VOLTS_SET_5V;
|
||||
|
||||
#if defined(ENABLE_CONFIG)
|
||||
|
||||
FsFile configFile;
|
||||
bool useConfig;
|
||||
|
||||
# if defined(ENABLE_GLOBAL_LOG)
|
||||
// Logging
|
||||
bool loggingEnabled = true;
|
||||
# endif /* ENABLE_GLOBAL_LOG */
|
||||
#endif /* ENABLE_CONFIG */
|
||||
|
||||
/*==== /VARIABLES =================================================*/
|
||||
|
||||
/*F******************************************************************
|
||||
|
@ -57,11 +107,11 @@ VOLTS voltage = VOLTS_SET_5V;
|
|||
* DESCRIPTION : Prints the version & feature string to serial
|
||||
*
|
||||
*F*/
|
||||
#if !defined(enable_serial) && defined(ENABLE_UPDATER)
|
||||
#if !defined(ENABLE_SERIAL) && defined(ENABLE_UPDATER)
|
||||
void printVersionToSerial() {
|
||||
ClockedSerial.print(F("OSCR"));
|
||||
ClockedSerial.print(FS(FSTRING_OSCR));
|
||||
ClockedSerial.print(F("::"));
|
||||
ClockedSerial.print(ver);
|
||||
ClockedSerial.print(FS(FSTRING_VERSION));
|
||||
ClockedSerial.print(F("//"));
|
||||
#if defined(HW1)
|
||||
ClockedSerial.print(F("HW1"));
|
||||
|
@ -81,20 +131,20 @@ void printVersionToSerial() {
|
|||
#if defined (ENABLE_VSELECT)
|
||||
ClockedSerial.print(F("|VSELECT"));
|
||||
#endif
|
||||
#if defined (RTC_installed)
|
||||
#if defined (ENABLE_RTC)
|
||||
ClockedSerial.print(F("|RTC"));
|
||||
#endif
|
||||
#if defined (clockgen_installed)
|
||||
#if defined (ENABLE_CLOCKGEN)
|
||||
ClockedSerial.print(F("|CLOCKGEN"));
|
||||
#endif
|
||||
#if defined (fastcrc)
|
||||
#if defined (OPTION_N64_FASTCRC)
|
||||
ClockedSerial.print(F("|FASTCRC"));
|
||||
#endif
|
||||
#if defined (ENABLE_3V3FIX)
|
||||
ClockedSerial.print(F("|3V3FIX"));
|
||||
#endif
|
||||
|
||||
ClockedSerial.println(F(""));
|
||||
ClockedSerial.println(FS(FSTRING_EMPTY));
|
||||
}
|
||||
#else
|
||||
void printVersionToSerial() {}
|
||||
|
@ -107,7 +157,8 @@ void printVersionToSerial() {}
|
|||
*
|
||||
* INPUTS :
|
||||
* PARAMETERS:
|
||||
* VOLTS ClockScale Clock scale
|
||||
* VOLTS ClockScale Clock scale
|
||||
* CLKSCALE ClockScale Clock scale
|
||||
*
|
||||
* PROCESS :
|
||||
* [1] Enable clock prescaler change
|
||||
|
@ -139,6 +190,24 @@ void setClockScale(VOLTS __x)
|
|||
); /*[2]*/
|
||||
}
|
||||
|
||||
void setClockScale(CLKSCALE __x)
|
||||
{
|
||||
clock = (__x == CLKSCALE_16MHZ ? CS_16MHZ : CS_8MHZ);
|
||||
uint8_t __tmp = _BV(CLKPCE); /*[1]*/
|
||||
__asm__ __volatile__ (
|
||||
"in __tmp_reg__,__SREG__" "\n\t"
|
||||
"cli" "\n\t"
|
||||
"sts %1, %0" "\n\t"
|
||||
"sts %1, %2" "\n\t"
|
||||
"out __SREG__, __tmp_reg__"
|
||||
: /* no outputs */
|
||||
: "d" (__tmp),
|
||||
"M" (_SFR_MEM_ADDR(CLKPR)),
|
||||
"d" (__x)
|
||||
: "r0"
|
||||
); /*[2]*/
|
||||
}
|
||||
|
||||
/*F******************************************************************
|
||||
* NAME : VOLTS setVoltage( Voltage )
|
||||
*
|
||||
|
@ -197,14 +266,14 @@ VOLTS setVoltage(VOLTS newVoltage) {
|
|||
// Adjust clock speed when 3V3FIX is enabled
|
||||
#if defined(ENABLE_3V3FIX)
|
||||
// Stop serial if running
|
||||
#if !defined(enable_serial) && defined(ENABLE_UPDATER)
|
||||
#if !defined(ENABLE_SERIAL) && defined(ENABLE_UPDATER)
|
||||
ClockedSerial.end();
|
||||
#endif
|
||||
// Set clock speed
|
||||
clock = CS_16MHZ;
|
||||
setClockScale(newVoltage); /*[2]*/
|
||||
// Restart serial
|
||||
#if !defined(enable_serial) && defined(ENABLE_UPDATER)
|
||||
#if !defined(ENABLE_SERIAL) && defined(ENABLE_UPDATER)
|
||||
ClockedSerial.begin(UPD_BAUD);
|
||||
#endif
|
||||
#else
|
||||
|
@ -230,13 +299,13 @@ VOLTS setVoltage(VOLTS newVoltage) {
|
|||
|
||||
// Adjust clock speed when 3V3FIX is enabled
|
||||
#if defined(ENABLE_3V3FIX)
|
||||
#if !defined(enable_serial) && defined(ENABLE_UPDATER)
|
||||
#if !defined(ENABLE_SERIAL) && defined(ENABLE_UPDATER)
|
||||
ClockedSerial.end();
|
||||
#endif
|
||||
// Set clock speed
|
||||
clock = CS_8MHZ;
|
||||
setClockScale(newVoltage); /*[2]*/
|
||||
#if !defined(enable_serial) && defined(ENABLE_UPDATER)
|
||||
#if !defined(ENABLE_SERIAL) && defined(ENABLE_UPDATER)
|
||||
ClockedSerial.begin(UPD_BAUD);
|
||||
#endif
|
||||
#endif
|
||||
|
@ -263,3 +332,146 @@ VOLTS setVoltage(VOLTS newVoltage __attribute__((unused))) {
|
|||
return VOLTS_NOTENABLED;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(ENABLE_CONFIG)
|
||||
|
||||
/*F******************************************************************
|
||||
* NAME : void configInit()
|
||||
*
|
||||
* DESCRIPTION : Setup the config file.
|
||||
*
|
||||
*F*/
|
||||
void configInit() {
|
||||
useConfig = configFile.open(CONFIG_FILE, O_READ);
|
||||
}
|
||||
|
||||
/*F******************************************************************
|
||||
* NAME : uint8_t configFindKey( Key, Value )
|
||||
*
|
||||
* DESCRIPTION : Search for a key=value pair.
|
||||
*
|
||||
* INPUTS :
|
||||
* PARAMETERS:
|
||||
* __FlashStringHelper Key The key to get the value for.
|
||||
* char* value Variable to store the value in.
|
||||
*
|
||||
* OUTPUTS :
|
||||
* RETURN :
|
||||
* Type: uint8_t Length of the value.
|
||||
*
|
||||
* PROCESS :
|
||||
* [1] Get key length and convert to char array/string.
|
||||
* [2] Parse file line by line.
|
||||
* [3] Check if key in file matches.
|
||||
* [4] Copy string after equals character.
|
||||
* [5] Add null terminator.
|
||||
*
|
||||
* NOTES :
|
||||
* You aren't meant to use this function directly. Check the
|
||||
* functions configGetStr() and configGetLong().
|
||||
*
|
||||
*F*/
|
||||
uint8_t configFindKey(const __FlashStringHelper* searchKey, char* value) {
|
||||
if (!useConfig) return 0;
|
||||
|
||||
char key[CONFIG_KEY_MAX + 1];
|
||||
char buffer[CONFIG_KEY_MAX + CONFIG_VALUE_MAX + 4];
|
||||
int keyLen = 0;
|
||||
int valueLen = 0;
|
||||
|
||||
keyLen = strlcpy_P(key, reinterpret_cast<const char *>(searchKey), CONFIG_KEY_MAX); /*[1]*/
|
||||
|
||||
configFile.rewind();
|
||||
|
||||
while (configFile.available()) { /*[2]*/
|
||||
int bufferLen = configFile.readBytesUntil('\n', buffer, CONFIG_KEY_MAX + CONFIG_VALUE_MAX + 3);
|
||||
|
||||
if (buffer[bufferLen - 1] == '\r')
|
||||
bufferLen--;
|
||||
|
||||
if (bufferLen > (keyLen + 1)) {
|
||||
if (memcmp(buffer, key, keyLen) == 0) { /*[3]*/
|
||||
if (buffer[keyLen] == '=') { /*[4]*/
|
||||
valueLen = bufferLen - keyLen - 1;
|
||||
memcpy(&value[0], &buffer[keyLen + 1], valueLen);
|
||||
value[valueLen] = '\0'; /*[5]*/
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return valueLen;
|
||||
}
|
||||
|
||||
/*F******************************************************************
|
||||
* NAME : String configGetStr( Key )
|
||||
*
|
||||
* DESCRIPTION : Return the value of a key as a string.
|
||||
*
|
||||
* INPUTS :
|
||||
* PARAMETERS:
|
||||
* __FlashStringHelper Key The key to get the value for.
|
||||
*
|
||||
* OUTPUTS :
|
||||
* RETURN :
|
||||
* Type: String The value of the key or an empty string.
|
||||
*
|
||||
* PROCESS :
|
||||
* [1] Find the key via configFindKey().
|
||||
* [2] Return empty if nothing was found.
|
||||
* [3] Convert to String type.
|
||||
*
|
||||
* NOTES :
|
||||
* You can use this to get strings stored in the config file.
|
||||
* Take care when allocating memory for strings. You should
|
||||
* probably use malloc for it if it's a global variable. If
|
||||
* you do, make sure to free() it after it's not needed.
|
||||
*
|
||||
*F*/
|
||||
String configGetStr(const __FlashStringHelper* key) {
|
||||
if (!useConfig) return {};
|
||||
char value[CONFIG_VALUE_MAX + 1];
|
||||
|
||||
uint8_t valueLen = configFindKey(key, value); /*[1]*/
|
||||
if (valueLen < 1) return {}; /*[2]*/
|
||||
|
||||
String stringVal(value); /*[3]*/
|
||||
|
||||
return stringVal;
|
||||
}
|
||||
|
||||
/*F******************************************************************
|
||||
* NAME : long configGetLong( Key, OnFailure )
|
||||
*
|
||||
* DESCRIPTION : Return the value of a key as an int/long.
|
||||
*
|
||||
* INPUTS :
|
||||
* PARAMETERS:
|
||||
* __FlashStringHelper Key The key to get the value for.
|
||||
* int onFail Value to return on failure. (def=0)
|
||||
*
|
||||
* OUTPUTS :
|
||||
* RETURN :
|
||||
* Type: int The value of the key or onFail.
|
||||
*
|
||||
* PROCESS :
|
||||
* [1] Find the key via configFindKey().
|
||||
* [2] Return onFail if nothing was found.
|
||||
* [3] Convert to long int type and return.
|
||||
*
|
||||
* NOTES :
|
||||
* You can specify hex, i.e. 0xFF for 255, if you want to.
|
||||
*
|
||||
*F*/
|
||||
long configGetLong(const __FlashStringHelper* key, int onFail) {
|
||||
if (!useConfig) return onFail;
|
||||
char value[CONFIG_VALUE_MAX + 1];
|
||||
|
||||
uint8_t valueLen = configFindKey(key, value); /*[1]*/
|
||||
if (valueLen < 1) return onFail; /*[2]*/
|
||||
|
||||
return strtol(value, NULL, 0); /*[3]*/
|
||||
}
|
||||
|
||||
#endif /* ENABLE_CONFIG */
|
||||
|
|
|
@ -10,24 +10,319 @@
|
|||
#include <Wire.h>
|
||||
#include <avr/pgmspace.h>
|
||||
#include <avr/wdt.h>
|
||||
#include "SdFat.h"
|
||||
|
||||
#include "Config.h"
|
||||
|
||||
/*==== SANITY CHECKS ==============================================*/
|
||||
#if !(defined(HW1) || defined(HW2) || defined(HW3) || defined(HW4) || defined(HW5) || defined(SERIAL_MONITOR))
|
||||
#error !!! PLEASE CHOOSE HARDWARE VERSION !!!
|
||||
#endif
|
||||
# if !(defined(HW1) || defined(HW2) || defined(HW3) || defined(HW4) || defined(HW5) || defined(SERIAL_MONITOR))
|
||||
# error !!! PLEASE CHOOSE HARDWARE VERSION IN CONFIG.H !!!
|
||||
# endif
|
||||
|
||||
#if defined(ENABLE_3V3FIX) && !defined(ENABLE_VSELECT)
|
||||
#warning Using 3V3FIX is best with VSELECT.
|
||||
#endif
|
||||
// Let user know unsafe configs are allowed
|
||||
# if defined(ALLOW_UNSAFE_CONFIG)
|
||||
// Error if defined during GitHub CI tests. This should not happen unless someone accidentally committed their Config.h
|
||||
# if defined(GITHUB_CI)
|
||||
# error !! UNSAFE CONFIGURATIONS ARE ALLOWED !! -- This should not be enabled on the repository!
|
||||
# else /* !defined(GITHUB_CI) */
|
||||
# warning !! UNSAFE CONFIGURATIONS ARE ALLOWED !! -- Unless you are a developer this probably is not something you want set.
|
||||
# endif /* GITHUB_CI */
|
||||
# endif /* ALLOW_UNSAFE_CONFIG */
|
||||
|
||||
# if defined(ENABLE_3V3FIX) && !defined(ENABLE_VSELECT)
|
||||
# warning Using 3V3FIX is best with VSELECT.
|
||||
# endif
|
||||
|
||||
# if defined(ENABLE_VSELECT)
|
||||
|
||||
// Error if not a supported hardware version
|
||||
# if !(defined(HW4) || defined(HW5) || defined(SERIAL_MONITOR))
|
||||
# if defined(ALLOW_UNSAFE_CONFIG)
|
||||
# warning Using VSELECT with hardware revisions other than 4 or 5 is not supported.
|
||||
# else /* !defined(ALLOW_UNSAFE_CONFIG) */
|
||||
# error Using VSELECT with hardware revisions other than 4 or 5 is not supported. \
|
||||
If you understand what you are doing you can define ALLOW_UNSAFE_CONFIG in Config.h to allow compiling.
|
||||
# endif /* ALLOW_UNSAFE_CONFIG */
|
||||
# endif /* !(HW4 | HW5 | SERIAL_MONITOR) */
|
||||
|
||||
// HW4 might work but needs tested. Make sure they know it's untested.
|
||||
# if defined(HW4)
|
||||
# if defined(ALLOW_UNSAFE_CONFIG)
|
||||
# warning Using VSELECT with HW4 is untested. Verification with a multimeter before use is strongly recommended. Please remember to report back with your findings.
|
||||
# else /* !defined(ALLOW_UNSAFE_CONFIG) */
|
||||
# error Using VSELECT with HW4 is untested. Verification with a multimeter before use is strongly recommended. \
|
||||
Define ALLOW_UNSAFE_CONFIG in Config.h to allow compiling. Please report back with your findings after testing!
|
||||
# endif /* ALLOW_UNSAFE_CONFIG */
|
||||
# endif /* HW4 */
|
||||
|
||||
// SERIAL might work but needs tested. Make sure they know it's untested.
|
||||
# if defined(SERIAL_MONITOR)
|
||||
# if defined(ALLOW_UNSAFE_CONFIG)
|
||||
# warning Using VSELECT with a serial-only OSCR is untested. Verification with a multimeter before use is strongly recommended. Please remember to report back with your findings.
|
||||
# else /* !defined(ALLOW_UNSAFE_CONFIG) */
|
||||
# error Using VSELECT with a serial-only OSCR is untested. Verification with a multimeter before use is strongly recommended. \
|
||||
Define ALLOW_UNSAFE_CONFIG in Config.h to allow compiling. Please report back with your findings after testing!
|
||||
# endif /* ALLOW_UNSAFE_CONFIG */
|
||||
# endif /* SERIAL_MONITOR */
|
||||
|
||||
# endif /* ENABLE_VSELECT */
|
||||
|
||||
/*==== CONSTANTS ==================================================*/
|
||||
/**
|
||||
* String Constants
|
||||
**/
|
||||
|
||||
// Version
|
||||
extern const char PROGMEM FSTRING_VERSION[];
|
||||
|
||||
// Universal
|
||||
extern const char PROGMEM FSTRING_OK[];
|
||||
extern const char PROGMEM FSTRING_EMPTY[];
|
||||
extern const char PROGMEM FSTRING_SPACE[];
|
||||
extern const char PROGMEM FSTRING_RESET[];
|
||||
extern const char PROGMEM FSTRING_CURRENT_SETTINGS[];
|
||||
|
||||
// Messages
|
||||
extern const char PROGMEM FSTRING_OSCR[];
|
||||
extern const char PROGMEM FSTRING_MODULE_NOT_ENABLED[];
|
||||
extern const char PROGMEM FSTRING_DATABASE_FILE_NOT_FOUND[];
|
||||
extern const char PROGMEM FSTRING_FILE_DOESNT_EXIST[];
|
||||
|
||||
// Cart
|
||||
extern const char PROGMEM FSTRING_READ_ROM[];
|
||||
extern const char PROGMEM FSTRING_READ_SAVE[];
|
||||
extern const char PROGMEM FSTRING_WRITE_SAVE[];
|
||||
extern const char PROGMEM FSTRING_SELECT_CART[];
|
||||
extern const char PROGMEM FSTRING_SELECT_CART_TYPE[];
|
||||
extern const char PROGMEM FSTRING_SET_SIZE[];
|
||||
extern const char PROGMEM FSTRING_REFRESH_CART[];
|
||||
extern const char PROGMEM FSTRING_MAPPER[];
|
||||
extern const char PROGMEM FSTRING_SIZE[];
|
||||
extern const char PROGMEM FSTRING_ROM_SIZE[];
|
||||
extern const char PROGMEM FSTRING_NAME[];
|
||||
extern const char PROGMEM FSTRING_CHECKSUM[];
|
||||
|
||||
#define FS(pmem_string) (reinterpret_cast<const __FlashStringHelper *>(pmem_string))
|
||||
|
||||
/**
|
||||
* Other Constants
|
||||
**/
|
||||
// Updater baud rate
|
||||
const uint16_t UPD_BAUD = 9600;
|
||||
constexpr uint16_t UPD_BAUD = 9600;
|
||||
// Clock speeds
|
||||
const unsigned long CS_16MHZ = 16000000UL;
|
||||
const unsigned long CS_8MHZ = 8000000UL;
|
||||
constexpr unsigned long CS_16MHZ = 16000000UL;
|
||||
constexpr unsigned long CS_8MHZ = 8000000UL;
|
||||
|
||||
enum CORES: uint8_t {
|
||||
# ifdef ENABLE_N64
|
||||
CORE_N64_CART,
|
||||
CORE_N64_CONTROLLER,
|
||||
# endif
|
||||
# ifdef ENABLE_SNES
|
||||
CORE_SNES,
|
||||
# endif
|
||||
# ifdef ENABLE_SFM
|
||||
CORE_SFM,
|
||||
# ifdef ENABLE_FLASH
|
||||
CORE_SFM_FLASH,
|
||||
# endif
|
||||
CORE_SFM_GAME,
|
||||
# endif
|
||||
# ifdef ENABLE_GBX
|
||||
CORE_GB,
|
||||
CORE_GBA,
|
||||
CORE_GBM,
|
||||
CORE_GB_GBSMART,
|
||||
CORE_GB_GBSMART_FLASH,
|
||||
CORE_GB_GBSMART_GAME,
|
||||
# endif
|
||||
# ifdef ENABLE_FLASH
|
||||
CORE_FLASH8,
|
||||
# ifdef ENABLE_FLASH16
|
||||
CORE_FLASH16,
|
||||
CORE_EPROM,
|
||||
# endif
|
||||
# endif
|
||||
# ifdef ENABLE_MD
|
||||
CORE_MD_CART,
|
||||
CORE_SEGA_CD,
|
||||
# endif
|
||||
# ifdef ENABLE_PCE
|
||||
CORE_PCE,
|
||||
# endif
|
||||
# ifdef ENABLE_SV
|
||||
CORE_SV,
|
||||
# endif
|
||||
# ifdef ENABLE_NES
|
||||
CORE_NES,
|
||||
# endif
|
||||
# ifdef ENABLE_SMS
|
||||
CORE_SMS,
|
||||
# endif
|
||||
# ifdef ENABLE_WS
|
||||
CORE_WS,
|
||||
# endif
|
||||
# ifdef ENABLE_NGP
|
||||
CORE_NGP,
|
||||
# endif
|
||||
# ifdef ENABLE_INTV
|
||||
CORE_INTV,
|
||||
# endif
|
||||
# ifdef ENABLE_COLV
|
||||
CORE_COL,
|
||||
# endif
|
||||
# ifdef ENABLE_VBOY
|
||||
CORE_VBOY,
|
||||
# endif
|
||||
# ifdef ENABLE_WSV
|
||||
CORE_WSV,
|
||||
# endif
|
||||
# ifdef ENABLE_PCW
|
||||
CORE_PCW,
|
||||
# endif
|
||||
# ifdef ENABLE_ODY2
|
||||
CORE_ODY2,
|
||||
# endif
|
||||
# ifdef ENABLE_ARC
|
||||
CORE_ARC,
|
||||
# endif
|
||||
# ifdef ENABLE_FAIRCHILD
|
||||
CORE_FAIRCHILD,
|
||||
# endif
|
||||
# ifdef ENABLE_SUPRACAN
|
||||
CORE_SUPRACAN,
|
||||
# endif
|
||||
# ifdef ENABLE_MSX
|
||||
CORE_MSX,
|
||||
# endif
|
||||
# ifdef ENABLE_POKE
|
||||
CORE_POKE,
|
||||
# endif
|
||||
# ifdef ENABLE_LOOPY
|
||||
CORE_LOOPY,
|
||||
# endif
|
||||
# ifdef ENABLE_C64
|
||||
CORE_C64,
|
||||
# endif
|
||||
# ifdef ENABLE_2600
|
||||
CORE_2600,
|
||||
# endif
|
||||
# ifdef ENABLE_5200
|
||||
CORE_5200,
|
||||
# endif
|
||||
# ifdef ENABLE_7800
|
||||
CORE_7800,
|
||||
# endif
|
||||
# ifdef ENABLE_VECTREX
|
||||
CORE_VECTREX,
|
||||
# endif
|
||||
# ifdef ENABLE_ST
|
||||
CORE_ST,
|
||||
# endif
|
||||
# ifdef ENABLE_GPC
|
||||
CORE_GPC,
|
||||
# endif
|
||||
CORE_MAX // Always last
|
||||
};
|
||||
|
||||
enum SYSTEM_MENU: uint8_t {
|
||||
# if defined(ENABLE_GBX)
|
||||
SYSTEM_MENU_GBX,
|
||||
# endif
|
||||
# if defined(ENABLE_NES)
|
||||
SYSTEM_MENU_NES,
|
||||
# endif
|
||||
# if defined(ENABLE_SNES)
|
||||
SYSTEM_MENU_SNES,
|
||||
# endif
|
||||
# if defined(ENABLE_N64)
|
||||
SYSTEM_MENU_N64,
|
||||
# endif
|
||||
# if defined(ENABLE_MD)
|
||||
SYSTEM_MENU_MD,
|
||||
# endif
|
||||
# if defined(ENABLE_SMS)
|
||||
SYSTEM_MENU_SMS,
|
||||
# endif
|
||||
# if defined(ENABLE_PCE)
|
||||
SYSTEM_MENU_PCE,
|
||||
# endif
|
||||
# if defined(ENABLE_WS)
|
||||
SYSTEM_MENU_WS,
|
||||
# endif
|
||||
# if defined(ENABLE_NGP)
|
||||
SYSTEM_MENU_NGP,
|
||||
# endif
|
||||
# if defined(ENABLE_INTV)
|
||||
SYSTEM_MENU_INTV,
|
||||
# endif
|
||||
# if defined(ENABLE_COLV)
|
||||
SYSTEM_MENU_COLV,
|
||||
# endif
|
||||
# if defined(ENABLE_VBOY)
|
||||
SYSTEM_MENU_VBOY,
|
||||
# endif
|
||||
# if defined(ENABLE_WSV)
|
||||
SYSTEM_MENU_WSV,
|
||||
# endif
|
||||
# if defined(ENABLE_PCW)
|
||||
SYSTEM_MENU_PCW,
|
||||
# endif
|
||||
# if defined(ENABLE_2600)
|
||||
SYSTEM_MENU_2600,
|
||||
# endif
|
||||
# if defined(ENABLE_ODY2)
|
||||
SYSTEM_MENU_ODY2,
|
||||
# endif
|
||||
# if defined(ENABLE_ARC)
|
||||
SYSTEM_MENU_ARC,
|
||||
# endif
|
||||
# if defined(ENABLE_FAIRCHILD)
|
||||
SYSTEM_MENU_FAIRCHILD,
|
||||
# endif
|
||||
# if defined(ENABLE_SUPRACAN)
|
||||
SYSTEM_MENU_SUPRACAN,
|
||||
# endif
|
||||
# if defined(ENABLE_MSX)
|
||||
SYSTEM_MENU_MSX,
|
||||
# endif
|
||||
# if defined(ENABLE_POKE)
|
||||
SYSTEM_MENU_POKE,
|
||||
# endif
|
||||
# if defined(ENABLE_LOOPY)
|
||||
SYSTEM_MENU_LOOPY,
|
||||
# endif
|
||||
# if defined(ENABLE_C64)
|
||||
SYSTEM_MENU_C64,
|
||||
# endif
|
||||
# if defined(ENABLE_5200)
|
||||
SYSTEM_MENU_5200,
|
||||
# endif
|
||||
# if defined(ENABLE_7800)
|
||||
SYSTEM_MENU_7800,
|
||||
# endif
|
||||
# if defined(ENABLE_VECTREX)
|
||||
SYSTEM_MENU_VECTREX,
|
||||
# endif
|
||||
# if defined(ENABLE_FLASH)
|
||||
SYSTEM_MENU_FLASH,
|
||||
# endif
|
||||
# if defined(ENABLE_SELFTEST)
|
||||
SYSTEM_MENU_SELFTEST,
|
||||
# endif
|
||||
SYSTEM_MENU_ABOUT,
|
||||
SYSTEM_MENU_RESET,
|
||||
|
||||
// Total number of options available.
|
||||
SYSTEM_MENU_TOTAL // Always immediately after last menu option
|
||||
};
|
||||
|
||||
// ENUM for VSELECT & 3V3FIX
|
||||
enum CLKSCALE: uint8_t {
|
||||
// Paramters to pass to setVoltage() and setClockScale()
|
||||
CLKSCALE_16MHZ = 0, // ClockScale 0 = 16MHz
|
||||
CLKSCALE_8MHZ, // ClockScale 1 = 8MHz
|
||||
};
|
||||
|
||||
// ENUM for VSELECT & 3V3FIX
|
||||
enum VOLTS: uint8_t {
|
||||
|
@ -42,16 +337,49 @@ enum VOLTS: uint8_t {
|
|||
VOLTS_UNKNOWN // Return value for all other states
|
||||
};
|
||||
|
||||
/*==== /CONSTANTS =================================================*/
|
||||
|
||||
/*==== VARIABLES ==================================================*/
|
||||
extern unsigned long clock;
|
||||
extern char ver[5];
|
||||
//extern char ver[5];
|
||||
extern VOLTS voltage;
|
||||
|
||||
# if defined(ENABLE_CONFIG)
|
||||
/**
|
||||
* Config File Stuff
|
||||
*
|
||||
* You can register GLOBAL configuration variables in this section.
|
||||
* You should put core-specific config variables in the related file.
|
||||
**/
|
||||
|
||||
extern bool useConfig;
|
||||
# ifdef ENABLE_GLOBAL_LOG
|
||||
extern bool loggingEnabled;
|
||||
# endif /* ENABLE_GLOBAL_LOG */
|
||||
# else /* !ENABLE_CONFIG */
|
||||
# ifdef ENABLE_GLOBAL_LOG
|
||||
constexpr bool loggingEnabled = true;
|
||||
# endif /* ENABLE_GLOBAL_LOG */
|
||||
# endif /* ENABLE_CONFIG */
|
||||
|
||||
/*==== /VARIABLES =================================================*/
|
||||
|
||||
/*==== FUNCTIONS ==================================================*/
|
||||
|
||||
extern void printVersionToSerial();
|
||||
extern void setClockScale(VOLTS __x);
|
||||
extern void setClockScale(CLKSCALE __x);
|
||||
extern VOLTS setVoltage(VOLTS volts);
|
||||
|
||||
# if defined(ENABLE_CONFIG)
|
||||
extern void configInit();
|
||||
extern uint8_t configFindKey(const __FlashStringHelper* key, char* value);
|
||||
extern String configGetStr(const __FlashStringHelper* key);
|
||||
extern long configGetLong(const __FlashStringHelper* key, int onFail = 0);
|
||||
# endif /* ENABLE_CONFIG */
|
||||
|
||||
/*==== /FUNCTIONS =================================================*/
|
||||
|
||||
#include "ClockedSerial.h"
|
||||
|
||||
#endif /* OSCR_H_ */
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
// Chris Covell - Tennokoe bank support
|
||||
//
|
||||
//******************************************
|
||||
#ifdef enable_PCE
|
||||
#ifdef ENABLE_PCE
|
||||
|
||||
/******************************************
|
||||
Defines
|
||||
|
@ -53,10 +53,9 @@ uint8_t tennokoe_bank_index = 0;
|
|||
static const char pceMenuItem1[] PROGMEM = "HuCARD (swapped)";
|
||||
static const char pceMenuItem2[] PROGMEM = "HuCARD(not swapped)";
|
||||
static const char pceMenuItem3[] PROGMEM = "Turbochip";
|
||||
static const char *const menuOptionspce[] PROGMEM = { pceMenuItem1, pceMenuItem2, pceMenuItem3, string_reset2 };
|
||||
static const char *const menuOptionspce[] PROGMEM = { pceMenuItem1, pceMenuItem2, pceMenuItem3, FSTRING_RESET };
|
||||
|
||||
// PCE card menu items
|
||||
static const char menuOptionspceCart_0[] PROGMEM = "Read ROM";
|
||||
static const char menuOptionspceCart_1[] PROGMEM = "Read RAM Bank %d";
|
||||
static const char menuOptionspceCart_2[] PROGMEM = "Write RAM Bank %d";
|
||||
static const char menuOptionspceCart_3[] PROGMEM = "Inc Bank Number";
|
||||
|
@ -65,8 +64,7 @@ static const char menuOptionspceCart_5[] PROGMEM = "Set %dK ROM size";
|
|||
static const char menuOptionspceCart_5_fmt[] PROGMEM = "ROM size now %dK";
|
||||
|
||||
// Turbochip menu items
|
||||
static const char pceTCMenuItem1[] PROGMEM = "Read ROM";
|
||||
static const char *const menuOptionspceTC[] PROGMEM = { pceTCMenuItem1, string_reset2 };
|
||||
static const char *const menuOptionspceTC[] PROGMEM = { FSTRING_READ_ROM, FSTRING_RESET };
|
||||
|
||||
// PCE start menu
|
||||
void pcsMenu(void) {
|
||||
|
@ -84,7 +82,7 @@ void pcsMenu(void) {
|
|||
display_Update();
|
||||
pce_internal_mode = HUCARD;
|
||||
setup_cart_PCE();
|
||||
mode = mode_PCE;
|
||||
mode = CORE_PCE;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
|
@ -93,7 +91,7 @@ void pcsMenu(void) {
|
|||
display_Update();
|
||||
pce_internal_mode = HUCARD_NOSWAP;
|
||||
setup_cart_PCE();
|
||||
mode = mode_PCE;
|
||||
mode = CORE_PCE;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
|
@ -102,7 +100,7 @@ void pcsMenu(void) {
|
|||
display_Update();
|
||||
pce_internal_mode = TURBOCHIP;
|
||||
setup_cart_PCE();
|
||||
mode = mode_PCE;
|
||||
mode = CORE_PCE;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
|
@ -314,9 +312,10 @@ uint32_t detect_rom_size_PCE(void) {
|
|||
uint32_t rom_size;
|
||||
uint8_t read_byte;
|
||||
uint8_t current_byte;
|
||||
uint8_t detect_32, detect_128, detect_256, detect_512, detect_768;
|
||||
uint8_t detect_16, detect_32, detect_128, detect_256, detect_512, detect_768;
|
||||
|
||||
//Initialize variables
|
||||
detect_16 = 0;
|
||||
detect_32 = 0;
|
||||
detect_128 = 0;
|
||||
detect_256 = 0;
|
||||
|
@ -326,16 +325,23 @@ uint32_t detect_rom_size_PCE(void) {
|
|||
//Set pins to read PC Engine cart
|
||||
pin_read_write_PCE();
|
||||
|
||||
//Confirm where mirror address start from (32KB, 128KB, 256KB, 512KB, 768KB, or 1024KB)
|
||||
//Confirm where mirror address start from (16KB, 32KB, 128KB, 256KB, 512KB, 768KB, or 1024KB)
|
||||
for (current_byte = 0; current_byte < DETECTION_SIZE; current_byte++) {
|
||||
if ((current_byte != detect_32) && (current_byte != detect_128) && (current_byte != detect_256) && (current_byte != detect_512) && (current_byte != detect_768)) {
|
||||
if ((current_byte != detect_16) && (current_byte != detect_32) && (current_byte != detect_128) && (current_byte != detect_256) && (current_byte != detect_512) && (current_byte != detect_768)) {
|
||||
//If none matched, it is 1024KB
|
||||
break;
|
||||
}
|
||||
|
||||
//read byte for 32KB, 128KB, 256KB, 512KB detection
|
||||
//read byte for 16KB, 32KB, 128KB, 256KB, 512KB detection
|
||||
read_byte = read_byte_PCE(current_byte);
|
||||
|
||||
//16KB detection
|
||||
if (current_byte == detect_16) {
|
||||
if (read_byte_PCE(current_byte + 16UL * 1024UL) == read_byte) {
|
||||
detect_16++;
|
||||
}
|
||||
}
|
||||
|
||||
//32KB detection
|
||||
if (current_byte == detect_32) {
|
||||
if (read_byte_PCE(current_byte + 32UL * 1024UL) == read_byte) {
|
||||
|
@ -374,11 +380,13 @@ uint32_t detect_rom_size_PCE(void) {
|
|||
}
|
||||
|
||||
//debug
|
||||
//sprintf(fileName, "%d %d %d %d %d", detect_32, detect_128, detect_256, detect_512, detect_768); //using filename global variable as string. Initialzed in below anyways.
|
||||
//sprintf(fileName, "%d %d %d %d %d %d", detect_16, detect_32, detect_128, detect_256, detect_512, detect_768); //using filename global variable as string. Initialzed in below anyways.
|
||||
//println_Msg(fileName);
|
||||
|
||||
//ROM size detection by result
|
||||
if (detect_32 == DETECTION_SIZE) {
|
||||
if (detect_16 == DETECTION_SIZE) {
|
||||
rom_size = 16;
|
||||
} else if (detect_32 == DETECTION_SIZE) {
|
||||
rom_size = 32;
|
||||
} else if (detect_128 == DETECTION_SIZE) {
|
||||
rom_size = 128;
|
||||
|
@ -408,7 +416,7 @@ uint32_t detect_rom_size_PCE(void) {
|
|||
if (read_byte_PCE(0x1F26) == 'P' && read_byte_PCE(0x1F27) == 'O' && read_byte_PCE(0x1F28) == 'P' && read_byte_PCE(0x1F29) == 'U' && read_byte_PCE(0x1F2A) == 'L' && read_byte_PCE(0x1F2B) == 'O' && read_byte_PCE(0x1F2C) == 'U' && read_byte_PCE(0x1F2D) == 'S') {
|
||||
rom_size = 512;
|
||||
}
|
||||
//Dinoforce (World)
|
||||
//Dinoforce (Japan)
|
||||
if (read_byte_PCE(0x15A) == 'D' && read_byte_PCE(0x15B) == 'I' && read_byte_PCE(0x15C) == 'N' && read_byte_PCE(0x15D) == 'O' && read_byte_PCE(0x15E) == '-' && read_byte_PCE(0x15F) == 'F' && read_byte_PCE(0x160) == 'O' && read_byte_PCE(0x161) == 'R' && read_byte_PCE(0x162) == 'C' && read_byte_PCE(0x163) == 'E') {
|
||||
rom_size = 512;
|
||||
}
|
||||
|
@ -590,9 +598,9 @@ void read_tennokoe_bank_PCE(int bank_index) {
|
|||
// for (int i = 0; i < 16; i++) {
|
||||
// uint8_t b = sdBuffer[c + i];
|
||||
// print_Msg_PaddedHexByte(b);
|
||||
// //print_Msg(F(" "));
|
||||
// //print_Msg(FS(FSTRING_SPACE));
|
||||
// }
|
||||
// println_Msg(F(""));
|
||||
// println_Msg(FS(FSTRING_EMPTY));
|
||||
// }
|
||||
|
||||
if (block_index == 0) {
|
||||
|
@ -601,7 +609,7 @@ void read_tennokoe_bank_PCE(int bank_index) {
|
|||
uint8_t b = sdBuffer[i];
|
||||
print_Msg_PaddedHexByte(b);
|
||||
}
|
||||
println_Msg(F(""));
|
||||
println_Msg(FS(FSTRING_EMPTY));
|
||||
}
|
||||
if (block_index == 0 && sdBuffer[2] == 0x42 && sdBuffer[3] == 0x4D) {
|
||||
if (sdBuffer[0] != 0x48 || sdBuffer[1] != 0x55) {
|
||||
|
@ -620,7 +628,7 @@ void read_tennokoe_bank_PCE(int bank_index) {
|
|||
//Close the file:
|
||||
myFile.close();
|
||||
|
||||
println_Msg(F(""));
|
||||
println_Msg(FS(FSTRING_EMPTY));
|
||||
print_STR(press_button_STR, 1);
|
||||
display_Update();
|
||||
wait();
|
||||
|
@ -717,10 +725,10 @@ void write_tennokoe_bank_PCE(int bank_index) {
|
|||
println_Msg(F("Finished"));
|
||||
|
||||
} else {
|
||||
print_Error(F("File doesn't exist"));
|
||||
print_Error(FS(FSTRING_FILE_DOESNT_EXIST));
|
||||
}
|
||||
|
||||
println_Msg(F(""));
|
||||
println_Msg(FS(FSTRING_EMPTY));
|
||||
print_STR(press_button_STR, 1);
|
||||
display_Update();
|
||||
wait();
|
||||
|
@ -743,15 +751,7 @@ void read_rom_PCE(void) {
|
|||
println_Msg(F("KB"));
|
||||
|
||||
// Get name, add extension and convert to char array for sd lib
|
||||
strcpy(fileName, "PCEROM");
|
||||
strcat(fileName, ".pce");
|
||||
|
||||
// create a new folder for the save file
|
||||
EEPROM_readAnything(0, foldern);
|
||||
sd.chdir("/");
|
||||
sprintf(folder, "PCE/ROM/%d", foldern);
|
||||
sd.mkdir(folder, true);
|
||||
sd.chdir(folder);
|
||||
createFolder("PCE", "ROM", "PCEROM", "pce");
|
||||
|
||||
print_Msg(F("Saving ROM to "));
|
||||
print_Msg(folder);
|
||||
|
@ -810,7 +810,7 @@ void read_rom_PCE(void) {
|
|||
//CRC search and rename ROM
|
||||
crc_search(fileName, folder, rom_size, crc);
|
||||
|
||||
println_Msg(F(""));
|
||||
println_Msg(FS(FSTRING_EMPTY));
|
||||
print_STR(press_button_STR, 1);
|
||||
display_Update();
|
||||
wait();
|
||||
|
@ -822,7 +822,7 @@ void pceMenu() {
|
|||
unsigned char mainMenu;
|
||||
|
||||
if (pce_internal_mode == HUCARD || pce_internal_mode == HUCARD_NOSWAP) {
|
||||
strcpy_P(menuOptions[0], menuOptionspceCart_0);
|
||||
strcpy_P(menuOptions[0], FSTRING_READ_ROM);
|
||||
sprintf_P(menuOptions[1], menuOptionspceCart_1, tennokoe_bank_index + 1);
|
||||
sprintf_P(menuOptions[2], menuOptionspceCart_2, tennokoe_bank_index + 1);
|
||||
strcpy_P(menuOptions[3], menuOptionspceCart_3);
|
||||
|
@ -832,7 +832,7 @@ void pceMenu() {
|
|||
} else {
|
||||
sprintf_P(menuOptions[5], menuOptionspceCart_5, FORCED_SIZE);
|
||||
}
|
||||
strcpy_P(menuOptions[6], string_reset2);
|
||||
strcpy_P(menuOptions[6], FSTRING_RESET);
|
||||
mainMenu = question_box(F("PCE HuCARD menu"), menuOptions, 7, 0);
|
||||
|
||||
// wait for user choice to come back from the question box menu
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
//******************************************
|
||||
// BENESSE POCKET CHALLENGE W MODULE
|
||||
//******************************************
|
||||
#ifdef enable_PCW
|
||||
#ifdef ENABLE_PCW
|
||||
|
||||
// Benesse Pocket Challenge W
|
||||
// Cartridge Pinout
|
||||
|
@ -92,7 +92,8 @@
|
|||
#define ADDR_WRITE DDRC = 0xFF // [OUTPUT]
|
||||
#define DETECTION_SIZE 64
|
||||
|
||||
boolean multipack = 0; // Multi-Pack Cart
|
||||
uint32_t rom_size;
|
||||
boolean multipack;
|
||||
byte bank0;
|
||||
byte bank1;
|
||||
|
||||
|
@ -127,21 +128,15 @@ void setup_PCW() {
|
|||
// Set Unused Pins HIGH
|
||||
PORTJ |= (1 << 0); // TIME(PJ0)
|
||||
|
||||
// Multi-Pack Cart Check
|
||||
check_multi_PCW();
|
||||
|
||||
strcpy(romName, "PCW");
|
||||
|
||||
mode = mode_PCW;
|
||||
mode = CORE_PCW;
|
||||
}
|
||||
|
||||
//******************************************
|
||||
// MENU
|
||||
//******************************************
|
||||
static const char pcwmenuItem1[] PROGMEM = "Read ROM";
|
||||
static const char pcwmenuItem2[] PROGMEM = "Read SRAM";
|
||||
static const char pcwmenuItem3[] PROGMEM = "Write SRAM";
|
||||
static const char* const menuOptionsPCW[] PROGMEM = { pcwmenuItem1, pcwmenuItem2, pcwmenuItem3, string_reset2 };
|
||||
static const char* const menuOptionsPCW[] PROGMEM = { FSTRING_READ_ROM, FSTRING_READ_SAVE, FSTRING_WRITE_SAVE, FSTRING_RESET };
|
||||
|
||||
void pcwMenu() {
|
||||
convertPgm(menuOptionsPCW, 4);
|
||||
|
@ -151,10 +146,11 @@ void pcwMenu() {
|
|||
case 0:
|
||||
// Read ROM
|
||||
sd.chdir("/");
|
||||
check_multi_PCW();
|
||||
if (multipack)
|
||||
readMultiROM_PCW();
|
||||
else
|
||||
readROM_PCW();
|
||||
readSingleROM_PCW();
|
||||
sd.chdir("/");
|
||||
break;
|
||||
|
||||
|
@ -370,232 +366,11 @@ void write_ram_byte_1B_PCW(unsigned long address, unsigned char data) {
|
|||
NAND_1B_HIGH;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
// Overload Multi-Pack Bank Switch
|
||||
//
|
||||
// Known Multi-Pack Carts (Yellow Label Carts)
|
||||
// 0BD400 [PS] (2MB Version)
|
||||
// 0BD400 [PS] (4MB Version)
|
||||
// 0BF400 [PL]
|
||||
// 1BF400 [PZ]
|
||||
// 8BD400 [CR]
|
||||
// 8BF400 [LP]
|
||||
// 9BF400 [SLP] (Undumped)
|
||||
|
||||
// Per Overload, identify multi-pack cart by reading 0x3FFA-0x3FFE
|
||||
// Multi-Pack carts are non-zero
|
||||
// 0x3FFA - Current Cartridge Bank
|
||||
// 0x3FFC - Value to Switch to Cartridge Bank 0
|
||||
// 0x3FFD - Value to Switch to Cartridge Bank 1
|
||||
// 0x3FFE - Last Value written to 0xFFFF
|
||||
|
||||
// Bank Settings for 2MB
|
||||
// Write 0x28 to 0xFFFF to read 1st half of ROM
|
||||
// Write 0x2E to 0xFFFF to read 2nd half of ROM
|
||||
|
||||
// Bank Settings for 4MB
|
||||
// Write 0x20 to 0xFFFF to read 1st half of ROM
|
||||
// Write 0x31 to 0xFFFF to read 2nd half of ROM
|
||||
|
||||
// MULTI-PACK CART CHECK
|
||||
void check_multi_PCW() {
|
||||
read_setup_PCW();
|
||||
byte tempbyte = read_rom_byte_PCW(0x3FFC); // Bank 0 Switch
|
||||
if (tempbyte) {
|
||||
bank0 = tempbyte; // Store Bank 0 Switch
|
||||
tempbyte = read_rom_byte_PCW(0x3FFD); // Bank 1 Switch
|
||||
if (tempbyte) {
|
||||
bank1 = tempbyte; // Store Bank 1 Switch
|
||||
// Check for 00s
|
||||
tempbyte = read_rom_byte_PCW(0x3FFB); // Should be 00
|
||||
if (!tempbyte) {
|
||||
tempbyte = read_rom_byte_PCW(0x3FFF); // Should be 00
|
||||
if (!tempbyte)
|
||||
multipack = 1; // Flag Multi-Cart
|
||||
else {
|
||||
bank0 = 0;
|
||||
bank1 = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void write_bank_byte_PCW(unsigned char data) {
|
||||
NAND_1A_LOW;
|
||||
NAND_1A_HIGH;
|
||||
NAND_1B_LOW;
|
||||
// Write to Address 0xFFFF
|
||||
PORTL = 0x00;
|
||||
PORTK = 0xFF; // A8-A15
|
||||
// Latch Address on AD0-AD7
|
||||
ADDR_WRITE;
|
||||
LE_HIGH; // Latch Enable
|
||||
PORTC = 0xFF; // A0-A7
|
||||
LE_LOW; // Address Latched
|
||||
// Write Data on AD0-AD7 - WE LOW ~728-736ns
|
||||
WE_LOW;
|
||||
PORTC = data;
|
||||
__asm__("nop\n\t"
|
||||
"nop\n\t"
|
||||
"nop\n\t"
|
||||
"nop\n\t"
|
||||
"nop\n\t");
|
||||
__asm__("nop\n\t"
|
||||
"nop\n\t"
|
||||
"nop\n\t"
|
||||
"nop\n\t"
|
||||
"nop\n\t");
|
||||
WE_HIGH;
|
||||
NAND_1B_HIGH;
|
||||
}
|
||||
|
||||
void switchBank_PCW(int bank) {
|
||||
if (bank == 1) { // Upper Half
|
||||
write_bank_byte_PCW(bank1);
|
||||
} else { // Lower Half (default)
|
||||
write_bank_byte_PCW(bank0);
|
||||
}
|
||||
}
|
||||
|
||||
//******************************************
|
||||
// READ ROM FUNCTIONS
|
||||
// SINGLE-PACK FUNCTIONS
|
||||
//******************************************
|
||||
|
||||
void readROM_PCW() {
|
||||
// Setup read mode
|
||||
read_setup_PCW();
|
||||
|
||||
// Detect rom size
|
||||
uint32_t rom_size = detect_rom_size_PCW();
|
||||
display_Clear();
|
||||
print_Msg(F("READING "));
|
||||
print_Msg(rom_size / 1024 / 1024);
|
||||
print_Msg("MB SINGLE-PACK");
|
||||
println_Msg(F(""));
|
||||
display_Update();
|
||||
|
||||
// Create file
|
||||
strcpy(fileName, romName);
|
||||
strcat(fileName, ".pcw");
|
||||
EEPROM_readAnything(0, foldern);
|
||||
sprintf(folder, "PCW/ROM/%d", foldern);
|
||||
sd.mkdir(folder, true);
|
||||
sd.chdir(folder);
|
||||
|
||||
print_STR(saving_to_STR, 0);
|
||||
print_Msg(folder);
|
||||
println_Msg(F("/..."));
|
||||
display_Update();
|
||||
|
||||
foldern = foldern + 1;
|
||||
EEPROM_writeAnything(0, foldern);
|
||||
|
||||
if (!myFile.open(fileName, O_RDWR | O_CREAT)) {
|
||||
print_FatalError(sd_error_STR);
|
||||
}
|
||||
|
||||
// Init progress bar
|
||||
uint32_t progress = 0;
|
||||
draw_progressbar(0, rom_size);
|
||||
|
||||
for (unsigned long address = 0; address < rom_size; address += 512) { // 4MB
|
||||
for (unsigned int x = 0; x < 512; x++) {
|
||||
sdBuffer[x] = read_rom_byte_PCW(address + x);
|
||||
}
|
||||
myFile.write(sdBuffer, 512);
|
||||
progress += 512;
|
||||
draw_progressbar(progress, rom_size);
|
||||
}
|
||||
myFile.flush();
|
||||
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("pcw.txt", 0, 1, 0);
|
||||
|
||||
// Wait for user input
|
||||
println_Msg(F(""));
|
||||
// Prints string out of the common strings array either with or without newline
|
||||
print_STR(press_button_STR, 1);
|
||||
display_Update();
|
||||
wait();
|
||||
}
|
||||
|
||||
void readMultiROM_PCW() {
|
||||
strcpy(fileName, romName);
|
||||
strcat(fileName, ".pcw");
|
||||
|
||||
EEPROM_readAnything(0, foldern);
|
||||
sprintf(folder, "PCW/ROM/%d", foldern);
|
||||
sd.mkdir(folder, true);
|
||||
sd.chdir(folder);
|
||||
|
||||
display_Clear();
|
||||
print_STR(saving_to_STR, 0);
|
||||
print_Msg(folder);
|
||||
println_Msg(F("/..."));
|
||||
display_Update();
|
||||
|
||||
foldern = foldern + 1;
|
||||
EEPROM_writeAnything(0, foldern);
|
||||
|
||||
if (!myFile.open(fileName, O_RDWR | O_CREAT)) {
|
||||
print_FatalError(sd_error_STR);
|
||||
}
|
||||
|
||||
display_Clear();
|
||||
println_Msg(F("READING MULTI-PACK"));
|
||||
println_Msg(F(""));
|
||||
display_Update();
|
||||
|
||||
// Init progress bar
|
||||
uint32_t progress = 0;
|
||||
draw_progressbar(0, 0x400000);
|
||||
|
||||
read_setup_PCW();
|
||||
// Lower Half
|
||||
switchBank_PCW(0);
|
||||
for (unsigned long address = 0; address < 0x200000; address += 512) { // 2MB
|
||||
for (unsigned int x = 0; x < 512; x++) {
|
||||
sdBuffer[x] = read_rom_byte_PCW(address + x);
|
||||
}
|
||||
myFile.write(sdBuffer, 512);
|
||||
progress += 512;
|
||||
draw_progressbar(progress, 0x400000);
|
||||
}
|
||||
|
||||
read_setup_PCW();
|
||||
// Upper Half
|
||||
switchBank_PCW(1);
|
||||
for (unsigned long address = 0x200000; address < 0x400000; address += 512) { // 2MB
|
||||
for (unsigned int x = 0; x < 512; x++) {
|
||||
sdBuffer[x] = read_rom_byte_PCW(address + x);
|
||||
}
|
||||
myFile.write(sdBuffer, 512);
|
||||
progress += 512;
|
||||
draw_progressbar(progress, 0x400000);
|
||||
}
|
||||
|
||||
myFile.flush();
|
||||
myFile.close();
|
||||
// Reset Bank
|
||||
switchBank_PCW(0);
|
||||
|
||||
// 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("pcw.txt", 0, 1, 0);
|
||||
|
||||
// Wait for user input
|
||||
println_Msg(F(""));
|
||||
// Prints string out of the common strings array either with or without newline
|
||||
print_STR(press_button_STR, 1);
|
||||
display_Update();
|
||||
wait();
|
||||
}
|
||||
|
||||
uint32_t detect_rom_size_PCW(void) {
|
||||
uint32_t rom_size;
|
||||
uint8_t read_byte;
|
||||
uint8_t current_byte;
|
||||
uint8_t detect_1m, detect_2m;
|
||||
|
@ -637,18 +412,206 @@ uint32_t detect_rom_size_PCW(void) {
|
|||
return rom_size;
|
||||
}
|
||||
|
||||
void readSingleROM_PCW() {
|
||||
// Setup read mode
|
||||
read_setup_PCW();
|
||||
|
||||
// Detect rom size
|
||||
uint32_t rom_size = detect_rom_size_PCW();
|
||||
display_Clear();
|
||||
print_Msg(F("READING "));
|
||||
print_Msg(rom_size / 1024 / 1024);
|
||||
print_Msg("MB SINGLE-PACK");
|
||||
println_Msg(FS(FSTRING_EMPTY));
|
||||
|
||||
// Create file
|
||||
createFolder("PCW", "ROM", romName, "pcw");
|
||||
|
||||
printAndIncrementFolder();
|
||||
|
||||
if (!myFile.open(fileName, O_RDWR | O_CREAT)) {
|
||||
print_FatalError(sd_error_STR);
|
||||
}
|
||||
|
||||
// Init progress bar
|
||||
uint32_t progress = 0;
|
||||
draw_progressbar(0, rom_size);
|
||||
|
||||
for (unsigned long address = 0; address < rom_size; address += 512) { // 4MB
|
||||
for (unsigned int x = 0; x < 512; x++) {
|
||||
sdBuffer[x] = read_rom_byte_PCW(address + x);
|
||||
}
|
||||
myFile.write(sdBuffer, 512);
|
||||
progress += 512;
|
||||
draw_progressbar(progress, rom_size);
|
||||
}
|
||||
myFile.flush();
|
||||
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("pcw.txt", 0, 1, 0);
|
||||
|
||||
// Wait for user input
|
||||
println_Msg(FS(FSTRING_EMPTY));
|
||||
print_STR(press_button_STR, 1);
|
||||
display_Update();
|
||||
wait();
|
||||
}
|
||||
|
||||
//******************************************
|
||||
// MULTI-PACK FUNCTIONS
|
||||
//******************************************
|
||||
|
||||
// Known Multi-Pack Carts (Yellow Label Carts)
|
||||
// 0BD400 [PS] (2MB Version)
|
||||
// 0BD400 [PS] (4MB Version)
|
||||
// 0BF400 [PL]
|
||||
// 1BF400 [PZ]
|
||||
// 8BD400 [CR]
|
||||
// 8BF400 [LP]
|
||||
// 9BF400 [SLP] (Undumped)
|
||||
|
||||
// Per Overload, identify multi-pack cart by reading 0x3FFA-0x3FFE. Multi-Pack carts are non-zero.
|
||||
// 0x3FFA - Current Cartridge Bank
|
||||
// 0x3FFC - Value to Switch to Cartridge Bank 0
|
||||
// 0x3FFD - Value to Switch to Cartridge Bank 1
|
||||
// 0x3FFE - Last Value written to 0xFFFF
|
||||
|
||||
// Bank Settings for 2MB
|
||||
// Write 0x28 to 0xFFFF to read 1st half of ROM
|
||||
// Write 0x2E to 0xFFFF to read 2nd half of ROM
|
||||
|
||||
// Bank Settings for 4MB
|
||||
// Write 0x20 to 0xFFFF to read 1st half of ROM
|
||||
// Write 0x31 to 0xFFFF to read 2nd half of ROM
|
||||
|
||||
void check_multi_PCW() {
|
||||
// init variables
|
||||
read_setup_PCW();
|
||||
multipack = 0;
|
||||
bank0 = 0;
|
||||
bank1 = 0;
|
||||
|
||||
byte tempbyte = read_rom_byte_PCW(0x3FFC); // Check for a bank 0 switch value
|
||||
if (tempbyte) {
|
||||
bank0 = tempbyte; // Store bank 0 switch value
|
||||
tempbyte = read_rom_byte_PCW(0x3FFD); // Check for a bank 1 switch value
|
||||
if (tempbyte) {
|
||||
bank1 = tempbyte; // Store bank 1 switch value
|
||||
if (!read_rom_byte_PCW(0x3FFB) && !read_rom_byte_PCW(0x3FFF)) { // Check for 00s
|
||||
multipack = 1; // Flag as multi-pack
|
||||
display_Clear();
|
||||
if ((bank0 == 0x28) && (bank1 == 0x2E)) // 2MB multi-pack cart
|
||||
rom_size = 0x200000;
|
||||
else if ((bank0 == 0x20) && (bank1 == 0x31)) // 4MB multi-pack cart
|
||||
rom_size = 0x400000;
|
||||
else { // Warn for unknown bank switch values, size set to 4MB
|
||||
println_Msg(F("Warning: Unknown cart size"));
|
||||
rom_size = 0x400000;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void write_bank_byte_PCW(unsigned char data) {
|
||||
NAND_1A_LOW;
|
||||
NAND_1A_HIGH;
|
||||
NAND_1B_LOW;
|
||||
// Write to Address 0xFFFF
|
||||
PORTL = 0x00;
|
||||
PORTK = 0xFF; // A8-A15
|
||||
// Latch Address on AD0-AD7
|
||||
ADDR_WRITE;
|
||||
LE_HIGH; // Latch Enable
|
||||
PORTC = 0xFF; // A0-A7
|
||||
LE_LOW; // Address Latched
|
||||
// Write Data on AD0-AD7 - WE LOW ~728-736ns
|
||||
WE_LOW;
|
||||
PORTC = data;
|
||||
|
||||
for (unsigned int x = 0; x < 40; x++)
|
||||
__asm__("nop\n\t");
|
||||
|
||||
WE_HIGH;
|
||||
NAND_1B_HIGH;
|
||||
}
|
||||
|
||||
void switchBank_PCW(int bank) {
|
||||
if (bank == 1) { // Upper Half
|
||||
write_bank_byte_PCW(bank1);
|
||||
} else { // Lower Half (default)
|
||||
write_bank_byte_PCW(bank0);
|
||||
}
|
||||
}
|
||||
|
||||
void readMultiROM_PCW() {
|
||||
print_Msg(F("READING "));
|
||||
print_Msg(rom_size / 1024 / 1024);
|
||||
print_Msg("MB MULTI-PACK");
|
||||
println_Msg(FS(FSTRING_EMPTY));
|
||||
|
||||
// Create file
|
||||
createFolder("PCW", "ROM", romName, "pcw");
|
||||
|
||||
printAndIncrementFolder();
|
||||
|
||||
if (!myFile.open(fileName, O_RDWR | O_CREAT)) {
|
||||
print_FatalError(sd_error_STR);
|
||||
}
|
||||
|
||||
// Init progress bar
|
||||
uint32_t progress = 0;
|
||||
draw_progressbar(0, rom_size);
|
||||
|
||||
// Lower Half
|
||||
read_setup_PCW();
|
||||
switchBank_PCW(0);
|
||||
for (unsigned long address = 0; address < (rom_size / 2); address += 512) {
|
||||
for (unsigned int x = 0; x < 512; x++) {
|
||||
sdBuffer[x] = read_rom_byte_PCW(address + x);
|
||||
}
|
||||
myFile.write(sdBuffer, 512);
|
||||
progress += 512;
|
||||
draw_progressbar(progress, rom_size);
|
||||
}
|
||||
|
||||
// Upper Half
|
||||
read_setup_PCW();
|
||||
switchBank_PCW(1);
|
||||
for (unsigned long address = 0x200000; address < (0x200000 + (rom_size / 2)); address += 512) {
|
||||
for (unsigned int x = 0; x < 512; x++) {
|
||||
sdBuffer[x] = read_rom_byte_PCW(address + x);
|
||||
}
|
||||
myFile.write(sdBuffer, 512);
|
||||
progress += 512;
|
||||
draw_progressbar(progress, rom_size);
|
||||
}
|
||||
|
||||
myFile.flush();
|
||||
myFile.close();
|
||||
|
||||
// Reset Bank
|
||||
switchBank_PCW(0);
|
||||
|
||||
// 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("pcw.txt", 0, 1, 0);
|
||||
|
||||
// Wait for user input
|
||||
println_Msg(FS(FSTRING_EMPTY));
|
||||
print_STR(press_button_STR, 1);
|
||||
display_Update();
|
||||
wait();
|
||||
}
|
||||
|
||||
//******************************************
|
||||
// SRAM FUNCTIONS
|
||||
//******************************************
|
||||
|
||||
void readSRAM_PCW() { // readSRAM_1A()
|
||||
strcpy(fileName, romName);
|
||||
strcat(fileName, ".srm");
|
||||
|
||||
EEPROM_readAnything(0, foldern);
|
||||
sprintf(folder, "PCW/SAVE/%d", foldern);
|
||||
sd.mkdir(folder, true);
|
||||
sd.chdir(folder);
|
||||
createFolder("PCW", "SAVE", romName, "srm");
|
||||
|
||||
foldern = foldern + 1;
|
||||
EEPROM_writeAnything(0, foldern);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
//******************************************
|
||||
// POKEMON MINI MODULE
|
||||
//******************************************
|
||||
#ifdef enable_POKE
|
||||
#ifdef ENABLE_POKE
|
||||
// Pokemon Mini
|
||||
// Cartridge Pinout
|
||||
// 32P 0.5mm pitch
|
||||
|
@ -79,8 +79,7 @@
|
|||
// Menu
|
||||
//******************************************
|
||||
// Base Menu
|
||||
static const char pokeMenuItem1[] PROGMEM = "Read ROM";
|
||||
static const char* const menuOptionsPOKE[] PROGMEM = { pokeMenuItem1, string_reset2 };
|
||||
static const char* const menuOptionsPOKE[] PROGMEM = { FSTRING_READ_ROM, FSTRING_RESET };
|
||||
|
||||
void pokeMenu() {
|
||||
convertPgm(menuOptionsPOKE, 2);
|
||||
|
@ -145,7 +144,7 @@ void setup_POKE() {
|
|||
|
||||
strcpy(romName, "POKEMINI");
|
||||
|
||||
mode = mode_POKE;
|
||||
mode = CORE_POKE;
|
||||
}
|
||||
|
||||
//******************************************
|
||||
|
@ -240,44 +239,29 @@ void writeData_POKE(uint32_t addr, uint8_t data) {
|
|||
//******************************************
|
||||
|
||||
void readROM_POKE() {
|
||||
strcpy(fileName, romName);
|
||||
strcat(fileName, ".min");
|
||||
|
||||
// create a new folder for storing rom file
|
||||
EEPROM_readAnything(0, foldern);
|
||||
sprintf(folder, "POKE/ROM/%d", foldern);
|
||||
sd.mkdir(folder, true);
|
||||
sd.chdir(folder);
|
||||
|
||||
display_Clear();
|
||||
print_STR(saving_to_STR, 0);
|
||||
print_Msg(folder);
|
||||
println_Msg(F("/..."));
|
||||
display_Update();
|
||||
|
||||
// open file on sdcard
|
||||
if (!myFile.open(fileName, O_RDWR | O_CREAT))
|
||||
print_FatalError(sd_error_STR);
|
||||
|
||||
// write new folder number back to EEPROM
|
||||
foldern++;
|
||||
EEPROM_writeAnything(0, foldern);
|
||||
createFolderAndOpenFile("POKE", "ROM", romName, "min");
|
||||
|
||||
// read rom
|
||||
uint32_t progress = 0;
|
||||
draw_progressbar(0, 0x80000);
|
||||
for (uint32_t addr = 0; addr < 0x80000; addr += 512) { // 512K
|
||||
for (int w = 0; w < 512; w++) {
|
||||
uint8_t temp = readData_POKE(addr + w);
|
||||
sdBuffer[w] = temp;
|
||||
}
|
||||
myFile.write(sdBuffer, 512);
|
||||
progress += 512;
|
||||
draw_progressbar(progress, 0x80000);
|
||||
}
|
||||
myFile.close();
|
||||
|
||||
calcCRC(fileName, 0x80000, NULL, 0); // 512K
|
||||
// compare dump CRC with db values
|
||||
compareCRC("pkmn.txt", 0, 1, 0);
|
||||
println_Msg(FS(FSTRING_EMPTY));
|
||||
|
||||
println_Msg(F(""));
|
||||
// Prints string out of the common strings array either with or without newline
|
||||
print_STR(press_button_STR, 1);
|
||||
display_Update();
|
||||
wait();
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -49,15 +49,14 @@ Also all the menus are stored in progmem and are only recalled to sram when need
|
|||
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};
|
||||
const char* const menuOptionsN64Controller[] PROGMEM = {N64ContMenuItem1, N64ContMenuItem2, N64ContMenuItem3, FSTRING_RESET};
|
||||
```
|
||||
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, auxiliary 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)
|
||||
if (ENABLE_OLED)
|
||||
display.print(message);
|
||||
if (enable_Serial)
|
||||
if (ENABLE_SERIAL)
|
||||
Serial.print(message);
|
||||
}
|
||||
```
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
//******************************************
|
||||
// SF MEMORY MODULE
|
||||
//******************************************
|
||||
#ifdef enable_SFM
|
||||
#ifdef ENABLE_SFM
|
||||
|
||||
/******************************************
|
||||
SF Memory Clock Source
|
||||
|
@ -29,8 +29,7 @@ byte gameAddress[8];
|
|||
// SFM menu items
|
||||
static const char sfmMenuItem1[] PROGMEM = "Game Menu";
|
||||
static const char sfmMenuItem2[] PROGMEM = "Flash Menu";
|
||||
//static const char sfmMenuItem3[] PROGMEM = "Reset"; (stored in common strings array)
|
||||
static const char* const menuOptionsSFM[] PROGMEM = { sfmMenuItem1, sfmMenuItem2, string_reset2 };
|
||||
static const char* const menuOptionsSFM[] PROGMEM = { sfmMenuItem1, sfmMenuItem2, FSTRING_RESET };
|
||||
|
||||
// SFM flash menu items
|
||||
static const char sfmFlashMenuItem1[] PROGMEM = "Read Flash";
|
||||
|
@ -42,12 +41,9 @@ static const char sfmFlashMenuItem6[] PROGMEM = "Back";
|
|||
static const char* const menuOptionsSFMFlash[] PROGMEM = { sfmFlashMenuItem1, sfmFlashMenuItem2, sfmFlashMenuItem3, sfmFlashMenuItem4, sfmFlashMenuItem5, sfmFlashMenuItem6 };
|
||||
|
||||
// SFM game menu items
|
||||
static const char sfmGameMenuItem1[] PROGMEM = "Read Sram";
|
||||
static const char sfmGameMenuItem2[] PROGMEM = "Read Game";
|
||||
static const char sfmGameMenuItem3[] PROGMEM = "Write Sram";
|
||||
static const char sfmGameMenuItem4[] PROGMEM = "Switch Game";
|
||||
//static const char sfmGameMenuItem5[] PROGMEM = "Reset"; (stored in common strings array)
|
||||
static const char* const menuOptionsSFMGame[] PROGMEM = { sfmGameMenuItem1, sfmGameMenuItem2, sfmGameMenuItem3, sfmGameMenuItem4, string_reset2 };
|
||||
static const char* const menuOptionsSFMGame[] PROGMEM = { FSTRING_READ_SAVE, sfmGameMenuItem2, FSTRING_WRITE_SAVE, sfmGameMenuItem4, FSTRING_RESET };
|
||||
|
||||
void sfmMenu() {
|
||||
// create menu with title and 3 options to choose from
|
||||
|
@ -64,7 +60,7 @@ void sfmMenu() {
|
|||
break;
|
||||
// Flash menu
|
||||
case 1:
|
||||
mode = mode_SFM_Flash;
|
||||
mode = CORE_SFM_FLASH;
|
||||
break;
|
||||
// Reset
|
||||
case 2:
|
||||
|
@ -108,7 +104,7 @@ void sfmGameMenu() {
|
|||
print_Msg(gameSubMenu + 0x80, HEX);
|
||||
println_Msg(F(" Timeout"));
|
||||
println_Msg(readBank_SFM(0, 0x2400), HEX);
|
||||
println_Msg(F(""));
|
||||
println_Msg(FS(FSTRING_EMPTY));
|
||||
print_FatalError(F("Powercycle SFM cart"));
|
||||
}
|
||||
}
|
||||
|
@ -117,7 +113,7 @@ void sfmGameMenu() {
|
|||
|
||||
// Print info
|
||||
getCartInfo_SFM();
|
||||
mode = mode_SFM_Game;
|
||||
mode = CORE_SFM_GAME;
|
||||
} else {
|
||||
// No menu so switch to only game
|
||||
// Switch to game
|
||||
|
@ -129,7 +125,7 @@ void sfmGameMenu() {
|
|||
|
||||
// Print info
|
||||
getCartInfo_SFM();
|
||||
mode = mode_SFM_Game;
|
||||
mode = CORE_SFM_GAME;
|
||||
}
|
||||
} else {
|
||||
print_Error(F("Switch to HiRom failed"));
|
||||
|
@ -193,7 +189,7 @@ void sfmGameOptions() {
|
|||
break;
|
||||
}
|
||||
if (gameSubMenu != 3) {
|
||||
println_Msg(F(""));
|
||||
println_Msg(FS(FSTRING_EMPTY));
|
||||
// Prints string out of the common strings array either with or without newline
|
||||
print_STR(press_button_STR, 1);
|
||||
display_Update();
|
||||
|
@ -201,7 +197,7 @@ void sfmGameOptions() {
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef enable_FLASH
|
||||
#ifdef ENABLE_FLASH
|
||||
void sfmFlashMenu() {
|
||||
// create menu with title and 6 options to choose from
|
||||
unsigned char flashSubMenu;
|
||||
|
@ -224,7 +220,7 @@ void sfmFlashMenu() {
|
|||
print_Msg(F("Switch to HiRom..."));
|
||||
display_Update();
|
||||
if (send_SFM(0x04) == 0x2A) {
|
||||
println_Msg(F("OK"));
|
||||
println_Msg(FS(FSTRING_OK));
|
||||
display_Update();
|
||||
|
||||
// Reset flash
|
||||
|
@ -301,7 +297,7 @@ void sfmFlashMenu() {
|
|||
print_Msg(F("Switch to HiRom..."));
|
||||
display_Update();
|
||||
if (send_SFM(0x04) == 0x2A) {
|
||||
println_Msg(F("OK"));
|
||||
println_Msg(FS(FSTRING_OK));
|
||||
display_Update();
|
||||
idFlash_SFM(0xC0);
|
||||
if (flashid == 0xc2f3) {
|
||||
|
@ -340,7 +336,7 @@ void sfmFlashMenu() {
|
|||
print_Msg(F("Switch to HiRom..."));
|
||||
display_Update();
|
||||
if (send_SFM(0x04) == 0x2A) {
|
||||
println_Msg(F("OK"));
|
||||
println_Msg(FS(FSTRING_OK));
|
||||
display_Update();
|
||||
idFlash_SFM(0xC0);
|
||||
if (flashid == 0xc2f3) {
|
||||
|
@ -391,7 +387,7 @@ void sfmFlashMenu() {
|
|||
print_Msg(F("Blankcheck..."));
|
||||
display_Update();
|
||||
if (blankcheckMapping_SFM()) {
|
||||
println_Msg(F("OK"));
|
||||
println_Msg(FS(FSTRING_OK));
|
||||
display_Update();
|
||||
} else {
|
||||
println_Msg(F("Nope"));
|
||||
|
@ -420,11 +416,11 @@ void sfmFlashMenu() {
|
|||
|
||||
// Go back
|
||||
case 5:
|
||||
mode = mode_SFM;
|
||||
mode = CORE_SFM;
|
||||
break;
|
||||
}
|
||||
if (flashSubMenu != 5) {
|
||||
println_Msg(F(""));
|
||||
println_Msg(FS(FSTRING_EMPTY));
|
||||
// Prints string out of the common strings array either with or without newline
|
||||
print_STR(press_button_STR, 1);
|
||||
display_Update();
|
||||
|
@ -577,7 +573,7 @@ void setup_SFM() {
|
|||
clockgen.output_enable(SI5351_CLK2, 0);
|
||||
clockgen.output_enable(SI5351_CLK0, 1);
|
||||
}
|
||||
#ifdef clockgen_installed
|
||||
#ifdef ENABLE_CLOCKGEN
|
||||
else {
|
||||
display_Clear();
|
||||
print_FatalError(F("Clock Generator not found"));
|
||||
|
@ -600,8 +596,8 @@ void setup_SFM() {
|
|||
// Abort, something is wrong
|
||||
if (timeout == 5) {
|
||||
println_Msg(F("Hirom All Timeout"));
|
||||
println_Msg(F(""));
|
||||
println_Msg(F(""));
|
||||
println_Msg(FS(FSTRING_EMPTY));
|
||||
println_Msg(FS(FSTRING_EMPTY));
|
||||
print_FatalError(F("Powercycle SFM cart"));
|
||||
}
|
||||
}
|
||||
|
@ -727,7 +723,7 @@ void getCartInfo_SFM() {
|
|||
if (checkcart_SFM() == 0) {
|
||||
// Checksum either corrupt or 0000
|
||||
errorLvl = 1;
|
||||
setColor_RGB(255, 0, 0);
|
||||
rgbLed(red_color);
|
||||
display_Clear();
|
||||
println_Msg(F("ERROR"));
|
||||
println_Msg(F("Rom header corrupt"));
|
||||
|
@ -739,17 +735,17 @@ void getCartInfo_SFM() {
|
|||
}
|
||||
|
||||
display_Clear();
|
||||
print_Msg(F("Name: "));
|
||||
print_Msg(FS(FSTRING_NAME));
|
||||
println_Msg(romName);
|
||||
println_Msg(F(" "));
|
||||
println_Msg(FS(FSTRING_SPACE));
|
||||
|
||||
print_Msg(F("Version: 1."));
|
||||
println_Msg(romVersion);
|
||||
|
||||
print_Msg(F("Checksum: "));
|
||||
print_Msg(FS(FSTRING_CHECKSUM));
|
||||
println_Msg(checksumStr);
|
||||
|
||||
print_Msg(F("Size: "));
|
||||
print_Msg(FS(FSTRING_SIZE));
|
||||
print_Msg(romSize);
|
||||
println_Msg(F("Mbit "));
|
||||
|
||||
|
@ -886,14 +882,7 @@ void readROM_SFM() {
|
|||
controlIn_SFM();
|
||||
|
||||
// Get name, add extension and convert to char array for sd lib
|
||||
strcpy(fileName, romName);
|
||||
strcat(fileName, ".sfc");
|
||||
|
||||
// create a new folder for the save file
|
||||
EEPROM_readAnything(0, foldern);
|
||||
sprintf(folder, "NP/%s/%d", romName, foldern);
|
||||
sd.mkdir(folder, true);
|
||||
sd.chdir(folder);
|
||||
createFolder("NP", "ROM", romName, "sfc");
|
||||
|
||||
//clear the screen
|
||||
display_Clear();
|
||||
|
@ -1641,14 +1630,14 @@ boolean unlockHirom() {
|
|||
print_Msg(F("Switch to HiRom..."));
|
||||
display_Update();
|
||||
if (send_SFM(0x04) == 0x2A) {
|
||||
println_Msg(F("OK"));
|
||||
println_Msg(FS(FSTRING_OK));
|
||||
display_Update();
|
||||
// Unlock Write Protection
|
||||
print_Msg(F("Enable Write..."));
|
||||
display_Update();
|
||||
send_SFM(0x02);
|
||||
if (readBank_SFM(0, 0x2401) == 0x4) {
|
||||
println_Msg(F("OK"));
|
||||
println_Msg(FS(FSTRING_OK));
|
||||
display_Update();
|
||||
return 1;
|
||||
} else {
|
||||
|
@ -1720,7 +1709,7 @@ void write_SFM(int startBank, uint32_t pos) {
|
|||
print_Msg(F("Blankcheck..."));
|
||||
display_Update();
|
||||
if (blankcheck_SFM(startBank)) {
|
||||
println_Msg(F("OK"));
|
||||
println_Msg(FS(FSTRING_OK));
|
||||
display_Update();
|
||||
} else {
|
||||
println_Msg(F("Nope"));
|
||||
|
@ -1733,7 +1722,7 @@ void write_SFM(int startBank, uint32_t pos) {
|
|||
print_Msg(F("Blankcheck..."));
|
||||
display_Update();
|
||||
if (blankcheck_SFM(startBank)) {
|
||||
println_Msg(F("OK"));
|
||||
println_Msg(FS(FSTRING_OK));
|
||||
display_Update();
|
||||
} else {
|
||||
print_FatalError(F("Could not erase flash"));
|
||||
|
@ -1750,7 +1739,7 @@ void write_SFM(int startBank, uint32_t pos) {
|
|||
display_Update();
|
||||
writeErrors = verifyFlash_SFM(startBank, pos);
|
||||
if (writeErrors == 0) {
|
||||
println_Msg(F("OK"));
|
||||
println_Msg(FS(FSTRING_OK));
|
||||
display_Update();
|
||||
} else {
|
||||
print_STR(error_STR, 0);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
//***********************************************************
|
||||
// SEGA MASTER SYSTEM / MARK III / GAME GEAR / SG-1000 MODULE
|
||||
//***********************************************************
|
||||
#ifdef enable_SMS
|
||||
#ifdef ENABLE_SMS
|
||||
|
||||
//******************************************
|
||||
// Menus
|
||||
|
@ -16,10 +16,7 @@ static const char SMSAdapterItem6[] PROGMEM = "SG-1000 raphnet";
|
|||
static const char* const SMSAdapterMenu[] PROGMEM = { SMSAdapterItem1, SMSAdapterItem2, SMSAdapterItem3, SMSAdapterItem4, SMSAdapterItem5, SMSAdapterItem6 };
|
||||
|
||||
// Operations menu
|
||||
static const char SMSOperationItem1[] PROGMEM = "Read Rom";
|
||||
static const char SMSOperationItem2[] PROGMEM = "Read from SRAM";
|
||||
static const char SMSOperationItem3[] PROGMEM = "Write to SRAM";
|
||||
static const char* const SMSOperationMenu[] PROGMEM = { SMSOperationItem1, SMSOperationItem2, SMSOperationItem3, string_reset2 };
|
||||
static const char* const SMSOperationMenu[] PROGMEM = { FSTRING_READ_ROM, FSTRING_READ_SAVE, FSTRING_WRITE_SAVE, FSTRING_RESET };
|
||||
|
||||
// Rom sizes menu
|
||||
static const char SMSRomSizeItem1[] PROGMEM = "8 KB";
|
||||
|
@ -103,40 +100,40 @@ void smsOperations() {
|
|||
|
||||
if (system_sms) {
|
||||
if (adapter_raphnet) {
|
||||
SMSOperation = question_box(F("SMS/MarkIII raphnet"), menuOptions, 4, 0);
|
||||
SMSOperation = question_box(FS(SMSAdapterItem1), menuOptions, 4, 0);
|
||||
} else if (adapter_retrode) {
|
||||
SMSOperation = question_box(F("SMS Retrode"), menuOptions, 4, 0);
|
||||
SMSOperation = question_box(FS(SMSAdapterItem2), menuOptions, 4, 0);
|
||||
} else if (adapter_retron) {
|
||||
SMSOperation = question_box(F("SMS Retron 3in1"), menuOptions, 4, 0);
|
||||
SMSOperation = question_box(FS(SMSAdapterItem3), menuOptions, 4, 0);
|
||||
}
|
||||
} else if (system_gg) {
|
||||
if (adapter_retrode) {
|
||||
SMSOperation = question_box(F("GameGear Retrode"), menuOptions, 4, 0);
|
||||
SMSOperation = question_box(FS(SMSAdapterItem4), menuOptions, 4, 0);
|
||||
} else if (adapter_retron) {
|
||||
SMSOperation = question_box(F("GameGear Retron 3in1"), menuOptions, 4, 0);
|
||||
SMSOperation = question_box(FS(SMSAdapterItem5), menuOptions, 4, 0);
|
||||
}
|
||||
} else if (system_sg1000) {
|
||||
SMSOperation = question_box(F("SG-1000 raphnet"), menuOptions, 1, 0);
|
||||
SMSOperation = question_box(FS(SMSAdapterItem6), menuOptions, 1, 0);
|
||||
}
|
||||
|
||||
switch (SMSOperation) {
|
||||
case 0:
|
||||
// Read ROM
|
||||
mode = mode_SMS;
|
||||
mode = CORE_SMS;
|
||||
setup_SMS();
|
||||
readROM_SMS();
|
||||
break;
|
||||
|
||||
case 1:
|
||||
// Read SRAM
|
||||
mode = mode_SMS;
|
||||
mode = CORE_SMS;
|
||||
setup_SMS();
|
||||
readSRAM_SMS();
|
||||
break;
|
||||
|
||||
case 2:
|
||||
// Write SRAM
|
||||
mode = mode_SMS;
|
||||
mode = CORE_SMS;
|
||||
setup_SMS();
|
||||
writeSRAM_SMS();
|
||||
break;
|
||||
|
@ -232,7 +229,7 @@ void writeByte_SMS(word myAddress, byte myData) {
|
|||
PORTF = myAddress & 0xFF;
|
||||
PORTK = (myAddress >> 8) & 0xFF;
|
||||
if (!adapter_retrode) {
|
||||
// CE(PH3) and OE(PH6) are connected
|
||||
// A15/M0-7(PH3) and OE(PH6) are connected
|
||||
PORTH = (PORTH & 0b11110111) | ((myAddress >> 12) & 0b00001000);
|
||||
}
|
||||
|
||||
|
@ -304,7 +301,7 @@ byte readByte_SMS(word myAddress) {
|
|||
PORTF = myAddress & 0xFF;
|
||||
PORTK = (myAddress >> 8) & 0xFF;
|
||||
if (!adapter_retrode) {
|
||||
// CE(PH3) and OE(PH6) are connected
|
||||
// A15/M0-7(PH3) and OE(PH6) are connected
|
||||
PORTH = (PORTH & 0b11110111) | ((myAddress >> 12) & 0b00001000);
|
||||
}
|
||||
|
||||
|
@ -394,7 +391,7 @@ void getCartInfo_SMS() {
|
|||
default:
|
||||
cartSize = 48 * 1024UL;
|
||||
// LED Error
|
||||
setColor_RGB(0, 0, 255);
|
||||
rgbLed(blue_color);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -421,7 +418,7 @@ void getCartInfo_SMS() {
|
|||
// print_Msg(bank);
|
||||
// print_Msg(F(" offset "));
|
||||
// print_Msg_PaddedHex32(mirror_offset + 0x7FF0);
|
||||
// println_Msg(F(""));
|
||||
// println_Msg(FS(FSTRING_EMPTY));
|
||||
|
||||
if (strcmp(romName2, romName) == 0) {
|
||||
break;
|
||||
|
@ -509,13 +506,13 @@ void getCartInfo_SMS() {
|
|||
// Display cart info
|
||||
display_Clear();
|
||||
println_Msg(F("SMS/GG header not found"));
|
||||
println_Msg(F(" "));
|
||||
print_Msg(F("Name: "));
|
||||
println_Msg(FS(FSTRING_SPACE));
|
||||
print_Msg(FS(FSTRING_NAME));
|
||||
println_Msg(romName);
|
||||
print_Msg(F("Selected Size: "));
|
||||
print_Msg(cartSize / 1024);
|
||||
println_Msg(F("KB"));
|
||||
println_Msg(F(" "));
|
||||
println_Msg(FS(FSTRING_SPACE));
|
||||
sprintf(romName, "UNKNOWN");
|
||||
}
|
||||
|
||||
|
@ -527,17 +524,17 @@ void getCartInfo_SMS() {
|
|||
} else {
|
||||
println_Msg(F("GG header info"));
|
||||
}
|
||||
println_Msg(F(" "));
|
||||
print_Msg(F("Name: "));
|
||||
println_Msg(FS(FSTRING_SPACE));
|
||||
print_Msg(FS(FSTRING_NAME));
|
||||
println_Msg(romName);
|
||||
print_Msg(F("Size: "));
|
||||
print_Msg(FS(FSTRING_SIZE));
|
||||
print_Msg(cartSize / 1024);
|
||||
println_Msg(F("KB"));
|
||||
println_Msg(F(" "));
|
||||
println_Msg(FS(FSTRING_SPACE));
|
||||
}
|
||||
|
||||
// Wait for user input
|
||||
#if (defined(enable_LCD) || defined(enable_OLED))
|
||||
#if (defined(ENABLE_LCD) || defined(ENABLE_OLED))
|
||||
// Prints string out of the common strings array either with or without newline
|
||||
print_STR(press_button_STR, 1);
|
||||
display_Update();
|
||||
|
@ -545,7 +542,7 @@ void getCartInfo_SMS() {
|
|||
#endif
|
||||
|
||||
// Turn off LED
|
||||
setColor_RGB(0, 0, 0);
|
||||
rgbLed(black_color);
|
||||
}
|
||||
|
||||
//******************************************
|
||||
|
@ -553,33 +550,15 @@ void getCartInfo_SMS() {
|
|||
//******************************************
|
||||
void readROM_SMS() {
|
||||
// Get name, add extension depending on the system and convert to char array for sd lib
|
||||
EEPROM_readAnything(0, foldern);
|
||||
strcpy(fileName, romName);
|
||||
if (system_sms) {
|
||||
strcat(fileName, ".sms");
|
||||
sprintf(folder, "SMS/ROM/%s/%d", romName, foldern);
|
||||
createFolder("SMS", "ROM", romName, "sms");
|
||||
} else if (system_gg) {
|
||||
strcat(fileName, ".gg");
|
||||
sprintf(folder, "GG/ROM/%s/%d", romName, foldern);
|
||||
createFolder("GG", "ROM", romName, "gg");
|
||||
} else {
|
||||
strcat(fileName, ".sg");
|
||||
sprintf(folder, "SG1000/ROM/%s/%d", romName, foldern);
|
||||
createFolder("SG1000", "ROM", romName, "sg");
|
||||
}
|
||||
|
||||
// Create a new folder
|
||||
sd.chdir("/");
|
||||
sd.mkdir(folder, true);
|
||||
sd.chdir(folder);
|
||||
|
||||
display_Clear();
|
||||
print_STR(saving_to_STR, 0);
|
||||
print_Msg(folder);
|
||||
println_Msg(F("/..."));
|
||||
display_Update();
|
||||
|
||||
// Write new folder number back to eeprom
|
||||
foldern = foldern + 1;
|
||||
EEPROM_writeAnything(0, foldern);
|
||||
printAndIncrementFolder(true);
|
||||
|
||||
// Open file on sd card
|
||||
if (!myFile.open(fileName, O_RDWR | O_CREAT)) {
|
||||
|
@ -619,13 +598,13 @@ void readROM_SMS() {
|
|||
// for (word xi = 0; xi < 0x100; xi++) {
|
||||
// if (xi%16==0) {
|
||||
// print_Msg_PaddedHex16(xi);
|
||||
// print_Msg(F(" "));
|
||||
// print_Msg(FS(FSTRING_SPACE));
|
||||
// }
|
||||
// print_Msg_PaddedHexByte(sdBuffer[xi]);
|
||||
// if (xi>0&&((xi+1)%16)==0) {
|
||||
// println_Msg(F(""));
|
||||
// println_Msg(FS(FSTRING_EMPTY));
|
||||
// } else {
|
||||
// print_Msg(F(" "));
|
||||
// print_Msg(FS(FSTRING_SPACE));
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
@ -649,7 +628,7 @@ void readROM_SMS() {
|
|||
compareCRC("sg1000.txt", 0, 1, 0);
|
||||
}
|
||||
|
||||
#ifdef global_log
|
||||
#ifdef ENABLE_GLOBAL_LOG
|
||||
save_log();
|
||||
#endif
|
||||
|
||||
|
@ -661,58 +640,37 @@ void readROM_SMS() {
|
|||
///*****************************************
|
||||
void readSRAM_SMS() {
|
||||
// Get name, add extension and convert to char array for sd lib
|
||||
strcpy(fileName, romName);
|
||||
strcat(fileName, ".sav");
|
||||
const char* system;
|
||||
|
||||
EEPROM_readAnything(0, foldern);
|
||||
if (system_gg) {
|
||||
sprintf(folder, "GG/SAVE/%s/%d", romName, foldern);
|
||||
system = "GG";
|
||||
} else {
|
||||
sprintf(folder, "SMS/SAVE/%s/%d", romName, foldern);
|
||||
system = "SMS";
|
||||
}
|
||||
createFolderAndOpenFile(system, "SAVE", romName, "sav");
|
||||
|
||||
// Create a new folder
|
||||
sd.chdir("/");
|
||||
sd.mkdir(folder, true);
|
||||
sd.chdir(folder);
|
||||
// Write the whole 32KB
|
||||
// When there is only 8KB of SRAM, the contents should be duplicated
|
||||
word bankSize = 16 * 1024UL;
|
||||
for (byte currBank = 0x0; currBank < 2; currBank++) {
|
||||
writeByte_SMS(0xFFFC, 0x08 | (currBank << 2));
|
||||
|
||||
display_Clear();
|
||||
print_STR(saving_to_STR, 0);
|
||||
print_Msg(folder);
|
||||
println_Msg(F("/..."));
|
||||
display_Update();
|
||||
// Blink led
|
||||
blinkLED();
|
||||
|
||||
// write new folder number back to eeprom
|
||||
foldern = foldern + 1;
|
||||
EEPROM_writeAnything(0, foldern);
|
||||
|
||||
// Create file on sd card
|
||||
if (myFile.open(fileName, O_RDWR | O_CREAT)) {
|
||||
// Write the whole 32KB
|
||||
// When there is only 8KB of SRAM, the contents should be duplicated
|
||||
word bankSize = 16 * 1024UL;
|
||||
for (byte currBank = 0x0; currBank < 2; currBank++) {
|
||||
writeByte_SMS(0xFFFC, 0x08 | (currBank << 2));
|
||||
|
||||
// Blink led
|
||||
blinkLED();
|
||||
|
||||
// Read 16KB from slot 2 which starts at 0x8000
|
||||
for (word currBuffer = 0; currBuffer < bankSize; currBuffer += 512) {
|
||||
// Fill SD buffer
|
||||
for (int currByte = 0; currByte < 512; currByte++) {
|
||||
sdBuffer[currByte] = readByte_SMS(0x8000 + currBuffer + currByte);
|
||||
}
|
||||
myFile.write(sdBuffer, 512);
|
||||
// Read 16KB from slot 2 which starts at 0x8000
|
||||
for (word currBuffer = 0; currBuffer < bankSize; currBuffer += 512) {
|
||||
// Fill SD buffer
|
||||
for (int currByte = 0; currByte < 512; currByte++) {
|
||||
sdBuffer[currByte] = readByte_SMS(0x8000 + currBuffer + currByte);
|
||||
}
|
||||
myFile.write(sdBuffer, 512);
|
||||
}
|
||||
// Close file
|
||||
myFile.close();
|
||||
print_STR(press_button_STR, 1);
|
||||
display_Update();
|
||||
} else {
|
||||
print_FatalError(sd_error_STR);
|
||||
}
|
||||
// Close file
|
||||
myFile.close();
|
||||
print_STR(press_button_STR, 1);
|
||||
display_Update();
|
||||
}
|
||||
|
||||
//**********************************************
|
||||
|
@ -740,7 +698,7 @@ void writeSRAM_SMS() {
|
|||
}
|
||||
print_Msg(F("sramSize: "));
|
||||
print_Msg(sramSize);
|
||||
println_Msg(F(""));
|
||||
println_Msg(FS(FSTRING_EMPTY));
|
||||
word bankSize = 16 * 1024;
|
||||
for (word address = 0x0; address < sramSize; address += 512) {
|
||||
byte currBank = address >= bankSize ? 1 : 0;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
//******************************************
|
||||
// SUPER NINTENDO MODULE
|
||||
//******************************************
|
||||
#ifdef enable_SNES
|
||||
#ifdef ENABLE_SNES
|
||||
|
||||
/******************************************
|
||||
Defines
|
||||
|
@ -32,41 +32,34 @@ boolean altconf = 0;
|
|||
static const char snsMenuItem1[] PROGMEM = "SNES/SFC cartridge";
|
||||
static const char snsMenuItem2[] PROGMEM = "SF Memory Cassette";
|
||||
static const char snsMenuItem3[] PROGMEM = "Satellaview BS-X";
|
||||
static const char snsMenuItem4[] PROGMEM = "Flash repro";
|
||||
#ifdef clockgen_calibration
|
||||
static const char snsMenuItem5[] PROGMEM = "Calibrate Clock";
|
||||
//static const char snsMenuItem6[] PROGMEM = "Reset"; (stored in common strings array)
|
||||
static const char* const menuOptionsSNS[] PROGMEM = { snsMenuItem1, snsMenuItem2, snsMenuItem3, snsMenuItem4, snsMenuItem5, string_reset2 };
|
||||
static const char snsMenuItem4[] PROGMEM = "Sufami Turbo";
|
||||
static const char snsMenuItem5[] PROGMEM = "Game Processor RAM";
|
||||
static const char snsMenuItem6[] PROGMEM = "Flash repro";
|
||||
#ifdef OPTION_CLOCKGEN_CALIBRATION
|
||||
static const char snsMenuItem7[] PROGMEM = "Calibrate Clock";
|
||||
static const char* const menuOptionsSNS[] PROGMEM = { snsMenuItem1, snsMenuItem2, snsMenuItem3, snsMenuItem4, snsMenuItem5, snsMenuItem6, snsMenuItem7, FSTRING_RESET };
|
||||
#else
|
||||
//static const char snsMenuItem5[] PROGMEM = "Reset"; (stored in common strings array)
|
||||
static const char* const menuOptionsSNS[] PROGMEM = { snsMenuItem1, snsMenuItem2, snsMenuItem3, snsMenuItem4, string_reset2 };
|
||||
static const char* const menuOptionsSNS[] PROGMEM = { snsMenuItem1, snsMenuItem2, snsMenuItem3, snsMenuItem4, snsMenuItem5, snsMenuItem6, FSTRING_RESET };
|
||||
#endif
|
||||
|
||||
// SNES menu items
|
||||
static const char SnesMenuItem1[] PROGMEM = "Read ROM";
|
||||
static const char SnesMenuItem2[] PROGMEM = "Read Save";
|
||||
static const char SnesMenuItem3[] PROGMEM = "Write Save";
|
||||
static const char SnesMenuItem4[] PROGMEM = "Test SRAM";
|
||||
static const char SnesMenuItem5[] PROGMEM = "Cycle cart";
|
||||
static const char SnesMenuItem6[] PROGMEM = "Force cart type";
|
||||
//static const char SnesMenuItem7[] PROGMEM = "Reset"; (stored in common strings array)
|
||||
static const char* const menuOptionsSNES[] PROGMEM = { SnesMenuItem1, SnesMenuItem2, SnesMenuItem3, SnesMenuItem4, SnesMenuItem5, SnesMenuItem6, string_reset2 };
|
||||
static const char* const menuOptionsSNES[] PROGMEM = { FSTRING_READ_ROM, FSTRING_READ_SAVE, FSTRING_WRITE_SAVE, SnesMenuItem4, FSTRING_REFRESH_CART, SnesMenuItem6, FSTRING_RESET };
|
||||
|
||||
// Manual config menu items
|
||||
static const char confMenuItem1[] PROGMEM = "Use header info";
|
||||
static const char confMenuItem2[] PROGMEM = "4MB LoROM 256K SRAM";
|
||||
static const char confMenuItem3[] PROGMEM = "4MB HiROM 64K SRAM";
|
||||
static const char confMenuItem4[] PROGMEM = "6MB ExROM 256K SRAM";
|
||||
//static const char confMenuItem5[] PROGMEM = "Reset"; (stored in common strings array)
|
||||
static const char* const menuOptionsConfManual[] PROGMEM = { confMenuItem1, confMenuItem2, confMenuItem3, confMenuItem4, string_reset2 };
|
||||
static const char* const menuOptionsConfManual[] PROGMEM = { confMenuItem1, confMenuItem2, confMenuItem3, confMenuItem4, FSTRING_RESET };
|
||||
|
||||
// Repro menu items
|
||||
static const char reproMenuItem1[] PROGMEM = "LoROM (P0)";
|
||||
static const char reproMenuItem2[] PROGMEM = "HiROM (P0)";
|
||||
static const char reproMenuItem3[] PROGMEM = "ExLoROM (P1)";
|
||||
static const char reproMenuItem4[] PROGMEM = "ExHiROM (P1)";
|
||||
//static const char reproMenuItem5[] PROGMEM = "Reset"; (stored in common strings array)
|
||||
static const char* const menuOptionsRepro[] PROGMEM = { reproMenuItem1, reproMenuItem2, reproMenuItem3, reproMenuItem4, string_reset2 };
|
||||
static const char* const menuOptionsRepro[] PROGMEM = { reproMenuItem1, reproMenuItem2, reproMenuItem3, reproMenuItem4, FSTRING_RESET };
|
||||
|
||||
// SNES repro menu
|
||||
void reproMenu() {
|
||||
|
@ -78,7 +71,7 @@ void reproMenu() {
|
|||
|
||||
// wait for user choice to come back from the question box menu
|
||||
switch (snsRepro) {
|
||||
#ifdef enable_FLASH
|
||||
#ifdef ENABLE_FLASH
|
||||
case 0:
|
||||
// LoRom
|
||||
display_Clear();
|
||||
|
@ -87,7 +80,7 @@ void reproMenu() {
|
|||
setup_Flash8();
|
||||
id_Flash8();
|
||||
wait();
|
||||
mode = mode_FLASH8;
|
||||
mode = CORE_FLASH8;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
|
@ -98,7 +91,7 @@ void reproMenu() {
|
|||
setup_Flash8();
|
||||
id_Flash8();
|
||||
wait();
|
||||
mode = mode_FLASH8;
|
||||
mode = CORE_FLASH8;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
|
@ -109,7 +102,7 @@ void reproMenu() {
|
|||
setup_Flash8();
|
||||
id_Flash8();
|
||||
wait();
|
||||
mode = mode_FLASH8;
|
||||
mode = CORE_FLASH8;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
|
@ -120,7 +113,7 @@ void reproMenu() {
|
|||
setup_Flash8();
|
||||
id_Flash8();
|
||||
wait();
|
||||
mode = mode_FLASH8;
|
||||
mode = CORE_FLASH8;
|
||||
break;
|
||||
#endif
|
||||
|
||||
|
@ -132,15 +125,15 @@ void reproMenu() {
|
|||
|
||||
// SNES start menu
|
||||
void snsMenu() {
|
||||
// create menu with title and 6 options to choose from
|
||||
// create menu with title and 7 options to choose from
|
||||
unsigned char snsCart;
|
||||
// Copy menuOptions out of progmem
|
||||
#ifdef clockgen_calibration
|
||||
convertPgm(menuOptionsSNS, 6);
|
||||
snsCart = question_box(F("Select Cart Type"), menuOptions, 6, 0);
|
||||
#ifdef OPTION_CLOCKGEN_CALIBRATION
|
||||
convertPgm(menuOptionsSNS, 8);
|
||||
snsCart = question_box(FS(FSTRING_SELECT_CART_TYPE), menuOptions, 8, 0);
|
||||
#else
|
||||
convertPgm(menuOptionsSNS, 5);
|
||||
snsCart = question_box(F("Select Cart Type"), menuOptions, 5, 0);
|
||||
convertPgm(menuOptionsSNS, 7);
|
||||
snsCart = question_box(FS(FSTRING_SELECT_CART_TYPE), menuOptions, 7, 0);
|
||||
#endif
|
||||
|
||||
// wait for user choice to come back from the question box menu
|
||||
|
@ -149,43 +142,64 @@ void snsMenu() {
|
|||
display_Clear();
|
||||
display_Update();
|
||||
setup_Snes();
|
||||
mode = mode_SNES;
|
||||
mode = CORE_SNES;
|
||||
break;
|
||||
|
||||
#ifdef enable_SFM
|
||||
#ifdef ENABLE_SFM
|
||||
case 1:
|
||||
display_Clear();
|
||||
display_Update();
|
||||
setup_SFM();
|
||||
mode = mode_SFM;
|
||||
mode = CORE_SFM;
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef enable_SV
|
||||
#ifdef ENABLE_SV
|
||||
case 2:
|
||||
display_Clear();
|
||||
display_Update();
|
||||
setup_SV();
|
||||
mode = mode_SV;
|
||||
mode = CORE_SV;
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef enable_FLASH
|
||||
#ifdef ENABLE_ST
|
||||
case 3:
|
||||
display_Clear();
|
||||
display_Update();
|
||||
setup_ST();
|
||||
mode = CORE_ST;
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_GPC
|
||||
case 4:
|
||||
display_Clear();
|
||||
display_Update();
|
||||
setup_GPC();
|
||||
mode = CORE_GPC;
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_FLASH
|
||||
case 5:
|
||||
setup_FlashVoltage();
|
||||
reproMenu();
|
||||
break;
|
||||
#endif
|
||||
|
||||
case 4:
|
||||
#ifdef clockgen_calibration
|
||||
case 6:
|
||||
#ifdef OPTION_CLOCKGEN_CALIBRATION
|
||||
clkcal();
|
||||
break;
|
||||
|
||||
case 5:
|
||||
case 7:
|
||||
#endif
|
||||
resetArduino();
|
||||
break;
|
||||
|
||||
default:
|
||||
print_MissingModule(); // does not return
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -211,7 +225,7 @@ void snesMenu() {
|
|||
compare_checksum();
|
||||
// CRC32
|
||||
compareCRC("snes.txt", 0, 1, 0);
|
||||
#ifdef global_log
|
||||
#ifdef ENABLE_GLOBAL_LOG
|
||||
save_log();
|
||||
#endif
|
||||
display_Update();
|
||||
|
@ -263,8 +277,8 @@ void snesMenu() {
|
|||
println_Msg(F("Warning:"));
|
||||
println_Msg(F("This can erase"));
|
||||
println_Msg(F("your save games"));
|
||||
println_Msg(F(""));
|
||||
println_Msg(F(""));
|
||||
println_Msg(FS(FSTRING_EMPTY));
|
||||
println_Msg(FS(FSTRING_EMPTY));
|
||||
println_Msg(F("Press any button to"));
|
||||
println_Msg(F("start sram testing"));
|
||||
display_Update();
|
||||
|
@ -321,7 +335,7 @@ void snesMenu() {
|
|||
resetArduino();
|
||||
break;
|
||||
}
|
||||
//println_Msg(F(""));
|
||||
//println_Msg(FS(FSTRING_EMPTY));
|
||||
// Prints string out of the common strings array either with or without newline
|
||||
print_STR(press_button_STR, 1);
|
||||
display_Update();
|
||||
|
@ -466,7 +480,7 @@ void setup_Snes() {
|
|||
clockgen.update_status();
|
||||
delay(500);
|
||||
}
|
||||
#ifdef clockgen_installed
|
||||
#ifdef ENABLE_CLOCKGEN
|
||||
else {
|
||||
display_Clear();
|
||||
print_FatalError(F("Clock Generator not found"));
|
||||
|
@ -726,14 +740,14 @@ void getCartInfo_SNES() {
|
|||
// Checksum either corrupt or 0000
|
||||
manualConfig = 1;
|
||||
errorLvl = 1;
|
||||
setColor_RGB(255, 0, 0);
|
||||
rgbLed(red_color);
|
||||
|
||||
display_Clear();
|
||||
println_Msg(F("ERROR"));
|
||||
println_Msg(F("Rom header corrupt"));
|
||||
println_Msg(F("or missing"));
|
||||
println_Msg(F(""));
|
||||
println_Msg(F(""));
|
||||
println_Msg(FS(FSTRING_EMPTY));
|
||||
println_Msg(FS(FSTRING_EMPTY));
|
||||
println_Msg(F("Press button for"));
|
||||
println_Msg(F("manual configuration"));
|
||||
println_Msg(F("or powercycle if SA1"));
|
||||
|
@ -744,7 +758,7 @@ void getCartInfo_SNES() {
|
|||
}
|
||||
|
||||
display_Clear();
|
||||
print_Msg(F("Title: "));
|
||||
print_Msg(FS(FSTRING_NAME));
|
||||
println_Msg(romName);
|
||||
|
||||
print_Msg(F("Revision: "));
|
||||
|
@ -759,7 +773,7 @@ void getCartInfo_SNES() {
|
|||
print_Msg(F("ExHiRom"));
|
||||
else
|
||||
print_Msg(romType);
|
||||
print_Msg(F(" "));
|
||||
print_Msg(FS(FSTRING_SPACE));
|
||||
if (romSpeed == 0)
|
||||
println_Msg(F("SlowROM"));
|
||||
else if (romSpeed == 2)
|
||||
|
@ -807,7 +821,7 @@ void getCartInfo_SNES() {
|
|||
else if (romChips == 249)
|
||||
println_Msg(F("SPC RAM RTC"));
|
||||
else
|
||||
println_Msg(F(""));
|
||||
println_Msg(FS(FSTRING_EMPTY));
|
||||
|
||||
|
||||
if (altconf)
|
||||
|
@ -832,19 +846,19 @@ void getCartInfo_SNES() {
|
|||
print_Msg(sramSize >> 3);
|
||||
println_Msg(F(" KB"));
|
||||
|
||||
print_Msg(F("Checksum: "));
|
||||
print_Msg(FS(FSTRING_CHECKSUM));
|
||||
println_Msg(checksumStr);
|
||||
display_Update();
|
||||
|
||||
// Wait for user input
|
||||
#if (defined(enable_LCD) || defined(enable_OLED))
|
||||
#if (defined(ENABLE_LCD) || defined(ENABLE_OLED))
|
||||
// Prints string out of the common strings array either with or without newline
|
||||
print_STR(press_button_STR, 1);
|
||||
display_Update();
|
||||
wait();
|
||||
#endif
|
||||
#ifdef enable_serial
|
||||
println_Msg(F(" "));
|
||||
#ifdef ENABLE_SERIAL
|
||||
println_Msg(FS(FSTRING_SPACE));
|
||||
#endif
|
||||
|
||||
// Start manual config
|
||||
|
@ -862,7 +876,7 @@ void checkAltConf(char crcStr[9]) {
|
|||
// Get cart info
|
||||
display_Clear();
|
||||
println_Msg(F("Searching database..."));
|
||||
print_Msg(F("Checksum: "));
|
||||
print_Msg(FS(FSTRING_CHECKSUM));
|
||||
println_Msg(checksumStr);
|
||||
display_Update();
|
||||
|
||||
|
@ -919,7 +933,7 @@ void checkAltConf(char crcStr[9]) {
|
|||
if (((romSize != romSize2) || (numBanks != numBanks2)) && ((romSize2 == 10) || (romSize2 == 12) || (romSize2 == 20) || (romSize2 == 24) || (romSize2 == 40) || (romSize2 == 48))) {
|
||||
// Correct size
|
||||
println_Msg(F("Correcting size"));
|
||||
print_Msg(F("Size: "));
|
||||
print_Msg(FS(FSTRING_SIZE));
|
||||
print_Msg(romSize);
|
||||
print_Msg(F(" -> "));
|
||||
print_Msg(romSize2);
|
||||
|
@ -992,6 +1006,8 @@ boolean checkcart_SNES() {
|
|||
romType = EX; // Check if ExHiROM
|
||||
} else if (romType == 0x3A) {
|
||||
romType = HI; // Check if SPC7110
|
||||
} else if (strcmp("3BB0", checksumStr) == 0) { // invalid romType due to too long ROM name (Yuyu no Quiz de GO!GO!)
|
||||
romType = LO;
|
||||
} else {
|
||||
romType &= 1; // Must be LoROM or HiROM
|
||||
}
|
||||
|
@ -1275,33 +1291,10 @@ void readROM_SNES() {
|
|||
controlIn_SNES();
|
||||
|
||||
// Get name, add extension and convert to char array for sd lib
|
||||
strcpy(fileName, romName);
|
||||
strcat(fileName, ".sfc");
|
||||
createFolderAndOpenFile("SNES", "ROM", romName, "sfc");
|
||||
|
||||
// create a new folder for the save file
|
||||
EEPROM_readAnything(0, foldern);
|
||||
sprintf(folder, "SNES/ROM/%s/%d", romName, foldern);
|
||||
sd.mkdir(folder, true);
|
||||
sd.chdir(folder);
|
||||
|
||||
//clear the screen
|
||||
display_Clear();
|
||||
print_STR(saving_to_STR, 0);
|
||||
print_Msg(folder);
|
||||
println_Msg(F("/..."));
|
||||
display_Update();
|
||||
|
||||
// write new folder number back to eeprom
|
||||
foldern = foldern + 1;
|
||||
EEPROM_writeAnything(0, foldern);
|
||||
|
||||
//open file on sd card
|
||||
if (!myFile.open(fileName, O_RDWR | O_CREAT)) {
|
||||
print_FatalError(create_file_STR);
|
||||
}
|
||||
|
||||
//Dump Derby Stallion '96 (Japan) Actual Size is 24Mb
|
||||
if ((romType == LO) && (numBanks == 96) && (strcmp("CC86", checksumStr) == 0)) {
|
||||
//Dump Derby Stallion '96 (Japan) and Sound Novel Tsukuru (Japan) - Actual Size is 24Mb
|
||||
if ((romType == LO) && (numBanks == 96) && ((strcmp("CC86", checksumStr) == 0) || (strcmp("A77B", checksumStr) == 0))) {
|
||||
// Read Banks 0x00-0x3F for the 1st/2nd MB
|
||||
for (int currBank = 0; currBank < 64; currBank++) {
|
||||
// Dump the bytes to SD 512B at a time
|
||||
|
@ -1433,7 +1426,7 @@ void readROM_SNES() {
|
|||
display_Update();
|
||||
readHiRomBanks(240, 256, &myFile);
|
||||
}
|
||||
//println_Msg(F(""));
|
||||
//println_Msg(FS(FSTRING_EMPTY));
|
||||
display_Clear(); // need more space due to the 4 progress bars
|
||||
|
||||
// Return mapping registers to initial settings...
|
||||
|
@ -1632,7 +1625,7 @@ void writeSRAM(boolean browseFile) {
|
|||
display_Update();
|
||||
|
||||
} else {
|
||||
print_Error(F("File doesnt exist"));
|
||||
print_Error(FS(FSTRING_FILE_DOESNT_EXIST));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1641,14 +1634,7 @@ void readSRAM() {
|
|||
controlIn_SNES();
|
||||
|
||||
// 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(0, foldern);
|
||||
sprintf(folder, "SNES/SAVE/%s/%d", romName, foldern);
|
||||
sd.mkdir(folder, true);
|
||||
sd.chdir(folder);
|
||||
createFolder("SNES", "SAVE", romName, "srm");
|
||||
|
||||
// write new folder number back to eeprom
|
||||
foldern = foldern + 1;
|
||||
|
@ -2233,7 +2219,7 @@ boolean eraseSRAM(byte b) {
|
|||
}
|
||||
}
|
||||
if (writeErrors == 0) {
|
||||
println_Msg(F("OK"));
|
||||
println_Msg(FS(FSTRING_OK));
|
||||
return 1;
|
||||
} else {
|
||||
println_Msg(F("ERROR"));
|
||||
|
|
190
Cart_Reader/ST.ino
Normal file
190
Cart_Reader/ST.ino
Normal file
|
@ -0,0 +1,190 @@
|
|||
/******************************************
|
||||
SUPER FAMICOM SUFAMI TURBO MODULE
|
||||
******************************************/
|
||||
#ifdef ENABLE_ST
|
||||
|
||||
/******************************************
|
||||
Menu
|
||||
*****************************************/
|
||||
// Sufami Turbo menu items
|
||||
static const char stMenuItem1[] PROGMEM = "Read cart in Slot A";
|
||||
static const char stMenuItem2[] PROGMEM = "Read cart in Slot B";
|
||||
static const char* const menuOptionsST[] PROGMEM = { stMenuItem1, stMenuItem2, FSTRING_RESET };
|
||||
|
||||
void stMenu() {
|
||||
// Create ST menu with title and 3 options to choose from
|
||||
unsigned char mainMenu;
|
||||
convertPgm(menuOptionsST, 3);
|
||||
mainMenu = question_box(F("Sufami Turbo"), menuOptions, 3, 0);
|
||||
|
||||
// Wait for user choice to come back from the question box menu
|
||||
switch (mainMenu) {
|
||||
// Read cart in ST slot A
|
||||
case 0:
|
||||
readSlot(0);
|
||||
break;
|
||||
|
||||
// Read cart in ST slot B
|
||||
case 1:
|
||||
readSlot(1);
|
||||
break;
|
||||
|
||||
// Reset
|
||||
case 2:
|
||||
resetArduino();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************
|
||||
Setup
|
||||
*****************************************/
|
||||
void setup_ST() {
|
||||
// Request 5V
|
||||
setVoltage(VOLTS_SET_5V);
|
||||
|
||||
// Set cicrstPin(PG1) to Output
|
||||
DDRG |= (1 << 1);
|
||||
// Output a high signal until we're ready to start
|
||||
PORTG |= (1 << 1);
|
||||
// Set cichstPin(PG0) to Input
|
||||
DDRG &= ~(1 << 0);
|
||||
|
||||
// Set Address Pins to Output
|
||||
//A0-A7
|
||||
DDRF = 0xFF;
|
||||
//A8-A15
|
||||
DDRK = 0xFF;
|
||||
//BA0-BA7
|
||||
DDRL = 0xFF;
|
||||
//PA0-PA7
|
||||
DDRA = 0xFF;
|
||||
|
||||
// Set Control Pins to Output RST(PH0) CS(PH3) WR(PH5) RD(PH6)
|
||||
DDRH |= (1 << 0) | (1 << 3) | (1 << 5) | (1 << 6);
|
||||
// Switch RST(PH0) and WR(PH5) to HIGH
|
||||
PORTH |= (1 << 0) | (1 << 5);
|
||||
// Switch CS(PH3) and RD(PH6) to LOW
|
||||
PORTH &= ~((1 << 3) | (1 << 6));
|
||||
// Set Refresh(PE5) to Output
|
||||
DDRE |= (1 << 5);
|
||||
// Switch Refresh(PE5) to LOW (needed for SA-1)
|
||||
PORTE &= ~(1 << 5);
|
||||
// Set CPU Clock(PH1) to Output
|
||||
DDRH |= (1 << 1);
|
||||
// Set IRQ(PH4) to Input
|
||||
DDRH &= ~(1 << 4);
|
||||
// Set expand(PG5) to Input
|
||||
DDRG &= ~(1 << 5);
|
||||
// Set Data Pins (D0-D7) to Input
|
||||
DDRC = 0x00;
|
||||
// Unused pins
|
||||
// Set wram(PE4) to Output
|
||||
DDRE |= (1 << 4);
|
||||
// Set pawr(PJ1) to Output
|
||||
DDRJ |= (1 << 1);
|
||||
// Set pard(PJ0) to Output
|
||||
DDRJ |= (1 << 0);
|
||||
|
||||
//Check if Sufami Turbo adapter is inserted
|
||||
if (!getHeader(0)) {
|
||||
display_Clear();
|
||||
println_Msg(F("Sufami Turbo adapter"));
|
||||
println_Msg(F("was not found."));
|
||||
display_Update();
|
||||
wait();
|
||||
resetArduino();
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************
|
||||
ROM Functions
|
||||
******************************************/
|
||||
// Verify if 'BANDAI' header is present in specified bank
|
||||
bool getHeader(unsigned int bank) {
|
||||
byte snesHeader[16];
|
||||
PORTL = bank;
|
||||
|
||||
// Read first bytes
|
||||
for (uint16_t c = 0, currByte = 0; c < 16; c++, currByte++) {
|
||||
PORTF = (currByte & 0xFF);
|
||||
PORTK = ((currByte >> 8) & 0xFF);
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
snesHeader[c] = PINC;
|
||||
}
|
||||
|
||||
// Format internal name
|
||||
buildRomName(romName, &snesHeader[0], 14);
|
||||
|
||||
// Check if 'BANDAI' header is present
|
||||
if (strncmp(romName, "BANDAI SFC-ADX", 14) == 0)
|
||||
return(1);
|
||||
else
|
||||
return(0);
|
||||
}
|
||||
|
||||
// Select the slot to use and detect cart size
|
||||
void readSlot(bool cartSlot) {
|
||||
// Set control
|
||||
dataIn();
|
||||
controlIn_SNES();
|
||||
sd.chdir("/");
|
||||
display_Clear();
|
||||
|
||||
if(!cartSlot) { // Slot A was selected
|
||||
if (getHeader(32)) { // Look for a cart in slot A
|
||||
if (getHeader(48)) // Look for mirrored data in slot A
|
||||
readRom_ST(32,48); // Dump 512KB cart
|
||||
else
|
||||
readRom_ST(32,64); // Dump 1MB cart
|
||||
}
|
||||
else {
|
||||
println_Msg(F("No cart detected in Slot A"));
|
||||
display_Update();
|
||||
wait();
|
||||
}
|
||||
}
|
||||
else { // Slot B was selected
|
||||
if (getHeader(64)) { // Look for a cart in slot B
|
||||
if (getHeader(80)) // Look for mirrored data in slot B
|
||||
readRom_ST(64,80); // Dump 512KB cart
|
||||
else
|
||||
readRom_ST(64,96); // Dump 1MB cart
|
||||
}
|
||||
else {
|
||||
println_Msg(F("No cart detected in Slot B"));
|
||||
display_Update();
|
||||
wait();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Read ST rom to SD card
|
||||
void readRom_ST(unsigned int bankStart, unsigned int bankEnd) {
|
||||
// create a new folder to save rom file
|
||||
createFolderAndOpenFile("ST", "ROM", "SUFAMI_TURBO", "st");
|
||||
|
||||
// Read specified banks
|
||||
readLoRomBanks(bankStart + 0x80, bankEnd + 0x80, &myFile);
|
||||
|
||||
// Close file:
|
||||
myFile.close();
|
||||
|
||||
// Compare dump CRC with db values
|
||||
compareCRC("st.txt", 0, 1, 0);
|
||||
|
||||
println_Msg(FS(FSTRING_EMPTY));
|
||||
print_STR(press_button_STR, 1);
|
||||
display_Update();
|
||||
wait();
|
||||
}
|
||||
#endif
|
||||
|
||||
//******************************************
|
||||
// End of File
|
||||
//******************************************
|
|
@ -2,19 +2,16 @@
|
|||
// Super A'can MODULE
|
||||
// Only tested with HW3 and HW5
|
||||
//******************************************
|
||||
#ifdef enable_SUPRACAN
|
||||
#ifdef ENABLE_SUPRACAN
|
||||
|
||||
/******************************************
|
||||
Menu
|
||||
*****************************************/
|
||||
static const char acanMenuItem1[] PROGMEM = "Read Rom";
|
||||
static const char acanMenuItem2[] PROGMEM = "Read Save";
|
||||
static const char acanMenuItem3[] PROGMEM = "Write Save";
|
||||
static const char acanMenuItem4[] PROGMEM = "Read UM6650";
|
||||
static const char acanMenuItem5[] PROGMEM = "Write UM6650";
|
||||
static const char acanMenuItem6[] PROGMEM = "Flash repro";
|
||||
|
||||
static const char *const menuOptionsAcan[] PROGMEM = { acanMenuItem1, acanMenuItem2, acanMenuItem3, acanMenuItem4, acanMenuItem5, string_reset2, acanMenuItem6 };
|
||||
static const char *const menuOptionsAcan[] PROGMEM = { FSTRING_READ_ROM, FSTRING_READ_SAVE, FSTRING_WRITE_SAVE, acanMenuItem4, acanMenuItem5, FSTRING_RESET, acanMenuItem6 };
|
||||
|
||||
void setup_SuprAcan() {
|
||||
// Request 5V
|
||||
|
@ -82,7 +79,7 @@ void setup_SuprAcan() {
|
|||
clockgen.update_status();
|
||||
delay(500);
|
||||
}
|
||||
#ifdef clockgen_installed
|
||||
#ifdef ENABLE_CLOCKGEN
|
||||
else {
|
||||
print_FatalError(F("Clock Generator not found"));
|
||||
}
|
||||
|
@ -142,7 +139,7 @@ void suprAcanMenu() {
|
|||
}
|
||||
}
|
||||
|
||||
println_Msg(F(""));
|
||||
println_Msg(FS(FSTRING_EMPTY));
|
||||
print_STR(press_button_STR, 1);
|
||||
display_Update();
|
||||
wait();
|
||||
|
@ -151,23 +148,7 @@ void suprAcanMenu() {
|
|||
static void readROM_Acan() {
|
||||
uint32_t crc32 = 0xffffffff;
|
||||
|
||||
EEPROM_readAnything(0, foldern);
|
||||
snprintf(folder, FILEPATH_LENGTH, "/ACAN/ROM/%d", foldern);
|
||||
|
||||
display_Clear();
|
||||
print_STR(saving_to_STR, 0);
|
||||
print_Msg(folder);
|
||||
println_Msg(F("/..."));
|
||||
display_Update();
|
||||
|
||||
sd.mkdir(folder, true);
|
||||
sd.chdir(folder);
|
||||
|
||||
if (!myFile.open("rom.bin", O_RDWR | O_CREAT))
|
||||
print_FatalError(create_file_STR);
|
||||
|
||||
foldern++;
|
||||
EEPROM_writeAnything(0, foldern);
|
||||
createFolderAndOpenFile("/ACAN", "ROM", "rom", "bin");
|
||||
|
||||
draw_progressbar(0, cartSize);
|
||||
|
||||
|
@ -190,29 +171,12 @@ static void readROM_Acan() {
|
|||
|
||||
print_Msg(F("CRC32: "));
|
||||
print_Msg_PaddedHex32(crc32);
|
||||
println_Msg(F(""));
|
||||
println_Msg(FS(FSTRING_EMPTY));
|
||||
print_STR(done_STR, 1);
|
||||
}
|
||||
|
||||
static void readSRAM_Acan() {
|
||||
// create a new folder for storing rom file
|
||||
EEPROM_readAnything(0, foldern);
|
||||
snprintf(folder, FILEPATH_LENGTH, "/ACAN/SAVE/%d", foldern);
|
||||
|
||||
display_Clear();
|
||||
print_STR(saving_to_STR, 0);
|
||||
print_Msg(folder);
|
||||
println_Msg(F("/..."));
|
||||
display_Update();
|
||||
|
||||
sd.mkdir(folder, true);
|
||||
sd.chdir(folder);
|
||||
|
||||
if (!myFile.open("save.bin", O_RDWR | O_CREAT))
|
||||
print_FatalError(create_file_STR);
|
||||
|
||||
foldern++;
|
||||
EEPROM_writeAnything(0, foldern);
|
||||
createFolderAndOpenFile("/ACAN", "SAVE", "save", "bin");
|
||||
|
||||
dataIn_MD();
|
||||
for (uint32_t i = 0; i < 0x10000; i += 1024) {
|
||||
|
@ -235,7 +199,7 @@ static void writeSRAM_Acan() {
|
|||
display_Clear();
|
||||
|
||||
if (!myFile.open(filePath, O_READ)) {
|
||||
print_Error(F("File doesn't exist"));
|
||||
print_Error(FS(FSTRING_FILE_DOESNT_EXIST));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -263,7 +227,7 @@ static void verifySRAM_Acan() {
|
|||
display_Update();
|
||||
|
||||
if (!myFile.open(filePath, O_READ)) {
|
||||
print_Error(F("File doesn't exist"));
|
||||
print_Error(FS(FSTRING_FILE_DOESNT_EXIST));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -293,24 +257,7 @@ static void verifySRAM_Acan() {
|
|||
}
|
||||
|
||||
static void readUM6650() {
|
||||
// create a new folder for storing rom file
|
||||
EEPROM_readAnything(0, foldern);
|
||||
snprintf(folder, sizeof(folder), "/ACAN/UM6650/%d", foldern);
|
||||
|
||||
display_Clear();
|
||||
print_STR(saving_to_STR, 0);
|
||||
print_Msg(folder);
|
||||
println_Msg(F("/..."));
|
||||
display_Update();
|
||||
|
||||
sd.mkdir(folder, true);
|
||||
sd.chdir(folder);
|
||||
|
||||
if (!myFile.open("UM6650.bin", O_RDWR | O_CREAT))
|
||||
print_FatalError(create_file_STR);
|
||||
|
||||
foldern++;
|
||||
EEPROM_writeAnything(0, foldern);
|
||||
createFolderAndOpenFile("/ACAN", "UM6650", "UM6650", "bin");
|
||||
|
||||
for (uint16_t i = 0; i < 256; i++) {
|
||||
dataOut_MD();
|
||||
|
@ -331,7 +278,7 @@ static void verifyUM6650() {
|
|||
display_Update();
|
||||
|
||||
if (!myFile.open(filePath, O_READ)) {
|
||||
print_Error(F("File doesn't exist"));
|
||||
print_Error(FS(FSTRING_FILE_DOESNT_EXIST));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -368,7 +315,7 @@ static void writeUM6650() {
|
|||
display_Clear();
|
||||
|
||||
if (!myFile.open(filePath, O_READ)) {
|
||||
print_Error(F("File doesn't exist"));
|
||||
print_Error(FS(FSTRING_FILE_DOESNT_EXIST));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -403,7 +350,7 @@ static void flashCart_Acan() {
|
|||
display_Clear();
|
||||
|
||||
if (!myFile.open(filePath, O_READ)) {
|
||||
print_Error(F("File doesn't exist"));
|
||||
print_Error(FS(FSTRING_FILE_DOESNT_EXIST));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -482,7 +429,7 @@ static void checkRomExist_Acan() {
|
|||
|
||||
cartSize = getRomSize_Acan();
|
||||
romSize = cartSize >> 17;
|
||||
mode = mode_SUPRACAN;
|
||||
mode = CORE_SUPRACAN;
|
||||
|
||||
if (cartSize == 0)
|
||||
print_Error(F("Unable to find rom signature..."));
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
// Revision 1.0.0 October 22nd 2018
|
||||
// Added BSX Sram, copied from skamans enhanced sketch //sanni
|
||||
//******************************************
|
||||
#ifdef enable_SV
|
||||
#ifdef ENABLE_SV
|
||||
|
||||
/******************************************
|
||||
Satellaview 8M Memory Pack
|
||||
|
@ -37,8 +37,7 @@ static const char svFlashMenuItem1[] PROGMEM = "Read Memory Pack";
|
|||
static const char svFlashMenuItem2[] PROGMEM = "Write Memory Pack";
|
||||
static const char svFlashMenuItem3[] PROGMEM = "Read BS-X Sram";
|
||||
static const char svFlashMenuItem4[] PROGMEM = "Write BS-X Sram";
|
||||
static const char svFlashMenuItem5[] PROGMEM = "Back";
|
||||
static const char* const menuOptionsSVFlash[] PROGMEM = { svFlashMenuItem1, svFlashMenuItem2, svFlashMenuItem3, svFlashMenuItem4, svFlashMenuItem5 };
|
||||
static const char* const menuOptionsSVFlash[] PROGMEM = { svFlashMenuItem1, svFlashMenuItem2, svFlashMenuItem3, svFlashMenuItem4, FSTRING_RESET };
|
||||
|
||||
|
||||
void svMenu() {
|
||||
|
@ -122,7 +121,7 @@ void setup_SV() {
|
|||
clockgen.output_enable(SI5351_CLK1, 0);
|
||||
clockgen.output_enable(SI5351_CLK2, 1);
|
||||
}
|
||||
#ifdef clockgen_installed
|
||||
#ifdef ENABLE_CLOCKGEN
|
||||
else {
|
||||
display_Clear();
|
||||
print_FatalError(F("Clock Generator not found"));
|
||||
|
@ -289,13 +288,7 @@ void readSRAM_SV() {
|
|||
controlIn_SNES();
|
||||
|
||||
// Get name, add extension and convert to char array for sd lib
|
||||
strcpy(fileName, "BSX.srm");
|
||||
|
||||
// create a new folder for the save file
|
||||
EEPROM_readAnything(0, foldern);
|
||||
sprintf(folder, "SNES/SAVE/BSX/%d", foldern);
|
||||
sd.mkdir(folder, true);
|
||||
sd.chdir(folder);
|
||||
createFolder("SNES", "SAVE", "BSX", "srm");
|
||||
|
||||
// write new folder number back to eeprom
|
||||
foldern = foldern + 1;
|
||||
|
@ -374,7 +367,7 @@ void writeSRAM_SV() {
|
|||
println_Msg(F("SRAM writing finished"));
|
||||
display_Update();
|
||||
} else {
|
||||
print_Error(F("File doesnt exist"));
|
||||
print_Error(FS(FSTRING_FILE_DOESNT_EXIST));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -420,29 +413,7 @@ void readROM_SV() {
|
|||
controlIn_SNES();
|
||||
|
||||
// Get name, add extension and convert to char array for sd lib
|
||||
strcpy(fileName, "MEMPACK.bs");
|
||||
|
||||
// create a new folder for the save file
|
||||
EEPROM_readAnything(0, foldern);
|
||||
sprintf(folder, "SNES/ROM/%s/%d", "MEMPACK", foldern);
|
||||
sd.mkdir(folder, true);
|
||||
sd.chdir(folder);
|
||||
|
||||
//clear the screen
|
||||
display_Clear();
|
||||
print_STR(saving_to_STR, 0);
|
||||
print_Msg(folder);
|
||||
println_Msg(F("/..."));
|
||||
display_Update();
|
||||
|
||||
// write new folder number back to eeprom
|
||||
foldern = foldern + 1;
|
||||
EEPROM_writeAnything(0, foldern);
|
||||
|
||||
//open file on sd card
|
||||
if (!myFile.open(fileName, O_RDWR | O_CREAT)) {
|
||||
print_FatalError(create_file_STR);
|
||||
}
|
||||
createFolderAndOpenFile("SNES", "ROM", "MEMPACK", "bs");
|
||||
|
||||
// Read Banks
|
||||
for (int currBank = 0x40; currBank < 0x50; currBank++) {
|
||||
|
@ -517,7 +488,7 @@ void writeROM_SV(void) {
|
|||
draw_progressbar(((currBank - 0xC0) * 0x10000), 0x100000);
|
||||
for (long currByte = 0; currByte < 65536; currByte++) {
|
||||
if (0xFF != readBank_SV(currBank, currByte)) {
|
||||
println_Msg(F(""));
|
||||
println_Msg(FS(FSTRING_EMPTY));
|
||||
println_Msg(F("Erase failed"));
|
||||
display_Update();
|
||||
myFile.close();
|
||||
|
@ -560,7 +531,7 @@ void writeROM_SV(void) {
|
|||
draw_progressbar(((currBank - 0xC0) * 0x10000), 0x100000);
|
||||
for (long currByte = 0; currByte < 65536; currByte++) {
|
||||
if (myFile.read() != readBank_SV(currBank, currByte)) {
|
||||
println_Msg(F(""));
|
||||
println_Msg(FS(FSTRING_EMPTY));
|
||||
println_Msg(F("Verify failed"));
|
||||
display_Update();
|
||||
myFile.close();
|
||||
|
@ -578,7 +549,7 @@ void writeROM_SV(void) {
|
|||
wait();
|
||||
|
||||
} else {
|
||||
print_Error(F("File doesn't exist"));
|
||||
print_Error(FS(FSTRING_FILE_DOESNT_EXIST));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
//******************************************
|
||||
// VIRTUALBOY MODULE
|
||||
//******************************************
|
||||
#ifdef enable_VBOY
|
||||
#ifdef ENABLE_VBOY
|
||||
// Nintendo VirtualBoy
|
||||
// Cartridge Pinout
|
||||
// 60P 2.00mm pitch connector
|
||||
|
@ -89,7 +89,7 @@ void setup_VBOY() {
|
|||
|
||||
getCartInfo_VB();
|
||||
|
||||
mode = mode_VBOY;
|
||||
mode = CORE_VBOY;
|
||||
}
|
||||
|
||||
//******************************************
|
||||
|
@ -97,11 +97,7 @@ void setup_VBOY() {
|
|||
//******************************************
|
||||
|
||||
// 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"; (stored in common strings array)
|
||||
static const char* const menuOptionsVBOY[] PROGMEM = { vboyMenuItem1, vboyMenuItem2, vboyMenuItem3, string_reset2 };
|
||||
static const char* const menuOptionsVBOY[] PROGMEM = { FSTRING_READ_ROM, FSTRING_READ_SAVE, FSTRING_WRITE_SAVE, FSTRING_RESET };
|
||||
|
||||
void vboyMenu() {
|
||||
convertPgm(menuOptionsVBOY, 4);
|
||||
|
@ -127,7 +123,7 @@ void vboyMenu() {
|
|||
} else {
|
||||
print_Error(F("Cart has no SRAM"));
|
||||
}
|
||||
#if (defined(enable_OLED) || defined(enable_LCD))
|
||||
#if (defined(ENABLE_OLED) || defined(ENABLE_LCD))
|
||||
// Wait for user input
|
||||
// Prints string out of the common strings array either with or without newline
|
||||
print_STR(press_button_STR, 1);
|
||||
|
@ -157,7 +153,7 @@ void vboyMenu() {
|
|||
} else {
|
||||
print_Error(F("Cart has no SRAM"));
|
||||
}
|
||||
#if (defined(enable_OLED) || defined(enable_LCD))
|
||||
#if (defined(ENABLE_OLED) || defined(ENABLE_LCD))
|
||||
// Wait for user input
|
||||
// Prints string out of the common strings array either with or without newline
|
||||
print_STR(press_button_STR, 1);
|
||||
|
@ -384,10 +380,10 @@ void getCartInfo_VB() {
|
|||
|
||||
display_Clear();
|
||||
println_Msg(F("Cart Info"));
|
||||
println_Msg(F(" "));
|
||||
print_Msg(F("Name: "));
|
||||
println_Msg(FS(FSTRING_SPACE));
|
||||
print_Msg(FS(FSTRING_NAME));
|
||||
println_Msg(romName);
|
||||
print_Msg(F("Size: "));
|
||||
print_Msg(FS(FSTRING_SIZE));
|
||||
print_Msg(cartSize * 8 / 1024 / 1024);
|
||||
println_Msg(F(" MBit"));
|
||||
print_Msg(F("Sram: "));
|
||||
|
@ -396,9 +392,9 @@ void getCartInfo_VB() {
|
|||
println_Msg(F(" KBit"));
|
||||
} else
|
||||
println_Msg(F("None"));
|
||||
println_Msg(F(" "));
|
||||
println_Msg(FS(FSTRING_SPACE));
|
||||
|
||||
#if (defined(enable_OLED) || defined(enable_LCD))
|
||||
#if (defined(ENABLE_OLED) || defined(ENABLE_LCD))
|
||||
// Wait for user input
|
||||
// Prints string out of the common strings array either with or without newline
|
||||
print_STR(press_button_STR, 1);
|
||||
|
@ -414,26 +410,7 @@ void getCartInfo_VB() {
|
|||
void readROM_VB() {
|
||||
dataIn_VB();
|
||||
|
||||
strcpy(fileName, romName);
|
||||
strcat(fileName, ".vb");
|
||||
|
||||
EEPROM_readAnything(0, foldern);
|
||||
sprintf(folder, "VBOY/ROM/%s/%d", romName, foldern);
|
||||
sd.mkdir(folder, true);
|
||||
sd.chdir(folder);
|
||||
|
||||
display_Clear();
|
||||
print_STR(saving_to_STR, 0);
|
||||
print_Msg(folder);
|
||||
println_Msg(F("/..."));
|
||||
display_Update();
|
||||
|
||||
foldern = foldern + 1;
|
||||
EEPROM_writeAnything(0, foldern);
|
||||
|
||||
if (!myFile.open(fileName, O_RDWR | O_CREAT)) {
|
||||
print_FatalError(sd_error_STR);
|
||||
}
|
||||
createFolderAndOpenFile("VBOY", "ROM", romName, "vb");
|
||||
|
||||
word d = 0;
|
||||
uint32_t progress = 0;
|
||||
|
@ -478,9 +455,9 @@ void readROM_VB() {
|
|||
// 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))
|
||||
#if (defined(ENABLE_OLED) || defined(ENABLE_LCD))
|
||||
// Wait for user input
|
||||
println_Msg(F(""));
|
||||
println_Msg(FS(FSTRING_EMPTY));
|
||||
// Prints string out of the common strings array either with or without newline
|
||||
print_STR(press_button_STR, 1);
|
||||
display_Update();
|
||||
|
@ -517,13 +494,7 @@ void writeSRAM_VB() {
|
|||
void readSRAM_VB() {
|
||||
dataIn_VB();
|
||||
|
||||
strcpy(fileName, romName);
|
||||
strcat(fileName, ".srm");
|
||||
|
||||
EEPROM_readAnything(0, foldern);
|
||||
sprintf(folder, "VBOY/SAVE/%s/%d", romName, foldern);
|
||||
sd.mkdir(folder, true);
|
||||
sd.chdir(folder);
|
||||
createFolder("VBOY", "SAVE", romName, "srm");
|
||||
|
||||
foldern = foldern + 1;
|
||||
EEPROM_writeAnything(0, foldern);
|
||||
|
|
342
Cart_Reader/VECTREX.ino
Normal file
342
Cart_Reader/VECTREX.ino
Normal file
|
@ -0,0 +1,342 @@
|
|||
//******************************************
|
||||
// VECTREX MODULE
|
||||
//******************************************
|
||||
#ifdef ENABLE_VECTREX
|
||||
// Vectrex
|
||||
// Cartridge Pinout
|
||||
// 36P 2.54mm pitch connector
|
||||
//
|
||||
// RIGHT
|
||||
// +-------+
|
||||
// +5V -| 2 1 |- /HALT
|
||||
// +5V -| 4 3 |- A7
|
||||
// A8 -| 6 5 |- A6
|
||||
// A9 -| 8 7 |- A5 B
|
||||
// L A11 -| 10 9 |- A4 O
|
||||
// A /OE -| 12 11 |- A3 T
|
||||
// B A10 -| 14 13 |- A2 T
|
||||
// E A15 -| 16 15 |- A1 O
|
||||
// L D7 -| 18 17 |- A0 M
|
||||
// D6 -| 20 19 |- D0
|
||||
// S D5 -| 22 21 |- D1 S
|
||||
// I D4 -| 24 23 |- D2 I
|
||||
// D D3 -| 26 25 |- GND D
|
||||
// E GND -| 28 27 |- GND E
|
||||
// R/W -| 30 29 |- A12
|
||||
// /CART -| 32 31 |- A13
|
||||
// /NMI -| 34 33 |- A14
|
||||
// /IRQ -| 36 35 |- PB6
|
||||
// +-------+
|
||||
// LEFT
|
||||
//
|
||||
// LABEL SIDE
|
||||
//
|
||||
// /IRQ /NMI /CART R/W GND D3 D4 D5 D6 D7 A15 A10 /OE A11 A9 A8 +5V +5V
|
||||
// +-------------------------------------------------------------------------------------------+
|
||||
// | 36 34 32 30 28 26 24 22 20 18 16 14 12 10 8 6 4 2 |
|
||||
// LEFT | | RIGHT
|
||||
// | 35 33 31 29 27 25 23 21 19 17 15 13 11 9 7 5 3 1 |
|
||||
// +-------------------------------------------------------------------------------------------+
|
||||
// PB6 A14 A13 A12 GND GND D2 D1 D0 A0 A1 A2 A3 A4 A5 A6 A7 /HALT
|
||||
//
|
||||
// BOTTOM SIDE
|
||||
|
||||
// CONTROL PINS:
|
||||
// /OE(PH1) - SNES CPUCLK
|
||||
// /CART(PH3) - SNES /CS
|
||||
// PB6(PH5) - SNES /WR
|
||||
// R/W(PH6) - SNES /RD
|
||||
|
||||
//******************************************
|
||||
// Defines
|
||||
//******************************************
|
||||
#define CLK_ENABLE PORTH |= (1 << 1) // /E HIGH
|
||||
#define CLK_DISABLE PORTH &= ~(1 << 1) // /E LOW
|
||||
#define PB6_ENABLE PORTH |= (1 << 5) // PB6 HIGH
|
||||
#define PB6_DISABLE PORTH &= ~(1 << 5) // PB6 LOW
|
||||
|
||||
byte VECTREX[] = { 4, 8, 12, 16, 32, 64 };
|
||||
byte vectrexlo = 0; // Lowest Entry
|
||||
byte vectrexhi = 5; // Highest Entry
|
||||
byte vectrexsize;
|
||||
|
||||
// EEPROM MAPPING
|
||||
// 08 ROM SIZE
|
||||
|
||||
//******************************************
|
||||
// Menu
|
||||
//******************************************
|
||||
// Base Menu
|
||||
static const char* const menuOptionsVECTREX[] PROGMEM = { FSTRING_SELECT_CART, FSTRING_READ_ROM, FSTRING_SET_SIZE, FSTRING_RESET };
|
||||
|
||||
void setup_VECTREX() {
|
||||
// Request 5V
|
||||
setVoltage(VOLTS_SET_5V);
|
||||
|
||||
// Set Address Pins to Output
|
||||
// Vectrex uses A0-A15 [A16-A23 UNUSED]
|
||||
//A0-A7
|
||||
DDRF = 0xFF;
|
||||
//A8-A15
|
||||
DDRK = 0xFF;
|
||||
//A16-A23
|
||||
DDRL = 0xFF;
|
||||
|
||||
// Set Control Pins to Output
|
||||
// ---(PH0) /OE(PH1) /CART(PH3) ---(PH4) PB6(PH5) R/W(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-D7) to Input
|
||||
DDRC = 0x00;
|
||||
|
||||
// Setting Control Pins to HIGH
|
||||
// ---(PH0) /OE(PH1) /CART(PH3) ---(PH4) PB6(PH5) R/W(PH6)
|
||||
PORTH |= (1 << 0) | (1 << 1) | (1 << 3) | (1 << 4) | (1 << 5) | (1 << 6);
|
||||
|
||||
// Set Unused Data Pins (PA0-PA7) to Output
|
||||
DDRA = 0xFF;
|
||||
|
||||
// Set Unused Pins HIGH
|
||||
PORTA = 0xFF;
|
||||
PORTL = 0xFF; // A16-A23
|
||||
PORTJ |= (1 << 0); // TIME(PJ0)
|
||||
|
||||
// Set /CART LOW
|
||||
PORTH &= ~(1 << 3); // Enable Cart
|
||||
// Set /OE LOW
|
||||
PORTH &= ~(1 << 1); // Output Enable
|
||||
|
||||
checkStatus_VECTREX();
|
||||
strcpy(romName, "VECTREX");
|
||||
|
||||
mode = CORE_VECTREX;
|
||||
}
|
||||
|
||||
void vectrexMenu() {
|
||||
convertPgm(menuOptionsVECTREX, 4);
|
||||
uint8_t mainMenu = question_box(F("VECTREX MENU"), menuOptions, 4, 0);
|
||||
|
||||
switch (mainMenu) {
|
||||
case 0:
|
||||
// Select Cart
|
||||
setCart_VECTREX();
|
||||
setup_VECTREX();
|
||||
break;
|
||||
|
||||
case 1:
|
||||
// Read ROM
|
||||
sd.chdir("/");
|
||||
readROM_VECTREX();
|
||||
sd.chdir("/");
|
||||
break;
|
||||
|
||||
case 2:
|
||||
// Set Size
|
||||
setROMSize_VECTREX();
|
||||
break;
|
||||
|
||||
case 3:
|
||||
// reset
|
||||
resetArduino();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//******************************************
|
||||
// READ CODE
|
||||
//******************************************
|
||||
|
||||
uint8_t readData_VECTREX(uint16_t addr) // Add Input Pullup
|
||||
{
|
||||
PORTF = addr & 0xFF; // A0-A7
|
||||
PORTK = (addr >> 8) & 0xFF; // A8-A15
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
|
||||
PORTC = 0xFF; // Input Pullup
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
NOP; // Added delay for better read
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
NOP;
|
||||
|
||||
uint8_t ret = PINC;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void readSegment_VECTREX(uint16_t startaddr, uint16_t endaddr) {
|
||||
for (uint16_t addr = startaddr; addr < endaddr; addr += 512) {
|
||||
for (int w = 0; w < 512; w++) {
|
||||
uint8_t temp = readData_VECTREX(addr + w);
|
||||
sdBuffer[w] = temp;
|
||||
}
|
||||
myFile.write(sdBuffer, 512);
|
||||
}
|
||||
}
|
||||
|
||||
//******************************************
|
||||
// READ ROM
|
||||
//******************************************
|
||||
|
||||
void readROM_VECTREX() {
|
||||
createFolderAndOpenFile("VECTREX", "ROM", romName, "vec");
|
||||
|
||||
PB6_DISABLE; // PB6 LOW - Switch Bank
|
||||
|
||||
// Standard Carts 4K/8K
|
||||
readSegment_VECTREX(0x0000, 0x1000); // 4K
|
||||
if (vectrexsize > 0) {
|
||||
readSegment_VECTREX(0x1000, 0x2000); // +4K = 8K
|
||||
// 12K (Dark Tower)
|
||||
if (vectrexsize > 1)
|
||||
readSegment_VECTREX(0x2000, 0x3000); // +4K = 12K
|
||||
// 16K Carts
|
||||
if (vectrexsize > 2)
|
||||
readSegment_VECTREX(0x3000, 0x4000); // +4K = 16K
|
||||
// Oversize 32K Carts
|
||||
if (vectrexsize > 3)
|
||||
readSegment_VECTREX(0x4000, 0x8000); // +16K = 32K
|
||||
// Oversize 64K Carts
|
||||
if (vectrexsize > 4) {
|
||||
PB6_ENABLE; // PB6 HIGH - Switch Bank
|
||||
readSegment_VECTREX(0x0000, 0x8000); // +32K = 64K
|
||||
PB6_DISABLE; // Reset PB6
|
||||
}
|
||||
}
|
||||
myFile.close();
|
||||
|
||||
printCRC(fileName, NULL, 0);
|
||||
|
||||
println_Msg(FS(FSTRING_EMPTY));
|
||||
// Prints string out of the common strings array either with or without newline
|
||||
print_STR(press_button_STR, 1);
|
||||
display_Update();
|
||||
wait();
|
||||
}
|
||||
|
||||
//******************************************
|
||||
// ROM SIZE
|
||||
//******************************************
|
||||
|
||||
#if (defined(ENABLE_OLED) || defined(ENABLE_LCD))
|
||||
void printRomSize_VECTREX(int index) {
|
||||
display_Clear();
|
||||
print_Msg(F("ROM Size: "));
|
||||
println_Msg(VECTREX[index]);
|
||||
}
|
||||
#endif
|
||||
|
||||
void setROMSize_VECTREX() {
|
||||
byte newvectrexsize;
|
||||
#if (defined(ENABLE_OLED) || defined(ENABLE_LCD))
|
||||
display_Clear();
|
||||
if (vectrexlo == vectrexhi)
|
||||
newvectrexsize = vectrexlo;
|
||||
else {
|
||||
newvectrexsize = navigateMenu(vectrexlo, vectrexhi, &printRomSize_VECTREX);
|
||||
|
||||
display.setCursor(0, 56); // Display selection at bottom
|
||||
}
|
||||
print_Msg(FS(FSTRING_ROM_SIZE));
|
||||
print_Msg(VECTREX[newvectrexsize]);
|
||||
println_Msg(F("KB"));
|
||||
display_Update();
|
||||
delay(1000);
|
||||
#else
|
||||
if (vectrexlo == vectrexhi)
|
||||
newvectrexsize = vectrexlo;
|
||||
else {
|
||||
setrom:
|
||||
String sizeROM;
|
||||
for (int i = 0; i < (vectrexhi - vectrexlo + 1); i++) {
|
||||
Serial.print(F("Select ROM Size: "));
|
||||
Serial.print(i);
|
||||
Serial.print(F(" = "));
|
||||
Serial.print(VECTREX[i + vectrexlo]);
|
||||
Serial.println(F("KB"));
|
||||
}
|
||||
Serial.print(F("Enter ROM Size: "));
|
||||
while (Serial.available() == 0) {}
|
||||
sizeROM = Serial.readStringUntil('\n');
|
||||
Serial.println(sizeROM);
|
||||
newvectrexsize = sizeROM.toInt() + vectrexlo;
|
||||
if (newvectrexsize > vectrexhi) {
|
||||
Serial.println(F("SIZE NOT SUPPORTED"));
|
||||
Serial.println(FS(FSTRING_EMPTY));
|
||||
goto setrom;
|
||||
}
|
||||
}
|
||||
Serial.print(F("ROM Size = "));
|
||||
Serial.print(VECTREX[newvectrexsize]);
|
||||
Serial.println(F("KB"));
|
||||
#endif
|
||||
EEPROM_writeAnything(8, newvectrexsize);
|
||||
vectrexsize = newvectrexsize;
|
||||
}
|
||||
|
||||
void checkStatus_VECTREX() {
|
||||
EEPROM_readAnything(8, vectrexsize);
|
||||
if (vectrexsize > 2) {
|
||||
vectrexsize = 0; // default 4KB
|
||||
EEPROM_writeAnything(8, vectrexsize);
|
||||
}
|
||||
|
||||
#if (defined(ENABLE_OLED) || defined(ENABLE_LCD))
|
||||
display_Clear();
|
||||
println_Msg(F("VECTREX READER"));
|
||||
println_Msg(FS(FSTRING_CURRENT_SETTINGS));
|
||||
println_Msg(FS(FSTRING_EMPTY));
|
||||
print_Msg(FS(FSTRING_ROM_SIZE));
|
||||
print_Msg(VECTREX[vectrexsize]);
|
||||
println_Msg(F("KB"));
|
||||
display_Update();
|
||||
wait();
|
||||
#else
|
||||
Serial.print(FS(FSTRING_ROM_SIZE));
|
||||
Serial.print(VECTREX[vectrexsize]);
|
||||
Serial.println(F("KB"));
|
||||
Serial.println(FS(FSTRING_EMPTY));
|
||||
#endif
|
||||
}
|
||||
|
||||
//******************************************
|
||||
// CART SELECT CODE
|
||||
//******************************************
|
||||
void setCart_VECTREX() {
|
||||
//go to root
|
||||
sd.chdir();
|
||||
|
||||
byte gameSize;
|
||||
|
||||
// Select starting letter
|
||||
//byte myLetter = starting_letter();
|
||||
|
||||
// Open database
|
||||
if (myFile.open("vectrexcart.txt", O_READ)) {
|
||||
// seek_first_letter_in_database(myFile, myLetter);
|
||||
|
||||
if(checkCartSelection(myFile, &readDataLineSingleDigit, &gameSize)) {
|
||||
EEPROM_writeAnything(8, gameSize);
|
||||
}
|
||||
} else {
|
||||
print_FatalError(FS(FSTRING_DATABASE_FILE_NOT_FOUND));
|
||||
}
|
||||
}
|
||||
#endif
|
|
@ -1,7 +1,7 @@
|
|||
//*********************************************************
|
||||
// BANDAI WONDERSWAN & BENESSE POCKET CHALLENGE V2 MODULE
|
||||
//*********************************************************
|
||||
#ifdef enable_WS
|
||||
#ifdef ENABLE_WS
|
||||
// Cartridge pinout
|
||||
// 48P 1.25mm pitch connector
|
||||
// C1, C48 : GND
|
||||
|
@ -23,7 +23,7 @@
|
|||
// C46 : INT (for RTC alarm interrupt)
|
||||
// C47 : CLK (384KHz on WS)
|
||||
|
||||
#ifdef ws_adapter_v2
|
||||
#ifdef OPTION_WS_ADAPTER_V2
|
||||
#define WS_CLK_BIT 5 // USE PE5 as CLK
|
||||
#else
|
||||
#define WS_CLK_BIT 3 // USE PE3 as CLK
|
||||
|
@ -32,12 +32,8 @@
|
|||
/******************************************
|
||||
Menu
|
||||
*****************************************/
|
||||
static const char wsMenuItem1[] PROGMEM = "Read Rom";
|
||||
static const char wsMenuItem2[] PROGMEM = "Read Save";
|
||||
static const char wsMenuItem3[] PROGMEM = "Write Save";
|
||||
//static const char wsMenuItem4[] PROGMEM = "Reset"; (stored in common strings array)
|
||||
static const char wsMenuItem5[] PROGMEM = "Write WitchOS";
|
||||
static const char *const menuOptionsWS[] PROGMEM = { wsMenuItem1, wsMenuItem2, wsMenuItem3, string_reset2, wsMenuItem5 };
|
||||
static const char *const menuOptionsWS[] PROGMEM = { FSTRING_READ_ROM, FSTRING_READ_SAVE, FSTRING_WRITE_SAVE, FSTRING_RESET, wsMenuItem5 };
|
||||
static const uint8_t wwLaunchCode[] PROGMEM = { 0xea, 0x00, 0x00, 0x00, 0xe0, 0x00, 0xff, 0xff };
|
||||
static uint8_t wsGameOrientation = 0;
|
||||
static uint8_t wsGameHasRTC = 0;
|
||||
|
@ -183,7 +179,7 @@ void wsMenu() {
|
|||
}
|
||||
}
|
||||
|
||||
println_Msg(F(""));
|
||||
println_Msg(FS(FSTRING_EMPTY));
|
||||
// Prints string out of the common strings array either with or without newline
|
||||
print_STR(press_button_STR, 1);
|
||||
|
||||
|
@ -407,7 +403,7 @@ static void showCartInfo_WS() {
|
|||
print_Msg(F("Version: 1."));
|
||||
println_Msg(romVersion, HEX);
|
||||
|
||||
print_Msg(F("Checksum: "));
|
||||
print_Msg(FS(FSTRING_CHECKSUM));
|
||||
println_Msg(checksumStr);
|
||||
|
||||
// Prints string out of the common strings array either with or without newline
|
||||
|
@ -493,20 +489,12 @@ static uint16_t readROM_WS(char *outPathBuf, size_t bufferSize) {
|
|||
if (outPathBuf != NULL && bufferSize > 0)
|
||||
snprintf(outPathBuf, bufferSize, "%s/%s", folder, fileName);
|
||||
|
||||
display_Clear();
|
||||
print_STR(saving_to_STR, 0);
|
||||
print_Msg(folder);
|
||||
println_Msg(F("/..."));
|
||||
display_Update();
|
||||
printAndIncrementFolder(true);
|
||||
|
||||
// open file on sdcard
|
||||
if (!myFile.open(fileName, O_RDWR | O_CREAT))
|
||||
print_FatalError(create_file_STR);
|
||||
|
||||
// write new folder number back to EEPROM
|
||||
foldern++;
|
||||
EEPROM_writeAnything(0, foldern);
|
||||
|
||||
// get correct starting rom bank
|
||||
uint16_t bank = (256 - (cartSize >> 16));
|
||||
uint32_t progress = 0;
|
||||
|
@ -565,25 +553,7 @@ static uint16_t readROM_WS(char *outPathBuf, size_t bufferSize) {
|
|||
|
||||
static void readSRAM_WS() {
|
||||
// generate fullname of rom file
|
||||
snprintf(fileName, FILENAME_LENGTH, "%s.sav", romName);
|
||||
|
||||
// create a new folder for storing rom file
|
||||
EEPROM_readAnything(0, foldern);
|
||||
snprintf(folder, sizeof(folder), "WS/SAVE/%s/%d", romName, foldern);
|
||||
sd.mkdir(folder, true);
|
||||
sd.chdir(folder);
|
||||
|
||||
display_Clear();
|
||||
print_Msg(F("Saving "));
|
||||
print_Msg(folder);
|
||||
println_Msg(F("/..."));
|
||||
display_Update();
|
||||
|
||||
foldern++;
|
||||
EEPROM_writeAnything(0, foldern);
|
||||
|
||||
if (!myFile.open(fileName, O_RDWR | O_CREAT))
|
||||
print_FatalError(create_file_STR);
|
||||
createFolderAndOpenFile("WS", "SAVE", romName, "save");
|
||||
|
||||
uint32_t bank_size = (sramSize << 7);
|
||||
uint16_t end_bank = (bank_size >> 16); // 64KB per bank
|
||||
|
@ -658,7 +628,7 @@ static void verifySRAM_WS() {
|
|||
print_Error(did_not_verify_STR);
|
||||
}
|
||||
} else {
|
||||
print_Error(F("File doesn't exist"));
|
||||
print_Error(FS(FSTRING_FILE_DOESNT_EXIST));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -704,31 +674,13 @@ static void writeSRAM_WS() {
|
|||
println_Msg(F("Writing finished"));
|
||||
display_Update();
|
||||
} else {
|
||||
print_Error(F("File doesn't exist"));
|
||||
print_Error(FS(FSTRING_FILE_DOESNT_EXIST));
|
||||
}
|
||||
}
|
||||
|
||||
static void readEEPROM_WS() {
|
||||
// generate fullname of eep file
|
||||
snprintf(fileName, FILENAME_LENGTH, "%s.eep", romName);
|
||||
|
||||
// create a new folder for storing eep file
|
||||
EEPROM_readAnything(0, foldern);
|
||||
snprintf(folder, sizeof(folder), "WS/SAVE/%s/%d", romName, foldern);
|
||||
sd.mkdir(folder, true);
|
||||
sd.chdir(folder);
|
||||
|
||||
display_Clear();
|
||||
print_Msg(F("Saving "));
|
||||
print_Msg(folder);
|
||||
println_Msg(F("/..."));
|
||||
display_Update();
|
||||
|
||||
foldern++;
|
||||
EEPROM_writeAnything(0, foldern);
|
||||
|
||||
if (!myFile.open(fileName, O_RDWR | O_CREAT))
|
||||
print_FatalError(create_file_STR);
|
||||
createFolderAndOpenFile("WS", "SAVE", romName, "eep");
|
||||
|
||||
uint32_t eepromSize = (sramSize << 7);
|
||||
uint32_t bufSize = (eepromSize < 512 ? eepromSize : 512);
|
||||
|
@ -812,7 +764,7 @@ static void verifyEEPROM_WS() {
|
|||
print_Error(did_not_verify_STR);
|
||||
}
|
||||
} else {
|
||||
print_Error(F("File doesn't exist"));
|
||||
print_Error(FS(FSTRING_FILE_DOESNT_EXIST));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -863,7 +815,7 @@ static void writeEEPROM_WS() {
|
|||
|
||||
print_STR(done_STR, 1);
|
||||
} else {
|
||||
print_Error(F("File doesn't exist"));
|
||||
print_Error(FS(FSTRING_FILE_DOESNT_EXIST));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -952,7 +904,7 @@ static void writeWitchOS_WS() {
|
|||
|
||||
print_STR(done_STR, 1);
|
||||
} else {
|
||||
print_Error(F("File doesn't exist"));
|
||||
print_Error(FS(FSTRING_FILE_DOESNT_EXIST));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1003,7 +955,7 @@ static boolean compareChecksum_WS(uint16_t checksum) {
|
|||
|
||||
return 1;
|
||||
} else {
|
||||
println_Msg(F(""));
|
||||
println_Msg(FS(FSTRING_EMPTY));
|
||||
print_Error(F("Checksum Error"));
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
//******************************************
|
||||
// WSV MODULE
|
||||
//******************************************
|
||||
#ifdef enable_WSV
|
||||
#ifdef ENABLE_WSV
|
||||
// Watara Supervision
|
||||
// Cartridge Pinout
|
||||
// 40P 2.5mm pitch connector
|
||||
|
@ -43,7 +43,6 @@ byte wsvlo = 0; // Lowest Entry
|
|||
byte wsvhi = 2; // Highest Entry
|
||||
|
||||
byte wsvsize;
|
||||
byte newwsvsize;
|
||||
|
||||
// EEPROM MAPPING
|
||||
// 08 ROM SIZE
|
||||
|
@ -94,7 +93,7 @@ void setup_WSV() {
|
|||
checkStatus_WSV();
|
||||
strcpy(romName, "SUPERVISION");
|
||||
|
||||
mode = mode_WSV;
|
||||
mode = CORE_WSV;
|
||||
}
|
||||
|
||||
//******************************************
|
||||
|
@ -102,11 +101,7 @@ void setup_WSV() {
|
|||
//******************************************
|
||||
|
||||
// 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"; (stored in common strings array)
|
||||
static const char* const menuOptionsSV[] PROGMEM = { wsvMenuItem1, wsvMenuItem2, wsvMenuItem3, string_reset2 };
|
||||
static const char* const menuOptionsSV[] PROGMEM = { FSTRING_SELECT_CART, FSTRING_READ_ROM, FSTRING_SET_SIZE, FSTRING_RESET };
|
||||
|
||||
void wsvMenu() {
|
||||
convertPgm(menuOptionsSV, 4);
|
||||
|
@ -190,29 +185,7 @@ uint8_t readByte_WSV(uint32_t addr) {
|
|||
//******************************************
|
||||
|
||||
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_STR(saving_to_STR, 0);
|
||||
print_Msg(folder);
|
||||
println_Msg(F("/..."));
|
||||
display_Update();
|
||||
|
||||
// open file on sdcard
|
||||
if (!myFile.open(fileName, O_RDWR | O_CREAT))
|
||||
print_FatalError(create_file_STR);
|
||||
|
||||
// write new folder number back to EEPROM
|
||||
foldern++;
|
||||
EEPROM_writeAnything(0, foldern);
|
||||
createFolderAndOpenFile("WSV", "ROM", romName, "sv");
|
||||
|
||||
// start reading rom
|
||||
dataIn_WSV();
|
||||
|
@ -235,7 +208,7 @@ void readROM_WSV() {
|
|||
// 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(FS(FSTRING_EMPTY));
|
||||
// Prints string out of the common strings array either with or without newline
|
||||
print_STR(press_button_STR, 1);
|
||||
display_Update();
|
||||
|
@ -246,78 +219,26 @@ void readROM_WSV() {
|
|||
// ROM SIZE
|
||||
//******************************************
|
||||
|
||||
#if (defined(ENABLE_OLED) || defined(ENABLE_LCD))
|
||||
void printRomSize_WSV(int index) {
|
||||
display_Clear();
|
||||
print_Msg(F("ROM Size: "));
|
||||
println_Msg(pgm_read_word(&(WSV[index])));
|
||||
}
|
||||
#endif
|
||||
|
||||
void setROMSize_WSV() {
|
||||
#if (defined(enable_OLED) || defined(enable_LCD))
|
||||
byte newwsvsize;
|
||||
#if (defined(ENABLE_OLED) || defined(ENABLE_LCD))
|
||||
display_Clear();
|
||||
if (wsvlo == wsvhi)
|
||||
newwsvsize = wsvlo;
|
||||
else {
|
||||
int b = 0;
|
||||
int i = wsvlo;
|
||||
newwsvsize = navigateMenu(wsvlo, wsvhi, &printRomSize_WSV);
|
||||
|
||||
display_Clear();
|
||||
print_Msg(F("ROM Size: "));
|
||||
println_Msg(pgm_read_word(&(WSV[i])));
|
||||
println_Msg(F(""));
|
||||
#if defined(enable_OLED)
|
||||
print_STR(press_to_change_STR, 1);
|
||||
print_STR(right_to_select_STR, 1);
|
||||
#elif defined(enable_LCD)
|
||||
print_STR(rotate_to_change_STR, 1);
|
||||
print_STR(press_to_select_STR, 1);
|
||||
#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(pgm_read_word(&(WSV[i])));
|
||||
println_Msg(F(""));
|
||||
#if defined(enable_OLED)
|
||||
print_STR(press_to_change_STR, 1);
|
||||
print_STR(right_to_select_STR, 1);
|
||||
#elif defined(enable_LCD)
|
||||
print_STR(rotate_to_change_STR, 1);
|
||||
print_STR(press_to_select_STR, 1);
|
||||
#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(pgm_read_word(&(WSV[i])));
|
||||
println_Msg(F(""));
|
||||
#if defined(enable_OLED)
|
||||
print_STR(press_to_change_STR, 1);
|
||||
print_STR(right_to_select_STR, 1);
|
||||
#elif defined(enable_LCD)
|
||||
print_STR(rotate_to_change_STR, 1);
|
||||
print_STR(press_to_select_STR, 1);
|
||||
#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(FS(FSTRING_ROM_SIZE));
|
||||
print_Msg(pgm_read_word(&(WSV[newwsvsize])));
|
||||
println_Msg(F("K"));
|
||||
display_Update();
|
||||
|
@ -342,7 +263,7 @@ setrom:
|
|||
newwsvsize = sizeROM.toInt() + wsvlo;
|
||||
if (newwsvsize > wsvhi) {
|
||||
Serial.println(F("SIZE NOT SUPPORTED"));
|
||||
Serial.println(F(""));
|
||||
Serial.println(FS(FSTRING_EMPTY));
|
||||
goto setrom;
|
||||
}
|
||||
}
|
||||
|
@ -361,12 +282,12 @@ void checkStatus_WSV() {
|
|||
EEPROM_writeAnything(8, wsvsize);
|
||||
}
|
||||
|
||||
#if (defined(enable_OLED) || defined(enable_LCD))
|
||||
#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: "));
|
||||
println_Msg(FS(FSTRING_CURRENT_SETTINGS));
|
||||
println_Msg(FS(FSTRING_EMPTY));
|
||||
print_Msg(FS(FSTRING_ROM_SIZE));
|
||||
print_Msg(pgm_read_word(&(WSV[wsvsize])));
|
||||
println_Msg(F("K"));
|
||||
display_Update();
|
||||
|
@ -375,151 +296,86 @@ void checkStatus_WSV() {
|
|||
Serial.print(F("CURRENT ROM SIZE: "));
|
||||
Serial.print(pgm_read_word(&(WSV[wsvsize])));
|
||||
Serial.println(F("K"));
|
||||
Serial.println(F(""));
|
||||
Serial.println(FS(FSTRING_EMPTY));
|
||||
#endif
|
||||
}
|
||||
|
||||
//******************************************
|
||||
// CART SELECT CODE
|
||||
//******************************************
|
||||
void setCart_WSV() {
|
||||
char gamename[100];
|
||||
char tempStr2[2];
|
||||
struct database_entry_WSV {
|
||||
char crc_search[9];
|
||||
byte gameSize;
|
||||
};
|
||||
|
||||
void readDataLine_WSV(FsFile& database, void* entry) {
|
||||
struct database_entry_WSV* castEntry = (database_entry_WSV*)entry;
|
||||
// Read CRC32 checksum
|
||||
for (byte i = 0; i < 8; i++) {
|
||||
checksumStr[i] = char(database.read());
|
||||
}
|
||||
|
||||
// Skip over semicolon
|
||||
database.seekCur(1);
|
||||
|
||||
// Read CRC32 of first 512 bytes
|
||||
for (byte i = 0; i < 8; i++) {
|
||||
castEntry->crc_search[i] = char(database.read());
|
||||
}
|
||||
|
||||
// Skip over semicolon
|
||||
database.seekCur(1);
|
||||
|
||||
// Read rom size
|
||||
// Read the next ascii character and subtract 48 to convert to decimal
|
||||
castEntry->gameSize = ((database.read() - 48) * 10) + (database.read() - 48);
|
||||
|
||||
// Skip rest of line
|
||||
database.seekCur(2);
|
||||
}
|
||||
|
||||
void printDataLine_WSV(void* entry) {
|
||||
struct database_entry_WSV* castEntry = (database_entry_WSV*)entry;
|
||||
print_Msg(FS(FSTRING_SIZE));
|
||||
if (castEntry->gameSize == 51)
|
||||
print_Msg(F("512"));
|
||||
else
|
||||
print_Msg(castEntry->gameSize);
|
||||
println_Msg(F("KB"));
|
||||
}
|
||||
|
||||
void setCart_WSV() {
|
||||
//go to root
|
||||
sd.chdir();
|
||||
|
||||
struct database_entry_WSV entry;
|
||||
|
||||
// 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);
|
||||
seek_first_letter_in_database(myFile, myLetter);
|
||||
|
||||
// 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;
|
||||
}
|
||||
if(checkCartSelection(myFile, &readDataLine_WSV, &entry, &printDataLine_WSV)) {
|
||||
//word WSV[] = {32,64,512};
|
||||
switch (entry.gameSize) {
|
||||
case 32:
|
||||
wsvsize = 0;
|
||||
break;
|
||||
|
||||
// Rewind one line
|
||||
rewind_line(myFile);
|
||||
}
|
||||
case 64:
|
||||
wsvsize = 1;
|
||||
break;
|
||||
|
||||
// Display database
|
||||
while (myFile.available()) {
|
||||
display_Clear();
|
||||
|
||||
// Read game name
|
||||
get_line(gamename, &myFile, 96);
|
||||
|
||||
// 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.seekCur(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.seekCur(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.seekCur(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)
|
||||
print_STR(press_to_change_STR, 1);
|
||||
print_STR(right_to_select_STR, 1);
|
||||
#elif defined(enable_LCD)
|
||||
print_STR(rotate_to_change_STR, 1);
|
||||
print_STR(press_to_select_STR, 1);
|
||||
#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) {
|
||||
case 51:
|
||||
wsvsize = 2;
|
||||
break;
|
||||
}
|
||||
|
||||
// Previous
|
||||
else if (b == 2) {
|
||||
rewind_line(myFile, 6);
|
||||
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;
|
||||
}
|
||||
}
|
||||
EEPROM_writeAnything(8, wsvsize);
|
||||
}
|
||||
} else {
|
||||
print_FatalError(F("Database file not found"));
|
||||
print_FatalError(FS(FSTRING_DATABASE_FILE_NOT_FOUND));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
20
README.md
20
README.md
|
@ -22,9 +22,9 @@ Happy making. 🔧🔨😊
|
|||
|
||||
#### Supported Systems:
|
||||
- NES/Famicom/Family Basic
|
||||
- SNES/Super Famicom (including SF Memory and Satellaview)
|
||||
- N64 (including Controller Pak and Gameshark)
|
||||
- Game Boy Color (including GB Memory)
|
||||
- Super Nintendo/Super Famicom (including SF Memory, Satellaview, Sufami Turbo, and Game Processor RAM Cassettes)
|
||||
- Nintendo 64 (including Controller Pak, Gameshark, and Xplorer 64)
|
||||
- Game Boy Color (including GB Memory, Codebreaker, and Gameshark)
|
||||
- Game Boy Advance
|
||||
- Sega Mega Drive/Genesis
|
||||
- Sega Master System
|
||||
|
@ -35,9 +35,9 @@ Happy making. 🔧🔨😊
|
|||
- Virtual Boy
|
||||
- Sega Game Gear
|
||||
- Sega Mark III
|
||||
- Sega SG-1000
|
||||
- Sega SG-1000/SC-3000
|
||||
- Sega Cards
|
||||
- PC engine/TG16
|
||||
- PC Engine/TurboGrafx-16/SuperGrafx
|
||||
- WonderSwan (Color)
|
||||
- NeoGeo Pocket (Color)
|
||||
- Intellivision
|
||||
|
@ -45,14 +45,16 @@ Happy making. 🔧🔨😊
|
|||
- Benesse Pocket Challenge W
|
||||
- Benesse Pocket Challenge V2
|
||||
- Watara Supervision
|
||||
- Atari 2600
|
||||
- Atari 2600/5200/7800
|
||||
- Emerson Arcadia 2001
|
||||
- Fairchild Channel F
|
||||
- Magnavox Odyssey 2
|
||||
- Magnavox Odyssey 2/Philips Videopac+
|
||||
- Super A'Can
|
||||
- MSX
|
||||
- Pokemon Mini
|
||||
- Casio Loopy
|
||||
- Pokémon Mini
|
||||
- Casio Loopy
|
||||
- Commodore 64
|
||||
- Vectrex
|
||||
|
||||
#### Open Source Licenses:
|
||||
- Software(everything in Cart_Reader folder) = GPL v3
|
||||
|
|
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Before Width: | Height: | Size: 693 KiB After Width: | Height: | Size: 841 KiB |
File diff suppressed because it is too large
Load Diff
|
@ -1,5 +1,6 @@
|
|||
{
|
||||
"board": {
|
||||
"3dviewports": [],
|
||||
"design_settings": {
|
||||
"defaults": {
|
||||
"board_outline_line_width": 0.09999999999999999,
|
||||
|
@ -130,7 +131,8 @@
|
|||
"zones_allow_external_fillets": false,
|
||||
"zones_use_no_outline": true
|
||||
},
|
||||
"layer_presets": []
|
||||
"layer_presets": [],
|
||||
"viewports": []
|
||||
},
|
||||
"boards": [],
|
||||
"cvpcb": {
|
||||
|
@ -314,18 +316,23 @@
|
|||
"rule_severities": {
|
||||
"bus_definition_conflict": "error",
|
||||
"bus_entry_needed": "error",
|
||||
"bus_label_syntax": "error",
|
||||
"bus_to_bus_conflict": "error",
|
||||
"bus_to_net_conflict": "error",
|
||||
"conflicting_netclasses": "error",
|
||||
"different_unit_footprint": "error",
|
||||
"different_unit_net": "error",
|
||||
"duplicate_reference": "error",
|
||||
"duplicate_sheet_names": "error",
|
||||
"endpoint_off_grid": "warning",
|
||||
"extra_units": "error",
|
||||
"global_label_dangling": "warning",
|
||||
"hier_label_mismatch": "error",
|
||||
"label_dangling": "error",
|
||||
"lib_symbol_issues": "warning",
|
||||
"missing_bidi_pin": "warning",
|
||||
"missing_input_pin": "warning",
|
||||
"missing_power_pin": "error",
|
||||
"missing_unit": "warning",
|
||||
"multiple_net_names": "warning",
|
||||
"net_not_bus_member": "warning",
|
||||
"no_connect_connected": "warning",
|
||||
|
@ -335,6 +342,7 @@
|
|||
"pin_to_pin": "warning",
|
||||
"power_pin_not_driven": "error",
|
||||
"similar_labels": "warning",
|
||||
"simulation_model_issue": "error",
|
||||
"unannotated": "error",
|
||||
"unit_value_mismatch": "error",
|
||||
"unresolved_variable": "error",
|
||||
|
@ -352,7 +360,7 @@
|
|||
"net_settings": {
|
||||
"classes": [
|
||||
{
|
||||
"bus_width": 12.0,
|
||||
"bus_width": 12,
|
||||
"clearance": 0.2,
|
||||
"diff_pair_gap": 0.25,
|
||||
"diff_pair_via_gap": 0.25,
|
||||
|
@ -366,10 +374,10 @@
|
|||
"track_width": 0.3,
|
||||
"via_diameter": 0.8,
|
||||
"via_drill": 0.4,
|
||||
"wire_width": 6.0
|
||||
"wire_width": 6
|
||||
},
|
||||
{
|
||||
"bus_width": 12.0,
|
||||
"bus_width": 12,
|
||||
"clearance": 0.2,
|
||||
"diff_pair_gap": 0.25,
|
||||
"diff_pair_via_gap": 0.25,
|
||||
|
@ -378,22 +386,29 @@
|
|||
"microvia_diameter": 0.3,
|
||||
"microvia_drill": 0.1,
|
||||
"name": "Power",
|
||||
"nets": [
|
||||
"GND",
|
||||
"VCC"
|
||||
],
|
||||
"pcb_color": "rgba(0, 0, 0, 0.000)",
|
||||
"schematic_color": "rgba(0, 0, 0, 0.000)",
|
||||
"track_width": 0.6,
|
||||
"via_diameter": 0.8,
|
||||
"via_drill": 0.4,
|
||||
"wire_width": 6.0
|
||||
"wire_width": 6
|
||||
}
|
||||
],
|
||||
"meta": {
|
||||
"version": 2
|
||||
"version": 3
|
||||
},
|
||||
"net_colors": null
|
||||
"net_colors": null,
|
||||
"netclass_assignments": null,
|
||||
"netclass_patterns": [
|
||||
{
|
||||
"netclass": "Power",
|
||||
"pattern": "GND"
|
||||
},
|
||||
{
|
||||
"netclass": "Power",
|
||||
"pattern": "VCC"
|
||||
}
|
||||
]
|
||||
},
|
||||
"pcbnew": {
|
||||
"last_paths": {
|
||||
|
@ -409,6 +424,8 @@
|
|||
"schematic": {
|
||||
"annotate_start_num": 0,
|
||||
"drawing": {
|
||||
"dashed_lines_dash_length_ratio": 12.0,
|
||||
"dashed_lines_gap_length_ratio": 3.0,
|
||||
"default_bus_thickness": 12.0,
|
||||
"default_line_thickness": 6.0,
|
||||
"default_text_size": 50.0,
|
||||
|
@ -442,7 +459,11 @@
|
|||
"page_layout_descr_file": "",
|
||||
"plot_directory": "",
|
||||
"spice_adjust_passive_values": false,
|
||||
"spice_current_sheet_as_root": false,
|
||||
"spice_external_command": "spice \"%I\"",
|
||||
"spice_model_current_sheet_as_root": true,
|
||||
"spice_save_all_currents": false,
|
||||
"spice_save_all_voltages": false,
|
||||
"subpart_first_id": 65,
|
||||
"subpart_id_separator": 0
|
||||
},
|
||||
|
|
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Binary file not shown.
Before Width: | Height: | Size: 2.7 MiB |
BIN
hardware/six_slot_adapter/six_slot_adapter_schematic.pdf
Normal file
BIN
hardware/six_slot_adapter/six_slot_adapter_schematic.pdf
Normal file
Binary file not shown.
1482
sd/2600.txt
Normal file
1482
sd/2600.txt
Normal file
File diff suppressed because it is too large
Load Diff
1278
sd/32x.txt
1278
sd/32x.txt
File diff suppressed because it is too large
Load Diff
225
sd/5200.txt
Normal file
225
sd/5200.txt
Normal file
|
@ -0,0 +1,225 @@
|
|||
Activision Decathlon
|
||||
0,2
|
||||
|
||||
Astro Chase
|
||||
1,2
|
||||
|
||||
Atari PAM - Pete's Test
|
||||
0,1
|
||||
|
||||
Atari PAM Diagnostics
|
||||
1,2
|
||||
|
||||
Atari PAM System Test
|
||||
0,1
|
||||
|
||||
Ballblazer
|
||||
0,3
|
||||
|
||||
Beamrider
|
||||
0,2
|
||||
|
||||
BerZerk
|
||||
0,2
|
||||
|
||||
Blue Print
|
||||
0,2
|
||||
|
||||
Boogie
|
||||
0,0
|
||||
|
||||
Bounty Bob Strikes Back!
|
||||
2,4
|
||||
|
||||
Buck Rogers
|
||||
1,2
|
||||
|
||||
Centipede
|
||||
1,2
|
||||
|
||||
Choplifter!
|
||||
0,2
|
||||
|
||||
Congo Bongo
|
||||
1,2
|
||||
|
||||
Countermeasure
|
||||
1,2
|
||||
|
||||
Defender
|
||||
1,2
|
||||
|
||||
Dig Dug
|
||||
1,2
|
||||
|
||||
Dreadnaught Factor
|
||||
0,1
|
||||
|
||||
Frogger
|
||||
0,1
|
||||
|
||||
Frogger II
|
||||
1,2
|
||||
|
||||
Galaxian
|
||||
0,1
|
||||
|
||||
Gorf
|
||||
0,1
|
||||
|
||||
Gremlins
|
||||
0,3
|
||||
|
||||
Gyruss
|
||||
1,2
|
||||
|
||||
H.E.R.O.
|
||||
0,2
|
||||
|
||||
James Bond 007
|
||||
1,2
|
||||
|
||||
Joust
|
||||
1,2
|
||||
|
||||
Jungle Hunt
|
||||
1,2
|
||||
|
||||
Kaboom!
|
||||
0,0
|
||||
|
||||
Kangaroo
|
||||
1,2
|
||||
|
||||
Keystone Kapers
|
||||
0,1
|
||||
|
||||
K-Razy Shoot-Out
|
||||
0,1
|
||||
|
||||
Mario Bros.
|
||||
0,3
|
||||
|
||||
MegaMania
|
||||
0,1
|
||||
|
||||
Meteorites
|
||||
0,2
|
||||
|
||||
Miner 2049er
|
||||
0,2
|
||||
|
||||
Missile Command
|
||||
0,1
|
||||
|
||||
Montezuma's Revenge
|
||||
1,2
|
||||
|
||||
Moon Patrol
|
||||
0,2
|
||||
|
||||
Mountain King
|
||||
0,1
|
||||
|
||||
Mr. Do!'s Castle
|
||||
0,1
|
||||
|
||||
Ms. Pac-Man
|
||||
1,2
|
||||
|
||||
Pac-Man
|
||||
1,2
|
||||
|
||||
Pengo
|
||||
0,3
|
||||
|
||||
Pitfall II
|
||||
0,2
|
||||
|
||||
Pitfall!
|
||||
0,1
|
||||
|
||||
Pole Position
|
||||
1,2
|
||||
|
||||
Popeye
|
||||
1,2
|
||||
|
||||
Q-bert
|
||||
0,1
|
||||
|
||||
QIX
|
||||
1,2
|
||||
|
||||
Quest for Quintana Roo
|
||||
0,2
|
||||
|
||||
RealSports Baseball
|
||||
0,3
|
||||
|
||||
RealSports Basketball
|
||||
0,3
|
||||
|
||||
RealSports Football
|
||||
1,2
|
||||
|
||||
RealSports Soccer
|
||||
1,2
|
||||
|
||||
RealSports Tennis
|
||||
1,2
|
||||
|
||||
Rescue on Fractalus!
|
||||
0,3
|
||||
|
||||
River Raid
|
||||
0,1
|
||||
|
||||
Robotron 2084
|
||||
0,2
|
||||
|
||||
Space Dungeon
|
||||
1,2
|
||||
|
||||
Space Invaders
|
||||
0,1
|
||||
|
||||
Space Shuttle
|
||||
0,2
|
||||
|
||||
Star Raiders
|
||||
1,2
|
||||
|
||||
Star Trek
|
||||
1,2
|
||||
|
||||
Star Wars - Return of the Jedi
|
||||
0,1
|
||||
|
||||
Star Wars - The Arcade Game
|
||||
1,2
|
||||
|
||||
Super Breakout
|
||||
0,0
|
||||
|
||||
Super Cobra
|
||||
0,1
|
||||
|
||||
Vanguard
|
||||
0,3
|
||||
|
||||
Wizard of Wor
|
||||
0,2
|
||||
|
||||
Yellow Submarine
|
||||
0,0
|
||||
|
||||
Zaxxon
|
||||
0,3
|
||||
|
||||
Zenji
|
||||
0,1
|
||||
|
||||
Zone Ranger
|
||||
0,2
|
||||
|
213
sd/7800.txt
Normal file
213
sd/7800.txt
Normal file
|
@ -0,0 +1,213 @@
|
|||
32 in 1
|
||||
0,3
|
||||
|
||||
Ace of Aces
|
||||
1,4
|
||||
|
||||
Alien Brigade
|
||||
2,5
|
||||
|
||||
Asteroids
|
||||
0,0
|
||||
|
||||
Atari 7800 Development Card
|
||||
0,0
|
||||
|
||||
Attack of the Petscii Robots
|
||||
7,4
|
||||
|
||||
Ballblazer
|
||||
0,1
|
||||
|
||||
Barnyard Blaster
|
||||
1,4
|
||||
|
||||
Baseball
|
||||
0,1
|
||||
|
||||
Basketbrawl
|
||||
1,4
|
||||
|
||||
Centipede
|
||||
0,0
|
||||
|
||||
Choplifter! (Europe)
|
||||
0,2
|
||||
|
||||
Choplifter! (USA)
|
||||
0,1
|
||||
|
||||
Commando
|
||||
1,4
|
||||
|
||||
Crack'ed
|
||||
1,4
|
||||
|
||||
Crossbow
|
||||
2,5
|
||||
|
||||
Dark Chambers
|
||||
1,4
|
||||
|
||||
Desert Falcon
|
||||
0,2
|
||||
|
||||
Diagnostic Test Cartridge
|
||||
0,1
|
||||
|
||||
Dig Dug (Europe)
|
||||
0,1
|
||||
|
||||
Dig Dug (USA)
|
||||
0,0
|
||||
|
||||
Donkey Kong
|
||||
0,2
|
||||
|
||||
Donkey Kong Junior
|
||||
0,2
|
||||
|
||||
Double Dragon
|
||||
4,4
|
||||
|
||||
F-18 Hornet
|
||||
3,3
|
||||
|
||||
Fatal Run
|
||||
1,4
|
||||
|
||||
Fight Night
|
||||
1,4
|
||||
|
||||
Food Fight (Europe)
|
||||
0,2
|
||||
|
||||
Food Fight (USA)
|
||||
0,1
|
||||
|
||||
Galaga (Europe)
|
||||
0,2
|
||||
|
||||
Galaga (USA)
|
||||
0,1
|
||||
|
||||
Hat Trick
|
||||
0,2
|
||||
|
||||
Ikari Warriors
|
||||
1,4
|
||||
|
||||
Impossible Mission
|
||||
1,4
|
||||
|
||||
Jinks
|
||||
1,4
|
||||
|
||||
Joust (Europe)
|
||||
0,2
|
||||
|
||||
Joust (USA)
|
||||
0,1
|
||||
|
||||
Karateka (Europe)
|
||||
6,3
|
||||
|
||||
Karateka (USA)
|
||||
0,2
|
||||
|
||||
Kung-Fu Master
|
||||
0,1
|
||||
|
||||
Mario Bros.
|
||||
0,2
|
||||
|
||||
Mat Mania Challenge
|
||||
1,4
|
||||
|
||||
Mean 18 Ultimate Golf
|
||||
1,4
|
||||
|
||||
Meltdown
|
||||
1,4
|
||||
|
||||
Midnight Mutants
|
||||
1,4
|
||||
|
||||
Motor Psycho
|
||||
1,4
|
||||
|
||||
Ms. Pac-Man (Europe)
|
||||
0,1
|
||||
|
||||
Ms. Pac-Man (USA)
|
||||
0,0
|
||||
|
||||
Ninja Golf
|
||||
1,4
|
||||
|
||||
One-on-One Basketball
|
||||
0,2
|
||||
|
||||
Pete Rose Baseball
|
||||
0,1
|
||||
|
||||
Planet Smashers
|
||||
1,4
|
||||
|
||||
Pole Position II
|
||||
0,1
|
||||
|
||||
Rampage
|
||||
4,4
|
||||
|
||||
RealSports Baseball
|
||||
5,3
|
||||
|
||||
Robotron 2084
|
||||
0,1
|
||||
|
||||
Scrapyard Dog
|
||||
1,4
|
||||
|
||||
Sentinel
|
||||
1,4
|
||||
|
||||
Summer Games
|
||||
1,4
|
||||
|
||||
Super Huey UH-IX
|
||||
0,2
|
||||
|
||||
Super Skateboardin'
|
||||
0,1
|
||||
|
||||
Tank Command
|
||||
5,3
|
||||
|
||||
Title Match Pro Wrestling
|
||||
0,1
|
||||
|
||||
Tomcat
|
||||
0,1
|
||||
|
||||
Touchdown Football
|
||||
1,4
|
||||
|
||||
Tower Toppler
|
||||
5,3
|
||||
|
||||
Water Ski
|
||||
5,3
|
||||
|
||||
Winter Games
|
||||
1,4
|
||||
|
||||
Xenophobe
|
||||
1,4
|
||||
|
||||
Xevious (Europe)
|
||||
0,2
|
||||
|
||||
Xevious (USA)
|
||||
0,1
|
||||
|
241
sd/README.md
241
sd/README.md
|
@ -98,3 +98,244 @@ D90FE762
|
|||
|
||||
Name
|
||||
Checksum
|
||||
|
||||
## 2600.txt
|
||||
This file stores known Atari VCS / 2600 games with the required mapping value.
|
||||
|
||||
Example:
|
||||
Wall-Defender
|
||||
064
|
||||
|
||||
Name
|
||||
mapper
|
||||
|
||||
mapper:
|
||||
004 = Atari 32K with RAM [F4SC]
|
||||
006 = Atari 16K with RAM [F6SC]
|
||||
008 = Atari 8K with RAM [F8SC]
|
||||
010 = UA Ltd 8K [UA]
|
||||
032 = Atari 2K
|
||||
063 = Tigervision 8K
|
||||
064 = Atari 4K (Default)
|
||||
192 = Commavid 2K [CV]
|
||||
208 = Pitfall II 10K [DPC]
|
||||
224 = Parker Bros 8K
|
||||
231 = M-Network 16K
|
||||
240 = Megaboy 64K
|
||||
244 = Atari 32K [F4]
|
||||
246 = Atari 16K [F6]
|
||||
248 = Atari 8K [F8]
|
||||
249 = Time Pilot 8K [TP]
|
||||
250 = CBS RAM Plus 12K
|
||||
254 = Activision 8K
|
||||
|
||||
## 5200.txt
|
||||
This file stores known Atari 5200 games with the required mapping value and cart size.
|
||||
|
||||
Example:
|
||||
Defender
|
||||
1,2
|
||||
|
||||
Name
|
||||
mapper, cart size
|
||||
|
||||
mapper:
|
||||
0 = Standard 4K/8K/16K/32K
|
||||
1 = Two Chip 16K
|
||||
2 = Bounty Bob Strikes Back 40K
|
||||
|
||||
cart size:
|
||||
0 = 4K
|
||||
1 = 8K
|
||||
2 = 16K
|
||||
3 = 32K
|
||||
4 = 40K
|
||||
|
||||
## 7800.txt
|
||||
This file stores known Atari 7800 games with the required mapping value and cart size.
|
||||
|
||||
Example:
|
||||
Rampage
|
||||
4,4
|
||||
|
||||
Name
|
||||
mapper, cart size
|
||||
|
||||
mapper:
|
||||
0 = Standard 16K/32K/48K [7816/7832/7848]
|
||||
1 = SuperGame 128K [78SG]
|
||||
2 = SuperGame - Alien Brigade/Crossbow 144K [78S9]
|
||||
3 = F-18 Hornet 64K [78AB]
|
||||
4 = Double Dragon/Rampage 128K [78AC]
|
||||
5 = Realsports Baseball/Tank Command/Tower Toppler/Waterski 64K [78S4]
|
||||
6 = Karateka (PAL) 64K [78S4 Variant]
|
||||
7 = Bankset switching
|
||||
|
||||
cart size:
|
||||
0 = 16K
|
||||
1 = 32K
|
||||
2 = 48K
|
||||
3 = 64K
|
||||
4 = 128K
|
||||
5 = 144K
|
||||
|
||||
## arccart.txt
|
||||
This file stores known Emerson Arcadia 2001 games with the required cart size.
|
||||
|
||||
Example:
|
||||
American Football
|
||||
2
|
||||
|
||||
Name
|
||||
cart size
|
||||
|
||||
cart size:
|
||||
0 = 2K
|
||||
1 = 4K
|
||||
2 = 6K
|
||||
3 = 8K
|
||||
|
||||
## c64cart.txt
|
||||
This file stores known Commodore 64 games with the required mapping value and cart size.
|
||||
|
||||
Example:
|
||||
Donkey Kong
|
||||
00,3
|
||||
|
||||
Name
|
||||
mapper, cart size
|
||||
|
||||
mapper:
|
||||
00 = Normal 4K/8K/16K + Ultimax 8K/16K
|
||||
01 = Action Replay 32K
|
||||
02 = KCS Power Cartridge 16K
|
||||
03 = Final Cartridge III 64K
|
||||
04 = Simons Basic 16K
|
||||
05 = Ocean 128K/256K/512K
|
||||
06 = Expert Cartridge 8K
|
||||
07 = Fun Play, Power Play 128K
|
||||
08 = Super Games 64K
|
||||
09 = Atomic Power 32K
|
||||
10 = Epyx Fastload 8K
|
||||
11 = Westermann Learning 16K
|
||||
12 = Rex Utility 8K
|
||||
13 = Final Cartridge I 16K
|
||||
14 = Magic Formel 64K
|
||||
15 = C64 Game System, System 3 512K
|
||||
16 = WarpSpeed 16K
|
||||
17 = Dinamic 128K
|
||||
18 = Zaxxon, Super Zaxxon (SEGA) 20K
|
||||
19 = Magic Desk, Domark, HES Australia 32K/64K/128K
|
||||
20 = Super Snapshot 5 64K
|
||||
21 = Comal-80 64K
|
||||
|
||||
cart size:
|
||||
0 = 4K
|
||||
1 = 8K
|
||||
2 = 12K
|
||||
3 = 16K
|
||||
4 = 20K
|
||||
5 = 32K
|
||||
6 = 64K
|
||||
7 = 128K
|
||||
8 = 256K
|
||||
9 = 512K
|
||||
|
||||
## fairchildcart.txt
|
||||
This file stores known Fairchild Channel F games with the required cart size.
|
||||
|
||||
Example:
|
||||
Hangman
|
||||
1
|
||||
|
||||
Name
|
||||
cart size
|
||||
|
||||
cart size:
|
||||
0 = 2K
|
||||
1 = 3K
|
||||
2 = 4K
|
||||
3 = 6K
|
||||
|
||||
## msxcart.txt
|
||||
This file stores known MSX games with the required mapper, cart size and ram size.
|
||||
|
||||
Example:
|
||||
Aoki Ookami - Genchou Hishi
|
||||
07,8,4
|
||||
|
||||
Name
|
||||
mapper, cart size, ram size
|
||||
|
||||
mapper:
|
||||
00 = NONE
|
||||
01 = ASCII8
|
||||
02 = ASCII16
|
||||
03 = CROSS BLAIM
|
||||
04 = GAME MASTER 2
|
||||
05 = HAL NOTE
|
||||
06 = HARRY FOX YUKI
|
||||
07 = KOEI
|
||||
08 = KONAMI
|
||||
09 = KONAMI SSC
|
||||
10 = MSX-DOS2
|
||||
11 = PAC/FM-PAC
|
||||
12 = R-TYPE
|
||||
13 = SUPER LODE RUNNER
|
||||
|
||||
cart size:
|
||||
0 = 0K
|
||||
1 = 8K
|
||||
2 = 16K
|
||||
3 = 32K
|
||||
4 = 64K
|
||||
5 = 128K
|
||||
6 = 256K
|
||||
7 = 512K
|
||||
8 = 1024K
|
||||
|
||||
ram size:
|
||||
0 = 0K
|
||||
1 = 2K
|
||||
2 = 8K
|
||||
3 = 16K
|
||||
4 = 32K
|
||||
|
||||
## ody2cart.txt
|
||||
This file stores known Magnavox Odyssey 2 games with the required mapper and cart size.
|
||||
|
||||
Example:
|
||||
Baseball
|
||||
0,0
|
||||
|
||||
Name
|
||||
mapper, cart size
|
||||
|
||||
mapper:
|
||||
0 = STANDARD
|
||||
1 = A10
|
||||
|
||||
cart size:
|
||||
0 = 2K
|
||||
1 = 4K
|
||||
2 = 8K
|
||||
3 = 12K
|
||||
4 = 16K
|
||||
|
||||
## vectrexcart.txt
|
||||
This file stores known Vectrex games with the required cart size.
|
||||
|
||||
Example:
|
||||
Mine Storm II
|
||||
0
|
||||
|
||||
Name
|
||||
cart size
|
||||
|
||||
cart size:
|
||||
0 = 4K
|
||||
1 = 8K
|
||||
2 = 12K
|
||||
3 = 16K
|
||||
4 = 32K
|
||||
5 = 64K
|
||||
|
|
193
sd/arccart.txt
193
sd/arccart.txt
|
@ -1,49 +1,144 @@
|
|||
3D Bowling,1,0
|
||||
3D Soccer,3,16
|
||||
Alien Invaders,1,16
|
||||
American Football,2,21
|
||||
Astro Invader,3,24
|
||||
Autorace,3,20
|
||||
Baseball,1,15
|
||||
Basketball,1,15
|
||||
Blackjack and Poker,1,17
|
||||
Boxing,1,26
|
||||
Brain Quiz,1,13
|
||||
Breakaway,1,17
|
||||
Capture,0,16
|
||||
Cat Trax,1,14
|
||||
Circus,1,15
|
||||
Combat,3,13
|
||||
Crazy Climber,1,13
|
||||
Crazy Gobbler,0,20
|
||||
Escape,1,20
|
||||
Funky Fish,3,13
|
||||
Golf,3,17
|
||||
Grand Slam Tennis,3,11
|
||||
Hobo,3,24
|
||||
Horse Racing,1,11
|
||||
Jump Bug,3,19
|
||||
Jungler,3,15
|
||||
Missile War,1,14
|
||||
Monaco Grand Prix,1,18
|
||||
Nibblemen,1,24
|
||||
Ocean Battle,1,16
|
||||
Parashooter,1,19
|
||||
Pleiades,3,18
|
||||
R2D Tank,1,15
|
||||
Red Clash,3,15
|
||||
Robot Killer,1,16
|
||||
Route 16,3,19
|
||||
Soccer,3,15
|
||||
Space Attack,1,13
|
||||
Space Mission,1,19
|
||||
Space Raiders,1,20
|
||||
Space Squadron,1,20
|
||||
Space Vultures,2,21
|
||||
Spiders,3,21
|
||||
Star Chess,1,14
|
||||
Super Gobbler,1,17
|
||||
Tanks a Lot,1,20
|
||||
The End,1,18
|
||||
Turtles,3,14
|
||||
EOF,0,0
|
||||
3D Bowling
|
||||
1
|
||||
|
||||
3D Soccer
|
||||
3
|
||||
|
||||
Alien Invaders
|
||||
1
|
||||
|
||||
American Football
|
||||
2
|
||||
|
||||
Astro Invader
|
||||
3
|
||||
|
||||
Autorace
|
||||
3
|
||||
|
||||
Baseball
|
||||
1
|
||||
|
||||
Basketball
|
||||
1
|
||||
|
||||
Blackjack and Poker
|
||||
1
|
||||
|
||||
Boxing
|
||||
1
|
||||
|
||||
Brain Quiz
|
||||
1
|
||||
|
||||
Breakaway
|
||||
1
|
||||
|
||||
Capture
|
||||
0
|
||||
|
||||
Cat Trax
|
||||
1
|
||||
|
||||
Circus
|
||||
1
|
||||
|
||||
Combat
|
||||
3
|
||||
|
||||
Crazy Climber
|
||||
1
|
||||
|
||||
Crazy Gobbler
|
||||
0
|
||||
|
||||
Escape
|
||||
1
|
||||
|
||||
Funky Fish
|
||||
3
|
||||
|
||||
Golf
|
||||
3
|
||||
|
||||
Grand Slam Tennis
|
||||
3
|
||||
|
||||
Hobo
|
||||
3
|
||||
|
||||
Horse Racing
|
||||
1
|
||||
|
||||
Jump Bug
|
||||
3
|
||||
|
||||
Jungler
|
||||
3
|
||||
|
||||
Missile War
|
||||
1
|
||||
|
||||
Monaco Grand Prix
|
||||
1
|
||||
|
||||
Nibblemen
|
||||
1
|
||||
|
||||
Ocean Battle
|
||||
1
|
||||
|
||||
Parashooter
|
||||
1
|
||||
|
||||
Pleiades
|
||||
3
|
||||
|
||||
R2D Tank
|
||||
1
|
||||
|
||||
Red Clash
|
||||
3
|
||||
|
||||
Robot Killer
|
||||
1
|
||||
|
||||
Route 16
|
||||
3
|
||||
|
||||
Soccer
|
||||
3
|
||||
|
||||
Space Attack
|
||||
1
|
||||
|
||||
Space Mission
|
||||
1
|
||||
|
||||
Space Raiders
|
||||
1
|
||||
|
||||
Space Squadron
|
||||
1
|
||||
|
||||
Space Vultures
|
||||
2
|
||||
|
||||
Spiders
|
||||
3
|
||||
|
||||
Star Chess
|
||||
1
|
||||
|
||||
Super Gobbler
|
||||
1
|
||||
|
||||
Tanks a Lot
|
||||
1
|
||||
|
||||
The End
|
||||
1
|
||||
|
||||
Turtles
|
||||
3
|
||||
|
||||
|
|
494
sd/ataricart.txt
494
sd/ataricart.txt
|
@ -1,494 +0,0 @@
|
|||
32 in 1,240,0
|
||||
3-D Tic-Tac-Toe,32,15
|
||||
Acid Drop,246,23
|
||||
Action Force,64,18
|
||||
Adventure,64,20
|
||||
Adventures of TRON,64,17
|
||||
Air Raid,64,26
|
||||
Air Raiders,64,16
|
||||
Airlock,64,19
|
||||
Air-Sea Battle,32,15
|
||||
AKA Space Adventure,64,22
|
||||
Alien,64,27
|
||||
Alpha Beam with Ernie,248,13
|
||||
Amidar,64,30
|
||||
Armor Ambush,64,14
|
||||
Artillery Duel,248,20
|
||||
Assault,64,23
|
||||
Asterix,248,15
|
||||
Asteroids,248,16
|
||||
Astroblast,64,18
|
||||
Atari Video Cube,64,18
|
||||
Atlantis,64,24
|
||||
Atlantis II,64,16
|
||||
Bachelor Party,64,19
|
||||
Bachelorette Party,64,22
|
||||
Backgammon,64,26
|
||||
Bank Heist,64,18
|
||||
Barnstorming,64,18
|
||||
Base Attack,64,20
|
||||
Basic Math,32,19
|
||||
BASIC Programming,64,18
|
||||
Basketball,32,25
|
||||
Battlezone,248,18
|
||||
Beamrider,248,19
|
||||
Beany Bopper,64,18
|
||||
Beat 'Em & Eat 'Em,64,20
|
||||
Berenstain Bears,248,26
|
||||
Bermuda,64,25
|
||||
Bermuda Triangle,64,15
|
||||
Berzerk,64,24
|
||||
Big Bird's Egg Catch,248,15
|
||||
Blackjack,32,29
|
||||
Blueprint,248,17
|
||||
BMX Air Master,246,18
|
||||
Bobby Is Going Home,64,23
|
||||
Boing!,64,27
|
||||
Bowling,32,14
|
||||
Boxing,32,15
|
||||
Brain Games,32,14
|
||||
Breakout,32,19
|
||||
Bridge,64,16
|
||||
Buck Rogers - Planet of Zoom,248,14
|
||||
Bugs,64,37
|
||||
Bump 'n' Jump,231,12
|
||||
Bumper Bash,64,22
|
||||
BurgerTime,231,19
|
||||
Burning Desire,64,19
|
||||
Cakewalk,64,22
|
||||
California Games,246,16
|
||||
Canyon Bomber,32,25
|
||||
Carnival,64,21
|
||||
Casino,64,16
|
||||
Cat Trax,64,14
|
||||
Cathouse Blues,64,16
|
||||
Centipede,248,22
|
||||
Challenge,248,18
|
||||
Challenge of.... Nexar,64,18
|
||||
Chase the Chuckwagon,64,30
|
||||
Checkers,32,28
|
||||
China Syndrome,64,16
|
||||
Chopper Command,64,22
|
||||
Chuck Norris Superkicks,248,23
|
||||
Circus Atari,64,32
|
||||
Coco Nuts,64,20
|
||||
Codebreaker,32,17
|
||||
Combat,32,19
|
||||
Commando,246,14
|
||||
Commando Raid,64,17
|
||||
Condor Attack,64,21
|
||||
Confrontation,64,21
|
||||
Congo Bongo,248,21
|
||||
Cookie Monster Munch,248,20
|
||||
Cosmic Ark,64,29
|
||||
Cosmic Commuter,64,18
|
||||
Cosmic Corridor,64,23
|
||||
Cosmic Creeps,64,23
|
||||
Cosmic Swarm,32,21
|
||||
Crackpots,64,20
|
||||
Crash Dive,64,17
|
||||
Crazy Climber,248,18
|
||||
Cross Force,64,22
|
||||
Crossbow,246,19
|
||||
Crypts of Chaos,64,17
|
||||
Crystal Castles,246,23
|
||||
Cubicolor,64,24
|
||||
Cubo Magico,64,17
|
||||
Custer's Revenge,64,19
|
||||
Dancing Plate,64,24
|
||||
Dark Cavern,64,21
|
||||
Dark Chambers,246,19
|
||||
Dark Mage,248,22
|
||||
Deadly Duck,64,18
|
||||
Death Trap,64,19
|
||||
Decathlon,254,18
|
||||
Defender,64,18
|
||||
Defender II,248,16
|
||||
Demolition Herby,64,20
|
||||
Demon Attack,64,24
|
||||
Demons to Diamonds,64,20
|
||||
Desert Falcon,246,26
|
||||
Dice Puzzle,64,22
|
||||
Dig Dug,246,19
|
||||
Dishaster,64,16
|
||||
Dodge 'Em,64,17
|
||||
Dolphin,64,17
|
||||
Donald Duck's Speedboat,248,15
|
||||
Donkey Kong,64,32
|
||||
Donkey Kong Jr,248,19
|
||||
Double Dragon,246,23
|
||||
Double Dunk,246,22
|
||||
Dragon Defender,64,20
|
||||
Dragonfire,64,23
|
||||
Dragster,32,18
|
||||
Dukes of Hazzard,246,16
|
||||
E.T.,248,25
|
||||
Earth Dies Screaming,64,13
|
||||
Eggomania,64,28
|
||||
Elevator Action,248,17
|
||||
Eli's Ladder,64,24
|
||||
Encounter at L-5,64,20
|
||||
Enduro,64,24
|
||||
Entombed,64,14
|
||||
Espial,63,16
|
||||
Exocet,64,14
|
||||
Extra Terrestrials,64,14
|
||||
Fantastic Voyage,64,26
|
||||
Farmyard Fun,64,24
|
||||
Fast Eddie,64,20
|
||||
Fast Food,64,18
|
||||
Fatal Run,244,17
|
||||
Fathom,248,18
|
||||
Fighter Pilot,246,15
|
||||
Final Approach,64,22
|
||||
Fire Fighter,64,22
|
||||
Fire Fly,64,20
|
||||
Fishing Derby,32,16
|
||||
Flag Capture,32,21
|
||||
Flash Gordon,64,20
|
||||
Football,32,20
|
||||
Forest,64,16
|
||||
Frankenstein's Monster,64,14
|
||||
Freeway,32,30
|
||||
Frisco,64,15
|
||||
Frog Pond,248,14
|
||||
Frogger,64,18
|
||||
Frogger II,224,15
|
||||
Frogs and Flies,64,19
|
||||
Front Line,248,23
|
||||
Frostbite,64,19
|
||||
G.I. Joe,64,17
|
||||
Galaxian,248,16
|
||||
Gamma Attack,32,17
|
||||
Gangster Alley,64,20
|
||||
Gas Hog,64,22
|
||||
Gauntlet,64,15
|
||||
Ghost Manor,248,16
|
||||
Ghostbusters,248,20
|
||||
Ghostbusters II,246,21
|
||||
Gigolo,64,24
|
||||
Glacier Patrol,64,14
|
||||
Glib,64,22
|
||||
Golf,32,12
|
||||
Gopher,64,12
|
||||
Gorf,64,14
|
||||
Grand Prix,246,12
|
||||
Gravitar,248,19
|
||||
Great Escape,64,17
|
||||
Gremlins,248,20
|
||||
Guardian,64,17
|
||||
Gyruss,224,16
|
||||
H.E.R.O.,248,15
|
||||
Halloween,64,17
|
||||
Hangman,64,17
|
||||
Harbor Escape,64,15
|
||||
Haunted House,64,21
|
||||
Hole Hunter,64,21
|
||||
Home Run,32,19
|
||||
Human Cannonball,32,16
|
||||
Hunt & Score,32,24
|
||||
I Want My Mommy,64,20
|
||||
Ice Hockey,64,23
|
||||
Ikari Warriors,246,18
|
||||
Indy 500,32,23
|
||||
Infiltrate,64,16
|
||||
International Soccer,64,18
|
||||
IQ 180,64,28
|
||||
James Bond 007,224,14
|
||||
Jaw Breaker,64,23
|
||||
Journey Escape,64,19
|
||||
Joust,248,22
|
||||
JoustPong,64,14
|
||||
Jr. Pac-Man,246,17
|
||||
Jungle Fever,64,20
|
||||
Jungle Hunt,248,20
|
||||
Kaboom!,32,20
|
||||
Kangaroo,248,15
|
||||
Karate,64,17
|
||||
Keystone Kapers,64,14
|
||||
King Kong,64,23
|
||||
Klax,246,17
|
||||
Knight on the Town,64,13
|
||||
Kool-Aid Man,64,26
|
||||
Krull,248,20
|
||||
Kung Fu Superkicks,248,14
|
||||
Kung-Fu Master,248,27
|
||||
Lady in Wading,64,23
|
||||
Laser Blast,32,22
|
||||
Laser Gates,64,19
|
||||
Lilly Advenure,64,19
|
||||
Lochjaw,64,22
|
||||
Lock 'n' Chase,64,15
|
||||
London Blitz,64,22
|
||||
Lost Luggage,64,20
|
||||
M.A.D.,64,20
|
||||
M.A.S.H,64,14
|
||||
MagiCard,192,15
|
||||
Malagai,64,17
|
||||
Mangia',64,15
|
||||
Marauder,64,15
|
||||
Marine Wars,64,16
|
||||
Mario Bros.,248,19
|
||||
Master Builder,64,20
|
||||
Masters of the Universe,231,22
|
||||
Math Gran Prix,64,32
|
||||
Maze Craze,64,22
|
||||
Mega Force,64,18
|
||||
MegaBoy,240,18
|
||||
MegaMania,64,16
|
||||
Midnight Magic,246,17
|
||||
Millipede,246,23
|
||||
Mind Maze,248,18
|
||||
Miner 2049er,63,18
|
||||
Miner 2049er Volume II,63,20
|
||||
Mines of Minos,64,30
|
||||
Miniature Golf,32,22
|
||||
Miss Piggy's Wedding,248,22
|
||||
Missile Command,64,29
|
||||
Missile Control,64,23
|
||||
Mission 3000 A.D.,64,23
|
||||
Mission Survive,64,25
|
||||
Mogul Maniac,64,23
|
||||
Montezuma's Revenge,224,20
|
||||
Moon Patrol,248,28
|
||||
Moonsweeper,248,20
|
||||
Motocross,64,20
|
||||
Motocross Racer,248,17
|
||||
MotoRodeo,246,24
|
||||
Mountain King,250,18
|
||||
Mouse Trap,64,22
|
||||
Mr. Do!,248,18
|
||||
Mr. Do!'s Castle,224,16
|
||||
Mr. Postman,64,25
|
||||
Ms. Pac-Man,248,19
|
||||
Music Machine,64,20
|
||||
My Golf,248,21
|
||||
Name This Game,64,16
|
||||
Night Driver,32,22
|
||||
Night Stalker,64,20
|
||||
Nightmare,64,21
|
||||
No Escape!,64,17
|
||||
Nuts,64,18
|
||||
Obelix,248,12
|
||||
Off the Wall,246,15
|
||||
Oink!,64,21
|
||||
Omega Race,250,13
|
||||
Open Sesame,64,19
|
||||
Oscar's Trash Race,248,19
|
||||
Othello,32,27
|
||||
Out of Control,64,15
|
||||
Outlaw,32,22
|
||||
Pac-Kong,64,14
|
||||
Pac-Man,64,16
|
||||
Panda Chase,64,15
|
||||
Parachute,64,19
|
||||
Pele's Soccer,64,17
|
||||
Pengo,248,21
|
||||
Pepsi Invaders,64,14
|
||||
Pete Rose Baseball,246,22
|
||||
Phantom Tank,64,27
|
||||
Pharaoh's Curse,64,20
|
||||
Philly Flasher,64,23
|
||||
Phoenix,248,22
|
||||
Pick 'n' Pile,246,16
|
||||
Picnic,64,22
|
||||
Piece o' Cake,64,14
|
||||
Pigs in Space,248,21
|
||||
Pitfall II,208,22
|
||||
Pitfall!,64,19
|
||||
Planet Patrol,64,16
|
||||
Plaque Attack,64,21
|
||||
Polaris,63,21
|
||||
Pole Position,248,15
|
||||
Polo,32,22
|
||||
Pompeii,64,12
|
||||
Pooyan,64,15
|
||||
Popeye,224,14
|
||||
Porky's,248,15
|
||||
Pressure Cooker,248,16
|
||||
Private Eye,248,24
|
||||
Pyramid War,64,20
|
||||
Q-bert,64,19
|
||||
Q-bert's Qubes,224,14
|
||||
Quadrun,248,23
|
||||
Quest for Quintana Roo,248,16
|
||||
Quick Step!,64,31
|
||||
Rabbit Transit,248,19
|
||||
Racing Car,64,23
|
||||
Racquetball,64,18
|
||||
Radar Lock,246,19
|
||||
Raft Rider,64,19
|
||||
Raiders of the Lost Ark,248,18
|
||||
Ram It,64,32
|
||||
Rampage!,246,14
|
||||
Raumpatrouille,64,17
|
||||
Reactor,64,22
|
||||
RealSports Baseball,248,15
|
||||
RealSports Boxing,246,28
|
||||
RealSports Football,248,26
|
||||
RealSports Soccer,248,28
|
||||
RealSports Tennis,248,26
|
||||
RealSports Volleyball,64,26
|
||||
Rescue Terra I,64,29
|
||||
Resgate Espacial,248,22
|
||||
Revenge of the Beefsteak Tomatoes,64,25
|
||||
Riddle of the Sphinx,64,41
|
||||
River Patrol,63,28
|
||||
River Raid,64,20
|
||||
River Raid II,246,18
|
||||
Road Runner,246,22
|
||||
Robin Hood,248,20
|
||||
Robot Tank,254,19
|
||||
Roc 'n Rope,248,19
|
||||
Room of Doom,64,20
|
||||
Rubik's Cube,64,20
|
||||
Save Our Ship,64,20
|
||||
Scuba Diver,64,21
|
||||
Sea Hawk,64,19
|
||||
Sea Hunt,64,16
|
||||
Sea Monster,64,16
|
||||
Seaquest,64,19
|
||||
Secret Quest,246,16
|
||||
Sentinel,246,21
|
||||
Shark Attack,64,17
|
||||
Shootin' Gallery,64,20
|
||||
Shuttle Orbiter,64,24
|
||||
Sir Lancelot,248,23
|
||||
Skate Boardin',248,21
|
||||
Skeet Shoot,32,23
|
||||
Ski Hunt,64,19
|
||||
Ski Run,64,16
|
||||
Skiing,32,15
|
||||
Sky Diver,32,14
|
||||
Sky Jinks,32,17
|
||||
Sky Skipper,64,17
|
||||
Slot Machine,32,19
|
||||
Slot Racers,32,20
|
||||
Smurf Rescue in Gargamels Castle,248,19
|
||||
Smurfs Save the Day,248,41
|
||||
Sneak 'n Peek,64,28
|
||||
Snoopy and the Red Baron,248,21
|
||||
Solar Fox,248,33
|
||||
Solar Storm,64,18
|
||||
Solaris,246,19
|
||||
Sorcerer,64,16
|
||||
Sorcerer's Apprentice,248,16
|
||||
Space Attack,64,30
|
||||
Space Canyon,64,20
|
||||
Space Cavern,64,20
|
||||
Space Invaders,64,20
|
||||
Space Jockey,32,22
|
||||
Space Shuttle,248,20
|
||||
Space Tunnel,64,22
|
||||
Space War,32,20
|
||||
Spacechase,64,17
|
||||
SpaceMaster X-7,64,18
|
||||
Spider Fighter,64,23
|
||||
Spider Maze,64,22
|
||||
Spider-Man,64,19
|
||||
Spike's Peak,248,18
|
||||
Spitfire Attack,64,21
|
||||
Springer,63,23
|
||||
Sprint Master,246,16
|
||||
Spy Hunter,248,22
|
||||
Squeeze Box,64,19
|
||||
Squirrel,64,19
|
||||
Sssnake,64,16
|
||||
Stampede,32,15
|
||||
Star Fox,64,16
|
||||
Star Raiders,248,16
|
||||
Star Ship,32,21
|
||||
Star Strike,64,17
|
||||
Star Trek,248,19
|
||||
Star Voyager,64,18
|
||||
Star Wars - Arcade Game,224,20
|
||||
Star Wars - Death Star Battle,224,32
|
||||
Star Wars - Empire Strikes Back,64,38
|
||||
Star Wars - Jedi Arena,64,39
|
||||
Stargate,246,30
|
||||
Stargunner,64,17
|
||||
StarMaster,64,18
|
||||
Steeplechase,32,18
|
||||
Stellar Track,64,20
|
||||
Strategy X,64,21
|
||||
Strawberry Shortcake,64,18
|
||||
Street Racer,32,28
|
||||
Stronghold,64,20
|
||||
Stunt Man,64,18
|
||||
Submarine Commander,64,17
|
||||
Sub-Scan,64,27
|
||||
Subterranea,248,16
|
||||
Summer Games,246,20
|
||||
Super Baseball,246,21
|
||||
Super Breakout,64,23
|
||||
Super Challenge Baseball,64,22
|
||||
Super Challenge Football,64,32
|
||||
Super Cobra,224,32
|
||||
Super Football,248,20
|
||||
Superman,64,23
|
||||
Surfer's Paradise,64,16
|
||||
Surround,32,25
|
||||
Survival Run,64,16
|
||||
SwordQuest - EarthWorld,248,20
|
||||
SwordQuest - FireWorld,248,32
|
||||
SwordQuest - WaterWorld,248,31
|
||||
Tac-Scan,64,32
|
||||
Tanks But No Tanks,64,16
|
||||
Tapeworm,64,26
|
||||
Tapper,248,16
|
||||
Tax Avoiders,248,15
|
||||
Taz,248,21
|
||||
Tempest,248,12
|
||||
Tennis,32,16
|
||||
Texas Chainsaw Massacre,64,14
|
||||
Threshold,64,31
|
||||
Thunderground,64,17
|
||||
Time Pilot,249,21
|
||||
Time Warp,64,19
|
||||
Title Match Pro Wrestling,248,17
|
||||
Tomarc the Barbarian,248,34
|
||||
Tomcat,246,29
|
||||
Tooth Protectors,224,15
|
||||
Towering Inferno,64,25
|
||||
Track and Field,246,24
|
||||
Treasure Below,64,24
|
||||
Treasure Island,64,22
|
||||
Trick Shot,64,23
|
||||
TRON - Deadly Discs,64,18
|
||||
Tunnel Runner,250,27
|
||||
Turmoil,64,22
|
||||
Tutankham,224,15
|
||||
Universal Chaos,64,18
|
||||
Up 'n Down,248,23
|
||||
Vanguard,248,19
|
||||
Venture,64,17
|
||||
Video Checkers,64,15
|
||||
Video Chess,64,22
|
||||
Video Jogger,64,19
|
||||
Video Life,32,20
|
||||
Video Olympics,32,18
|
||||
Video Pinball,64,22
|
||||
Video Reflex,64,21
|
||||
Vogel Flieh,64,20
|
||||
Vulture Attack,64,19
|
||||
Wabbit,64,22
|
||||
Walker,64,14
|
||||
Wall Ball,64,14
|
||||
Wall Break,64,17
|
||||
Wall-Defender,64,18
|
||||
Warlords,64,21
|
||||
Warplock,64,16
|
||||
Wing War,248,16
|
||||
Wings,250,17
|
||||
Winter Games,246,14
|
||||
Wizard of Wor,64,21
|
||||
Word Zapper,64,21
|
||||
World End,64,19
|
||||
Worm War I,64,17
|
||||
Xenophobe,246,18
|
||||
X-Man,64,18
|
||||
Yars' Revenge,64,13
|
||||
Zaxxon,248,21
|
||||
Zoo Fun,64,15
|
||||
Z-Tack,64,15
|
||||
EOF,0,0
|
822
sd/c64cart.txt
Normal file
822
sd/c64cart.txt
Normal file
|
@ -0,0 +1,822 @@
|
|||
128er Quickload
|
||||
00,1
|
||||
|
||||
256K-EPROM-System
|
||||
00,1
|
||||
|
||||
64 Doctor
|
||||
00,1
|
||||
|
||||
64MON
|
||||
00,1
|
||||
|
||||
Action Cartridge Plus
|
||||
01,5
|
||||
|
||||
Action Replay Professional
|
||||
01,5
|
||||
|
||||
Activision Decathlon
|
||||
00,3
|
||||
|
||||
Adventure 1
|
||||
00,3
|
||||
|
||||
Adventure 3
|
||||
00,3
|
||||
|
||||
Adventure Creator
|
||||
00,3
|
||||
|
||||
Aegean Voyage
|
||||
00,3
|
||||
|
||||
After the War
|
||||
17,7
|
||||
|
||||
Alf in the Color Caves
|
||||
00,3
|
||||
|
||||
Alien Sidestep
|
||||
00,1
|
||||
|
||||
Alpha Build
|
||||
00,1
|
||||
|
||||
Alphabet Zoo
|
||||
00,3
|
||||
|
||||
Arnie Armchair's Howzat Cricket Game
|
||||
00,3
|
||||
|
||||
Astroblitz
|
||||
00,1
|
||||
|
||||
Attack of the Mutant Camels
|
||||
00,1
|
||||
|
||||
Avenger (MAX)
|
||||
00,1
|
||||
|
||||
BadLands
|
||||
05,6
|
||||
|
||||
Batman
|
||||
05,7
|
||||
|
||||
Battle Command
|
||||
05,7
|
||||
|
||||
Battlezone
|
||||
00,3
|
||||
|
||||
BC's Quest for Tires
|
||||
00,3
|
||||
|
||||
Beamrider
|
||||
00,3
|
||||
|
||||
Big Bird's Funhouse
|
||||
00,3
|
||||
|
||||
Big Bird's Special Delivery
|
||||
00,3
|
||||
|
||||
Black Box
|
||||
00,3
|
||||
|
||||
Blueprint
|
||||
00,3
|
||||
|
||||
Bowling (MAX)
|
||||
00,3
|
||||
|
||||
Bridge 64
|
||||
00,3
|
||||
|
||||
Bubble Burst
|
||||
00,3
|
||||
|
||||
Buck Rogers
|
||||
00,3
|
||||
|
||||
Bug Crusher
|
||||
00,1
|
||||
|
||||
C-64 Diagnostic
|
||||
00,1
|
||||
|
||||
C-64 Import Test Diag
|
||||
00,1
|
||||
|
||||
C64-FORTH
|
||||
00,2
|
||||
|
||||
Calc Result Advanced
|
||||
00,1
|
||||
|
||||
Castle Hassle
|
||||
00,3
|
||||
|
||||
Centipede
|
||||
00,1
|
||||
|
||||
Chase H.Q. II
|
||||
05,8
|
||||
|
||||
Checkers
|
||||
00,3
|
||||
|
||||
Choplifter!
|
||||
00,3
|
||||
|
||||
Close Encounters of the Worst Kind
|
||||
00,1
|
||||
|
||||
Clowns (MAX)
|
||||
00,1
|
||||
|
||||
Coccinelle cherche dessinateur
|
||||
00,1
|
||||
|
||||
Coco-Notes
|
||||
00,3
|
||||
|
||||
Colossus Chess +2
|
||||
08,6
|
||||
|
||||
COMAL 80
|
||||
21,6
|
||||
|
||||
Commodore 64 Diagnostic
|
||||
00,1
|
||||
|
||||
Congo Bongo
|
||||
00,3
|
||||
|
||||
Conrad Disk Booster
|
||||
00,1
|
||||
|
||||
Cosmic Life
|
||||
00,1
|
||||
|
||||
Crisis Mountain
|
||||
00,3
|
||||
|
||||
Cyberball
|
||||
05,7
|
||||
|
||||
Dance Fantasy
|
||||
00,1
|
||||
|
||||
Dancing Feats
|
||||
00,3
|
||||
|
||||
DeathFlood
|
||||
19,7
|
||||
|
||||
Defender
|
||||
00,3
|
||||
|
||||
Dela S-4-Modul
|
||||
00,1
|
||||
|
||||
Delta Drawing
|
||||
00,3
|
||||
|
||||
Der Rechenlowe
|
||||
11,3
|
||||
|
||||
Der Rechtschreiblowe
|
||||
11,3
|
||||
|
||||
Designer's Pencil
|
||||
00,3
|
||||
|
||||
Diamond Mine
|
||||
00,3
|
||||
|
||||
Diary 64
|
||||
00,1
|
||||
|
||||
Dig Dug
|
||||
00,3
|
||||
|
||||
Doc'64
|
||||
00,1
|
||||
|
||||
Donkey Kong
|
||||
00,3
|
||||
|
||||
Dot Gobbler
|
||||
00,1
|
||||
|
||||
Double Dragon (HES)
|
||||
19,7
|
||||
|
||||
Double Dragon (Ocean)
|
||||
05,7
|
||||
|
||||
Dragonsden
|
||||
00,3
|
||||
|
||||
Ducks Ahoy!
|
||||
00,3
|
||||
|
||||
Electronic Mailbox-64
|
||||
00,1
|
||||
|
||||
Epyx Fast Load Cartridge
|
||||
10,1
|
||||
|
||||
Ernie's Magic Shapes
|
||||
00,3
|
||||
|
||||
Espial
|
||||
00,3
|
||||
|
||||
ExBASIC Level II
|
||||
00,1
|
||||
|
||||
Expert
|
||||
06,1
|
||||
|
||||
Facemaker
|
||||
00,1
|
||||
|
||||
Falconian Invaders
|
||||
00,1
|
||||
|
||||
Fiendish Freddy's Big Top o' Fun +3
|
||||
15,9
|
||||
|
||||
Final Cartridge
|
||||
13,3
|
||||
|
||||
Final Cartridge III
|
||||
03,6
|
||||
|
||||
Financial Advisor
|
||||
00,1
|
||||
|
||||
Format- und Hardcopymodul
|
||||
12,1
|
||||
|
||||
Fraction Fever
|
||||
00,1
|
||||
|
||||
Frog Master
|
||||
00,1
|
||||
|
||||
Frogger
|
||||
00,3
|
||||
|
||||
Frogger +3
|
||||
19,6
|
||||
|
||||
Frogger II
|
||||
00,3
|
||||
|
||||
Galaxian
|
||||
00,3
|
||||
|
||||
Galaxions +1
|
||||
00,3
|
||||
|
||||
Gateway to Apshai
|
||||
00,3
|
||||
|
||||
Ghostbusters
|
||||
05,5
|
||||
|
||||
Gorf
|
||||
00,3
|
||||
|
||||
Graf 64
|
||||
00,1
|
||||
|
||||
Gridrunner
|
||||
00,1
|
||||
|
||||
Gridrunner II
|
||||
00,1
|
||||
|
||||
Gyruss
|
||||
00,3
|
||||
|
||||
H.E.R.O.
|
||||
00,3
|
||||
|
||||
Halftime Battlin' Bands
|
||||
00,3
|
||||
|
||||
Happy-Packer
|
||||
12,1
|
||||
|
||||
HES Mon 64
|
||||
00,1
|
||||
|
||||
HES Writer 64
|
||||
00,1
|
||||
|
||||
Hop Along Counting
|
||||
00,1
|
||||
|
||||
Human Skeleton Tutorial
|
||||
00,1
|
||||
|
||||
Hypra-Disk-Modul II
|
||||
00,1
|
||||
|
||||
International Football
|
||||
00,3
|
||||
|
||||
Jack Attack
|
||||
00,3
|
||||
|
||||
James Bond 007
|
||||
00,3
|
||||
|
||||
Jawbreaker
|
||||
00,1
|
||||
|
||||
Juice!
|
||||
00,3
|
||||
|
||||
Jukebox
|
||||
00,1
|
||||
|
||||
Jumpman Junior
|
||||
00,3
|
||||
|
||||
Jungle Hunt
|
||||
00,3
|
||||
|
||||
Jupiter Lander (MAX)
|
||||
00,1
|
||||
|
||||
Kickman (MAX)
|
||||
00,1
|
||||
|
||||
Kids on Keys
|
||||
00,1
|
||||
|
||||
Kindercomp
|
||||
00,1
|
||||
|
||||
Kung-Fu Master
|
||||
05,5
|
||||
|
||||
Laser Cycles
|
||||
00,1
|
||||
|
||||
Lazarian
|
||||
00,3
|
||||
|
||||
Lazer Zone
|
||||
00,1
|
||||
|
||||
Leader Board
|
||||
05,5
|
||||
|
||||
Learning with Leeper
|
||||
00,3
|
||||
|
||||
LeMans (MAX)
|
||||
00,1
|
||||
|
||||
Linking Logic
|
||||
00,3
|
||||
|
||||
Lode Runner
|
||||
00,3
|
||||
|
||||
Logic Levels
|
||||
00,3
|
||||
|
||||
Lunar Leeper
|
||||
00,3
|
||||
|
||||
Magic Desk I
|
||||
19,5
|
||||
|
||||
Magic Formel
|
||||
14,6
|
||||
|
||||
Mario's Brewery
|
||||
00,1
|
||||
|
||||
MasterType
|
||||
00,3
|
||||
|
||||
Math Mileage
|
||||
00,3
|
||||
|
||||
MAX BASIC (MAX)
|
||||
00,3
|
||||
|
||||
Maze Man
|
||||
00,1
|
||||
|
||||
Maze Master
|
||||
00,3
|
||||
|
||||
Memory Manor
|
||||
00,1
|
||||
|
||||
MicroProse Soccer +2
|
||||
07,7
|
||||
|
||||
Miner 2049er
|
||||
00,3
|
||||
|
||||
MINI BASIC I (MAX)
|
||||
00,1
|
||||
|
||||
Minnesota Fat's Pool Challenger
|
||||
00,1
|
||||
|
||||
Mole Attack (MAX)
|
||||
00,1
|
||||
|
||||
Money Wars (MAX)
|
||||
00,1
|
||||
|
||||
Moon Patrol
|
||||
00,3
|
||||
|
||||
Moondust
|
||||
00,1
|
||||
|
||||
Motor Mania
|
||||
00,3
|
||||
|
||||
Mountain King
|
||||
00,3
|
||||
|
||||
Movie Musical Madness
|
||||
00,3
|
||||
|
||||
Mr. Cool
|
||||
00,1
|
||||
|
||||
Mr. TNT
|
||||
00,1
|
||||
|
||||
Ms. Pac-Man
|
||||
00,3
|
||||
|
||||
Muistio 64
|
||||
00,1
|
||||
|
||||
Music Composer (MAX)
|
||||
00,1
|
||||
|
||||
Music Machine (MAX)
|
||||
00,1
|
||||
|
||||
Myth
|
||||
15,9
|
||||
|
||||
Narco Police
|
||||
17,7
|
||||
|
||||
Navy SEALs
|
||||
05,7
|
||||
|
||||
Ninja Remix
|
||||
15,9
|
||||
|
||||
Nordic Power Action Cartridge
|
||||
09,5
|
||||
|
||||
Nova Blast
|
||||
00,3
|
||||
|
||||
Number Nabber Shape Grabber
|
||||
00,1
|
||||
|
||||
Number Tumblers
|
||||
00,1
|
||||
|
||||
Oil's Well
|
||||
00,3
|
||||
|
||||
Omega Race
|
||||
00,1
|
||||
|
||||
Omega Race (MAX)
|
||||
00,1
|
||||
|
||||
Pac-Man
|
||||
00,1
|
||||
|
||||
Paint Brush
|
||||
00,3
|
||||
|
||||
Pancho
|
||||
00,3
|
||||
|
||||
Pang
|
||||
05,7
|
||||
|
||||
Park Patrol
|
||||
19,5
|
||||
|
||||
Pastfinder
|
||||
00,3
|
||||
|
||||
Peanut Butter Panic
|
||||
00,3
|
||||
|
||||
Pinball Spectacular (MAX)
|
||||
00,3
|
||||
|
||||
Pipes
|
||||
00,1
|
||||
|
||||
Pit
|
||||
00,1
|
||||
|
||||
Pitfall II
|
||||
00,3
|
||||
|
||||
Pitfall!
|
||||
00,1
|
||||
|
||||
Pitstop
|
||||
00,3
|
||||
|
||||
Pole Position
|
||||
00,3
|
||||
|
||||
Popeye
|
||||
00,3
|
||||
|
||||
Power Cartridge
|
||||
02,3
|
||||
|
||||
Princess and the Frog
|
||||
00,3
|
||||
|
||||
Professional Skateboard Simulator +2
|
||||
07,7
|
||||
|
||||
PS-64t
|
||||
00,1
|
||||
|
||||
Q-bert
|
||||
00,3
|
||||
|
||||
Rack 'em Up!
|
||||
00,3
|
||||
|
||||
Radar Rat Race(MAX)
|
||||
00,1
|
||||
|
||||
Ranch
|
||||
00,3
|
||||
|
||||
Retro Ball
|
||||
00,1
|
||||
|
||||
REX-Ramfloppy
|
||||
00,1
|
||||
|
||||
River Raid
|
||||
00,3
|
||||
|
||||
Road Race (MAX)
|
||||
00,1
|
||||
|
||||
RoboCop 2
|
||||
05,8
|
||||
|
||||
RoboCop 3
|
||||
05,7
|
||||
|
||||
Robotron - 2084
|
||||
00,3
|
||||
|
||||
Rootin' Tootin'
|
||||
00,3
|
||||
|
||||
Sales Cartridge
|
||||
00,3
|
||||
|
||||
Sammy Lightfoot
|
||||
00,3
|
||||
|
||||
Satan
|
||||
17,7
|
||||
|
||||
Save New York
|
||||
00,1
|
||||
|
||||
Sea Speller
|
||||
00,1
|
||||
|
||||
Sea Wolf (MAX)
|
||||
00,1
|
||||
|
||||
Seafox
|
||||
00,3
|
||||
|
||||
Seahorse Hide'n Seek
|
||||
00,3
|
||||
|
||||
Serpentine
|
||||
00,3
|
||||
|
||||
Sesame Street
|
||||
00,3
|
||||
|
||||
Shadow of the Beast
|
||||
05,8
|
||||
|
||||
Simons' BASIC
|
||||
04,3
|
||||
|
||||
Solar Fox
|
||||
00,3
|
||||
|
||||
Song Maker
|
||||
00,1
|
||||
|
||||
Space Action
|
||||
00,1
|
||||
|
||||
Space Gun
|
||||
05,8
|
||||
|
||||
Space Ric-O-Shay
|
||||
00,1
|
||||
|
||||
Space Shuttle
|
||||
00,3
|
||||
|
||||
Speed Math & Bingo Math (MAX)
|
||||
00,1
|
||||
|
||||
Speedsaver $C000
|
||||
00,0
|
||||
|
||||
Speedsaver Combi
|
||||
00,1
|
||||
|
||||
Spitball
|
||||
00,1
|
||||
|
||||
Spy Hunter
|
||||
00,3
|
||||
|
||||
Star Post
|
||||
00,1
|
||||
|
||||
Star Ranger
|
||||
00,3
|
||||
|
||||
Star Trek
|
||||
00,3
|
||||
|
||||
Star Wars
|
||||
00,3
|
||||
|
||||
Stat 64
|
||||
00,1
|
||||
|
||||
States and Capitals Tutorial
|
||||
00,1
|
||||
|
||||
Stix
|
||||
00,1
|
||||
|
||||
Story Machine
|
||||
00,3
|
||||
|
||||
Super Alien (MAX)
|
||||
00,1
|
||||
|
||||
Super Expander 64
|
||||
00,1
|
||||
|
||||
Super Sketch
|
||||
00,1
|
||||
|
||||
Super Smash
|
||||
00,1
|
||||
|
||||
Super Snapshot 5
|
||||
20,6
|
||||
|
||||
Super Zaxxon
|
||||
18,4
|
||||
|
||||
Tank Wars
|
||||
00,1
|
||||
|
||||
Tapper
|
||||
00,3
|
||||
|
||||
Teledata
|
||||
00,1
|
||||
|
||||
Tennis
|
||||
19,5
|
||||
|
||||
Tenpins
|
||||
00,1
|
||||
|
||||
Tenpins +2
|
||||
19,5
|
||||
|
||||
Terminator 2 +2
|
||||
05,9
|
||||
|
||||
Threshold
|
||||
00,1
|
||||
|
||||
Timebound
|
||||
00,3
|
||||
|
||||
Toki
|
||||
05,7
|
||||
|
||||
Tool-64
|
||||
00,1
|
||||
|
||||
Tooth Invaders
|
||||
00,3
|
||||
|
||||
Toy Bizarre
|
||||
00,3
|
||||
|
||||
Trashman
|
||||
00,1
|
||||
|
||||
Turbo Maze Man
|
||||
00,1
|
||||
|
||||
Tyler's Dungeons
|
||||
00,1
|
||||
|
||||
Ultrex Quadro Maze
|
||||
00,1
|
||||
|
||||
Up & Add'Em
|
||||
00,3
|
||||
|
||||
Up for Grabs
|
||||
00,1
|
||||
|
||||
Up'n Down
|
||||
00,3
|
||||
|
||||
Utah Counties Tutorial
|
||||
00,1
|
||||
|
||||
VIC-Text 64
|
||||
00,3
|
||||
|
||||
Viduzzles
|
||||
00,3
|
||||
|
||||
Viking Raider
|
||||
00,3
|
||||
|
||||
Vindicators
|
||||
05,6
|
||||
|
||||
Visible Solar System (MAX)
|
||||
00,1
|
||||
|
||||
Warp Speed
|
||||
16,3
|
||||
|
||||
Webster
|
||||
00,3
|
||||
|
||||
Wizard of Id's Wiztype
|
||||
00,3
|
||||
|
||||
Wizard of Wor
|
||||
00,3
|
||||
|
||||
Wizard of Wor (MAX)
|
||||
00,1
|
||||
|
||||
Wonder Boy
|
||||
05,6
|
||||
|
||||
Write Now! 64
|
||||
00,3
|
||||
|
||||
Zaxxon
|
||||
18,4
|
||||
|
||||
Zenji
|
||||
00,3
|
||||
|
||||
Zone Ranger
|
||||
00,3
|
||||
|
1170
sd/colv.txt
1170
sd/colv.txt
File diff suppressed because it is too large
Load Diff
6
sd/config.txt
Normal file
6
sd/config.txt
Normal file
|
@ -0,0 +1,6 @@
|
|||
oscr.logging=1
|
||||
lcd.confColor=0
|
||||
lcd.red=0
|
||||
lcd.green=100
|
||||
lcd.blue=0
|
||||
md.saveType=0
|
|
@ -1,33 +1,96 @@
|
|||
Alien Invasion,2,0
|
||||
Backgammon/Acey-Deucey,0,20
|
||||
Baseball,0,29
|
||||
Bowling,0,15
|
||||
Casino Poker,2,14
|
||||
Checkers,0,19
|
||||
Demonstration Cartridge,0,15
|
||||
Demonstration Cartridge 2,0,30
|
||||
Desert Fox/Shooting Gallery,0,32
|
||||
Dodge It,0,34
|
||||
Drag Race,0,15
|
||||
Galactic Space Wars/Lunar Lander,0,16
|
||||
Hangman,1,39
|
||||
Magic Numbers,0,14
|
||||
Math Quiz I,0,20
|
||||
Math Quiz II,0,18
|
||||
Maze (Multi),0,19
|
||||
Memory Match 1 & 2,0,19
|
||||
Muehle (Multi),0,25
|
||||
Ordtaevling,1,21
|
||||
Pinball Challenge,0,18
|
||||
Pro Football,2,24
|
||||
Rat' Mal,1,19
|
||||
Robot War/Torpedo Alley,0,15
|
||||
Schach,3,30
|
||||
Slot Machine,0,13
|
||||
Sonar Search,0,19
|
||||
Space War,0,19
|
||||
Spitfire,0,16
|
||||
Tic-Tac-Toe (Multi),0,15
|
||||
Video Blackjack,0,26
|
||||
Video Whizball,1,22
|
||||
EOF,0,0
|
||||
Alien Invasion
|
||||
2
|
||||
|
||||
Backgammon/Acey-Deucey
|
||||
0
|
||||
|
||||
Baseball
|
||||
0
|
||||
|
||||
Bowling
|
||||
0
|
||||
|
||||
Casino Poker
|
||||
2
|
||||
|
||||
Checkers
|
||||
0
|
||||
|
||||
Demonstration Cartridge
|
||||
0
|
||||
|
||||
Demonstration Cartridge 2
|
||||
0
|
||||
|
||||
Desert Fox/Shooting Gallery
|
||||
0
|
||||
|
||||
Dodge It
|
||||
0
|
||||
|
||||
Drag Race
|
||||
0
|
||||
|
||||
Galactic Space Wars/Lunar Lander
|
||||
0
|
||||
|
||||
Hangman
|
||||
1
|
||||
|
||||
Magic Numbers
|
||||
0
|
||||
|
||||
Math Quiz I
|
||||
0
|
||||
|
||||
Math Quiz II
|
||||
0
|
||||
|
||||
Maze (Multi)
|
||||
0
|
||||
|
||||
Memory Match 1 & 2
|
||||
0
|
||||
|
||||
Muehle (Multi)
|
||||
0
|
||||
|
||||
Ordtaevling
|
||||
1
|
||||
|
||||
Pinball Challenge
|
||||
0
|
||||
|
||||
Pro Football
|
||||
2
|
||||
|
||||
Rat' Mal
|
||||
1
|
||||
|
||||
Robot War/Torpedo Alley
|
||||
0
|
||||
|
||||
Schach
|
||||
3
|
||||
|
||||
Slot Machine
|
||||
0
|
||||
|
||||
Sonar Search
|
||||
0
|
||||
|
||||
Space War
|
||||
0
|
||||
|
||||
Spitfire
|
||||
0
|
||||
|
||||
Tic-Tac-Toe (Multi)
|
||||
0
|
||||
|
||||
Video Blackjack
|
||||
0
|
||||
|
||||
Video Whizball
|
||||
1
|
||||
|
||||
|
|
19992
sd/gba.txt
19992
sd/gba.txt
File diff suppressed because it is too large
Load Diff
1158
sd/intv.txt
1158
sd/intv.txt
File diff suppressed because it is too large
Load Diff
|
@ -1,6 +1,9 @@
|
|||
Anime Land.bin
|
||||
98A0597D
|
||||
|
||||
Chakrakun no Omajinai Paradise.bin
|
||||
A5341F72
|
||||
|
||||
HARIHARI Seal Paradise.bin
|
||||
7CB100B3
|
||||
|
||||
|
|
2905
sd/msxcart.txt
2905
sd/msxcart.txt
File diff suppressed because it is too large
Load Diff
6162
sd/n64.txt
6162
sd/n64.txt
File diff suppressed because it is too large
Load Diff
18675
sd/nes.txt
18675
sd/nes.txt
File diff suppressed because it is too large
Load Diff
533
sd/ody2cart.txt
533
sd/ody2cart.txt
|
@ -1,134 +1,399 @@
|
|||
4 en 1 Ligne,1,1,0
|
||||
4 in 1 Row,1,1,20
|
||||
Air Battle (V+),0,3,19
|
||||
Alien Invaders - Plus,0,0,24
|
||||
Alpine Skiing,0,0,30
|
||||
Armored Encounter + Sub Chase,0,0,22
|
||||
Atlantis,0,1,38
|
||||
Attack of the Timelord,0,1,17
|
||||
Baseball,0,0,31
|
||||
Billard Americain,0,0,17
|
||||
Billard Americain (V+),0,2,26
|
||||
Billard Electrique,0,0,31
|
||||
Billard Electrique (V+),0,2,27
|
||||
Blackjack,0,0,32
|
||||
Blobbers,0,2,18
|
||||
Blockout + Breakdown,0,0,17
|
||||
Bombardeio Submarino + Tiro ao Alvo,0,0,29
|
||||
Bowling + Basketball,0,0,44
|
||||
Buraco Negro,0,2,29
|
||||
Casino Slot Machine,0,0,21
|
||||
Catch the Ball + Noughts and Crosses,0,0,28
|
||||
Chat et Souris,0,1,45
|
||||
Chess,0,0,23
|
||||
Chez Maxime (V+),0,1,14
|
||||
Chinese Logic,0,0,25
|
||||
Clay Pigeon,0,1,22
|
||||
Comando Noturno,0,2,20
|
||||
Computer Golf,0,0,24
|
||||
Computer Intro,0,0,22
|
||||
Computer Programmer,0,0,23
|
||||
Conflit Cosmique,0,0,28
|
||||
Conquest of the World,0,1,25
|
||||
Cosmic Conflict,0,0,30
|
||||
Cosmic Conflict (V+),0,2,24
|
||||
Course de Voitures + Autodrome + Cryptogramme,0,0,29
|
||||
Course de Voitures + Autodrome + Cryptogramme (V+),0,2,54
|
||||
Demon Attack,0,1,59
|
||||
Demon Attack (V+),0,2,21
|
||||
Depth Charge + Marksman,0,0,26
|
||||
Desafio Chines,0,0,32
|
||||
Dynasty,0,0,23
|
||||
Electronic Table Soccer,0,0,16
|
||||
Exojet (V+),0,2,32
|
||||
Football,0,0,20
|
||||
Football Electronique + Hockey Electronique,0,0,17
|
||||
Freedom Fighters,0,1,52
|
||||
Freedom Fighters (V+),0,2,25
|
||||
Frogger,0,2,30
|
||||
Golf,0,0,16
|
||||
Great Wall Street Fortune Hunt,0,1,13
|
||||
Guerre de l'Espace (V+),0,2,39
|
||||
Guerre Laser,0,0,32
|
||||
Gunfighter,0,0,21
|
||||
Helicopter Rescue (V+),0,4,19
|
||||
Hockey + Soccer,0,0,31
|
||||
I've Got Your Number,0,0,24
|
||||
Invaders from Hyperspace,0,0,29
|
||||
Jeu de Quilles + Basketball,0,0,33
|
||||
Jeu de Quilles + Basketball (V+),0,2,36
|
||||
Jumping Acrobats,0,0,41
|
||||
K.C. Munchkin,0,1,25
|
||||
K.C.'s Krazy Chase,0,1,22
|
||||
Keyboard Creations,0,0,27
|
||||
Killer Bees,0,2,27
|
||||
Killer Bees (V+),0,2,20
|
||||
Kinder im Verkehr 1,0,0,25
|
||||
La Quete des Anneaux,0,1,28
|
||||
La Ruche Infernale (V+),0,2,29
|
||||
Labyrinth Game + Supermind,0,0,32
|
||||
Las Vegas,0,0,35
|
||||
Las Vegas Blackjack,0,0,18
|
||||
Laser War,0,0,28
|
||||
Le Mur Magique,0,0,18
|
||||
Le Tresor Englouti (V+),0,2,23
|
||||
Loony Balloon (V+),0,2,32
|
||||
Matchmaker + Logix + Buzzword,0,0,27
|
||||
Math-A-Magic + Echo,0,0,38
|
||||
Mathematicien + Echo,0,0,28
|
||||
Monkeyshines,0,1,29
|
||||
Morse,0,0,21
|
||||
Moto-Crash (V+),0,2,14
|
||||
Mousing Cat,0,1,24
|
||||
Munchkin,0,1,20
|
||||
Musician,1,1,17
|
||||
Neutron Star (V+),0,3,17
|
||||
Newscaster,0,0,26
|
||||
Nightmare,0,2,19
|
||||
Nightmare (V+),0,2,18
|
||||
Nimble Numbers Ned,0,1,23
|
||||
Norseman (V+),0,2,27
|
||||
O Malabarista + Jogo da Velha,0,0,22
|
||||
O Segredo do Farao,0,1,38
|
||||
Out of this World + Helicopter Rescue,0,0,27
|
||||
P.T. Barnum's Acrobats,0,1,46
|
||||
Pachinko,0,0,31
|
||||
Pairs + Space Rendezvous + Logic,0,0,17
|
||||
Pick Axe Pete,0,1,41
|
||||
Pickaxe Pete (V+),0,2,22
|
||||
Pocket Billiards,0,0,26
|
||||
Popeye,0,2,25
|
||||
Power Lords,0,1,15
|
||||
Power Lords (Alt),0,2,20
|
||||
Prendre l'Argent et Fuir,0,0,26
|
||||
Q-Bert,0,2,33
|
||||
Quest for the Rings,0,1,15
|
||||
Race + Spin-out + Cryptogram (V+),0,2,28
|
||||
Samurai,0,0,42
|
||||
Satellite Attack,0,0,16
|
||||
Satellite Attack (V+),0,2,25
|
||||
Secret of the Pharaohs,0,0,30
|
||||
Showdown in 2100 A.D.,0,0,31
|
||||
Sid the Spellbinder,0,1,30
|
||||
Skiing,0,0,28
|
||||
Smithereens,0,1,15
|
||||
Speedway + Spin-out + Crypto-logic,0,0,20
|
||||
Stone Sling,0,0,43
|
||||
Stone Sling (V+),0,2,20
|
||||
Super Bee,0,1,25
|
||||
Super Cobra,0,2,18
|
||||
Syracuse (V+),0,1,20
|
||||
Take the Money and Run,0,0,22
|
||||
Terrahawks (V+),0,2,31
|
||||
Thunderball,0,0,24
|
||||
Trans American Rally (V+),0,4,20
|
||||
Turtles,0,2,34
|
||||
Type & Tell,0,1,16
|
||||
UFO,0,0,20
|
||||
Verkehrsspiele 1,0,0,12
|
||||
Verkehrsspiele 2,0,0,25
|
||||
Volleyball,0,0,25
|
||||
Volleyball Electronique,0,0,19
|
||||
Wall Street,0,1,32
|
||||
War of Nerves,0,0,20
|
||||
EOF,0,0,22
|
||||
4 en 1 Ligne
|
||||
1,1
|
||||
|
||||
4 in 1 Row
|
||||
1,1
|
||||
|
||||
Air Battle (V+)
|
||||
0,3
|
||||
|
||||
Alien Invaders - Plus
|
||||
0,0
|
||||
|
||||
Alpine Skiing
|
||||
0,0
|
||||
|
||||
Armored Encounter + Sub Chase
|
||||
0,0
|
||||
|
||||
Atlantis
|
||||
0,1
|
||||
|
||||
Attack of the Timelord
|
||||
0,1
|
||||
|
||||
Baseball
|
||||
0,0
|
||||
|
||||
Billard Americain
|
||||
0,0
|
||||
|
||||
Billard Americain (V+)
|
||||
0,2
|
||||
|
||||
Billard Electrique
|
||||
0,0
|
||||
|
||||
Billard Electrique (V+)
|
||||
0,2
|
||||
|
||||
Blackjack
|
||||
0,0
|
||||
|
||||
Blobbers
|
||||
0,2
|
||||
|
||||
Blockout + Breakdown
|
||||
0,0
|
||||
|
||||
Bombardeio Submarino + Tiro ao Alvo
|
||||
0,0
|
||||
|
||||
Bowling + Basketball
|
||||
0,0
|
||||
|
||||
Buraco Negro
|
||||
0,2
|
||||
|
||||
Casino Slot Machine
|
||||
0,0
|
||||
|
||||
Catch the Ball + Noughts and Crosses
|
||||
0,0
|
||||
|
||||
Chat et Souris
|
||||
0,1
|
||||
|
||||
Chess
|
||||
0,0
|
||||
|
||||
Chez Maxime (V+)
|
||||
0,1
|
||||
|
||||
Chinese Logic
|
||||
0,0
|
||||
|
||||
Clay Pigeon
|
||||
0,1
|
||||
|
||||
Comando Noturno
|
||||
0,2
|
||||
|
||||
Computer Golf
|
||||
0,0
|
||||
|
||||
Computer Intro
|
||||
0,0
|
||||
|
||||
Computer Programmer
|
||||
0,0
|
||||
|
||||
Conflit Cosmique
|
||||
0,0
|
||||
|
||||
Conquest of the World
|
||||
0,1
|
||||
|
||||
Cosmic Conflict
|
||||
0,0
|
||||
|
||||
Cosmic Conflict (V+)
|
||||
0,2
|
||||
|
||||
Course de Voitures + Autodrome + Cryptogramme
|
||||
0,0
|
||||
|
||||
Course de Voitures + Autodrome + Cryptogramme (V+)
|
||||
0,2
|
||||
|
||||
Demon Attack
|
||||
0,1
|
||||
|
||||
Demon Attack (V+)
|
||||
0,2
|
||||
|
||||
Depth Charge + Marksman
|
||||
0,0
|
||||
|
||||
Desafio Chines
|
||||
0,0
|
||||
|
||||
Dynasty
|
||||
0,0
|
||||
|
||||
Electronic Table Soccer
|
||||
0,0
|
||||
|
||||
Exojet (V+)
|
||||
0,2
|
||||
|
||||
Football
|
||||
0,0
|
||||
|
||||
Football Electronique + Hockey Electronique
|
||||
0,0
|
||||
|
||||
Freedom Fighters
|
||||
0,1
|
||||
|
||||
Freedom Fighters (V+)
|
||||
0,2
|
||||
|
||||
Frogger
|
||||
0,2
|
||||
|
||||
Golf
|
||||
0,0
|
||||
|
||||
Great Wall Street Fortune Hunt
|
||||
0,1
|
||||
|
||||
Guerre de l'Espace (V+)
|
||||
0,2
|
||||
|
||||
Guerre Laser
|
||||
0,0
|
||||
|
||||
Gunfighter
|
||||
0,0
|
||||
|
||||
Helicopter Rescue (V+)
|
||||
0,4
|
||||
|
||||
Hockey + Soccer
|
||||
0,0
|
||||
|
||||
I've Got Your Number
|
||||
0,0
|
||||
|
||||
Invaders from Hyperspace
|
||||
0,0
|
||||
|
||||
Jeu de Quilles + Basketball
|
||||
0,0
|
||||
|
||||
Jeu de Quilles + Basketball (V+)
|
||||
0,2
|
||||
|
||||
Jumping Acrobats
|
||||
0,0
|
||||
|
||||
K.C. Munchkin
|
||||
0,1
|
||||
|
||||
K.C.'s Krazy Chase
|
||||
0,1
|
||||
|
||||
Keyboard Creations
|
||||
0,0
|
||||
|
||||
Killer Bees
|
||||
0,2
|
||||
|
||||
Killer Bees (V+)
|
||||
0,2
|
||||
|
||||
Kinder im Verkehr 1
|
||||
0,0
|
||||
|
||||
La Quete des Anneaux
|
||||
0,1
|
||||
|
||||
La Ruche Infernale (V+)
|
||||
0,2
|
||||
|
||||
Labyrinth Game + Supermind
|
||||
0,0
|
||||
|
||||
Las Vegas
|
||||
0,0
|
||||
|
||||
Las Vegas Blackjack
|
||||
0,0
|
||||
|
||||
Laser War
|
||||
0,0
|
||||
|
||||
Le Mur Magique
|
||||
0,0
|
||||
|
||||
Le Tresor Englouti (V+)
|
||||
0,2
|
||||
|
||||
Loony Balloon (V+)
|
||||
0,2
|
||||
|
||||
Matchmaker + Logix + Buzzword
|
||||
0,0
|
||||
|
||||
Math-A-Magic + Echo
|
||||
0,0
|
||||
|
||||
Mathematicien + Echo
|
||||
0,0
|
||||
|
||||
Monkeyshines
|
||||
0,1
|
||||
|
||||
Morse
|
||||
0,0
|
||||
|
||||
Moto-Crash (V+)
|
||||
0,2
|
||||
|
||||
Mousing Cat
|
||||
0,1
|
||||
|
||||
Munchkin
|
||||
0,1
|
||||
|
||||
Musician
|
||||
1,1
|
||||
|
||||
Neutron Star (V+)
|
||||
0,3
|
||||
|
||||
Newscaster
|
||||
0,0
|
||||
|
||||
Nightmare
|
||||
0,2
|
||||
|
||||
Nightmare (V+)
|
||||
0,2
|
||||
|
||||
Nimble Numbers Ned
|
||||
0,1
|
||||
|
||||
Norseman (V+)
|
||||
0,2
|
||||
|
||||
O Malabarista + Jogo da Velha
|
||||
0,0
|
||||
|
||||
O Segredo do Farao
|
||||
0,1
|
||||
|
||||
Out of this World + Helicopter Rescue
|
||||
0,0
|
||||
|
||||
P.T. Barnum's Acrobats
|
||||
0,1
|
||||
|
||||
Pachinko
|
||||
0,0
|
||||
|
||||
Pairs + Space Rendezvous + Logic
|
||||
0,0
|
||||
|
||||
Pick Axe Pete
|
||||
0,1
|
||||
|
||||
Pickaxe Pete (V+)
|
||||
0,2
|
||||
|
||||
Pocket Billiards
|
||||
0,0
|
||||
|
||||
Popeye
|
||||
0,2
|
||||
|
||||
Power Lords
|
||||
0,1
|
||||
|
||||
Power Lords (Alt)
|
||||
0,2
|
||||
|
||||
Prendre l'Argent et Fuir
|
||||
0,0
|
||||
|
||||
Q-Bert
|
||||
0,2
|
||||
|
||||
Quest for the Rings
|
||||
0,1
|
||||
|
||||
Race + Spin-out + Cryptogram (V+)
|
||||
0,2
|
||||
|
||||
Samurai
|
||||
0,0
|
||||
|
||||
Satellite Attack
|
||||
0,0
|
||||
|
||||
Satellite Attack (V+)
|
||||
0,2
|
||||
|
||||
Secret of the Pharaohs
|
||||
0,0
|
||||
|
||||
Showdown in 2100 A.D.
|
||||
0,0
|
||||
|
||||
Sid the Spellbinder
|
||||
0,1
|
||||
|
||||
Skiing
|
||||
0,0
|
||||
|
||||
Smithereens
|
||||
0,1
|
||||
|
||||
Speedway + Spin-out + Crypto-logic
|
||||
0,0
|
||||
|
||||
Stone Sling
|
||||
0,0
|
||||
|
||||
Stone Sling (V+)
|
||||
0,2
|
||||
|
||||
Super Bee
|
||||
0,1
|
||||
|
||||
Super Cobra
|
||||
0,2
|
||||
|
||||
Syracuse (V+)
|
||||
0,1
|
||||
|
||||
Take the Money and Run
|
||||
0,0
|
||||
|
||||
Terrahawks (V+)
|
||||
0,2
|
||||
|
||||
Thunderball
|
||||
0,0
|
||||
|
||||
Trans American Rally (V+)
|
||||
0,4
|
||||
|
||||
Turtles
|
||||
0,2
|
||||
|
||||
Type & Tell
|
||||
0,1
|
||||
|
||||
UFO
|
||||
0,0
|
||||
|
||||
Verkehrsspiele 1
|
||||
0,0
|
||||
|
||||
Verkehrsspiele 2
|
||||
0,0
|
||||
|
||||
Volleyball
|
||||
0,0
|
||||
|
||||
Volleyball Electronique
|
||||
0,0
|
||||
|
||||
Wall Street
|
||||
0,1
|
||||
|
||||
War of Nerves
|
||||
0,0
|
||||
|
||||
|
|
2760
sd/pce.txt
2760
sd/pce.txt
File diff suppressed because it is too large
Load Diff
384
sd/pcw.txt
384
sd/pcw.txt
|
@ -1,153 +1,231 @@
|
|||
Shinkenzemi 'Chuugaku Kouza' - Chuu 2 Eigo (Japan) (5BB211NH).pcw
|
||||
505F954E
|
||||
|
||||
Shinkenzemi 'Chuugaku Kouza' - Chuu 2 Eigo (Japan) (5BB212SS).pcw
|
||||
FF3E9B62
|
||||
|
||||
Shinkenzemi 'Chuugaku Kouza' - Chuugaku Chiri (Japan) (6BD410).pcw
|
||||
AD5136AE
|
||||
|
||||
Shinkenzemi 'Chuugaku Kouza' - Chuugaku Rekishi (Japan) (5BC410).pcw
|
||||
7865BE62
|
||||
|
||||
Shinkenzemi 'Chuugaku Kouza' - Koukou Juken (Ei - Sha - Ri) (Japan) (6BI711).pcw
|
||||
B9831924
|
||||
|
||||
Shinkenzemi 'Chuugaku Kouza' - Koukou Juken (Koku - Suu) (Japan) (6BI712).pcw
|
||||
81F4FA3E
|
||||
|
||||
Shinkenzemi Chuugaku Kouza - Chuu 1 Eigo (Japan) (0BB111NH).pcw
|
||||
D7FD8C5D
|
||||
|
||||
Shinkenzemi Chuugaku Kouza - Chuu 1 Eigo (Japan) (0BB113NC).pcw
|
||||
5711252F
|
||||
|
||||
Shinkenzemi Chuugaku Kouza - Chuu 1 Eigo (Japan) (7BB111NH).pcw
|
||||
BE0CFA07
|
||||
|
||||
Shinkenzemi Chuugaku Kouza - Chuu 1 Eigo (Japan) (7BB112SS).pcw
|
||||
FEACC308
|
||||
|
||||
Shinkenzemi Chuugaku Kouza - Chuu 1 Suugaku (Japan) (1BM111).pcw
|
||||
5DB9B999
|
||||
|
||||
Shinkenzemi Chuugaku Kouza - Chuu 2 Eigo (Japan) (7BB211NH).pcw
|
||||
5138519C
|
||||
|
||||
Shinkenzemi Chuugaku Kouza - Chuu 2 Eigo (Japan) (7BB212SS).pcw
|
||||
31E9E8CC
|
||||
|
||||
Shinkenzemi Chuugaku Kouza - Chuu 2 Eigo (Japan) (7BB214TE).pcw
|
||||
3C08E0DA
|
||||
|
||||
Shinkenzemi Chuugaku Kouza - Chuu 3 Eigo (Japan) (7BB311NH).pcw
|
||||
A18685A5
|
||||
|
||||
Shinkenzemi Chuugaku Kouza - Chuu 3 Eigo (Japan) (7BB312SS).pcw
|
||||
C4676FC9
|
||||
|
||||
Shinkenzemi Chuugaku Kouza - Chuu 3 Eigo (Japan) (7BB313NC).pcw
|
||||
DDE96468
|
||||
|
||||
Shinkenzemi Chuugaku Kouza - Chuu 3 Eigo (Japan) (7BB315OW).pcw
|
||||
AE06430D
|
||||
|
||||
Shinkenzemi Chuugaku Kouza - Chuu 3 Eigo (Japan) (7BB317CB).pcw
|
||||
149501FB
|
||||
|
||||
Shinkenzemi Chuugaku Kouza - Chuugaku Chiri (Japan) (7BD410).pcw
|
||||
8DE1ED5A
|
||||
|
||||
Shinkenzemi Chuugaku Kouza - Chuugaku Chiri (Japan) (9BD410).pcw
|
||||
A1B3C2C9
|
||||
|
||||
Shinkenzemi Chuugaku Kouza - Chuugaku Chiri - Rekishi Pack (Chiri Soft - Rekishi Soft Kanzen Taiou Ban) (Japan) (8BD400).pcw
|
||||
77D1D534
|
||||
|
||||
Shinkenzemi Chuugaku Kouza - Chuugaku Chiri - Rekishi Pack (Japan) (0BD400).pcw
|
||||
21895AF8
|
||||
|
||||
Shinkenzemi Chuugaku Kouza - Chuugaku Chiri - Rekishi Pack (Japan) (0BD401).pcw
|
||||
660E84A5
|
||||
|
||||
Shinkenzemi Chuugaku Kouza - Chuugaku Kokugo - Hyakunin Isshu (Japan) (1BK401).pcw
|
||||
B0444C88
|
||||
|
||||
Shinkenzemi Chuugaku Kouza - Chuugaku Koumin (Japan) (0BE311).pcw
|
||||
BF9DA3EA
|
||||
|
||||
Shinkenzemi Chuugaku Kouza - Chuugaku Koumin (Japan) (7BE310).pcw
|
||||
EFEF730E
|
||||
|
||||
Shinkenzemi Chuugaku Kouza - Chuugaku Rekishi (Japan) (7BC410).pcw
|
||||
2EB6506E
|
||||
|
||||
Shinkenzemi Chuugaku Kouza - Chuugaku Rika (1-bunya) (Japan) (7BF411).pcw
|
||||
BDC7847D
|
||||
|
||||
Shinkenzemi Chuugaku Kouza - Chuugaku Rika (1-bunya) (Japan) (Rev 1) (7BF411).pcw
|
||||
0C80EC13
|
||||
|
||||
Shinkenzemi Chuugaku Kouza - Chuugaku Rika (2-bunya) (Japan) (7BF412).pcw
|
||||
A6E409E8
|
||||
|
||||
Shinkenzemi Chuugaku Kouza - Chuugaku Rika (2-bunya) (Japan) (Rev 1) (7BF412).pcw
|
||||
336289BC
|
||||
|
||||
Shinkenzemi Chuugaku Kouza - Chuugaku Rika Pack (1-bunya - Soft 2-bunya Soft Kanzen Taiou Ban) (Japan) (8BF400).pcw
|
||||
E1D5C9E0
|
||||
|
||||
Shinkenzemi Chuugaku Kouza - Chuugaku Rika Pack (Japan) (0BF400).pcw
|
||||
341E732B
|
||||
|
||||
Shinkenzemi Chuugaku Kouza - Chuugaku Rika Pack (Japan) (1BF400).pcw
|
||||
6205144B
|
||||
|
||||
Shinkenzemi Chuugaku Kouza - Hinshutsu Sekaishi Kouryaku (Japan) (8BCD01).pcw
|
||||
38384AD4
|
||||
|
||||
Shinkenzemi Chuugaku Kouza - Jitsugi 4-kyouka (Gijutsu Katei, Hoken Taiiku, Ongaku, Bijutsu) (Japan) (9BG410).pcw
|
||||
E34787BB
|
||||
|
||||
Shinkenzemi Chuugaku Kouza - Koukou Juken (Ei - Sha - Ri) (Japan) (0BI711).pcw
|
||||
7F23D0D6
|
||||
|
||||
Shinkenzemi Chuugaku Kouza - Koukou Juken (Ei - Sha - Ri) (Japan) (1BI711).pcw
|
||||
CADEA841
|
||||
|
||||
Shinkenzemi Chuugaku Kouza - Koukou Juken (Ei - Sha - Ri) (Japan) (9BI711).pcw
|
||||
61F2A31B
|
||||
|
||||
Shinkenzemi Chuugaku Kouza - Koukou Juken (Ei - Sha - Ri) (Japan) (7BI711).pcw
|
||||
53C2FF43
|
||||
|
||||
Shinkenzemi Chuugaku Kouza - Koukou Juken (Koku - Suu) (Japan) (7BI712).pcw
|
||||
410BAC94
|
||||
|
||||
Shinkenzemi Chuugaku Kouza - Koukou Juken (Koku - Suu) (Japan) (9BI712).pcw
|
||||
0FCDC311
|
||||
|
||||
Shinkenzemi Chuugaku Kouza - Hinshutsu Nihonshi Kouryaku (Japan) (8BCD02).pcw
|
||||
68BC5E95
|
||||
|
||||
Shinkenzemi Koukou Kouza - Daigaku Juken Series - Hinshutsu Eijukugo (Japan) (7BBD02).pcw
|
||||
C3DB01F2
|
||||
|
||||
Shinkenzemi Koukou Kouza - Daigaku Juken Series - Hinshutsu Eitango (Japan) (7BBD01).pcw
|
||||
2BAD015C
|
||||
|
||||
Shinkenzemi Koukou Kouza - Daigaku Juken Series - Juuyou Eigo Koubun (Japan) (7BBD03).pcw
|
||||
9C9C0426
|
||||
|
||||
Shinkenzemi Koukou Kouza - Hinshutsu Nihonshi Kouryaku (Japan) (9BCD02).pcw
|
||||
7911AEC2
|
||||
|
||||
Shinkenzemi Koukou Kouza - Hinshutsu Sekaishi Kouryaku (Japan) (9BCD01).pcw
|
||||
9E274AC9
|
||||
|
||||
Shinkenzemi Koukou Kouza - Juuyou Kobun Kouryaku (Japan) (0BKD01).pcw
|
||||
C6157409
|
||||
|
||||
Shinkenzemi Koukou Kouza - Juuyou Kobun Kouryaku (Japan) (8BKD01).pcw
|
||||
F5DF48F5
|
||||
|
||||
Eiken Jun 2-kyuu + 3-kyuu (Japan) (2BK922).pcw
|
||||
1BE3A77A
|
||||
|
||||
Shinkenzemi 'Chuugaku Kouza' - Chuu 1 Eigo (Japan) (5BB111NH).pcw
|
||||
55AB157D
|
||||
|
||||
Shinkenzemi 'Chuugaku Kouza' - Chuu 1 Eigo (Japan) (5BB112SS).pcw
|
||||
7F7AAF5B
|
||||
|
||||
Shinkenzemi 'Chuugaku Kouza' - Chuu 2 Eigo (Japan) (5BB211NH).pcw
|
||||
505F954E
|
||||
|
||||
Shinkenzemi 'Chuugaku Kouza' - Chuu 2 Eigo (Japan) (5BB212SS).pcw
|
||||
FF3E9B62
|
||||
|
||||
Shinkenzemi 'Chuugaku Kouza' - Chuu 2 Eigo (Japan) (5BB215OW).pcw
|
||||
E07172BD
|
||||
|
||||
Shinkenzemi 'Chuugaku Kouza' - Chuu 3 Eigo (Japan) (6BB311NH).pcw
|
||||
3CE2760D
|
||||
|
||||
Shinkenzemi 'Chuugaku Kouza' - Chuugaku Chiri (Japan) (6BD410).pcw
|
||||
AD5136AE
|
||||
|
||||
Shinkenzemi 'Chuugaku Kouza' - Chuugaku Chiri (Japan) (6BD410) (Alt).pcw
|
||||
32A902B8
|
||||
|
||||
Shinkenzemi 'Chuugaku Kouza' - Chuugaku Koumin (Japan) (6BE310).pcw
|
||||
0AF098CA
|
||||
|
||||
Shinkenzemi 'Chuugaku Kouza' - Chuugaku Rekishi (Japan) (5BC410).pcw
|
||||
7865BE62
|
||||
|
||||
Shinkenzemi 'Chuugaku Kouza' - Chuugaku Rekishi (Japan) (5BC410) (Alt).pcw
|
||||
44AFEBAD
|
||||
|
||||
Shinkenzemi 'Chuugaku Kouza' - Chuugaku Rekishi (Japan) (5BC410) (Alt 2).pcw
|
||||
A5EEC22E
|
||||
|
||||
Shinkenzemi 'Chuugaku Kouza' - Koukou Juken (Ei - Sha - Ri) (Japan) (6BI711).pcw
|
||||
B9831924
|
||||
|
||||
Shinkenzemi 'Chuugaku Kouza' - Koukou Juken (Koku - Suu) (Japan) (6BI712).pcw
|
||||
AEEC5776
|
||||
|
||||
Shinkenzemi Chuugaku Kouza - Chuu 1 Eigo (Japan) (0BB113NC - 7BB113NC).pcw
|
||||
775E1A65
|
||||
|
||||
Shinkenzemi Chuugaku Kouza - Chuu 1 Eigo (Japan) (0BB111NH - 7BB111NH).pcw
|
||||
BE0CFA07
|
||||
|
||||
Shinkenzemi Chuugaku Kouza - Chuu 1 Eigo (Japan) (7BB112SS).pcw
|
||||
742C17C3
|
||||
|
||||
Shinkenzemi Chuugaku Kouza - Chuu 1 Eigo (Japan) (7BB115OW).pcw
|
||||
2CB93051
|
||||
|
||||
Shinkenzemi Chuugaku Kouza - Chuu 1 Suugaku (Japan) (1BM111).pcw
|
||||
5DB9B999
|
||||
|
||||
Shinkenzemi Chuugaku Kouza - Chuu 2 Eigo (Japan) (7BB211NH).pcw
|
||||
5138519C
|
||||
|
||||
Shinkenzemi Chuugaku Kouza - Chuu 2 Eigo (Japan) (7BB212SS).pcw
|
||||
31E9E8CC
|
||||
|
||||
Shinkenzemi Chuugaku Kouza - Chuu 2 Eigo (Japan) (7BB213NC).pcw
|
||||
9C279B5A
|
||||
|
||||
Shinkenzemi Chuugaku Kouza - Chuu 2 Eigo (Japan) (7BB214TE).pcw
|
||||
3C08E0DA
|
||||
|
||||
Shinkenzemi Chuugaku Kouza - Chuu 2 Eigo (Japan) (7BB215OW).pcw
|
||||
370CFF2F
|
||||
|
||||
Shinkenzemi Chuugaku Kouza - Chuu 2 Eigo (New Horizon, Columbus 21) (Japan) (2BB211).pcw
|
||||
0B20B2D4
|
||||
|
||||
Shinkenzemi Chuugaku Kouza - Chuu 3 Eigo (Japan) (0BB313NC - 7BB313NC).pcw
|
||||
DDE96468
|
||||
|
||||
Shinkenzemi Chuugaku Kouza - Chuu 3 Eigo (Japan) (0BB314TE).pcw
|
||||
D87A661F
|
||||
|
||||
Shinkenzemi Chuugaku Kouza - Chuu 3 Eigo (Japan) (0BB311NH - 7BB311NH).pcw
|
||||
A18685A5
|
||||
|
||||
Shinkenzemi Chuugaku Kouza - Chuu 3 Eigo (Japan) (7BB312SS).pcw
|
||||
C4676FC9
|
||||
|
||||
Shinkenzemi Chuugaku Kouza - Chuu 3 Eigo (Japan) (0BB315OW - 7BB315OW).pcw
|
||||
AE06430D
|
||||
|
||||
Shinkenzemi Chuugaku Kouza - Chuu 3 Eigo (Japan) (7BB317CB).pcw
|
||||
149501FB
|
||||
|
||||
Shinkenzemi Chuugaku Kouza - Chuu 3 Eigo (New Crown, Total English) (Japan) (2BB314).pcw
|
||||
63CD8224
|
||||
|
||||
Shinkenzemi Chuugaku Kouza - Chuu 3 Eigo (New Horizon, Columbus 21) (Japan) (2BB311).pcw
|
||||
919279ED
|
||||
|
||||
Shinkenzemi Chuugaku Kouza - Chuugaku Chiri (Japan) (0BD410).pcw
|
||||
AC87B035
|
||||
|
||||
Shinkenzemi Chuugaku Kouza - Chuugaku Chiri (Japan) (1BD411).pcw
|
||||
22E0A9B1
|
||||
|
||||
Shinkenzemi Chuugaku Kouza - Chuugaku Chiri (Japan) (7BD410).pcw
|
||||
8DE1ED5A
|
||||
|
||||
Shinkenzemi Chuugaku Kouza - Chuugaku Chiri (Japan) (9BD410 - 9BD411).pcw
|
||||
A1B3C2C9
|
||||
|
||||
Shinkenzemi Chuugaku Kouza - Chuugaku Chiri - Rekishi Pack (Japan) (0BD400).pcw
|
||||
5601F35C
|
||||
|
||||
Shinkenzemi Chuugaku Kouza - Chuugaku Chiri - Rekishi Pack (Japan) (0BD400) (Alt).pcw
|
||||
660E84A5
|
||||
|
||||
Shinkenzemi Chuugaku Kouza - Chuugaku Chiri - Rekishi Pack (Japan) (8BD400).pcw
|
||||
F27575FE
|
||||
|
||||
Shinkenzemi Chuugaku Kouza - Chuugaku Kokugo - Hyakunin Isshu (Japan) (1BK401).pcw
|
||||
B0444C88
|
||||
|
||||
Shinkenzemi Chuugaku Kouza - Chuugaku Kokugo - Hyakunin Isshu (Japan) (1BK401) (Alt).pcw
|
||||
7A5EF3D5
|
||||
|
||||
Shinkenzemi Chuugaku Kouza - Chuugaku Koumin (Japan) (0BE311).pcw
|
||||
BF9DA3EA
|
||||
|
||||
Shinkenzemi Chuugaku Kouza - Chuugaku Koumin (Japan) (2BE310).pcw
|
||||
48A3B1B7
|
||||
|
||||
Shinkenzemi Chuugaku Kouza - Chuugaku Koumin (Japan) (0BE310 - 7BE310).pcw
|
||||
EFEF730E
|
||||
|
||||
Shinkenzemi Chuugaku Kouza - Chuugaku Rekishi (Japan) (0BC410).pcw
|
||||
D0FD58EE
|
||||
|
||||
Shinkenzemi Chuugaku Kouza - Chuugaku Rekishi (Japan) (7BC410).pcw
|
||||
2EB6506E
|
||||
|
||||
Shinkenzemi Chuugaku Kouza - Chuugaku Rika (1-bunya) (Japan) (0BF411).pcw
|
||||
83883CB6
|
||||
|
||||
Shinkenzemi Chuugaku Kouza - Chuugaku Rika (1-bunya) (Japan) (1BF411).pcw
|
||||
1B2B5622
|
||||
|
||||
Shinkenzemi Chuugaku Kouza - Chuugaku Rika (1-bunya) (Japan) (7BF411).pcw
|
||||
BDC7847D
|
||||
|
||||
Shinkenzemi Chuugaku Kouza - Chuugaku Rika (1-bunya) (Japan) (Rev 1) (7BF411).pcw
|
||||
0C80EC13
|
||||
|
||||
Shinkenzemi Chuugaku Kouza - Chuugaku Rika (2-bunya) (Japan) (0BF412).pcw
|
||||
B820F013
|
||||
|
||||
Shinkenzemi Chuugaku Kouza - Chuugaku Rika (2-bunya) (Japan) (1BF412).pcw
|
||||
CAD91342
|
||||
|
||||
Shinkenzemi Chuugaku Kouza - Chuugaku Rika (2-bunya) (Japan) (7BF412).pcw
|
||||
A6E409E8
|
||||
|
||||
Shinkenzemi Chuugaku Kouza - Chuugaku Rika (2-bunya) (Japan) (Rev 1) (7BF412).pcw
|
||||
336289BC
|
||||
|
||||
Shinkenzemi Chuugaku Kouza - Chuugaku Rika Pack (Japan) (0BF400).pcw
|
||||
50016928
|
||||
|
||||
Shinkenzemi Chuugaku Kouza - Chuugaku Rika Pack (Japan) (1BF400).pcw
|
||||
6205144B
|
||||
|
||||
Shinkenzemi Chuugaku Kouza - Chuugaku Rika Pack (Japan) (8BF400).pcw
|
||||
D35A38DA
|
||||
|
||||
Shinkenzemi Chuugaku Kouza - Hinshutsu Sekaishi Kouryaku (Japan) (8BCD01).pcw
|
||||
38384AD4
|
||||
|
||||
Shinkenzemi Chuugaku Kouza - Jitsugi 4-kyouka (Gijutsu Katei, Hoken Taiiku, Ongaku, Bijutsu) (Japan) (9BG410).pcw
|
||||
E34787BB
|
||||
|
||||
Shinkenzemi Chuugaku Kouza - Koukou Juken (Ei - Sha - Ri) (Japan) (0BI711).pcw
|
||||
7F23D0D6
|
||||
|
||||
Shinkenzemi Chuugaku Kouza - Koukou Juken (Ei - Sha - Ri) (Japan) (1BI711).pcw
|
||||
CADEA841
|
||||
|
||||
Shinkenzemi Chuugaku Kouza - Koukou Juken (Ei - Sha - Ri) (Japan) (9BI711).pcw
|
||||
61F2A31B
|
||||
|
||||
Shinkenzemi Chuugaku Kouza - Koukou Juken (Ei - Sha - Ri) (Japan) (7BI711).pcw
|
||||
53C2FF43
|
||||
|
||||
Shinkenzemi Chuugaku Kouza - Koukou Juken (Koku - Suu) (Japan) (7BI712).pcw
|
||||
410BAC94
|
||||
|
||||
Shinkenzemi Chuugaku Kouza - Koukou Juken (Koku - Suu) (Japan) (9BI712).pcw
|
||||
0FCDC311
|
||||
|
||||
Shinkenzemi Chuugaku Kouza - Koukou Juken (Koku - Suu) (Japan) (9BI712) (Alt).pcw
|
||||
C35A53A4
|
||||
|
||||
Shinkenzemi Chuugaku Kouza - Koukou Juken EX (Yuugou - Shiryou Mondai Kouryaku) Rika Shakai (Japan) (3BI710).pcw
|
||||
588F8570
|
||||
|
||||
Shinkenzemi Chuugaku Kouza - Hinshutsu Nihonshi Kouryaku (Japan) (8BCD02).pcw
|
||||
68BC5E95
|
||||
|
||||
Shinkenzemi Koukou Kouza - Daigaku Juken Series - Hinshutsu Eijukugo (Japan) (7BBD02).pcw
|
||||
C3DB01F2
|
||||
|
||||
Shinkenzemi Koukou Kouza - Daigaku Juken Series - Hinshutsu Eitango (Japan) (7BBD01).pcw
|
||||
2BAD015C
|
||||
|
||||
Shinkenzemi Koukou Kouza - Daigaku Juken Series - Juuyou Eigo Koubun (Japan) (7BBD03).pcw
|
||||
9C9C0426
|
||||
|
||||
Shinkenzemi Koukou Kouza - Hinshutsu Nihonshi Kouryaku (Japan) (9BCD02).pcw
|
||||
7911AEC2
|
||||
|
||||
Shinkenzemi Koukou Kouza - Hinshutsu Sekaishi Kouryaku (Japan) (9BCD01).pcw
|
||||
9E274AC9
|
||||
|
||||
Shinkenzemi Koukou Kouza - Juuyou Kobun Kouryaku (Japan) (0BKD01).pcw
|
||||
C6157409
|
||||
|
||||
Shinkenzemi Koukou Kouza - Juuyou Kobun Kouryaku (Japan) (8BKD01).pcw
|
||||
F5DF48F5
|
||||
|
||||
|
|
59
sd/pkmn.txt
Normal file
59
sd/pkmn.txt
Normal file
|
@ -0,0 +1,59 @@
|
|||
Pichu Bros. Mini (Japan).min
|
||||
00D8C968
|
||||
|
||||
Pokemon Anime Card Daisakusen (Japan).min
|
||||
199D7AB1
|
||||
|
||||
Pokemon Party Mini (Europe).min
|
||||
54ACB670
|
||||
|
||||
Pokemon Party Mini (Japan).min
|
||||
AE2DDE60
|
||||
|
||||
Pokemon Party Mini (USA).min
|
||||
938D3819
|
||||
|
||||
Pokemon Pinball Mini (Japan).min
|
||||
398D47DE
|
||||
|
||||
Pokemon Pinball Mini (USA, Europe).min
|
||||
A0091534
|
||||
|
||||
Pokemon Puzzle Collection (France).min
|
||||
3004C354
|
||||
|
||||
Pokemon Puzzle Collection (Germany).min
|
||||
22101046
|
||||
|
||||
Pokemon Puzzle Collection (Japan).min
|
||||
95AFAE59
|
||||
|
||||
Pokemon Puzzle Collection (USA, Europe).min
|
||||
2B348340
|
||||
|
||||
Pokemon Puzzle Collection Vol. 2 (Japan).min
|
||||
76A1BBF8
|
||||
|
||||
Pokemon Race Mini (Japan).min
|
||||
F8C842B5
|
||||
|
||||
Pokemon Shock Tetris (Japan).min
|
||||
B4B5CC20
|
||||
|
||||
Pokemon Sodateyasan Mini (Japan).min
|
||||
D55FC4C8
|
||||
|
||||
Pokemon Tetris (Europe) (En,Ja,Fr).min
|
||||
2FB23527
|
||||
|
||||
Pokemon Zany Cards (France).min
|
||||
830DA957
|
||||
|
||||
Pokemon Zany Cards (Germany).min
|
||||
C009D501
|
||||
|
||||
Pokemon Zany Cards (USA, Europe).min
|
||||
8A2FC063
|
||||
|
||||
Togepi no Daibouken (Japan).min
|
||||
33B3492B
|
1476
sd/sg1000.txt
1476
sd/sg1000.txt
File diff suppressed because it is too large
Load Diff
4050
sd/sms.txt
4050
sd/sms.txt
File diff suppressed because it is too large
Load Diff
23428
sd/snes.txt
23428
sd/snes.txt
File diff suppressed because it is too large
Load Diff
40
sd/st.txt
Normal file
40
sd/st.txt
Normal file
|
@ -0,0 +1,40 @@
|
|||
Bishoujo Senshi Sailor Moon Sailor Stars - Fuwafuwa Panic 2 (Japan).st
|
||||
BB5C4238
|
||||
|
||||
Crayon Shin-chan - Nagagutsu Dobon!! (Japan).st
|
||||
8EB753F3
|
||||
|
||||
Gegege no Kitarou - Youkai Donjara (Japan).st
|
||||
4296500D
|
||||
|
||||
Gekisou Sentai Carranger - Zenkai! Racer Senshi (Japan).st
|
||||
14C66FCA
|
||||
|
||||
Poi Poi Ninja World (Japan).st
|
||||
32B2B3DD
|
||||
|
||||
SD Gundam Generation - Axis Senki (Japan).st
|
||||
72B4235F
|
||||
|
||||
SD Gundam Generation - Babylonia Kenkoku Senki (Japan).st
|
||||
792D884C
|
||||
|
||||
SD Gundam Generation - Colony Kakutouki (Japan).st
|
||||
C5DFA8FD
|
||||
|
||||
SD Gundam Generation - Gryps Senki (Japan).st
|
||||
48ECAE44
|
||||
|
||||
SD Gundam Generation - Ichinen Sensouki (Japan).st
|
||||
AFD74DCB
|
||||
|
||||
SD Gundam Generation - Zanscare Senki (Japan).st
|
||||
EFD3A865
|
||||
|
||||
SD Ultra Battle - Seven Densetsu (Japan).st
|
||||
43AD5A45
|
||||
|
||||
SD Ultra Battle - Ultraman Densetsu (Japan).st
|
||||
04939D14
|
||||
|
||||
|
198
sd/vb.txt
198
sd/vb.txt
|
@ -1,99 +1,99 @@
|
|||
3-D Tetris (USA).vb
|
||||
BB71B522
|
||||
|
||||
Bound High (Japan) (En) (Proto).vb
|
||||
E81A3703
|
||||
|
||||
Galactic Pinball (Japan, USA) (En).vb
|
||||
C9710A36
|
||||
|
||||
Golf (USA).vb
|
||||
2199AF41
|
||||
|
||||
Hyper Fighting (World) (Aftermarket) (Pirate).vb
|
||||
3F2A6BA2
|
||||
|
||||
Hyper Fighting (World) (Beta) (Aftermarket) (Pirate).vb
|
||||
4450EDE0
|
||||
|
||||
Innsmouth no Yakata (Japan).vb
|
||||
83CB6A00
|
||||
|
||||
Jack Bros. (USA).vb
|
||||
A44DE03C
|
||||
|
||||
Jack Bros. no Meiro de Hiihoo! (Japan).vb
|
||||
CAB61E8B
|
||||
|
||||
Mario Clash (Japan, USA) (En).vb
|
||||
A47DE78C
|
||||
|
||||
Mario's Tennis (Japan, USA) (En).vb
|
||||
7CE7460D
|
||||
|
||||
Nester's Funky Bowling (USA).vb
|
||||
DF4D56B4
|
||||
|
||||
Niko-chan Battle (Japan) (Proto).vb
|
||||
F3CD40DD
|
||||
|
||||
Panic Bomber (USA).vb
|
||||
19BB2DFB
|
||||
|
||||
Red Alarm (Japan).vb
|
||||
7E85C45D
|
||||
|
||||
Red Alarm (USA).vb
|
||||
AA10A7B4
|
||||
|
||||
SD Gundam - Dimension War (Japan).vb
|
||||
44788197
|
||||
|
||||
Space Invaders - Virtual Collection (Japan).vb
|
||||
FA44402D
|
||||
|
||||
Space Pinball (Japan) (En) (Proto).vb
|
||||
44C2B723
|
||||
|
||||
Space Squash (Japan).vb
|
||||
60895693
|
||||
|
||||
T&E Virtual Golf (Japan).vb
|
||||
6BA07915
|
||||
|
||||
Teleroboxer (Japan, USA) (En).vb
|
||||
36103000
|
||||
|
||||
Tobidase! Panibon (Japan).vb
|
||||
40498F5E
|
||||
|
||||
V-Tetris (Japan).vb
|
||||
3CCB67AE
|
||||
|
||||
Vertical Force (Japan).vb
|
||||
9E9B8B92
|
||||
|
||||
Vertical Force (USA).vb
|
||||
4C32BA5E
|
||||
|
||||
Virtual Bowling (Japan).vb
|
||||
20688279
|
||||
|
||||
Virtual Boy Wario Land (Japan, USA) (En).vb
|
||||
133E9372
|
||||
|
||||
Virtual Fishing (Japan).vb
|
||||
526CC969
|
||||
|
||||
Virtual Lab (Japan).vb
|
||||
8989FE0A
|
||||
|
||||
Virtual League Baseball (USA).vb
|
||||
736B40D6
|
||||
|
||||
Virtual Pro Yakyuu '95 (Japan).vb
|
||||
9BA8BB5E
|
||||
|
||||
Waterworld (USA).vb
|
||||
82A95E51
|
||||
|
||||
3-D Tetris (USA).vb
|
||||
BB71B522
|
||||
|
||||
Bound High (Japan) (En) (Proto).vb
|
||||
E81A3703
|
||||
|
||||
Galactic Pinball (Japan, USA) (En).vb
|
||||
C9710A36
|
||||
|
||||
Golf (USA).vb
|
||||
2199AF41
|
||||
|
||||
Hyper Fighting (World) (Aftermarket) (Pirate).vb
|
||||
3F2A6BA2
|
||||
|
||||
Hyper Fighting (World) (Beta) (Aftermarket) (Pirate).vb
|
||||
4450EDE0
|
||||
|
||||
Innsmouth no Yakata (Japan).vb
|
||||
83CB6A00
|
||||
|
||||
Jack Bros. (USA).vb
|
||||
A44DE03C
|
||||
|
||||
Jack Bros. no Meiro de Hiihoo! (Japan).vb
|
||||
CAB61E8B
|
||||
|
||||
Mario Clash (Japan, USA) (En).vb
|
||||
A47DE78C
|
||||
|
||||
Mario's Tennis (Japan, USA) (En).vb
|
||||
7CE7460D
|
||||
|
||||
Nester's Funky Bowling (USA).vb
|
||||
DF4D56B4
|
||||
|
||||
Niko-chan Battle (Japan) (Proto).vb
|
||||
F3CD40DD
|
||||
|
||||
Panic Bomber (USA).vb
|
||||
19BB2DFB
|
||||
|
||||
Red Alarm (Japan).vb
|
||||
7E85C45D
|
||||
|
||||
Red Alarm (USA).vb
|
||||
AA10A7B4
|
||||
|
||||
SD Gundam - Dimension War (Japan).vb
|
||||
44788197
|
||||
|
||||
Space Invaders - Virtual Collection (Japan).vb
|
||||
FA44402D
|
||||
|
||||
Space Pinball (Japan) (En) (Proto).vb
|
||||
44C2B723
|
||||
|
||||
Space Squash (Japan).vb
|
||||
60895693
|
||||
|
||||
T&E Virtual Golf (Japan).vb
|
||||
6BA07915
|
||||
|
||||
Teleroboxer (Japan, USA) (En).vb
|
||||
36103000
|
||||
|
||||
Tobidase! Panibon (Japan).vb
|
||||
40498F5E
|
||||
|
||||
V-Tetris (Japan).vb
|
||||
3CCB67AE
|
||||
|
||||
Vertical Force (Japan).vb
|
||||
9E9B8B92
|
||||
|
||||
Vertical Force (USA).vb
|
||||
4C32BA5E
|
||||
|
||||
Virtual Bowling (Japan).vb
|
||||
20688279
|
||||
|
||||
Virtual Boy Wario Land (Japan, USA) (En).vb
|
||||
133E9372
|
||||
|
||||
Virtual Fishing (Japan).vb
|
||||
526CC969
|
||||
|
||||
Virtual Lab (Japan).vb
|
||||
8989FE0A
|
||||
|
||||
Virtual League Baseball (USA).vb
|
||||
736B40D6
|
||||
|
||||
Virtual Pro Yakyuu '95 (Japan).vb
|
||||
9BA8BB5E
|
||||
|
||||
Waterworld (USA).vb
|
||||
82A95E51
|
||||
|
||||
|
|
94
sd/vectrexcart.txt
Normal file
94
sd/vectrexcart.txt
Normal file
|
@ -0,0 +1,94 @@
|
|||
3D Crazy Coaster
|
||||
1
|
||||
|
||||
3D Mine Storm
|
||||
1
|
||||
|
||||
3D Narrow Escape
|
||||
1
|
||||
|
||||
AnimAction
|
||||
1
|
||||
|
||||
Armor..Attack
|
||||
0
|
||||
|
||||
Art Master
|
||||
0
|
||||
|
||||
Bedlam
|
||||
0
|
||||
|
||||
Berzerk
|
||||
0
|
||||
|
||||
Blitz!
|
||||
1
|
||||
|
||||
Clean Sweep
|
||||
0
|
||||
|
||||
Cosmic Chasm
|
||||
0
|
||||
|
||||
Fortress of Narzod
|
||||
1
|
||||
|
||||
Heads-Up
|
||||
1
|
||||
|
||||
HyperChase
|
||||
0
|
||||
|
||||
Melody Master
|
||||
1
|
||||
|
||||
Mine Storm
|
||||
0
|
||||
|
||||
Mine Storm II
|
||||
0
|
||||
|
||||
Polar Rescue
|
||||
1
|
||||
|
||||
Pole Position
|
||||
1
|
||||
|
||||
Rip Off
|
||||
0
|
||||
|
||||
Scramble
|
||||
0
|
||||
|
||||
Solar Quest
|
||||
0
|
||||
|
||||
Space Wars
|
||||
0
|
||||
|
||||
Spike
|
||||
1
|
||||
|
||||
Spin ball
|
||||
1
|
||||
|
||||
Star Castle
|
||||
0
|
||||
|
||||
Star Ship
|
||||
0
|
||||
|
||||
Star Trek
|
||||
0
|
||||
|
||||
StarHawk
|
||||
0
|
||||
|
||||
WebWarp
|
||||
1
|
||||
|
||||
WebWars
|
||||
1
|
||||
|
||||
|
420
sd/wsv.txt
420
sd/wsv.txt
|
@ -1,207 +1,213 @@
|
|||
2 in 1 - Block Buster + Cross High (USA, Europe).sv
|
||||
7E05D84F,057195A3,64
|
||||
|
||||
2 in 1 - Hash Blocks + Eagle Plan (USA, Europe).sv
|
||||
C1354952,21795D9D,64
|
||||
|
||||
4 in 1 - Hash Block + Challenger Tank + Brain Power + Jacky Lucky (USA, Europe).sv
|
||||
AB3BBF1A,B2AA7578,64
|
||||
|
||||
Alien (USA, Europe).sv
|
||||
8DBB2C53,B587490C,64
|
||||
|
||||
Balloon Fight (USA, Europe).sv
|
||||
8188B755,F59A28E2,64
|
||||
|
||||
Block Buster (USA, Europe).sv
|
||||
0A3DB285,B2AA7578,64
|
||||
|
||||
Brain Power (USA, Europe).sv
|
||||
5E6706B9,69BED4DE,64
|
||||
|
||||
Bubble World (USA, Europe).sv
|
||||
E5C2CFB5,137FA3A1,64
|
||||
|
||||
Carrier (USA, Europe).sv
|
||||
5ECFB674,A74DF889,32
|
||||
|
||||
Cave Wonders (USA, Europe).sv
|
||||
E0266CE7,B61BDFB4,64
|
||||
|
||||
Challenger Tank (USA, Europe).sv
|
||||
C92382CE,B2AA7578,64
|
||||
|
||||
Chimera (USA, Europe).sv
|
||||
4A458AA8,FFA4C239,64
|
||||
|
||||
Chinese Checkers (USA, Europe).sv
|
||||
EDED8AEC,9574D04D,64
|
||||
|
||||
Classic Casino (USA, Europe).sv
|
||||
72A96443,3E796E26,64
|
||||
|
||||
Climber (USA, Europe).sv
|
||||
12C45309,52CC2CD7,32
|
||||
|
||||
Cross High (USA, Europe).sv
|
||||
1E6836A2,0176ECF0,64
|
||||
|
||||
Crystball (USA, Europe).sv
|
||||
10DCC110,B2AA7578,64
|
||||
|
||||
Dancing Block (USA, Europe).sv
|
||||
345CA42A,D08490A7,32
|
||||
|
||||
Delta Hero (USA, Europe).sv
|
||||
32CCDF89,4EFE40D0,64
|
||||
|
||||
Dream World (USA, Europe).sv
|
||||
DB0F463F,8DD1E2E9,64
|
||||
|
||||
Eagle Plan (USA, Europe).sv
|
||||
01CB8364,B2AA7578,64
|
||||
|
||||
Earth Defender (USA, Europe).sv
|
||||
A6CBB074,B2AA7578,64
|
||||
|
||||
Fatal Craft (USA, Europe).sv
|
||||
917CAB48,B2AA7578,64
|
||||
|
||||
Final Combat (USA, Europe).sv
|
||||
2861DE5E,A1DBD9A6,32
|
||||
|
||||
Galactic Crusader (USA, Europe).sv
|
||||
B494BC5C,DB41A00C,64
|
||||
|
||||
Galaxy Fighter (USA, Europe).sv
|
||||
581703BE,083694D0,64
|
||||
|
||||
Grand Prix (USA, Europe).sv
|
||||
CEF3F295,E8F8829F,64
|
||||
|
||||
Happy Pairs (USA, Europe).sv
|
||||
112F5EED,089CC77D,64
|
||||
|
||||
Happy Race (USA, Europe).sv
|
||||
552AFA89,50376A85,64
|
||||
|
||||
Hash Blocks (USA, Europe).sv
|
||||
6BD7C885,B2AA7578,64
|
||||
|
||||
Hero Hawk (USA, Europe).sv
|
||||
99BF6CF5,E69938C1,64
|
||||
|
||||
Hero Kid (USA, Europe).sv
|
||||
25DDD6E1,162F0753,64
|
||||
|
||||
Honey Bee (USA, Europe).sv
|
||||
E856875A,1961B97C,64
|
||||
|
||||
Jacky Lucky (USA, Europe).sv
|
||||
7D8A607F,ACFF2095,64
|
||||
|
||||
Jaguar Bomber (USA, Europe).sv
|
||||
AA4372D4,6F0A43E8,64
|
||||
|
||||
John Adventure (USA, Europe).sv
|
||||
E9EA3AE0,874EEC5A,64
|
||||
|
||||
Journey to the West (USA).sv
|
||||
9FB4DB9A,B1F9E5FE,51
|
||||
|
||||
Juggler (USA, Europe).sv
|
||||
32E68D6F,D0CA45AE,64
|
||||
|
||||
Kabi Island - Gold in Island (USA, Europe).sv
|
||||
2BC03096,C723789D,64
|
||||
|
||||
Kitchen War (USA, Europe).sv
|
||||
20225F5C,B2AA7578,64
|
||||
|
||||
Kung-Fu Street (USA, Europe).sv
|
||||
7DAED2EB,8D2E613A,64
|
||||
|
||||
Linear Racing (USA, Europe).sv
|
||||
6F8ABAF9,42DE0B39,64
|
||||
|
||||
Magincross (USA, Europe).sv
|
||||
E406A91C,C64A27A7,64
|
||||
|
||||
Majong (USA, Europe).sv
|
||||
96E2E6D7,B2AA7578,64
|
||||
|
||||
Matta Blatta (USA, Europe).sv
|
||||
21864295,F846E93F,64
|
||||
|
||||
Olympic Trials (USA, Europe).sv
|
||||
85DC8111,1DFFC61C,64
|
||||
|
||||
P-52 Sea Battle (USA, Europe).sv
|
||||
748F9DAE,FDB5A1D1,64
|
||||
|
||||
PacBoy & Mouse (USA, Europe).sv
|
||||
1A89AC88,B2AA7578,64
|
||||
|
||||
Pacific Battle (USA, Europe).sv
|
||||
E5DCE795,D26572CA,64
|
||||
|
||||
Penguin Hideout (USA, Europe).sv
|
||||
FE5F9774,16D33C46,32
|
||||
|
||||
Police Bust (USA, Europe).sv
|
||||
531F0B51,B2AA7578,64
|
||||
|
||||
Popo Team (USA, Europe).sv
|
||||
E11A756C,9DF52936,64
|
||||
|
||||
Pyramid (USA, Europe).sv
|
||||
E0BFE163,74388E90,32
|
||||
|
||||
Recycle Design (USA, Europe).sv
|
||||
C36BD216,5A5C19A8,64
|
||||
|
||||
Scaffolder (USA, Europe).sv
|
||||
46FB22C5,3B167A03,64
|
||||
|
||||
Soccer Champion (USA, Europe).sv
|
||||
45204DC4,B2AA7578,64
|
||||
|
||||
Sonny X'Press (USA, Europe).sv
|
||||
C99B985A,ADC6B8C6,64
|
||||
|
||||
Space Fighter (USA, Europe).sv
|
||||
7CD650C8,75FE30AA,64
|
||||
|
||||
SSSnake (USA, Europe).sv
|
||||
BE9B6F10,8EA0C5AB,64
|
||||
|
||||
Super Block (USA, Europe).sv
|
||||
02E2C7AD,5F1DD5D7,32
|
||||
|
||||
Super Kong (USA, Europe).sv
|
||||
59C7FF64,3438D914,64
|
||||
|
||||
Super Pang (USA, Europe).sv
|
||||
181D12DD,653576B2,64
|
||||
|
||||
Tasac 2010 (USA, Europe).sv
|
||||
3D5F3964,9B451BB4,64
|
||||
|
||||
Tennis Pro '92 (USA, Europe).sv
|
||||
BD004CB7,22802ED1,64
|
||||
|
||||
Thunder Shooting (USA, Europe).sv
|
||||
AD147842,73276EBC,64
|
||||
|
||||
Treasure Hunter (USA, Europe).sv
|
||||
DB35B809,B2AA7578,64
|
||||
|
||||
TV-Link (USA, Europe).sv
|
||||
AF3EA0DD,96C646A2,32
|
||||
|
||||
Untouchable (USA, Europe).sv
|
||||
DB3FE76A,9B4B4770,64
|
||||
|
||||
Witty Cat (USA, Europe).sv
|
||||
24A115F9,964FBC96,64
|
||||
|
||||
2 in 1 - Block Buster + Cross High (USA, Europe).sv
|
||||
7E05D84F,057195A3,64
|
||||
|
||||
2 in 1 - Hash Blocks + Eagle Plan (USA, Europe).sv
|
||||
C1354952,21795D9D,64
|
||||
|
||||
Alien (USA, Europe).sv
|
||||
8DBB2C53,B587490C,64
|
||||
|
||||
Assembloids (World) (Aftermarket) (Unl).sv
|
||||
85A0E7C8,059EB9DC,64
|
||||
|
||||
Balloon Fight (USA, Europe).sv
|
||||
8188B755,F59A28E2,64
|
||||
|
||||
Block Buster (USA, Europe).sv
|
||||
0A3DB285,B2AA7578,64
|
||||
|
||||
Brain Power (USA, Europe).sv
|
||||
5E6706B9,69BED4DE,64
|
||||
|
||||
Bubble World (USA, Europe).sv
|
||||
E5C2CFB5,137FA3A1,64
|
||||
|
||||
Carrier (USA, Europe).sv
|
||||
5ECFB674,A74DF889,32
|
||||
|
||||
Cave Wonders (USA, Europe).sv
|
||||
E0266CE7,B61BDFB4,64
|
||||
|
||||
Challenger Tank (USA, Europe).sv
|
||||
C92382CE,B2AA7578,64
|
||||
|
||||
Chimera (USA, Europe).sv
|
||||
4A458AA8,FFA4C239,64
|
||||
|
||||
Chinese Checkers (USA, Europe).sv
|
||||
EDED8AEC,9574D04D,64
|
||||
|
||||
Classic Casino (USA, Europe).sv
|
||||
72A96443,3E796E26,64
|
||||
|
||||
Climber (USA, Europe).sv
|
||||
12C45309,52CC2CD7,32
|
||||
|
||||
Cross High (USA, Europe).sv
|
||||
1E6836A2,0176ECF0,64
|
||||
|
||||
Crystball (USA, Europe).sv
|
||||
10DCC110,B2AA7578,64
|
||||
|
||||
Dancing Block (USA, Europe).sv
|
||||
345CA42A,D08490A7,32
|
||||
|
||||
Delta Hero (USA, Europe).sv
|
||||
32CCDF89,4EFE40D0,64
|
||||
|
||||
Dream World (USA, Europe).sv
|
||||
DB0F463F,8DD1E2E9,64
|
||||
|
||||
Eagle Plan (USA, Europe).sv
|
||||
01CB8364,B2AA7578,64
|
||||
|
||||
Earth Defender (USA, Europe).sv
|
||||
A6CBB074,B2AA7578,64
|
||||
|
||||
Fatal Craft (USA, Europe).sv
|
||||
917CAB48,B2AA7578,64
|
||||
|
||||
Final Combat (USA, Europe).sv
|
||||
2861DE5E,A1DBD9A6,32
|
||||
|
||||
Galactic Crusader (USA, Europe).sv
|
||||
B494BC5C,DB41A00C,64
|
||||
|
||||
Galaxy Fighter (USA, Europe).sv
|
||||
581703BE,083694D0,64
|
||||
|
||||
Grand Prix (USA, Europe).sv
|
||||
CEF3F295,E8F8829F,64
|
||||
|
||||
Happy Pairs (USA, Europe).sv
|
||||
112F5EED,089CC77D,64
|
||||
|
||||
Happy Race (USA, Europe).sv
|
||||
552AFA89,50376A85,64
|
||||
|
||||
Hash Blocks (USA, Europe).sv
|
||||
6BD7C885,B2AA7578,64
|
||||
|
||||
Hero Hawk (USA, Europe).sv
|
||||
99BF6CF5,E69938C1,64
|
||||
|
||||
Hero Kid (USA, Europe).sv
|
||||
25DDD6E1,162F0753,64
|
||||
|
||||
Honey Bee (USA, Europe).sv
|
||||
E856875A,1961B97C,64
|
||||
|
||||
Jacky Lucky (USA, Europe).sv
|
||||
7D8A607F,ACFF2095,64
|
||||
|
||||
Jaguar Bomber (USA, Europe).sv
|
||||
AA4372D4,6F0A43E8,64
|
||||
|
||||
John Adventure (USA, Europe).sv
|
||||
E9EA3AE0,874EEC5A,64
|
||||
|
||||
Journey to the West (USA).sv
|
||||
9FB4DB9A,B1F9E5FE,51
|
||||
|
||||
Juggler (USA, Europe).sv
|
||||
32E68D6F,D0CA45AE,64
|
||||
|
||||
Kabi Island - Gold in Island (USA, Europe).sv
|
||||
2BC03096,C723789D,64
|
||||
|
||||
Kitchen War (USA, Europe).sv
|
||||
20225F5C,B2AA7578,64
|
||||
|
||||
Kung-Fu Street (USA, Europe).sv
|
||||
7DAED2EB,8D2E613A,64
|
||||
|
||||
Linear Racing (USA, Europe).sv
|
||||
6F8ABAF9,42DE0B39,64
|
||||
|
||||
Magincross (USA, Europe).sv
|
||||
E406A91C,C64A27A7,64
|
||||
|
||||
Majong (USA, Europe).sv
|
||||
96E2E6D7,B2AA7578,64
|
||||
|
||||
Matta Blatta (USA, Europe).sv
|
||||
21864295,F846E93F,64
|
||||
|
||||
Olympic Trials (USA, Europe).sv
|
||||
85DC8111,1DFFC61C,64
|
||||
|
||||
P-52 Sea Battle (USA, Europe).sv
|
||||
748F9DAE,FDB5A1D1,64
|
||||
|
||||
PacBoy & Mouse (USA, Europe).sv
|
||||
1A89AC88,B2AA7578,64
|
||||
|
||||
Pacific Battle (USA, Europe).sv
|
||||
E5DCE795,D26572CA,64
|
||||
|
||||
Penguin Hideout (USA, Europe).sv
|
||||
FE5F9774,16D33C46,32
|
||||
|
||||
Police Bust (USA, Europe).sv
|
||||
531F0B51,B2AA7578,64
|
||||
|
||||
Popo Team (USA, Europe).sv
|
||||
E11A756C,9DF52936,64
|
||||
|
||||
Pyramid (USA, Europe).sv
|
||||
E0BFE163,74388E90,32
|
||||
|
||||
Recycle Design (USA, Europe).sv
|
||||
C36BD216,5A5C19A8,64
|
||||
|
||||
Scaffolder (USA, Europe).sv
|
||||
46FB22C5,3B167A03,64
|
||||
|
||||
Soccer Champion (USA, Europe).sv
|
||||
45204DC4,B2AA7578,64
|
||||
|
||||
Sonny X'Press (USA, Europe).sv
|
||||
C99B985A,ADC6B8C6,64
|
||||
|
||||
Space Fighter (USA, Europe).sv
|
||||
7CD650C8,75FE30AA,64
|
||||
|
||||
SSSnake (USA, Europe).sv
|
||||
BE9B6F10,8EA0C5AB,64
|
||||
|
||||
Super Block (USA, Europe).sv
|
||||
02E2C7AD,5F1DD5D7,32
|
||||
|
||||
Super Kong (USA, Europe).sv
|
||||
59C7FF64,3438D914,64
|
||||
|
||||
Super Pang (USA, Europe).sv
|
||||
181D12DD,653576B2,64
|
||||
|
||||
Tasac 2010 (USA, Europe).sv
|
||||
3D5F3964,9B451BB4,64
|
||||
|
||||
Tennis Pro '92 (USA, Europe).sv
|
||||
EAA08104,22802ED1,64
|
||||
|
||||
Tennis Pro '92 (USA, Europe) (Alt).sv
|
||||
BD004CB7,22802ED1,64
|
||||
|
||||
Thunder Shooting (USA, Europe).sv
|
||||
AD147842,73276EBC,64
|
||||
|
||||
Treasure Hunter (USA, Europe).sv
|
||||
DB35B809,B2AA7578,64
|
||||
|
||||
Treasure Hunter (USA, Europe) (Rev 1).sv
|
||||
69068337,3E796E26,64
|
||||
|
||||
TV-Link (USA, Europe).sv
|
||||
AF3EA0DD,96C646A2,32
|
||||
|
||||
Untouchable (USA, Europe).sv
|
||||
DB3FE76A,9B4B4770,64
|
||||
|
||||
Witty Cat (USA, Europe).sv
|
||||
24A115F9,964FBC96,64
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user