Compare commits

...

138 Commits

Author SHA1 Message Date
Ancyker
2b01f7fc4d
Add checks for unsafe configurations
* Fixes #929
* Updated `ci.yml` to define `GITHUB_CI`
* Compilation will now error if VSELECT is enabled on hardware versions that don't support it (any version other than HW5).
  * HW4 and SERIAL might work but are untested. The error message for these versions reflects this.
* Erroring when unsafe configurations are defined can be overridden by defining `ALLOW_UNSAFE_CONFIG` which will throw a warning instead.
  * This should only be done if trying to implement or test on a currently unsupported platform.
  * If both `GITHUB_CI` and `ALLOW_UNSAFE_CONFIG` are defined an error will be thrown causing the CI tests to fail. This is just in case someone makes a commit with it defined.
2024-06-02 11:56:08 -04:00
Ancyker
740c2698bc
Fix compilation errors and warnings
Fixing issues when only ENABLE_GBX was enabled or when compiling for a serial-only firmware.
2024-06-02 11:15:50 -04:00
smesgr9000
ad69abdf57 use common function to create file/folder and increment foldern counter 2024-06-01 09:58:23 +02:00
smesgr9000
22e06d8ec1 reuse n64 flashrom Xplorer command sequence 2024-05-30 18:52:38 +02:00
smesgr9000
fb78a1fce5 reuse n64 flashrom command sequence 2024-05-30 18:18:53 +02:00
smesgr9000
86059ae070 reuse code to write NES maker command 2024-05-30 08:15:22 +02:00
smesgr9000
5b43a162b8 reuse common strings, remove duplicate 2024-05-30 08:00:13 +02:00
smesgr9000
d039c590cc define more commonly used string in OSCR and reuse them 2024-05-28 21:11:48 +02:00
smesgr9000
0d9596eb70 replace custom FLASH saving code with common function 2024-05-28 20:20:29 +02:00
smesgr9000
cb111077f8 replace NES defines with rgbLed function calls 2024-05-26 22:43:41 +02:00
smesgr9000
363d18b542 add common function to open create folder, print message and open file. Remove duplicate code 2024-05-26 22:20:47 +02:00
smesgr9000
78bf1462d0 replace custom folder creation function with common 2024-05-26 21:48:57 +02:00
smesgr9000
41182a7eb0 add option to clear display and remove duplicate code 2024-05-25 14:25:35 +02:00
smesgr9000
6abe29fcd9 remove duplicate code to print saving and increment of folder id 2024-05-25 14:07:08 +02:00
smesgr9000
d1d83bbd10 remove local variables which are only used in function context 2024-05-25 09:57:46 +02:00
smesgr9000
73700e2886 support mapper > 255, implement mapper 446 submapper 0&1 - thanks to NewRisingSun for support, fix iNES2.0 mapper parsing of byte 8 2024-05-24 23:54:13 +02:00
smesgr9000
1aaa90af97 remove custom code to print 0 prefixes in sprintf 2024-05-20 13:17:44 +02:00
smesgr9000
4d000418a8 remove duplicate code to write Flash Command 2024-05-20 12:54:33 +02:00
smesgr9000
aaaa6ea3cd reuse menu item strings 2024-05-20 12:27:53 +02:00
smesgr9000
a32c6b3bff define PROGMEM string for Attention 3.3V 2024-05-20 12:07:28 +02:00
smesgr9000
f82be2d5db remove duplicate code to open file for verfication 2024-05-20 11:57:32 +02:00
smesgr9000
d7e795fbed remove duplicate code to open file to write on flash 2024-05-20 11:39:35 +02:00
smesgr9000
ea0b47de57 use constant for "Saving to" instead declare the string several times 2024-05-12 15:54:49 +02:00
smesgr9000
9f0aa09197 remove duplicate code to create folder 2024-05-12 15:37:11 +02:00
smesgr9000
38b2b2476b remove duplicate GB Flash reading function 2024-05-12 14:33:21 +02:00
smesgr9000
dc47202c4d remove duplicate code for 2600 3E & 3F mapper 2024-05-12 14:03:34 +02:00
smesgr9000
a8cd9c52a6 reduce duplicate code in bank 7800 switching code 2024-05-12 12:09:59 +02:00
smesgr9000
32f6b4151b reduce duplicate code by parameterise ROML/ROMH 2024-05-12 11:40:34 +02:00
smesgr9000
c09e772299 replace hardcoded bank maps with power of 2 2024-05-12 08:15:03 +02:00
smesgr9000
7ba32d24fc remove duplicate code for checking pin number 2024-05-11 23:44:40 +02:00
smesgr9000
74352c6e31 define "File doesn't exist" in OSCR.cpp/h 2024-05-11 23:32:06 +02:00
smesgr9000
ab03ab879c pass onyl 16bit parameter where only 16bit address is used 2024-05-11 23:18:31 +02:00
smesgr9000
90fa37c491 add serial printing to print instructions 2024-05-10 19:15:24 +02:00
smesgr9000
9e2ef3580c reuse print instructions function, more efficiant read code 2024-05-10 19:13:19 +02:00
smesgr9000
94c6bd460a add c64 function to read 16k segments. Remove duplicate code for C64 2024-05-10 18:14:54 +02:00
Ancyker
40238b18a1
Fixed (added) missing FS() macro on some FSTRING constants
This was causing two symptoms/bugs:
* OSCR_LOG.txt was being spammed with random data.
* The size of OSCR_LOG.txt would get so big that copying the log would take a long time, possibly minutes. Oftentimes this caused the display to appear to hang after searching for the CRC (after "->") but before displaying the result.

If using the global log and a version of master since e61ac414d8 you should delete OSCR_LOG.txt from your SD card as it will likely be very large and continue to cause dumping to be slow.
2024-05-07 17:16:51 -04:00
smesgr9000
8bd6d7dfdc remove duplicate code for F4,F6 & F8 mapper 2024-05-07 20:30:02 +02:00
smesgr9000
53b71f9108 fix 2600 mapper selection for Serial 2024-05-07 19:38:31 +02:00
sanni
825a5fe7b6
Merge pull request #941 from plaidpants/master
Add support for mapper 3E, 32K ROM 32K RAM Tigervision
2024-05-04 19:00:34 +02:00
JWS
2c72652671 Add support for X07 mapper (Stella's Stockings) 2024-05-03 20:34:26 -05:00
JWS
f4ba8d7af8 Add support for mapper 3E, 32K ROM 32K RAM Tigervision 2024-05-03 18:52:37 -05:00
smesgr9000
2134c9f58b move PRG/CHR dumping code to own function 2024-05-03 23:42:06 +02:00
smesgr9000
4b70766094 remove duplicate code to store NES games with and without header 2024-05-03 21:56:22 +02:00
smesgr9000
5f3d63a123 fix signed/unsigned warning 2024-05-03 20:47:48 +02:00
smesgr9000
990b61ca3a make cast in read function explicit and reduce duplicate read functions 2024-05-03 19:12:48 +02:00
smesgr9000
e8e6d15a72 remove duplicate string literals 2024-05-03 17:12:31 +02:00
smesgr9000
6c05709871 fix compiler warnings 2024-05-03 17:11:55 +02:00
smesgr9000
330e615b8c remove duplicate code to select mapper, rom and ram configurations 2024-05-01 21:27:45 +02:00
smesgr9000
2826ded431 remove duplicate code in printing CRC 2024-05-01 18:59:00 +02:00
smesgr9000
d233387acc fix issue #939. Remove duplicate write of laster buffer. Also add Berzerk Enhanced 2024-05-01 18:50:35 +02:00
smesgr9000
254982cbe7 remove duplicate CRC printing and calculation function 2024-05-01 10:48:58 +02:00
smesgr9000
ccc06ef4e4 fix reading mapper > 9 from database 2024-05-01 09:35:00 +02:00
smesgr9000
d7c1afd57c
Add fairchild, ody2, msx and vectrex to README.md 2024-05-01 09:28:56 +02:00
smesgr9000
bb12c99fac replace FAIRCHILD, ODY2, MSX and VECTREX cart selection code with code used in NES, COLV & INTV. Define "Database not found" in OSCR.cpp 2024-05-01 09:06:23 +02:00
sanni
ecc937bab3
Fix romType for Yuyu no Quiz de GO!GO!
https://github.com/sanni/cartreader/issues/922
2024-04-30 12:25:58 +02:00
smesgr9000
14c3ca2a83
add 5200 and arccart section to README.md 2024-04-29 19:22:21 +02:00
smesgr9000
9909fdafb3 replace 5200 and ARC cart selection code with code used in NES, COLV & INTV 2024-04-29 19:09:50 +02:00
smesgr9000
06d5f28d0c port NES fast forward selection to other systems 2024-04-28 13:35:21 +02:00
smesgr9000
38f3ebdc8d
fix formatting of newly added documentation 2024-04-28 10:30:58 +02:00
smesgr9000
c3c701cd93
add c64cart section to README.md 2024-04-28 10:27:31 +02:00
smesgr9000
c5c82d4902
fix ordering in 7800.txt 2024-04-28 10:21:41 +02:00
smesgr9000
fa90691f89
Add DeathFlood to c64cart.txt 2024-04-28 10:20:00 +02:00
smesgr9000
82173ab775
Add Attack of the Petscii Robots to 7800.txt 2024-04-28 09:54:58 +02:00
smesgr9000
394dcdcf1f replace C64 cart selection code with code used in NES, COLV & INTV 2024-04-28 09:50:48 +02:00
sakman55
254c824292
Update 7800.ino
Update checkStatus_7800() to account for the added Bankset mapper (#7).
2024-04-27 18:33:27 -10:00
sakman55
9f51bb1af7
Update c64cart.txt
Updated to work with C64.ino that fixes Issue #902
2024-04-27 12:52:37 -10:00
sakman55
43e18fce80
Update C64.ino
Fix Issue #902 Handling of GAME and EXROM lines of C64 cartridges is wrong.  Requires updated c64cart.txt on SD card.
2024-04-27 12:49:34 -10:00
smesgr9000
a539f9b7de add description of 2600.txt and 7800.txt to README.md 2024-04-27 10:14:51 +02:00
smesgr9000
57bf121c06 replace 2600 cart selection code with code used in NES, COLV & INTV 2024-04-27 09:59:36 +02:00
sanni
d2fbb30b95
Merge pull request #935 from smesgr9000/a7800database
replace cart selection code of A7800 with one used at NES, COLV, INTV, WSV
2024-04-26 19:24:29 +02:00
sanni
15c94c110b
Merge pull request #934 from smesgr9000/master
remove duplicate code of seeking database files for letters
2024-04-26 19:24:20 +02:00
smesgr9000
3ff99bfe48 Merge remote-tracking branch 'origin/master' into a7800database 2024-04-24 20:28:42 +02:00
smesgr9000
4502d1e56e revert accidently committed Config.h 2024-04-24 20:17:10 +02:00
smesgr9000
d8809b198d revert accidently committed Config.h 2024-04-24 20:13:45 +02:00
smesgr9000
3ce23a57ad replace cart select code with code used in NES, COLV, INTV 2024-04-24 20:07:44 +02:00
smesgr9000
3441cedfd4 remove duplicate code of seeking database files for letter 2024-04-24 19:55:43 +02:00
sanni
50a147bad7
Merge pull request #933 from smesgr9000/master
remove some duplicate printing code and declare more global text strings
2024-04-22 21:56:50 +02:00
smesgr9000
e7e0da80b0 remove some duplicate printing code and declare more global text strings 2024-04-22 18:51:01 +02:00
sanni
5d0ae986c9
Merge pull request #932 from PsychoFox11/master
Fix Slaughter Sport title, two CRC32s
2024-04-22 12:42:08 +02:00
sanni
5a79277a27
Merge pull request #928 from smesgr9000/master
support CLOCKGEN for C64
2024-04-22 12:41:34 +02:00
PsyK0p4T
ea3adb09bc
Update pcw.txt 2024-04-21 11:39:11 +02:00
Don Jones
8b617851a1
Update md.txt
Fix two CRC32s
2024-04-21 02:09:33 -04:00
Don Jones
dc1e776b19
Update MD.ino
Fix Slaughter Sport's title and folder name
2024-04-21 02:08:30 -04:00
smesgr9000
4c8f8266a1 support CLOCKGEN for C64 2024-04-18 18:09:19 +02:00
PsyK0p4T
7fc0f9b154
Merge pull request #927 from PsychoFox11/master
Update wsv.txt
2024-04-15 11:45:37 +02:00
Don Jones
8458fe6bf7
Update wsv.txt 2024-04-15 05:39:39 -04:00
PsyK0p4T
017da53f42
Merge pull request #924 from smesgr9000/c64fix
fix reading mapping > 5 causes crc 0x0000000
2024-04-15 11:29:52 +02:00
sanni
083182b5fb
Merge pull request #923 from smesgr9000/master
reduce memory footprint for 7800.ino
2024-04-13 19:23:30 +02:00
smesgr9000
e1716d48bb fix reading mapping > 5 causes crc32 0x0000000 2024-04-12 20:15:16 +02:00
smesgr9000
cf1d01855d reduce memory footprint for 7800.ino 2024-04-12 19:07:00 +02:00
PsyK0p4T
8afd2a580e
Update pcw.txt 2024-04-07 23:58:10 +02:00
PsyK0p4T
8fbab1e760
Update pcw.txt 2024-04-07 22:39:46 +02:00
PsyK0p4T
980208e18f
Update pcw.txt
Fixed duplicated entry
2024-04-07 20:49:26 +02:00
PsyK0p4T
229b1ba544
Update gba.txt
Fix CRC32 for some 32MB games.
2024-04-03 00:14:42 +02:00
sanni
baa7dce0c1
Merge pull request #920 from smesgr9000/master
support for F4SC, F6SC & F8SC
2024-03-30 18:55:36 +01:00
smesgr9000
9ad338a821 support for F4SC, F6SC & F8SC 2024-03-24 14:06:06 +01:00
PsyK0p4T
316f8ef2fd
Merge pull request #919 from smesgr9000/master
Add support for Atari 7800 Bankset bank switch
2024-03-24 11:25:32 +01:00
smesgr9000
a2924e4f58 create a merge request for https://github.com/sanni/cartreader/issues/916 2024-03-23 23:30:17 +01:00
PsyK0p4T
385b6b03f4
Merge pull request #912 from PsyK0p4T/master
CRC check added for Sufami Turbo
2024-03-11 16:40:20 +01:00
PsyK0p4T
281639370f
CRC check added
CRC check added for SFC Sufami Turbo sub-carts
2024-03-11 16:38:10 +01:00
PsyK0p4T
d79357d963
CRCs file for Sufami Turbo 2024-03-11 16:36:20 +01:00
PsyK0p4T
44b26960f5
Update gba.txt
"Game Boy Advance Video" entries added.
2024-03-10 22:35:49 +01:00
PsyK0p4T
a455b10019
Update pce.txt 2024-03-10 21:54:07 +01:00
PsyK0p4T
6d89a279f2
Update MD.ino
Thanks to psychofox : 
- Fix Madden NFL 98 (USA)
- More aftermarket games added
2024-03-07 11:13:09 +01:00
PsyK0p4T
4de1c52798
Update gba.txt
List reworked : 
- Alphabetical ordering
- All (beta) entries removed to avoid conflicts
2024-03-06 23:41:59 +01:00
Ancyker
a86f140198 Follow up to/fix for e61ac414d8 2024-03-02 11:30:44 -05:00
Ancyker
e61ac414d8 Code optimization, cleanup, and stylization
* Reduced PROGMEM / DRAM usage slightly (Using defaults w/HW5: Before -> 214,668 bytes / 5,757 bytes; After -> 213,414 bytes / 5,751 bytes)
  * Optimized some menu options and calls
  * Added more string constants and implemented them where found.
* Fixed some stylization
  * Constants should always be uppercase.
  * Features should use the `ENABLE_<feature name>` format.
  * Options for features should use the `OPTION_<feature name>_<option name>` format.
  * Added ENUMs for more clarity and better type checking.
  * Moved some defines over to `constexpr` and `const` types. These are preferred over preprocessor constants when not intended for use with `#if` and other preprocessor language.
2024-03-02 11:26:35 -05:00
Ancyker
3468703a51 Added ability to use config file for some options.
A sample `config.txt` is in the SD folder. Currently the option is disabled by default and must be enabled.

Also:
* Eliminated the 5V spike at boot when VSELECT is installed and enabled. See discussion #906
* Fixed a warning in `MD.ino`
* Did some code cleanup, more cleanup to come.
2024-02-29 17:52:04 -05:00
PsyK0p4T
35eca2a9f4
Update 7800.ino
Add clock generator usage to fix timing issues (thanks to @smesgr9000)
2024-02-29 23:17:41 +01:00
sanni
f947fb4e3f Add support for MBC30 flash cart by HDR (thx to ManCloud)
Two issues were resolved:
- this flashcart uses the Audio-In pin instead of the WR pin
- Writing 4MB gets stuck after bank 170 and needed the SRAM to be mapped (same as MBC5)
2024-02-29 09:36:23 +01:00
PsyK0p4T
5f3983b36c
Update pce.txt 2024-02-26 09:28:56 +01:00
PsyK0p4T
ddd8b94bd7
Merge pull request #903 from PsyK0p4T/master
Update MD.ino
2024-02-25 14:15:15 +01:00
PsyK0p4T
d007c455e7
Update md.txt 2024-02-25 14:11:46 +01:00
PsyK0p4T
417e88d7d1
Update MD.ino
Force saveType to 0 for some aftermarket games not using SRAM
2024-02-25 13:58:06 +01:00
PsyK0p4T
7e2e2a6bf2
Update README.md 2024-02-17 14:02:00 +01:00
PsyK0p4T
f762f29ee4
Merge pull request #897 from LuigiBlood/gpc4m
SNES: Add Game Processor RAM Cassette Read/Write support
2024-02-17 13:56:35 +01:00
LuigiBlood
bbe37d9839 SNES: Add Game Processor RAM Cassette Read/Write support 2024-02-09 23:02:59 +01:00
PsyK0p4T
e4e4c7f1f5
Update PCE.ino
Add compatibility for "Games Express CD Card (Japan) (Green Version)"
2024-02-02 00:12:39 +01:00
PsyK0p4T
24b7c2f2e1
Merge pull request #882 from PsyK0p4T/master
Standardize all Atari ino/txt files
2023-12-26 23:17:27 +01:00
PsyK0p4T
d556e5a4af
Update Cart_Reader.ino
Standardize all Atari codes
2023-12-26 23:13:51 +01:00
PsyK0p4T
a8b493026e
Update Config.h
Standardize all Atari codes
2023-12-26 23:12:11 +01:00
PsyK0p4T
a9bccaf8f7
Update 5200.ino
Standardize all Atari codes
2023-12-26 23:10:23 +01:00
PsyK0p4T
2bdba9c8bd
Update 7800.ino
Standardize all Atari codes
2023-12-26 23:09:38 +01:00
PsyK0p4T
c06f1c4e95
Update 2600.ino
Modify Atari 2600 code to follow 5200/7800 model.
2023-12-26 23:08:10 +01:00
PsyK0p4T
5e7861be1c
Rename ataricart.txt to 2600.txt 2023-12-26 23:05:12 +01:00
PsyK0p4T
1b70d71518
Rename 7800cart.txt to 7800.txt 2023-12-26 23:04:56 +01:00
PsyK0p4T
8ee28d55f4
Rename 5200cart.txt to 5200.txt 2023-12-26 23:04:37 +01:00
PsyK0p4T
272c2935e5
Merge pull request #881 from PsyK0p4T/master
Update VECTREX.ino
2023-12-26 21:56:59 +01:00
PsyK0p4T
319d110339
Update VECTREX.ino
Allows to manually select and dump carts up to 64 KB.
2023-12-26 21:53:39 +01:00
PsyK0p4T
107dd9f1d7
Merge pull request #872 from PsyK0p4T/master
Add SuperGrafx entries to SD
2023-11-29 01:00:38 +01:00
PsyK0p4T
3a965600cc
Update README.md 2023-11-29 00:58:48 +01:00
PsyK0p4T
7078adcd22
Update pce.txt
Add SuperGrafx entries
2023-11-29 00:57:58 +01:00
PsyK0p4T
dece32c130
Merge pull request #871 from PsyK0p4T/master
Add Sufami Turbo support
2023-11-25 00:40:07 +01:00
PsyK0p4T
3d810823e1
Update README.md 2023-11-25 00:36:08 +01:00
PsyK0p4T
d0fe5c8ca1
Update Cart_Reader.ino
Add Sufami Turbo support
2023-11-25 00:34:13 +01:00
PsyK0p4T
70d52636d7
Update SNES.ino
Add Sufami Turbo support
2023-11-25 00:32:51 +01:00
PsyK0p4T
0287ea8ed2
Update Config.h
add Sufami Turbo support
2023-11-25 00:29:55 +01:00
PsyK0p4T
f86a861628
Add Sufami Turbo module 2023-11-25 00:26:38 +01:00
64 changed files with 21355 additions and 22092 deletions

View File

@ -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
View 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
//******************************************

View File

@ -1,7 +1,7 @@
//******************************************
// ATARI 5200 MODULE
//******************************************
#ifdef enable_5200
#ifdef ENABLE_5200
// Atari 5200
// Cartridge Pinout
// 36P 2.54mm pitch connector
@ -73,9 +73,7 @@ byte a5200[] = { 4, 8, 16, 32, 40 };
byte a5200lo = 0; // Lowest Entry
byte a5200hi = 4; // Highest Entry
byte a5200mapper = 0;
byte new5200mapper;
byte a5200size;
byte new5200size;
// EEPROM MAPPING
// 07 MAPPER
@ -85,10 +83,7 @@ byte new5200size;
// Menu
//******************************************
// Base Menu
static const char a5200MenuItem1[] PROGMEM = "Select Cart";
static const char a5200MenuItem2[] PROGMEM = "Read ROM";
static const char a5200MenuItem3[] PROGMEM = "Set Mapper + Size";
static const char* const menuOptions5200[] PROGMEM = { a5200MenuItem1, a5200MenuItem2, a5200MenuItem3, string_reset2 };
static const char* const menuOptions5200[] PROGMEM = { FSTRING_SELECT_CART, FSTRING_READ_ROM, FSTRING_SET_SIZE, FSTRING_RESET };
void setup_5200() {
// Request 5V
@ -128,7 +123,7 @@ void setup_5200() {
checkStatus_5200();
strcpy(romName, "ATARI");
mode = mode_5200;
mode = CORE_5200;
}
void a5200Menu() {
@ -139,7 +134,6 @@ void a5200Menu() {
case 0:
// Select Cart
setCart_5200();
wait();
setup_5200();
break;
@ -222,31 +216,9 @@ void readSegment_5200(uint16_t startaddr, uint16_t endaddr) {
//******************************************
void readROM_5200() {
strcpy(fileName, romName);
strcat(fileName, ".a52");
// create a new folder for storing rom file
EEPROM_readAnything(0, foldern);
sprintf(folder, "5200/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("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
@ -331,10 +303,9 @@ void readROM_5200() {
}
myFile.close();
unsigned long crcsize = a5200[a5200size] * 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();
@ -345,6 +316,24 @@ void readROM_5200() {
// 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;
@ -357,78 +346,26 @@ void checkMapperSize_5200() {
}
}
#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() {
#if (defined(enable_OLED) || defined(enable_LCD))
byte new5200size;
#if (defined(ENABLE_OLED) || defined(ENABLE_LCD))
display_Clear();
if (a5200lo == a5200hi)
new5200size = a5200lo;
else {
int b = 0;
int i = a5200lo;
display_Clear();
print_Msg(F("ROM Size: "));
println_Msg(a5200[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 == a5200lo)
i = a5200hi;
else
i--;
// Only update display after input because of slow LCD library
display_Clear();
print_Msg(F("ROM Size: "));
println_Msg(a5200[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 == a5200hi)
i = a5200lo;
else
i++;
// Only update display after input because of slow LCD library
display_Clear();
print_Msg(F("ROM Size: "));
println_Msg(a5200[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)
new5200size = i;
break;
}
}
new5200size = navigateMenu(a5200lo, a5200hi, &printRomSize_5200);
display.setCursor(0, 56); // Display selection at bottom
}
print_Msg(F("ROM SIZE "));
print_Msg(FS(FSTRING_ROM_SIZE));
print_Msg(a5200[new5200size]);
println_Msg(F("K"));
display_Update();
@ -453,7 +390,7 @@ setrom:
new5200size = sizeROM.toInt() + a5200lo;
if (new5200size > a5200hi) {
Serial.println(F("SIZE NOT SUPPORTED"));
Serial.println(F(""));
Serial.println(FS(FSTRING_EMPTY));
goto setrom;
}
}
@ -477,20 +414,15 @@ void checkStatus_5200() {
EEPROM_writeAnything(8, a5200size);
}
#if (defined(enable_OLED) || defined(enable_LCD))
#if (defined(ENABLE_OLED) || defined(ENABLE_LCD))
display_Clear();
println_Msg(F("ATARI 5200 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(a5200mapper);
if (a5200mapper == 0)
println_Msg(F("STANDARD"));
else if (a5200mapper == 1)
println_Msg(F("TWO CHIP"));
else if (a5200mapper == 2)
println_Msg(F("BOUNTY BOB"));
print_Msg(F("ROM SIZE: "));
println_Mapper5200(a5200mapper);
print_Msg(FS(FSTRING_ROM_SIZE));
print_Msg(a5200[a5200size]);
println_Msg(F("K"));
display_Update();
@ -498,16 +430,11 @@ void checkStatus_5200() {
#else
Serial.print(F("MAPPER: "));
Serial.println(a5200mapper);
if (a5200mapper == 0)
Serial.println(F("STANDARD"));
else if (a5200mapper == 1)
Serial.println(F("TWO CHIP"));
else if (a5200mapper == 2)
Serial.println(F("BOUNTY BOB"));
Serial.print(F("ROM SIZE: "));
println_Mapper5200(a5200mapper);
Serial.print(FS(FSTRING_ROM_SIZE));
Serial.print(a5200[a5200size]);
Serial.println(F("K"));
Serial.println(F(""));
Serial.println(FS(FSTRING_EMPTY));
#endif
}
@ -515,136 +442,23 @@ void checkStatus_5200() {
// 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() {
#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 = a5200mapcount - 1;
else
i--;
break;
}
display_Clear();
print_Msg(F("Mapper: "));
a5200index = i * 3;
a5200mapselect = pgm_read_byte(a5200mapsize + a5200index);
println_Msg(a5200mapselect);
if (a5200mapselect == 0)
println_Msg(F("STANDARD"));
else if (a5200mapselect == 1)
println_Msg(F("TWO CHIP"));
else if (a5200mapselect == 2)
println_Msg(F("BOUNTY BOB"));
display_Update();
if (i == (a5200mapcount - 1))
i = 0;
else
i++;
delay(250);
}
}
byte new5200mapper;
#if (defined(ENABLE_OLED) || defined(ENABLE_LCD))
navigateMenu(0, a5200mapcount - 1, &printMapperSelection_5200);
new5200mapper = a5200mapselect;
display_Clear();
print_Msg(F("Mapper: "));
a5200index = i * 3;
a5200mapselect = pgm_read_byte(a5200mapsize + a5200index);
println_Msg(a5200mapselect);
if (a5200mapselect == 0)
println_Msg(F("STANDARD"));
else if (a5200mapselect == 1)
println_Msg(F("TWO CHIP"));
else if (a5200mapselect == 2)
println_Msg(F("BOUNTY BOB"));
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 = a5200mapcount - 1;
else
i--;
// Only update display after input because of slow LCD library
display_Clear();
print_Msg(F("Mapper: "));
a5200index = i * 3;
a5200mapselect = pgm_read_byte(a5200mapsize + a5200index);
println_Msg(a5200mapselect);
if (a5200mapselect == 0)
println_Msg(F("STANDARD"));
else if (a5200mapselect == 1)
println_Msg(F("TWO CHIP"));
else if (a5200mapselect == 2)
println_Msg(F("BOUNTY BOB"));
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 == (a5200mapcount - 1))
i = 0;
else
i++;
// Only update display after input because of slow LCD library
display_Clear();
print_Msg(F("Mapper: "));
a5200index = i * 3;
a5200mapselect = pgm_read_byte(a5200mapsize + a5200index);
println_Msg(a5200mapselect);
if (a5200mapselect == 0)
println_Msg(F("STANDARD"));
else if (a5200mapselect == 1)
println_Msg(F("TWO CHIP"));
else if (a5200mapselect == 2)
println_Msg(F("BOUNTY BOB"));
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)
new5200mapper = a5200mapselect;
break;
}
}
display.setCursor(0, 56);
print_Msg(F("MAPPER "));
print_Msg(new5200mapper);
@ -672,258 +486,25 @@ setmapper:
//******************************************
// CART SELECT CODE
//******************************************
FsFile a5200csvFile;
char a5200game[39]; // title
char a5200mm[3]; // mapper
char a5200rr[3]; // romsize
char a5200ll[4]; // linelength (previous line)
unsigned long a5200csvpos; // CSV File Position
char a5200cartCSV[] = "5200cart.txt"; // CSV List
char a5200csvEND[] = "EOF"; // CSV End Marker for scrolling
bool readLine_5200(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_5200(char* a5200game, char* a5200mm, char* a5200rr, char* a5200ll) {
char line[44];
a5200csvpos = a5200csvFile.position();
if (!readLine_5200(a5200csvFile, line, sizeof(line))) {
return false; // EOF or too long
}
char* comma = strtok(line, ",");
int x = 0;
while (comma != NULL) {
if (x == 0)
strcpy(a5200game, comma);
else if (x == 1)
strcpy(a5200mm, comma);
else if (x == 2)
strcpy(a5200rr, comma);
else if (x == 3)
strcpy(a5200ll, comma);
comma = strtok(NULL, ",");
x += 1;
}
return true;
}
bool getCartListInfo_5200() {
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_5200(a5200game, a5200mm, a5200rr, a5200ll)) {
if (strcmp(a5200csvEND, a5200game) == 0) {
a5200csvFile.seek(0); // Restart
} else {
#if (defined(enable_OLED) || defined(enable_LCD))
display_Clear();
println_Msg(F("CART TITLE:"));
println_Msg(F(""));
println_Msg(a5200game);
display_Update();
#else
Serial.print(F("CART TITLE:"));
Serial.println(a5200game);
#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_5200(a5200game, a5200mm, a5200rr, a5200ll)) {
if (strcmp(a5200csvEND, a5200game) == 0) {
a5200csvFile.seek(0); // Restart
} else {
#if (defined(enable_OLED) || defined(enable_LCD))
display_Clear();
println_Msg(F("CART TITLE:"));
println_Msg(F(""));
println_Msg(a5200game);
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(a5200game);
#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(a5200ll, NULL, 10);
a5200csvpos -= prevline;
a5200csvFile.seek(a5200csvpos);
break;
}
if (b == 3) { // Long Press - Select Cart (hold)
new5200mapper = strtol(a5200mm, NULL, 10);
new5200size = strtol(a5200rr, NULL, 10);
EEPROM_writeAnything(7, new5200mapper);
EEPROM_writeAnything(8, new5200size);
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_5200() {
if (getCartListInfo_5200()) {
#if (defined(enable_OLED) || defined(enable_LCD))
display_Clear();
println_Msg(F("CART SELECTED"));
println_Msg(F(""));
println_Msg(a5200game);
display_Update();
// Display Settings
display.setCursor(0, 56);
print_Msg(F("CODE: M"));
print_Msg(new5200mapper);
print_Msg(F("/R"));
println_Msg(new5200size);
display_Update();
#else
Serial.println(F(""));
Serial.println(F("CART SELECTED"));
Serial.println(a5200game);
// Display Settings
Serial.print(F("CODE: M"));
Serial.print(new5200mapper);
Serial.print(F("/R"));
Serial.println(new5200size);
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 checkSize_5200() {
EEPROM_readAnything(7, a5200mapper);
for (int i = 0; i < a5200mapcount; i++) {
a5200index = i * 3;
if (a5200mapper == pgm_read_byte(a5200mapsize + a5200index)) {
a5200size = pgm_read_byte(a5200mapsize + a5200index + 1);
EEPROM_writeAnything(8, a5200size);
break;
}
}
}
void setCart_5200() {
#if (defined(enable_OLED) || defined(enable_LCD))
display_Clear();
println_Msg(a5200cartCSV);
display_Update();
#endif
//go to root
sd.chdir();
sprintf(folder, "5200/CSV");
sd.chdir(folder); // Switch Folder
a5200csvFile = sd.open(a5200cartCSV, O_READ);
if (!a5200csvFile) {
#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_5200();
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));
}
checkCSV_5200();
a5200csvFile.close();
}
#endif

View File

@ -1,7 +1,7 @@
//******************************************
// ATARI 7800 MODULE
//******************************************
#ifdef enable_7800
#ifdef ENABLE_7800
// Atari 7800
// Cartridge Pinout
// 32P 2.54mm pitch (USE 36P CONNECTOR)
@ -44,6 +44,7 @@
// CONTROL PINS:
// CLK(PH1) - SNES CPUCLK
// R/W(PH6) - SNES /RD
// HALT(PH0) - SNES /RESET
//******************************************
// Supported Mappers
@ -58,9 +59,10 @@ static const byte PROGMEM a7800mapsize[] = {
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 = 7; // (sizeof(a7800mapsize) / sizeof(a7800mapsize[0])) / 3;
byte a7800mapcount = 8; // (sizeof(a7800mapsize) / sizeof(a7800mapsize[0])) / 3;
byte a7800mapselect;
int a7800index;
@ -68,9 +70,7 @@ byte a7800[] = { 16, 32, 48, 64, 128, 144 };
byte a7800lo = 0; // Lowest Entry
byte a7800hi = 5; // Highest Entry
byte a7800mapper = 0;
byte new7800mapper;
byte a7800size;
byte new7800size;
// EEPROM MAPPING
// 07 MAPPER
@ -80,10 +80,7 @@ byte new7800size;
// Menu
//******************************************
// Base Menu
static const char a7800MenuItem1[] PROGMEM = "Select Cart";
static const char a7800MenuItem2[] PROGMEM = "Read ROM";
static const char a7800MenuItem3[] PROGMEM = "Set Mapper + Size";
static const char* const menuOptions7800[] PROGMEM = { a7800MenuItem1, a7800MenuItem2, a7800MenuItem3, string_reset2 };
static const char* const menuOptions7800[] PROGMEM = { FSTRING_SELECT_CART, FSTRING_READ_ROM, FSTRING_SET_SIZE, FSTRING_RESET };
void setup_7800() {
// Request 5V
@ -99,8 +96,8 @@ void setup_7800() {
DDRL = 0xFF;
// Set Control Pins to Output
// ---(PH0) CLK(PH1) ---(PH3) ---(PH4) ---(PH5) R/W(PH6)
DDRH |= (1 << 0) | (1 << 1) | (1 << 3) | (1 << 4) | (1 << 5) | (1 << 6);
// 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);
@ -109,8 +106,8 @@ void setup_7800() {
DDRC = 0x00;
// Setting Control Pins to HIGH
// ---(PH0) CLK(PH1) ---(PH3) ---(PH4) ---(PH5) R/W(PH6)
PORTH |= (1 << 0) | (1 << 1) | (1 << 3) | (1 << 4) | (1 << 5) | (1 << 6);
// 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;
@ -120,10 +117,36 @@ void setup_7800() {
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 = mode_7800;
mode = CORE_7800;
}
void a7800Menu() {
@ -134,7 +157,6 @@ void a7800Menu() {
case 0:
// Select Cart
setCart_7800();
wait();
setup_7800();
break;
@ -163,7 +185,7 @@ void a7800Menu() {
// READ CODE
//******************************************
uint8_t readData_7800(uint32_t addr) // Add Input Pullup
uint8_t readData_7800(uint16_t addr) // Add Input Pullup
{
PORTF = addr & 0xFF; // A0-A7
PORTK = (addr >> 8) & 0xFF; // A8-A15
@ -201,7 +223,7 @@ uint8_t readData_7800(uint32_t addr) // Add Input Pullup
return ret;
}
void readSegment_7800(uint32_t startaddr, uint32_t endaddr) {
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);
@ -211,7 +233,29 @@ void readSegment_7800(uint32_t startaddr, uint32_t endaddr) {
}
}
void writeData_7800(uint32_t addr, uint8_t data) {
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;
@ -240,13 +284,38 @@ void writeData_7800(uint32_t addr, uint8_t data) {
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(uint32_t addr) {
void bankSwitch_7800(uint16_t addr) {
PORTF = addr & 0xFF; // A0-A7
PORTK = (addr >> 8) & 0xFF; // A8-A15
NOP;
@ -273,53 +342,20 @@ void bankSwitch_7800(uint32_t addr) {
//******************************************
void readROM_7800() {
strcpy(fileName, romName);
strcat(fileName, ".a78");
// create a new folder for storing rom file
EEPROM_readAnything(0, foldern);
sprintf(folder, "7800/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("7800", "ROM", romName, "a78");
switch (a7800mapper) {
case 0: // Standard 16K/32K/48K [7816/7832/7848]
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
readStandard_7800();
break;
case 1: // SuperGame 128K [78SG]
for (int x = 0; x < 7; x++) {
writeData_7800(0x8000, x); // Banks 0-6
readSegment_7800(0x8000, 0xC000); // 16K * 7 = 112K
}
readSegment_7800(0xC000, 0x10000); // Bank 7 +16 = 128K
readSupergame_7800();
break;
case 2: // SuperGame - Alien Brigade/Crossbow 144K [78S9]
readSegment_7800(0x4000, 0x8000); // 16K
for (int x = 0; x < 8; x++) {
writeData_7800(0x8000, x); // Banks 0-7
readSegment_7800(0x8000, 0xC000); // 16K * 8 = +128K = 144K
}
readSegmentBank_7800(0, 8); // 16K * 8 = +128K = 144K
break;
case 3: // F-18 Hornet 64K [78AB]
@ -357,31 +393,53 @@ void readROM_7800() {
break;
case 5: // Realsports Baseball/Tank Command/Tower Toppler/Waterski 64K [78S4]
for (int x = 0; x < 4; x++) {
writeData_7800(0x8000, x);
readSegment_7800(0x8000, 0xC000); // 16K * 4 = 64K
}
readSegmentBank_7800(0, 4); // 16K * 4 = 64K
break;
case 6: // Karateka (PAL) 64K [78S4 Variant]
for (int x = 4; x < 8; x++) {
writeData_7800(0x8000, x);
readSegment_7800(0x8000, 0xC000); // 16K * 4 = 64K
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();
unsigned long crcsize = a7800[a7800size] * 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();
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
//******************************************
@ -398,76 +456,46 @@ void checkMapperSize_7800() {
}
}
#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() {
#if (defined(enable_OLED) || defined(enable_LCD))
byte new7800size;
#if (defined(ENABLE_OLED) || defined(ENABLE_LCD))
display_Clear();
if (a7800lo == a7800hi)
new7800size = a7800lo;
else {
int b = 0;
int i = a7800lo;
display_Clear();
print_Msg(F("ROM Size: "));
println_Msg(a7800[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 == a7800lo)
i = a7800hi;
else
i--;
display_Clear();
print_Msg(F("ROM Size: "));
println_Msg(a7800[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 == a7800hi)
i = a7800lo;
else
i++;
display_Clear();
print_Msg(F("ROM Size: "));
println_Msg(a7800[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)
new7800size = i;
break;
}
}
new7800size = navigateMenu(a7800lo, a7800hi, &printRomSize_7800);
display.setCursor(0, 56); // Display selection at bottom
}
print_Msg(F("ROM SIZE "));
print_Msg(FS(FSTRING_ROM_SIZE));
print_Msg(a7800[new7800size]);
println_Msg(F("K"));
display_Update();
@ -492,7 +520,7 @@ setrom:
new7800size = sizeROM.toInt() + a7800lo;
if (new7800size > a7800hi) {
Serial.println(F("SIZE NOT SUPPORTED"));
Serial.println(F(""));
Serial.println(FS(FSTRING_EMPTY));
goto setrom;
}
}
@ -507,7 +535,7 @@ setrom:
void checkStatus_7800() {
EEPROM_readAnything(7, a7800mapper);
EEPROM_readAnything(8, a7800size);
if (a7800mapper > 6) {
if (a7800mapper > 7) {
a7800mapper = 0; // default
EEPROM_writeAnything(7, a7800mapper);
}
@ -516,28 +544,15 @@ void checkStatus_7800() {
EEPROM_writeAnything(8, a7800size);
}
#if (defined(enable_OLED) || defined(enable_LCD))
#if (defined(ENABLE_OLED) || defined(ENABLE_LCD))
display_Clear();
println_Msg(F("ATARI 7800 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(a7800mapper);
if (a7800mapper == 0)
println_Msg(F("STANDARD"));
else if (a7800mapper == 1)
println_Msg(F("SUPERGAME [78SG]"));
else if (a7800mapper == 2)
println_Msg(F("SUPERGAME [78S9]"));
else if (a7800mapper == 3)
println_Msg(F("F-18 HORNET [78AB]"));
else if (a7800mapper == 4)
println_Msg(F("DBLDRGN/RMPG [78AC]"));
else if (a7800mapper == 5)
println_Msg(F("BASEBALL/ETC [78S4]"));
else if (a7800mapper == 6)
println_Msg(F("KARATEKA(PAL)[78S4]"));
print_Msg(F("ROM SIZE: "));
println_Mapper7800(a7800mapper);
print_Msg(FS(FSTRING_ROM_SIZE));
print_Msg(a7800[a7800size]);
println_Msg(F("K"));
display_Update();
@ -559,10 +574,12 @@ void checkStatus_7800() {
Serial.println(F("Realsports Baseball/Tank Command/Tower Toppler/Waterski [78S4]"));
else if (a7800mapper == 6)
Serial.println(F("Karateka (PAL) [78S4 Variant]"));
Serial.print(F("ROM SIZE: "));
else if (a7800mapper == 7)
Serial.println(F("Bankset"));
Serial.print(FS(FSTRING_ROM_SIZE));
Serial.print(A7800[a7800size]);
Serial.println(F("K"));
Serial.println(F(""));
Serial.println(FS(FSTRING_EMPTY));
#endif
}
@ -570,166 +587,23 @@ void checkStatus_7800() {
// 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() {
#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 = a7800mapcount - 1;
else
i--;
break;
}
display_Clear();
print_Msg(F("Mapper: "));
a7800index = i * 3;
a7800mapselect = pgm_read_byte(a7800mapsize + a7800index);
println_Msg(a7800mapselect);
if (a7800mapselect == 0)
println_Msg(F("STANDARD"));
else if (a7800mapselect == 1)
println_Msg(F("SUPERGAME 128K[78SG]"));
else if (a7800mapselect == 2)
println_Msg(F("SUPERGAME 144K[78S9]"));
else if (a7800mapselect == 3)
println_Msg(F("F-18 HORNET [78AB]"));
else if (a7800mapselect == 4)
println_Msg(F("DBLDRGN/RAMPG [78AC]"));
else if (a7800mapselect == 5)
println_Msg(F("BASEBALL/ETC [78S4]"));
else if (a7800mapselect == 6)
println_Msg(F("KARATEKA(PAL) [78S4]"));
display_Update();
if (i == (a7800mapcount - 1))
i = 0;
else
i++;
delay(250);
}
}
byte new7800mapper = 0;
#if (defined(ENABLE_OLED) || defined(ENABLE_LCD))
navigateMenu(0, a7800mapcount - 1, &printMapperSelection_7800);
new7800mapper = a7800mapselect;
display_Clear();
print_Msg(F("Mapper: "));
a7800index = i * 3;
a7800mapselect = pgm_read_byte(a7800mapsize + a7800index);
println_Msg(a7800mapselect);
if (a7800mapselect == 0)
println_Msg(F("STANDARD"));
else if (a7800mapselect == 1)
println_Msg(F("SUPERGAME 128K[78SG]"));
else if (a7800mapselect == 2)
println_Msg(F("SUPERGAME 144K[78S9]"));
else if (a7800mapselect == 3)
println_Msg(F("F-18 HORNET [78AB]"));
else if (a7800mapselect == 4)
println_Msg(F("DBLDRGN/RAMPG [78AC]"));
else if (a7800mapselect == 5)
println_Msg(F("BASEBALL/ETC [78S4]"));
else if (a7800mapselect == 6)
println_Msg(F("KARATEKA(PAL) [78S4]"));
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 = a7800mapcount - 1;
else
i--;
display_Clear();
print_Msg(F("Mapper: "));
a7800index = i * 3;
a7800mapselect = pgm_read_byte(a7800mapsize + a7800index);
println_Msg(a7800mapselect);
if (a7800mapselect == 0)
println_Msg(F("STANDARD"));
else if (a7800mapselect == 1)
println_Msg(F("SUPERGAME 128K[78SG]"));
else if (a7800mapselect == 2)
println_Msg(F("SUPERGAME 144K[78S9]"));
else if (a7800mapselect == 3)
println_Msg(F("F-18 HORNET [78AB]"));
else if (a7800mapselect == 4)
println_Msg(F("DBLDRGN/RAMPG [78AC]"));
else if (a7800mapselect == 5)
println_Msg(F("BASEBALL/ETC [78S4]"));
else if (a7800mapselect == 6)
println_Msg(F("KARATEKA(PAL) [78S4]"));
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 == (a7800mapcount - 1))
i = 0;
else
i++;
display_Clear();
print_Msg(F("Mapper: "));
a7800index = i * 3;
a7800mapselect = pgm_read_byte(a7800mapsize + a7800index);
println_Msg(a7800mapselect);
if (a7800mapselect == 0)
println_Msg(F("STANDARD"));
else if (a7800mapselect == 1)
println_Msg(F("SUPERGAME 128K[78SG]"));
else if (a7800mapselect == 2)
println_Msg(F("SUPERGAME 144K[78S9]"));
else if (a7800mapselect == 3)
println_Msg(F("F-18 HORNET [78AB]"));
else if (a7800mapselect == 4)
println_Msg(F("DBLDRGN/RAMPG [78AC]"));
else if (a7800mapselect == 5)
println_Msg(F("BASEBALL/ETC [78S4]"));
else if (a7800mapselect == 6)
println_Msg(F("KARATEKA(PAL) [78S4]"));
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)
new7800mapper = a7800mapselect;
break;
}
}
display.setCursor(0, 56);
print_Msg(F("MAPPER "));
print_Msg(new7800mapper);
@ -747,7 +621,8 @@ setmapper:
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.print(F("Enter Mapper [0-6]: "));
Serial.println(F("7 = Bankset"));
Serial.print(F("Enter Mapper [0-7]: "));
while (Serial.available() == 0) {}
newmap = Serial.readStringUntil('\n');
Serial.println(newmap);
@ -765,257 +640,25 @@ setmapper:
// CART SELECT CODE
//******************************************
FsFile a7800csvFile;
char a7800game[36]; // title
char a7800mm[3]; // mapper
char a7800rr[3]; // mapper
char a7800ll[4]; // linelength (previous line)
unsigned long a7800csvpos; // CSV File Position
char a7800cartCSV[] = "7800cart.txt"; // CSV List
char a7800csvEND[] = "EOF"; // CSV End Marker for scrolling
bool readLine_7800(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_7800(char* a7800game, char* a7800mm, char* a7800rr, char* a7800ll) {
char line[44];
a7800csvpos = a7800csvFile.position();
if (!readLine_7800(a7800csvFile, line, sizeof(line))) {
return false; // EOF or too long
}
char* comma = strtok(line, ",");
int x = 0;
while (comma != NULL) {
if (x == 0)
strcpy(a7800game, comma);
else if (x == 1)
strcpy(a7800mm, comma);
else if (x == 2)
strcpy(a7800rr, comma);
else if (x == 3)
strcpy(a7800ll, comma);
comma = strtok(NULL, ",");
x += 1;
}
return true;
}
bool getCartListInfo_7800() {
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_7800(a7800game, a7800mm, a7800rr, a7800ll)) {
if (strcmp(a7800csvEND, a7800game) == 0) {
a7800csvFile.seek(0); // Restart
} else {
#if (defined(enable_OLED) || defined(enable_LCD))
display_Clear();
println_Msg(F("CART TITLE:"));
println_Msg(F(""));
println_Msg(a7800game);
display_Update();
#else
Serial.print(F("CART TITLE:"));
Serial.println(a7800game);
#endif
#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
buttonreleased = 1;
break;
}
if (buttonreleased) {
buttonreleased = 0; // Reset Flag
break;
}
}
}
#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
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_7800(a7800game, a7800mm, a7800rr, a7800ll)) {
if (strcmp(a7800csvEND, a7800game) == 0) {
a7800csvFile.seek(0); // Restart
} else {
#if (defined(enable_OLED) || defined(enable_LCD))
display_Clear();
println_Msg(F("CART TITLE:"));
println_Msg(F(""));
println_Msg(a7800game);
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(a7800game);
#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(a7800ll, NULL, 10);
a7800csvpos -= prevline;
a7800csvFile.seek(a7800csvpos);
break;
}
if (b == 3) { // Long Press - Select Cart (hold)
new7800mapper = strtol(a7800mm, NULL, 10);
new7800size = strtol(a7800rr, NULL, 10);
EEPROM_writeAnything(7, new7800mapper);
EEPROM_writeAnything(8, new7800size);
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_7800() {
if (getCartListInfo_7800()) {
#if (defined(enable_OLED) || defined(enable_LCD))
display_Clear();
println_Msg(F("CART SELECTED"));
println_Msg(F(""));
println_Msg(a7800game);
display_Update();
// Display Settings
display.setCursor(0, 56);
print_Msg(F("CODE: M"));
print_Msg(new7800mapper);
print_Msg(F("/R"));
println_Msg(new7800size);
display_Update();
#else
Serial.println(F(""));
Serial.println(F("CART SELECTED"));
Serial.println(a7800game);
// Display Settings
Serial.print(F("CODE: M"));
Serial.print(new7800mapper);
Serial.print(F("/R"));
Serial.println(new7800size);
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 checkSize_7800() {
EEPROM_readAnything(7, a7800mapper);
for (int i = 0; i < a7800mapcount; i++) {
a7800index = i * 3;
if (a7800mapper == pgm_read_byte(a7800mapsize + a7800index)) {
a7800size = pgm_read_byte(a7800mapsize + a7800index + 1);
EEPROM_writeAnything(8, a7800size);
break;
}
}
}
void setCart_7800() {
#if (defined(enable_OLED) || defined(enable_LCD))
display_Clear();
println_Msg(a7800cartCSV);
display_Update();
#endif
//go to root
sd.chdir();
sprintf(folder, "7800/CSV");
sd.chdir(folder); // Switch Folder
a7800csvFile = sd.open(a7800cartCSV, O_READ);
if (!a7800csvFile) {
#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_7800();
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));
}
checkCSV_7800();
a7800csvFile.close();
}
#endif

View File

@ -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,246 +253,32 @@ 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 {
#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_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
//******************************************

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -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

View File

@ -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

View File

@ -53,7 +53,7 @@
automatically be enabled if you selected HW2 or newer above.
*/
//#define clockgen_installed
//#define ENABLE_CLOCKGEN
/****/
@ -62,7 +62,7 @@
type later in this file.
*/
//#define RTC_installed
//#define ENABLE_RTC
/****/
@ -71,217 +71,252 @@
/* [ Atari 2600 --------------------------------------------------- ]
*/
//#define enable_ATARI
//#define ENABLE_2600
/****/
/* [ Atari 5200 --------------------------------------------------- ]
*/
//#define enable_5200
//#define ENABLE_5200
/****/
/* [ Atari 7800 --------------------------------------------------- ]
*/
//#define enable_7800
//#define ENABLE_7800
/****/
/* [ Benesse Pocket Challenge W ----------------------------------- ]
*/
//#define enable_PCW
//#define ENABLE_PCW
/****/
/* [ C64 --------------------------------------------------- ]
*/
//#define enable_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
//#define ENABLE_VECTREX
/****/
/* [ Virtual Boy -------------------------------------------------- ]
*/
//#define enable_VBOY
//#define ENABLE_VBOY
/****/
/* [ 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 ===========================================*/
/* [ 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 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 background_color 100, 0, 0
#define OPTION_LCD_BG_COLOR 100, 0, 0
/****/
@ -312,15 +347,18 @@
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
Can be toggled off using config:
oscr.logging=0
*/
#define global_log
#define ENABLE_GLOBAL_LOG
/****/
@ -338,8 +376,8 @@
Toggle clock calibration menu and whether or not to use calibration data from snes_clk.txt
*/
//#define clockgen_calibration
//#define use_clockgen_calibration
//#define OPTION_CLOCKGEN_CALIBRATION
//#define OPTION_CLOCKGEN_USE_CALIBRATION
/****/
@ -353,16 +391,29 @@
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
/****/
@ -372,7 +423,7 @@
with all Cart Readers
*/
//#define fastcrc
//#define OPTION_N64_FASTCRC
/****/
@ -380,7 +431,7 @@
Enable to save a n64log.txt file with rom info in /N64/ROM
*/
//#define savesummarytotxt
//#define OPTION_N64_SAVESUMMARY
/****/
@ -390,39 +441,47 @@
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 */

View File

@ -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;
@ -459,7 +432,7 @@ void readROM_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();
}
}
@ -476,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();
@ -511,14 +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 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
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();
}
}
@ -531,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();
@ -543,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();
@ -636,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;
}
}
@ -655,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();
@ -669,246 +585,32 @@ 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
//******************************************

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -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"));
}
}

View File

@ -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();

View File

@ -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
View 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
//******************************************

View File

@ -1,7 +1,7 @@
//******************************************
// INTELLIVISION MODULE
//******************************************
#ifdef enable_INTV
#ifdef ENABLE_INTV
// Mattel Intellivision
// Cartridge Pinout
@ -80,9 +80,7 @@ byte intvlo = 0; // Lowest 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,28 +303,7 @@ 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/12K/16K/24K/32K)
@ -428,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();
@ -488,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);
@ -618,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;
}
@ -639,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();
@ -735,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;
}
}
@ -759,14 +589,14 @@ void checkStatus_INTV() {
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();
@ -777,178 +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, 12, 16, 24, 32, 48};
switch (cartSize) {
case 8:
intvsize = 0;
break;
case 12:
intvsize = 1;
break;
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, 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

View File

@ -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);

View File

@ -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
@ -87,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
@ -111,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++) {
@ -173,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);
@ -197,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() {
@ -230,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("/");
@ -279,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();
@ -324,7 +329,7 @@ void mdCartMenu() {
} else {
print_Error(F("Cart has no ROM"));
}
#ifdef global_log
#ifdef ENABLE_GLOBAL_LOG
save_log();
#endif
break;
@ -453,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();
@ -467,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
@ -745,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
@ -770,48 +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 0x2078: //Dynamite Headdy (USA, Europe)
case 0x2078: // Dynamite Headdy (USA, Europe)
chksum = 0x9877;
break;
case 0xAE95: //Winter Olympic Games (USA)
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;
@ -819,55 +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 0x5B3A: //NHL 98 (USA)
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)
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)
case 0xA760: // Gain Ground (USA)
chksum = 0x97CD;
break;
case 0x1404: //Wonder Boy III - Monster Lair (Japan, Europe) (En)
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;
@ -890,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) {
@ -1073,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
@ -1095,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"));
}
}
@ -1173,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];
@ -1222,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:
@ -1271,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);
@ -1284,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();
@ -1352,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 };
@ -1650,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();
}
@ -1665,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();
}
}
@ -1781,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;
@ -1896,7 +1939,7 @@ unsigned long verifySram_MD() {
return writeErrors;
}
#ifdef enable_FLASH
#ifdef ENABLE_FLASH
//******************************************
// Flashrom Functions
//******************************************
@ -2642,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;
@ -2684,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);
@ -2719,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();
@ -2742,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;
@ -2772,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);
@ -2804,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();
@ -2837,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)

View File

@ -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,255 +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);
#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(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

View File

@ -1,7 +1,7 @@
//******************************************
// NINTENDO 64 MODULE
//******************************************
#ifdef enable_N64
#ifdef ENABLE_N64
/******************************************
Defines
@ -39,18 +39,15 @@ boolean MN63F81MPN = false;
//ControllerTest
bool quit = 1;
#ifdef savesummarytotxt
#ifdef OPTION_N64_SAVESUMMARY
String CRC1 = "";
String CRC2 = "";
#endif
#if !defined(enable_FLASH)
#if !defined(ENABLE_FLASH)
unsigned long flashSize;
#endif
static const char N64_EEP_FILENAME_FMT[] PROGMEM = "%s.eep";
static const char N64_SAVE_DIRNAME_FMT[] PROGMEM = "N64/SAVE/%s/%d";
/******************************************
Menu
*****************************************/
@ -60,30 +57,23 @@ static const char n64MenuItem2[] PROGMEM = "Controller";
static const char n64MenuItem3[] PROGMEM = "Flash Repro";
static const char n64MenuItem4[] PROGMEM = "Flash Gameshark";
static const char n64MenuItem5[] PROGMEM = "Flash Xplorer 64";
//static const char n64MenuItem6[] PROGMEM = "Reset"; (stored in common strings array)
static const char* const menuOptionsN64[] PROGMEM = { n64MenuItem1, n64MenuItem2, n64MenuItem3, n64MenuItem4, n64MenuItem5, string_reset2 };
static const char* const menuOptionsN64[] PROGMEM = { n64MenuItem1, n64MenuItem2, n64MenuItem3, n64MenuItem4, n64MenuItem5, FSTRING_RESET };
// N64 controller menu items
static const char N64ContMenuItem1[] PROGMEM = "Test Controller";
static const char N64ContMenuItem2[] PROGMEM = "Read ControllerPak";
static const char N64ContMenuItem3[] PROGMEM = "Write ControllerPak";
//static const char N64ContMenuItem4[] PROGMEM = "Reset"; (stored in common strings array)
static const char* const menuOptionsN64Controller[] PROGMEM = { N64ContMenuItem1, N64ContMenuItem2, N64ContMenuItem3, string_reset2 };
static const char* const menuOptionsN64Controller[] PROGMEM = { N64ContMenuItem1, N64ContMenuItem2, N64ContMenuItem3, FSTRING_RESET };
// N64 cart menu items
static const char N64CartMenuItem1[] PROGMEM = "Read ROM";
static const char N64CartMenuItem2[] PROGMEM = "Read Save";
static const char N64CartMenuItem3[] PROGMEM = "Write Save";
static const char N64CartMenuItem4[] PROGMEM = "Force Savetype";
//static const char N64CartMenuItem5[] PROGMEM = "Reset"; (stored in common strings array)
static const char* const menuOptionsN64Cart[] PROGMEM = { N64CartMenuItem1, N64CartMenuItem2, N64CartMenuItem3, N64CartMenuItem4, string_reset2 };
static const char* const menuOptionsN64Cart[] PROGMEM = { FSTRING_READ_ROM, FSTRING_READ_SAVE, FSTRING_WRITE_SAVE, N64CartMenuItem4, FSTRING_RESET };
// N64 CRC32 error menu items
static const char N64CRCMenuItem1[] PROGMEM = "No";
static const char N64CRCMenuItem2[] PROGMEM = "Yes and keep old";
static const char N64CRCMenuItem3[] PROGMEM = "Yes and delete old";
//static const char N64CRCMenuItem4[] PROGMEM = "Reset"; (stored in common strings array)
static const char* const menuOptionsN64CRC[] PROGMEM = { N64CRCMenuItem1, N64CRCMenuItem2, N64CRCMenuItem3, string_reset2 };
static const char* const menuOptionsN64CRC[] PROGMEM = { N64CRCMenuItem1, N64CRCMenuItem2, N64CRCMenuItem3, FSTRING_RESET };
// Rom menu
static const char N64RomItem1[] PROGMEM = "4 MB";
@ -132,14 +122,14 @@ void n64Menu() {
display_Update();
setup_N64_Cart();
printCartInfo_N64();
mode = mode_N64_Cart;
mode = CORE_N64_CART;
break;
case 1:
display_Clear();
display_Update();
setup_N64_Controller();
mode = mode_N64_Controller;
mode = CORE_N64_CONTROLLER;
break;
case 2:
@ -148,7 +138,7 @@ void n64Menu() {
setup_N64_Cart();
flashRepro_N64();
printCartInfo_N64();
mode = mode_N64_Cart;
mode = CORE_N64_CART;
break;
case 3:
@ -157,7 +147,7 @@ void n64Menu() {
setup_N64_Cart();
flashGameshark_N64();
printCartInfo_N64();
mode = mode_N64_Cart;
mode = CORE_N64_CART;
break;
case 4:
@ -165,7 +155,7 @@ void n64Menu() {
display_Update();
setup_N64_Cart();
flashXplorer_N64();
mode = mode_N64_Cart;
mode = CORE_N64_CART;
print_STR(press_button_STR, 1);
display_Update();
wait();
@ -192,9 +182,9 @@ void n64ControllerMenu() {
resetController();
display_Clear();
display_Update();
#if (defined(enable_OLED) || defined(enable_LCD))
#if (defined(ENABLE_OLED) || defined(ENABLE_LCD))
controllerTest_Display();
#elif defined(enable_serial)
#elif defined(ENABLE_SERIAL)
controllerTest_Serial();
#endif
quit = 1;
@ -208,7 +198,7 @@ void n64ControllerMenu() {
readMPK();
verifyCRC();
validateMPK();
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();
@ -230,7 +220,7 @@ void n64ControllerMenu() {
writeMPK();
delay(500);
verifyMPK();
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 +246,7 @@ void n64CartMenu() {
case 0:
display_Clear();
sd.chdir("/");
#ifndef fastcrc
#ifndef OPTION_N64_FASTCRC
// Dumping ROM slow
readRom_N64();
sd.chdir("/");
@ -266,7 +256,7 @@ void n64CartMenu() {
compareCRC("n64.txt", readRom_N64(), 1, 0);
#endif
#ifdef global_log
#ifdef ENABLE_GLOBAL_LOG
save_log();
#endif
@ -296,7 +286,7 @@ void n64CartMenu() {
} else {
print_Error(F("Savetype 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();
@ -332,7 +322,7 @@ void n64CartMenu() {
display_Update();
writeErrors = verifyFram(flashramType);
if (writeErrors == 0) {
println_Msg(F("OK"));
println_Msg(FS(FSTRING_OK));
display_Update();
} else {
println_Msg("");
@ -448,7 +438,7 @@ void setup_N64_Cart() {
PORTC &= ~(1 << 0);
PORTC |= (1 << 1);
#ifdef clockgen_installed
#ifdef ENABLE_CLOCKGEN
// Adafruit Clock Generator
initializeClockOffset();
@ -479,7 +469,7 @@ void setup_N64_Cart() {
// Set sram base address
sramBase = 0x08000000;
#ifdef clockgen_installed
#ifdef ENABLE_CLOCKGEN
// Wait for clock generator
clockgen.update_status();
#endif
@ -1011,7 +1001,7 @@ void get_button() {
/******************************************
N64 Controller Test
*****************************************/
#ifdef enable_serial
#ifdef ENABLE_SERIAL
void controllerTest_Serial() {
while (quit) {
// Get Button and analog stick
@ -1038,7 +1028,7 @@ void controllerTest_Serial() {
}
#endif
#if (defined(enable_LCD) || defined(enable_OLED))
#if (defined(ENABLE_LCD) || defined(ENABLE_OLED))
#define CENTER 64
// on which screens do we start
int startscreen = 1;
@ -1933,7 +1923,7 @@ void printCartInfo_N64() {
// Print start page
if (cartSize != 0) {
display_Clear();
print_Msg(F("Title: "));
print_Msg(FS(FSTRING_NAME));
println_Msg(romName);
print_Msg(F("Serial: "));
println_Msg(cartID);
@ -1967,7 +1957,7 @@ void printCartInfo_N64() {
println_Msg(checksumStr);
// Wait for user input
println_Msg(F(" "));
println_Msg(FS(FSTRING_SPACE));
// Prints string out of the common strings array either with or without newline
print_STR(press_button_STR, 1);
display_Update();
@ -1977,7 +1967,7 @@ void printCartInfo_N64() {
display_Clear();
println_Msg(F("GAMEPAK ERROR"));
println_Msg("");
print_Msg(F("Title: "));
print_Msg(FS(FSTRING_NAME));
println_Msg(romName);
print_Msg(F("Serial: "));
println_Msg(cartID);
@ -2189,7 +2179,7 @@ void idCart() {
strcpy(romName, cartID);
}
#ifdef savesummarytotxt
#ifdef OPTION_N64_SAVESUMMARY
// Get CRC1
for (int i = 0; i < 4; i++) {
if (sdBuffer[0x10 + i] < 0x10) {
@ -2288,30 +2278,15 @@ boolean readEepromPageList(byte* output, byte page_number, byte page_count) {
void readEeprom() {
if ((saveType == 5) || (saveType == 6)) {
// Get name, add extension and convert to char array for sd lib
snprintf_P(fileName, sizeof(fileName), N64_EEP_FILENAME_FMT, romName);
// create a new folder for the save file
EEPROM_readAnything(0, foldern);
snprintf_P(folder, sizeof(folder), N64_SAVE_DIRNAME_FMT, romName, foldern);
sd.mkdir(folder, true);
sd.chdir(folder);
// 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("N64", "SAVE", romName, "eep");
for (int i = 0; i < eepPages; i += sizeof(sdBuffer) / 8) {
// If any missing bytes error out
if (readEepromPageList(sdBuffer, i, sizeof(sdBuffer) / 8) == 0) {
println_Msg(F(""));
println_Msg(FS(FSTRING_EMPTY));
print_STR(error_STR, 0);
println_Msg(F("no data received"));
println_Msg(F(""));
println_Msg(FS(FSTRING_EMPTY));
break;
}
// Write 64 pages at once to the SD card
@ -2419,30 +2394,16 @@ void readSram(unsigned long sramSize, byte flashramType) {
}
// Get name, add extension and convert to char array for sd lib
strcpy(fileName, romName);
const char* suffix;
if (saveType == 4) {
strcat(fileName, ".fla");
suffix = "fla";
} else if (saveType == 1) {
strcat(fileName, ".sra");
suffix = "sra";
} else {
print_FatalError(F("Savetype Error"));
}
// create a new folder for the save file
EEPROM_readAnything(0, foldern);
sprintf(folder, "N64/SAVE/%s/%d", romName, foldern);
sd.mkdir(folder, true);
sd.chdir(folder);
// write new folder number back to eeprom
foldern = foldern + 1;
EEPROM_writeAnything(0, foldern);
// Open file on sd card
if (!myFile.open(fileName, O_RDWR | O_CREAT)) {
print_FatalError(sd_error_STR);
}
createFolderAndOpenFile("N64", "SAVE", romName, suffix);
for (unsigned long currByte = sramBase; currByte < (sramBase + (sramSize / flashramType)); currByte += offset) {
// Set the address
@ -2546,7 +2507,7 @@ void writeFram(byte flashramType) {
// Check if empty
if (blankcheck_N64(flashramType) == 0) {
println_Msg(F("OK"));
println_Msg(FS(FSTRING_OK));
display_Update();
} else {
println_Msg(F("FAIL"));
@ -2568,7 +2529,7 @@ void writeFram(byte flashramType) {
print_Msg(F("Bank "));
for (byte bank = 0; bank < 8; bank++) {
print_Msg(bank);
print_Msg(F(" "));
print_Msg(FS(FSTRING_SPACE));
display_Update();
// Write one bank of 128*128 bytes
@ -2824,29 +2785,15 @@ void getFramType() {
Rom functions
*****************************************/
// Read rom and save to the SD card
#ifndef fastcrc
#ifndef OPTION_N64_FASTCRC
// dumping rom slow
void readRom_N64() {
// Get name, add extension and convert to char array for sd lib
strcpy(fileName, romName);
strcat(fileName, ".Z64");
// create a new folder
EEPROM_readAnything(0, foldern);
sprintf(folder, "N64/ROM/%s/%d", romName, foldern);
sd.mkdir(folder, true);
sd.chdir(folder);
createFolder("N64", "ROM", romName, "Z64");
// 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);
printAndIncrementFolder();
// Open file on sd card
if (!myFile.open(fileName, O_RDWR | O_CREAT)) {
@ -2883,25 +2830,11 @@ void readRom_N64() {
// dumping rom fast
uint32_t readRom_N64() {
// Get name, add extension and convert to char array for sd lib
strcpy(fileName, romName);
strcat(fileName, ".Z64");
// create a new folder
EEPROM_readAnything(0, foldern);
sprintf(folder, "N64/ROM/%s/%d", romName, foldern);
sd.mkdir(folder, true);
sd.chdir(folder);
createFolder("N64", "ROM", romName, "Z64");
// 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);
printAndIncrementFolder();
// Open file on sd card
if (!myFile.open(fileName, O_RDWR | O_CREAT)) {
@ -2993,7 +2926,7 @@ uint32_t readRom_N64() {
}
#endif
#ifdef savesummarytotxt
#ifdef OPTION_N64_SAVESUMMARY
// Save an info.txt with information on the dumped rom to the SD card
void savesummary_N64(boolean checkfound, char crcStr[9], unsigned long timeElapsed) {
// Open file on sd card
@ -3044,7 +2977,7 @@ void savesummary_N64(boolean checkfound, char crcStr[9], unsigned long timeElaps
myFile.print(F("Saved To: "));
myFile.println(folder);
#ifdef RTC_installed
#ifdef ENABLE_RTC
myFile.print(F("Dumped\t: "));
myFile.println(RTCStamp());
#endif
@ -3064,7 +2997,7 @@ void savesummary_N64(boolean checkfound, char crcStr[9], unsigned long timeElaps
myFile.print(F("Time\t: "));
myFile.println(timeElapsed);
myFile.println(F(" "));
myFile.println(FS(FSTRING_SPACE));
// Close the file:
myFile.close();
@ -3127,11 +3060,11 @@ void flashRepro_N64() {
println_Msg(F("Unknown flashrom"));
print_Msg(F("ID: "));
print_Msg(vendorID);
print_Msg(F(" "));
print_Msg(FS(FSTRING_SPACE));
print_Msg(flashid_str);
print_Msg(F(" "));
print_Msg(FS(FSTRING_SPACE));
println_Msg(cartID);
println_Msg(F(" "));
println_Msg(FS(FSTRING_SPACE));
println_Msg(F("Press button for"));
println_Msg(F("manual config"));
println_Msg(F("This will erase your"));
@ -3294,7 +3227,7 @@ void flashRepro_N64() {
// Check if erase was successful
if (blankcheckFlashrom_N64()) {
// Write flashrom
println_Msg(F("OK"));
println_Msg(FS(FSTRING_OK));
print_Msg(F("Writing "));
println_Msg(filePath);
display_Update();
@ -3336,7 +3269,7 @@ void flashRepro_N64() {
display_Update();
writeErrors = verifyFlashrom_N64();
if (writeErrors == 0) {
println_Msg(F("OK"));
println_Msg(FS(FSTRING_OK));
display_Update();
} else {
print_Msg(writeErrors);
@ -3384,17 +3317,21 @@ void resetFlashrom_N64(unsigned long flashBase) {
delay(100);
}
void sendFlashromCommand_N64(unsigned long addr, byte cmd) {
setAddress_N64(addr + (0x555 << 1));
writeWord_N64(0xAA);
setAddress_N64(addr + (0x2AA << 1));
writeWord_N64(0x55);
setAddress_N64(addr + (0x555 << 1));
writeWord_N64(cmd);
}
void idFlashrom_N64() {
// Set size to 0 if no ID is found
cartSize = 0;
// Send flashrom ID command
setAddress_N64(romBase + (0x555 << 1));
writeWord_N64(0xAA);
setAddress_N64(romBase + (0x2AA << 1));
writeWord_N64(0x55);
setAddress_N64(romBase + (0x555 << 1));
writeWord_N64(0x90);
sendFlashromCommand_N64(romBase, 0x90);
// Read 1 byte vendor ID
setAddress_N64(romBase);
@ -3414,12 +3351,7 @@ void idFlashrom_N64() {
resetFlashrom_N64(romBase);
// Test for second flashrom chip at 0x2000000 (32MB)
setAddress_N64(romBase + 0x2000000 + (0x555 << 1));
writeWord_N64(0xAA);
setAddress_N64(romBase + 0x2000000 + (0x2AA << 1));
writeWord_N64(0x55);
setAddress_N64(romBase + 0x2000000 + (0x555 << 1));
writeWord_N64(0x90);
sendFlashromCommand_N64(romBase + 0x2000000, 0x90);
char tempID[5];
setAddress_N64(romBase + 0x2000000);
@ -3442,12 +3374,7 @@ void idFlashrom_N64() {
resetFlashrom_N64(romBase + 0x800000);
// Test for second flashrom chip at 0x800000 (8MB)
setAddress_N64(romBase + 0x800000 + (0x555 << 1));
writeWord_N64(0xAA);
setAddress_N64(romBase + 0x800000 + (0x2AA << 1));
writeWord_N64(0x55);
setAddress_N64(romBase + 0x800000 + (0x555 << 1));
writeWord_N64(0x90);
sendFlashromCommand_N64(romBase + 0x800000, 0x90);
char tempID[5];
setAddress_N64(romBase + 0x800000);
@ -3470,12 +3397,7 @@ void idFlashrom_N64() {
resetIntel4400_N64();
// Test if second half of the flashrom might be hidden
setAddress_N64(romBase + 0x2000000 + (0x555 << 1));
writeWord_N64(0xAA);
setAddress_N64(romBase + 0x2000000 + (0x2AA << 1));
writeWord_N64(0x55);
setAddress_N64(romBase + 0x2000000 + (0x555 << 1));
writeWord_N64(0x90);
sendFlashromCommand_N64(romBase + 0x2000000, 0x90);
// Read manufacturer ID
setAddress_N64(romBase + 0x2000000);
@ -3718,18 +3640,8 @@ void eraseFlashrom_N64() {
display_Update();
// Send Erase Command
setAddress_N64(romBase + (0x555 << 1));
writeWord_N64(0xAA);
setAddress_N64(romBase + (0x2AA << 1));
writeWord_N64(0x55);
setAddress_N64(romBase + (0x555 << 1));
writeWord_N64(0x80);
setAddress_N64(romBase + (0x555 << 1));
writeWord_N64(0xAA);
setAddress_N64(romBase + (0x2AA << 1));
writeWord_N64(0x55);
setAddress_N64(romBase + (0x555 << 1));
writeWord_N64(0x10);
sendFlashromCommand_N64(romBase, 0x80);
sendFlashromCommand_N64(romBase, 0x10);
// Read the status register
setAddress_N64(romBase);
@ -3765,12 +3677,7 @@ void eraseSector_N64(unsigned long sectorSize) {
}
// Send Erase Command
setAddress_N64(flashBase + (0x555 << 1));
writeWord_N64(0xAA);
setAddress_N64(flashBase + (0x2AA << 1));
writeWord_N64(0x55);
setAddress_N64(flashBase + (0x555 << 1));
writeWord_N64(0x80);
sendFlashromCommand_N64(flashBase, 0x80);
setAddress_N64(flashBase + (0x555 << 1));
writeWord_N64(0xAA);
setAddress_N64(flashBase + (0x2AA << 1));
@ -3778,6 +3685,7 @@ void eraseSector_N64(unsigned long sectorSize) {
setAddress_N64(romBase + currSector);
writeWord_N64(0x30);
// Read the status register
setAddress_N64(romBase + currSector);
word statusReg = readWord_N64();
@ -3998,13 +3906,7 @@ void writeFlashrom_N64(unsigned long sectorSize) {
// Join two bytes into one word
word currWord = ((sdBuffer[currByte] & 0xFF) << 8) | (sdBuffer[currByte + 1] & 0xFF);
// 2 unlock commands
setAddress_N64(flashBase + (0x555 << 1));
writeWord_N64(0xAA);
setAddress_N64(flashBase + (0x2AA << 1));
writeWord_N64(0x55);
// Program command
setAddress_N64(flashBase + (0x555 << 1));
writeWord_N64(0xA0);
sendFlashromCommand_N64(flashBase, 0xA0);
// Write word
setAddress_N64(romBase + currSector + currSdBuffer + currByte);
writeWord_N64(currWord);
@ -4064,6 +3966,15 @@ unsigned long verifyFlashrom_N64() {
/******************************************
N64 Gameshark Flash Functions
*****************************************/
void sendFlashromGamesharkCommand_N64(uint16_t cmd) {
setAddress_N64(0x1EF0AAA8);
writeWord_N64(0xAAAA);
setAddress_N64(0x1EE05554);
writeWord_N64(0x5555);
setAddress_N64(0x1EF0AAA8);
writeWord_N64(cmd);
}
void flashGameshark_N64() {
// Check flashrom ID's
unlockGSAddressRanges();
@ -4141,7 +4052,7 @@ void flashGameshark_N64() {
display_Clear();
display_Update();
println_Msg(F("Verfied OK"));
println_Msg(F(""));
println_Msg(FS(FSTRING_EMPTY));
println_Msg(F("Turn Cart Reader off now"));
display_Update();
while (1)
@ -4178,12 +4089,7 @@ void unlockGSAddressRanges() {
void idGameshark_N64() {
flashid = 0x0;
//Send flashrom ID command
setAddress_N64(0x1EF0AAA8);
writeWord_N64(0xAAAA);
setAddress_N64(0x1EE05554);
writeWord_N64(0x5555);
setAddress_N64(0x1EF0AAA8);
writeWord_N64(0x9090);
sendFlashromGamesharkCommand_N64(0x9090);
setAddress_N64(0x1EC00000);
// Read 1 byte vendor ID
@ -4213,48 +4119,18 @@ void idGameshark_N64() {
void resetGameshark_N64() {
if (flashid == 0x0808 || flashid == 0x3535 || flashid == 0x0707) {
// Send reset command for SST 29LE010 / AMTEL AT29LV010A / SST 29EE010
setAddress_N64(0x1EF0AAA8);
writeWord_N64(0xAAAA);
setAddress_N64(0x1EE05554);
writeWord_N64(0x5555);
setAddress_N64(0x1EF0AAA8);
writeWord_N64(0xF0F0);
sendFlashromGamesharkCommand_N64(0xF0F0);
delay(100);
} else if (flashid == 0x0404) {
// Send reset command for SST 28LF040
setAddress_N64(0x1EF0AAA8);
writeWord_N64(0xAAAA);
setAddress_N64(0x1EE05554);
writeWord_N64(0x5555);
setAddress_N64(0x1EF0AAA8);
writeWord_N64(0xFFFF);
sendFlashromGamesharkCommand_N64(0xFFFF);
delay(300);
}
}
// Read rom and save to the SD card
void backupGameshark_N64() {
// create a new folder
EEPROM_readAnything(0, foldern);
sprintf(fileName, "GS%d", foldern);
strcat(fileName, ".z64");
sd.mkdir("N64/ROM/Gameshark", true);
sd.chdir("N64/ROM/Gameshark");
display_Clear();
print_Msg(F("Saving "));
print_Msg(fileName);
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("N64", "ROM", "GameShark", "z64");
for (unsigned long currByte = romBase + 0xEC00000; currByte < (romBase + 0xEC00000 + flashSize); currByte += 512) {
// Blink led
@ -4286,18 +4162,8 @@ void eraseGameshark_N64() {
// Send chip erase to SST 29LE010 / AMTEL AT29LV010A / SST 29EE010
if (flashid == 0x0808 || flashid == 0x3535 || flashid == 0x0707) {
setAddress_N64(0x1EF0AAA8);
writeWord_N64(0xAAAA);
setAddress_N64(0x1EE05554);
writeWord_N64(0x5555);
setAddress_N64(0x1EF0AAA8);
writeWord_N64(0x8080);
setAddress_N64(0x1EF0AAA8);
writeWord_N64(0xAAAA);
setAddress_N64(0x1EE05554);
writeWord_N64(0x5555);
setAddress_N64(0x1EF0AAA8);
writeWord_N64(0x1010);
sendFlashromGamesharkCommand_N64(0x8080);
sendFlashromGamesharkCommand_N64(0x1010);
delay(20);
}
@ -4321,12 +4187,7 @@ void eraseGameshark_N64() {
delay(1000);
//Erase flash
setAddress_N64(0x1EF0AAA8);
writeWord_N64(0xAAAA);
setAddress_N64(0x1EE05554);
writeWord_N64(0x5555);
setAddress_N64(0x1EF0AAA8);
writeWord_N64(0x3030);
sendFlashromGamesharkCommand_N64(0x3030);
setAddress_N64(0x1EF0AAA8);
writeWord_N64(0x3030);
delay(1000);
@ -4369,12 +4230,7 @@ void writeGameshark_N64() {
myFile.read(sdBuffer, 256);
//Send page write command to both flashroms
setAddress_N64(0x1EF0AAA8);
writeWord_N64(0xAAAA);
setAddress_N64(0x1EE05554);
writeWord_N64(0x5555);
setAddress_N64(0x1EF0AAA8);
writeWord_N64(0xA0A0);
sendFlashromGamesharkCommand_N64(0xA0A0);
// Write 1 page each, one flashrom gets the low byte, the other the high byte.
for (unsigned long currByte = 0; currByte < 256; currByte += 2) {
@ -4406,12 +4262,7 @@ void writeGameshark_N64() {
for (unsigned long currByte = 0; currByte < 256; currByte += 2) {
// Send byte program command
setAddress_N64(0x1EF0AAA8);
writeWord_N64(0xAAAA);
setAddress_N64(0x1EE05554);
writeWord_N64(0x5555);
setAddress_N64(0x1EF0AAA8);
writeWord_N64(0x1010);
sendFlashromGamesharkCommand_N64(0x1010);
// Set address
setAddress_N64(romBase + 0xEC00000 + currSector + currSdBuffer + currByte);
@ -4451,7 +4302,7 @@ void writeGameshark_N64() {
unsigned long verifyGameshark_N64() {
uint32_t processedProgressBar = 0;
uint32_t totalProgressBar = (uint32_t)(fileSize);
println_Msg(F(""));
println_Msg(FS(FSTRING_EMPTY));
draw_progressbar(0, totalProgressBar);
// Open file on sd card
if (myFile.open(filePath, O_READ)) {
@ -4489,6 +4340,12 @@ unsigned long verifyGameshark_N64() {
/******************************************
XPLORER 64 Functions
*****************************************/
void sendFlashromXplorerCommand_N64(uint16_t cmd) {
oddXPaddrWrite(0x1040AAAA, 0xAAAA);
evenXPaddrWrite(0x10405555, 0x5555);
oddXPaddrWrite(0x1040AAAA, cmd);
}
void flashXplorer_N64() {
// Check flashrom ID's
idXplorer_N64();
@ -4552,7 +4409,7 @@ void flashXplorer_N64() {
display_Clear();
display_Update();
println_Msg(F("Verfied OK"));
println_Msg(F(""));
println_Msg(FS(FSTRING_EMPTY));
println_Msg(F("Turn Cart Reader off now"));
display_Update();
while (1);
@ -4581,9 +4438,7 @@ void flashXplorer_N64() {
void idXplorer_N64() {
flashid = 0x0;
//Send flashrom ID command
oddXPaddrWrite(0x1040AAAA, 0xAAAA);
evenXPaddrWrite(0x10405555, 0x5555);
oddXPaddrWrite(0x1040AAAA, 0x9090);
sendFlashromXplorerCommand_N64(0x9090);
setAddress_N64(0x10760000);
readWord_N64();
@ -4608,35 +4463,14 @@ void idXplorer_N64() {
void resetXplorer_N64() {
// Send reset command for SST 29LE010
oddXPaddrWrite(0x1040AAAA, 0xAAAA);
evenXPaddrWrite(0x10405555, 0x5555);
oddXPaddrWrite(0x1040AAAA, 0xF0F0);
sendFlashromXplorerCommand_N64(0xF0F0);
delay(100);
}
// Read rom and save to the SD card
void backupXplorer_N64() {
// create a new folder
EEPROM_readAnything(0, foldern);
sprintf(fileName, "XP64-%d", foldern);
strcat(fileName, ".z64");
sd.mkdir("N64/ROM/XPLORER64", true);
sd.chdir("N64/ROM/XPLORER64");
display_Clear();
print_Msg(F("Saving "));
print_Msg(fileName);
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("N64", "ROM", "XPLORER64", "z64");
for (unsigned long currByte = 0x10400000; currByte <= 0x1043FFFF; currByte += 512) {
// Blink led
@ -4719,12 +4553,8 @@ void eraseXplorer_N64() {
display_Update();
// Send chip erase to SST 29LE010
oddXPaddrWrite(0x1040AAAA, 0xAAAA);
evenXPaddrWrite(0x10405555, 0x5555);
oddXPaddrWrite(0x1040AAAA, 0x8080);
oddXPaddrWrite(0x1040AAAA, 0xAAAA);
evenXPaddrWrite(0x10405555, 0x5555);
oddXPaddrWrite(0x1040AAAA,0x1010);
sendFlashromXplorerCommand_N64(0x8080);
sendFlashromXplorerCommand_N64(0x1010);
delay(20);
}
@ -4770,9 +4600,7 @@ void writeXplorer_N64() {
}
//Send page write command to both flashroms
oddXPaddrWrite(0x1040AAAA, 0xAAAA);
evenXPaddrWrite(0x10405555, 0x5555);
oddXPaddrWrite(0x1040AAAA, 0xA0A0);
sendFlashromXplorerCommand_N64(0xA0A0);
// Write 1 page each, one flashrom gets the low byte, the other the high byte.
for (unsigned long currByte = 0; currByte < 256; currByte += 2) {
@ -4794,7 +4622,7 @@ void writeXplorer_N64() {
unsigned long verifyXplorer_N64() {
uint32_t processedProgressBar = 0;
uint32_t totalProgressBar = (uint32_t)(262144);
println_Msg(F(""));
println_Msg(FS(FSTRING_EMPTY));
draw_progressbar(0, totalProgressBar);
// Open file on sd card
if (myFile.open(filePath, O_READ)) {

File diff suppressed because it is too large Load Diff

View File

@ -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);

View File

@ -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
//******************************************

View File

@ -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] = "13.1";
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 */

View File

@ -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 IN CONFIG.H !!!
#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_ */

View File

@ -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

View File

@ -1,7 +1,7 @@
//******************************************
// BENESSE POCKET CHALLENGE W MODULE
//******************************************
#ifdef enable_PCW
#ifdef ENABLE_PCW
// Benesse Pocket Challenge W
// Cartridge Pinout
@ -130,16 +130,13 @@ void setup_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);
@ -425,23 +422,12 @@ void readSingleROM_PCW() {
print_Msg(F("READING "));
print_Msg(rom_size / 1024 / 1024);
print_Msg("MB SINGLE-PACK");
println_Msg(F(""));
println_Msg(FS(FSTRING_EMPTY));
// 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);
createFolder("PCW", "ROM", romName, "pcw");
print_STR(saving_to_STR, 0);
print_Msg(folder);
println_Msg(F("/..."));
display_Update();
foldern = foldern + 1;
EEPROM_writeAnything(0, foldern);
printAndIncrementFolder();
if (!myFile.open(fileName, O_RDWR | O_CREAT)) {
print_FatalError(sd_error_STR);
@ -467,7 +453,7 @@ void readSingleROM_PCW() {
compareCRC("pcw.txt", 0, 1, 0);
// Wait for user input
println_Msg(F(""));
println_Msg(FS(FSTRING_EMPTY));
print_STR(press_button_STR, 1);
display_Update();
wait();
@ -564,23 +550,12 @@ void readMultiROM_PCW() {
print_Msg(F("READING "));
print_Msg(rom_size / 1024 / 1024);
print_Msg("MB MULTI-PACK");
println_Msg(F(""));
println_Msg(FS(FSTRING_EMPTY));
// 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);
createFolder("PCW", "ROM", romName, "pcw");
print_STR(saving_to_STR, 0);
print_Msg(folder);
println_Msg(F("/..."));
display_Update();
foldern = foldern + 1;
EEPROM_writeAnything(0, foldern);
printAndIncrementFolder();
if (!myFile.open(fileName, O_RDWR | O_CREAT)) {
print_FatalError(sd_error_STR);
@ -625,7 +600,7 @@ void readMultiROM_PCW() {
compareCRC("pcw.txt", 0, 1, 0);
// Wait for user input
println_Msg(F(""));
println_Msg(FS(FSTRING_EMPTY));
print_STR(press_button_STR, 1);
display_Update();
wait();
@ -636,13 +611,7 @@ void readMultiROM_PCW() {
//******************************************
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);

View File

@ -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,28 +239,7 @@ 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;
@ -279,7 +257,7 @@ void readROM_POKE() {
// compare dump CRC with db values
compareCRC("pkmn.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);

View File

@ -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);
}
```

View File

@ -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);

View File

@ -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;
@ -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;

View File

@ -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,40 +142,58 @@ 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;
@ -214,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();
@ -266,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();
@ -324,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();
@ -469,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"));
@ -729,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"));
@ -747,7 +758,7 @@ void getCartInfo_SNES() {
}
display_Clear();
print_Msg(F("Title: "));
print_Msg(FS(FSTRING_NAME));
println_Msg(romName);
print_Msg(F("Revision: "));
@ -762,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)
@ -810,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)
@ -835,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
@ -865,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();
@ -922,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);
@ -995,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
}
@ -1278,30 +1291,7 @@ void readROM_SNES() {
controlIn_SNES();
// 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, "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);
}
createFolderAndOpenFile("SNES", "ROM", romName, "sfc");
//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))) {
@ -1436,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...
@ -1635,7 +1625,7 @@ void writeSRAM(boolean browseFile) {
display_Update();
} else {
print_Error(F("File doesnt exist"));
print_Error(FS(FSTRING_FILE_DOESNT_EXIST));
}
}
@ -1644,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;
@ -2236,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
View 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
//******************************************

View 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..."));

View File

@ -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));
}
}

View File

@ -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);

View File

@ -1,7 +1,7 @@
//******************************************
// VECTREX MODULE
//******************************************
#ifdef enable_VECTREX
#ifdef ENABLE_VECTREX
// Vectrex
// Cartridge Pinout
// 36P 2.54mm pitch connector
@ -55,11 +55,10 @@
#define PB6_ENABLE PORTH |= (1 << 5) // PB6 HIGH
#define PB6_DISABLE PORTH &= ~(1 << 5) // PB6 LOW
byte VECTREX[] = { 4, 8, 12 };
byte VECTREX[] = { 4, 8, 12, 16, 32, 64 };
byte vectrexlo = 0; // Lowest Entry
byte vectrexhi = 2; // Highest Entry
byte vectrexhi = 5; // Highest Entry
byte vectrexsize;
byte newvectrexsize;
// EEPROM MAPPING
// 08 ROM SIZE
@ -68,10 +67,7 @@ byte newvectrexsize;
// Menu
//******************************************
// Base Menu
static const char vectrexMenuItem1[] PROGMEM = "Select Cart";
static const char vectrexMenuItem2[] PROGMEM = "Read ROM";
static const char vectrexMenuItem3[] PROGMEM = "Set Size";
static const char* const menuOptionsVECTREX[] PROGMEM = { vectrexMenuItem1, vectrexMenuItem2, vectrexMenuItem3, string_reset2 };
static const char* const menuOptionsVECTREX[] PROGMEM = { FSTRING_SELECT_CART, FSTRING_READ_ROM, FSTRING_SET_SIZE, FSTRING_RESET };
void setup_VECTREX() {
// Request 5V
@ -116,7 +112,7 @@ void setup_VECTREX() {
checkStatus_VECTREX();
strcpy(romName, "VECTREX");
mode = mode_VECTREX;
mode = CORE_VECTREX;
}
void vectrexMenu() {
@ -127,7 +123,6 @@ void vectrexMenu() {
case 0:
// Select Cart
setCart_VECTREX();
wait();
setup_VECTREX();
break;
@ -201,45 +196,25 @@ void readSegment_VECTREX(uint16_t startaddr, uint16_t endaddr) {
//******************************************
void readROM_VECTREX() {
strcpy(fileName, romName);
strcat(fileName, ".vec");
// create a new folder for storing rom file
EEPROM_readAnything(0, foldern);
sprintf(folder, "VECTREX/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("VECTREX", "ROM", romName, "vec");
PB6_DISABLE; // PB6 LOW - Switch Bank
// Standard Carts 4K/8K
readSegment_VECTREX(0x0000, 0x0400); // 1K
readSegment_VECTREX(0x0400, 0x0800); // +1K = 2K
readSegment_VECTREX(0x0800, 0x0C00); // +1K = 3K
readSegment_VECTREX(0x0C00, 0x1000); // +1K = 4K
readSegment_VECTREX(0x0000, 0x1000); // 4K
if (vectrexsize > 0) {
readSegment_VECTREX(0x1000, 0x2000); // +4K = 8K
// Dark Tower 12K
// 12K (Dark Tower)
if (vectrexsize > 1)
readSegment_VECTREX(0x2000, 0x3000); // +4K = 12K
// Oversize 32K Cart
// 16K Carts
if (vectrexsize > 2)
readSegment_VECTREX(0x3000, 0x8000); // +20K = 32K
// Oversize 64K Cart - PB6 Bankswitch
if (vectrexsize > 3) { // [UNTESTED]
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
@ -247,10 +222,9 @@ void readROM_VECTREX() {
}
myFile.close();
unsigned long crcsize = VECTREX[vectrexsize] * 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();
@ -261,78 +235,28 @@ void readROM_VECTREX() {
// 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() {
#if (defined(enable_OLED) || defined(enable_LCD))
byte newvectrexsize;
#if (defined(ENABLE_OLED) || defined(ENABLE_LCD))
display_Clear();
if (vectrexlo == vectrexhi)
newvectrexsize = vectrexlo;
else {
int b = 0;
int i = vectrexlo;
display_Clear();
print_Msg(F("ROM Size: "));
println_Msg(VECTREX[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 == vectrexlo)
i = vectrexhi;
else
i--;
display_Clear();
print_Msg(F("ROM Size: "));
println_Msg(VECTREX[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 == vectrexhi)
i = vectrexlo;
else
i++;
display_Clear();
print_Msg(F("ROM Size: "));
println_Msg(VECTREX[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)
newvectrexsize = i;
break;
}
}
newvectrexsize = navigateMenu(vectrexlo, vectrexhi, &printRomSize_VECTREX);
display.setCursor(0, 56); // Display selection at bottom
}
print_Msg(F("ROM SIZE "));
print_Msg(FS(FSTRING_ROM_SIZE));
print_Msg(VECTREX[newvectrexsize]);
println_Msg(F("K"));
println_Msg(F("KB"));
display_Update();
delay(1000);
#else
@ -346,7 +270,7 @@ setrom:
Serial.print(i);
Serial.print(F(" = "));
Serial.print(VECTREX[i + vectrexlo]);
Serial.println(F("K"));
Serial.println(F("KB"));
}
Serial.print(F("Enter ROM Size: "));
while (Serial.available() == 0) {}
@ -355,13 +279,13 @@ setrom:
newvectrexsize = sizeROM.toInt() + vectrexlo;
if (newvectrexsize > vectrexhi) {
Serial.println(F("SIZE NOT SUPPORTED"));
Serial.println(F(""));
Serial.println(FS(FSTRING_EMPTY));
goto setrom;
}
}
Serial.print(F("ROM Size = "));
Serial.print(VECTREX[newvectrexsize]);
Serial.println(F("K"));
Serial.println(F("KB"));
#endif
EEPROM_writeAnything(8, newvectrexsize);
vectrexsize = newvectrexsize;
@ -374,258 +298,45 @@ void checkStatus_VECTREX() {
EEPROM_writeAnything(8, vectrexsize);
}
#if (defined(enable_OLED) || defined(enable_LCD))
#if (defined(ENABLE_OLED) || defined(ENABLE_LCD))
display_Clear();
println_Msg(F("VECTREX 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(VECTREX[vectrexsize]);
println_Msg(F("K"));
println_Msg(F("KB"));
display_Update();
wait();
#else
Serial.print(F("ROM SIZE: "));
Serial.print(FS(FSTRING_ROM_SIZE));
Serial.print(VECTREX[vectrexsize]);
Serial.println(F("K"));
Serial.println(F(""));
Serial.println(F("KB"));
Serial.println(FS(FSTRING_EMPTY));
#endif
}
//******************************************
// CART SELECT CODE
//******************************************
FsFile vectrexcsvFile;
char vectrexgame[25]; // title
char vectrexrr[4]; // romsize
char vectrexll[4]; // linelength (previous line)
unsigned long vectrexcsvpos; // CSV File Position
char vectrexcartCSV[] = "vectrexcart.txt"; // CSV List
char vectrexcsvEND[] = "EOF"; // CSV End Marker for scrolling
bool readLine_VECTREX(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_VECTREX(char* vectrexgame, char* vectrexrr, char* vectrexll) {
char line[31];
vectrexcsvpos = vectrexcsvFile.position();
if (!readLine_VECTREX(vectrexcsvFile, line, sizeof(line))) {
return false; // EOF or too long
}
char* comma = strtok(line, ",");
int x = 0;
while (comma != NULL) {
if (x == 0)
strcpy(vectrexgame, comma);
else if (x == 1)
strcpy(vectrexrr, comma);
else if (x == 2)
strcpy(vectrexll, comma);
comma = strtok(NULL, ",");
x += 1;
}
return true;
}
bool getCartListInfo_VECTREX() {
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_VECTREX(vectrexgame, vectrexrr, vectrexll)) {
if (strcmp(vectrexcsvEND, vectrexgame) == 0) {
vectrexcsvFile.seek(0); // Restart
} else {
#if (defined(enable_OLED) || defined(enable_LCD))
display_Clear();
println_Msg(F("CART TITLE:"));
println_Msg(F(""));
println_Msg(vectrexgame);
display_Update();
#else
Serial.print(F("CART TITLE:"));
Serial.println(vectrexgame);
#endif
#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
buttonreleased = 1;
break;
}
if (buttonreleased) {
buttonreleased = 0; // Reset Flag
break;
}
}
}
#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
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_VECTREX(vectrexgame, vectrexrr, vectrexll)) {
if (strcmp(vectrexcsvEND, vectrexgame) == 0) {
vectrexcsvFile.seek(0); // Restart
} else {
#if (defined(enable_OLED) || defined(enable_LCD))
display_Clear();
println_Msg(F("CART TITLE:"));
println_Msg(F(""));
println_Msg(vectrexgame);
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(vectrexgame);
#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(vectrexll, NULL, 10);
vectrexcsvpos -= prevline;
vectrexcsvFile.seek(vectrexcsvpos);
break;
}
if (b == 3) { // Long Press - Select Cart (hold)
newvectrexsize = strtol(vectrexrr, NULL, 10);
EEPROM_writeAnything(8, newvectrexsize);
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_VECTREX() {
if (getCartListInfo_VECTREX()) {
#if (defined(enable_OLED) || defined(enable_LCD))
display_Clear();
println_Msg(F("CART SELECTED"));
println_Msg(F(""));
println_Msg(vectrexgame);
display_Update();
// Display Settings
display.setCursor(0, 56);
print_Msg(F("CODE: R"));
println_Msg(newvectrexsize);
display_Update();
#else
Serial.println(F(""));
Serial.println(F("CART SELECTED"));
Serial.println(vectrexgame);
// Display Settings
Serial.print(F("CODE: R"));
Serial.println(newvectrexsize);
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_VECTREX() {
#if (defined(enable_OLED) || defined(enable_LCD))
display_Clear();
println_Msg(vectrexcartCSV);
display_Update();
#endif
//go to root
sd.chdir();
sprintf(folder, "VECTREX/CSV");
sd.chdir(folder); // Switch Folder
vectrexcsvFile = sd.open(vectrexcartCSV, O_READ);
if (!vectrexcsvFile) {
#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_VECTREX();
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));
}
checkCSV_VECTREX();
vectrexcsvFile.close();
}
#endif

View File

@ -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;
}

View File

@ -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

View File

@ -22,7 +22,7 @@ Happy making. 🔧🔨😊
#### Supported Systems:
- NES/Famicom/Family Basic
- Super Nintendo/Super Famicom (including SF Memory and Satellaview)
- 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
@ -37,7 +37,7 @@ Happy making. 🔧🔨😊
- Sega Mark III
- Sega SG-1000/SC-3000
- Sega Cards
- PC engine/TurboGrafx-16
- PC Engine/TurboGrafx-16/SuperGrafx
- WonderSwan (Color)
- NeoGeo Pocket (Color)
- Intellivision

1482
sd/2600.txt Normal file

File diff suppressed because it is too large Load Diff

225
sd/5200.txt Normal file
View 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

View File

@ -1,76 +0,0 @@
Activision Decathlon,0,2,0
Astro Chase,1,2,28
Atari PAM - Pete's Test,0,1,20
Atari PAM Diagnostics,1,2,32
Atari PAM System Test,0,1,30
Ballblazer,0,3,30
Beamrider,0,2,19
BerZerk,0,2,18
Blue Print,0,2,16
Boogie,0,0,19
Bounty Bob Strikes Back!,2,4,15
Buck Rogers,1,2,33
Centipede,1,2,20
Choplifter!,0,2,18
Congo Bongo,1,2,20
Countermeasure,1,2,20
Defender,1,2,23
Dig Dug,1,2,17
Dreadnaught Factor,0,1,16
Frogger,0,1,27
Frogger II,1,2,16
Galaxian,0,1,19
Gorf,0,1,17
Gremlins,0,3,13
Gyruss,1,2,17
H.E.R.O.,0,2,15
James Bond 007,1,2,17
Joust,1,2,23
Jungle Hunt,1,2,14
Kaboom!,0,0,20
Kangaroo,1,2,16
Keystone Kapers,0,1,17
K-Razy Shoot-Out,0,1,24
Mario Bros.,0,3,25
MegaMania,0,1,20
Meteorites,0,2,18
Miner 2049er,0,2,19
Missile Command,0,1,21
Montezuma's Revenge,1,2,24
Moon Patrol,0,2,28
Mountain King,0,1,20
Mr. Do!'s Castle,0,1,22
Ms. Pac-Man,1,2,25
Pac-Man,1,2,20
Pengo,0,3,16
Pitfall II,0,2,14
Pitfall!,0,1,19
Pole Position,1,2,17
Popeye,1,2,22
Q-bert,0,1,15
QIX,1,2,15
Quest for Quintana Roo,0,2,12
RealSports Baseball,0,3,31
RealSports Basketball,0,3,28
RealSports Football,1,2,30
RealSports Soccer,1,2,28
RealSports Tennis,1,2,26
Rescue on Fractalus!,0,3,26
River Raid,0,1,29
Robotron 2084,0,2,19
Space Dungeon,1,2,22
Space Invaders,0,1,22
Space Shuttle,0,2,23
Star Raiders,1,2,22
Star Trek,1,2,21
Star Wars - Return of the Jedi,0,1,18
Star Wars - The Arcade Game,1,2,39
Super Breakout,0,0,36
Super Cobra,0,1,23
Vanguard,0,3,20
Wizard of Wor,0,2,17
Yellow Submarine,0,0,22
Zaxxon,0,3,25
Zenji,0,1,15
Zone Ranger,0,2,14
EOF,0,0,0

213
sd/7800.txt Normal file
View 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

View File

@ -1,71 +0,0 @@
32 in 1,0,3,0
Ace of Aces,1,4,15
Alien Brigade,2,5,20
Asteroids,0,0,22
Atari 7800 Development Card,0,0,18
Ballblazer,0,1,36
Barnyard Blaster,1,4,19
Baseball,0,1,25
Basketbrawl,1,4,17
Centipede,0,0,20
Choplifter! (Europe),0,2,18
Choplifter! (USA),0,1,29
Commando,1,4,26
Crack'ed,1,4,17
Crossbow,2,5,17
Dark Chambers,1,4,17
Desert Falcon,0,2,22
Diagnostic Test Cartridge,0,1,22
Dig Dug (Europe),0,1,34
Dig Dug (USA),0,0,25
Donkey Kong,0,2,22
Donkey Kong Junior,0,2,20
Double Dragon,4,4,27
F-18 Hornet,3,3,22
Fatal Run,1,4,20
Fight Night,1,4,18
Food Fight (Europe),0,2,20
Food Fight (USA),0,1,28
Galaga (Europe),0,2,25
Galaga (USA),0,1,24
Hat Trick,0,2,21
Ikari Warriors,1,4,18
Impossible Mission,1,4,23
Jinks,1,4,27
Joust (Europe),0,2,14
Joust (USA),0,1,23
Karateka (Europe),6,3,20
Karateka (USA),0,2,26
Kung-Fu Master,0,1,23
Mario Bros.,0,2,23
Mat Mania Challenge,1,4,20
Mean 18 Ultimate Golf,1,4,28
Meltdown,1,4,30
Midnight Mutants,1,4,17
Motor Psycho,1,4,25
Ms. Pac-Man (Europe),0,1,21
Ms. Pac-Man (USA),0,0,29
Ninja Golf,1,4,26
One-on-One Basketball,0,2,19
Pete Rose Baseball,0,1,30
Planet Smashers,1,4,27
Pole Position II,0,1,24
Rampage,4,4,25
RealSports Baseball,5,3,16
Robotron 2084,0,1,28
Scrapyard Dog,1,4,22
Sentinel,1,4,22
Summer Games,1,4,17
Super Huey UH-IX,0,2,21
Super Skateboardin',0,1,25
Tank Command,5,3,28
Title Match Pro Wrestling,0,1,21
Tomcat,0,1,34
Touchdown Football,1,4,15
Tower Toppler,5,3,27
Water Ski,5,3,22
Winter Games,1,4,18
Xenophobe,1,4,21
Xevious (Europe),0,2,18
Xevious (USA),0,1,25
EOF,0,0,0

View File

@ -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

View File

@ -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

View File

@ -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

File diff suppressed because it is too large Load Diff

6
sd/config.txt Normal file
View File

@ -0,0 +1,6 @@
oscr.logging=1
lcd.confColor=0
lcd.red=0
lcd.green=100
lcd.blue=0
md.saveType=0

View File

@ -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

18342
sd/gba.txt

File diff suppressed because it is too large Load Diff

View File

@ -2116,6 +2116,9 @@ Elitserien 96 (Sweden).md
Empire of Steel (Europe).md
E5517B77
Enryuu Seiken Xiao-Mei (Japan) (Aftermarket) (Unl).md
D7DD3791
Escape 2042 - The Truth Defenders (World) (En,Ja,Fr,Es) (Preview) (Aftermarket) (Unl).md
0D81511C
@ -2159,7 +2162,7 @@ ESPN Baseball Tonight (USA).md
96D8440C
ESPN National Hockey Night (USA).md
1D08828C
401DC618
ESPN National Hockey Night (USA) (Beta).md
A427814A
@ -3463,6 +3466,9 @@ LHX Attack Chopper (USA, Europe).md
Liberty or Death (USA).md
2ADB0364
Life on Earth - Reimagined (World) (Aftermarket) (Unl).md
883552AD
Life on Mars (World) (Aftermarket) (Unl).md
FD214116
@ -5494,8 +5500,8 @@ Runes (World) (Aftermarket) (Homebrew).bin
Ryuuko no Ken (Japan).md
054CF5F6
Sacred Line Genesis (World) (1.1.9) (Aftermarket) (Unl).md
2E029AB4
Sacred Line Genesis (World) (v1.1.9) (Aftermarket) (Unl).md
80D8F0CC
Sacred Line Genesis (World) (Aftermarket) (Unl).md
AFF86301
@ -5503,6 +5509,9 @@ AFF86301
Sacred Line Zero (World) (Proto) (Aftermarket) (Unl).md
D8A662AF
Sacred Line II (World) (v1.02) (Aftermarket) (Unl).md
C03ABCED
Sagaia (USA).md
F1E22F43
@ -5834,7 +5843,7 @@ Slap Fight MD (Japan) (En) (Beta).md
DBB62949
Slaughter Sport (USA).md
AF9F9D9C
AAB2C6C4
Slime World (Japan).md
7FF5529F

File diff suppressed because it is too large Load Diff

View File

@ -1069,6 +1069,9 @@ B683A856,368C1B65,4E45531A081010080000000000000001
Blaster Master (USA).nes
3F0FD764,368C1B65,4E45531A081010080000000000000001
Blazing Rangers (World) (Homebrew).nes
030D9844,C9DA7A15,4E45531A2000E0B81100000C00000001
Block Out (USA) (Proto).nes
CF992E34,E3183FD1,4E45531A080040080000070700000001

View File

@ -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

View File

@ -22,6 +22,9 @@
[BIOS] TurboGrafx CD System Card (USA) (v2.0).pce
FF2A5EC3
1941 - Counter Attack (Japan).sgx
8C4588E2
1943 Kai (Japan).pce
FDE08D6D
@ -49,6 +52,9 @@ Air Zonk (USA).pce
Air Zonk (USA, Europe) (WiiU Virtual Console).pce
D76C4169
Aldynes - The Misson Code for Rage Crisis (Japan).sgx
4C2126B0
Alien Crush (USA, Europe).pce
EA488494
@ -100,6 +106,9 @@ Barunba (Japan).pce
Batman (Japan).pce
106BB7B2
Battle Ace (Japan).sgx
3B13AF61
Battle Chopper (World) (En,Ja).pce
2CB92290
@ -181,10 +190,13 @@ Bonk's Adventure (USA).pce
Bonk's Adventure (USA, Europe) (WiiU Virtual Console).pce
704C801E
Bonk's Revenge (USA, Europe) (Virtual Console).pce
Bonk's Revenge (USA).pce
F36FFEE1
Bonk's Revenge (USA).pce
Bonk's Revenge (USA) (Alt).pce
68782A2F
Bonk's Revenge (USA) (Alt 2).pce
14250F9A
Bonk's Revenge (USA, Europe) (WiiU Virtual Console).pce
@ -277,6 +289,9 @@ A594FAC0
Daichi-kun Crisis - Do Natural (Japan).pce
61A2935F
Daimakaimura (Japan).sgx
B486A8ED
Daisenpuu (Japan).pce
9107BCC8
@ -658,6 +673,9 @@ Legendary Axe, The (USA).pce
Lode Runner - Lost Labyrinth (Japan).pce
E6EE1468
Madou King Granzort (Japan).sgx
1F041166
Maerchen Maze (Japan).pce
A15A1F37

View File

@ -22,7 +22,7 @@ Shinkenzemi 'Chuugaku Kouza' - Chuu 3 Eigo (Japan) (6BB311NH).pcw
Shinkenzemi 'Chuugaku Kouza' - Chuugaku Chiri (Japan) (6BD410).pcw
AD5136AE
Shinkenzemi 'Chuugaku Kouza' - Chuugaku Chiri (Alt) (Japan) (6BD410).pcw
Shinkenzemi 'Chuugaku Kouza' - Chuugaku Chiri (Japan) (6BD410) (Alt).pcw
32A902B8
Shinkenzemi 'Chuugaku Kouza' - Chuugaku Koumin (Japan) (6BE310).pcw
@ -31,16 +31,19 @@ Shinkenzemi 'Chuugaku Kouza' - Chuugaku Koumin (Japan) (6BE310).pcw
Shinkenzemi 'Chuugaku Kouza' - Chuugaku Rekishi (Japan) (5BC410).pcw
7865BE62
Shinkenzemi 'Chuugaku Kouza' - Chuugaku Rekishi (Alt) (Japan) (5BC410).pcw
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).pcw
Shinkenzemi Chuugaku Kouza - Chuu 1 Eigo (Japan) (0BB113NC - 7BB113NC).pcw
775E1A65
Shinkenzemi Chuugaku Kouza - Chuu 1 Eigo (Japan) (0BB111NH - 7BB111NH).pcw
@ -73,16 +76,13 @@ Shinkenzemi Chuugaku Kouza - Chuu 2 Eigo (Japan) (7BB215OW).pcw
Shinkenzemi Chuugaku Kouza - Chuu 2 Eigo (New Horizon, Columbus 21) (Japan) (2BB211).pcw
0B20B2D4
Shinkenzemi Chuugaku Kouza - Chuu 3 Eigo (Japan) (0BB311NH).pcw
A18685A5
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) (7BB311NH).pcw
Shinkenzemi Chuugaku Kouza - Chuu 3 Eigo (Japan) (0BB311NH - 7BB311NH).pcw
A18685A5
Shinkenzemi Chuugaku Kouza - Chuu 3 Eigo (Japan) (7BB312SS).pcw
@ -133,7 +133,7 @@ BF9DA3EA
Shinkenzemi Chuugaku Kouza - Chuugaku Koumin (Japan) (2BE310).pcw
48A3B1B7
Shinkenzemi Chuugaku Kouza - Chuugaku Koumin (Japan) (7BE310).pcw
Shinkenzemi Chuugaku Kouza - Chuugaku Koumin (Japan) (0BE310 - 7BE310).pcw
EFEF730E
Shinkenzemi Chuugaku Kouza - Chuugaku Rekishi (Japan) (0BC410).pcw
@ -199,7 +199,7 @@ Shinkenzemi Chuugaku Kouza - Koukou Juken (Koku - Suu) (Japan) (7BI712).pcw
Shinkenzemi Chuugaku Kouza - Koukou Juken (Koku - Suu) (Japan) (9BI712).pcw
0FCDC311
Shinkenzemi Chuugaku Kouza - Koukou Juken (Koku - Suu) (Alt) (Japan) (9BI712).pcw
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

40
sd/st.txt Normal file
View 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

View File

@ -1,32 +1,94 @@
3D Crazy Coaster,1,0
3D Mine Storm,1,22
3D Narrow Escape,1,20
AnimAction,1,23
Armor..Attack,0,17
Art Master,0,20
Bedlam,0,17
Berzerk,0,13
Blitz!,1,14
Clean Sweep,0,13
Cosmic Chasm,0,18
Fortress of Narzod,1,19
Heads-Up,1,25
HyperChase,0,15
Melody Master,1,17
Mine Storm,0,20
Mine Storm II,0,17
Polar Rescue,1,20
Pole Position,1,19
Rip Off,0,20
Scramble,0,14
Solar Quest,0,15
Space Wars,0,18
Spike,1,17
Spin ball,1,12
Star Castle,0,16
Star Ship,0,18
Star Trek,0,16
StarHawk,0,16
WebWarp,1,15
WebWars,1,14
EOF,0,0
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

View File

@ -188,6 +188,9 @@ 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