Add new modules (thx to skaman)

This commit is contained in:
sanni 2024-07-08 19:25:29 +02:00
parent 08cb821387
commit 72dfb04624
28 changed files with 10357 additions and 24 deletions

499
Cart_Reader/ATARI8.ino Normal file
View File

@ -0,0 +1,499 @@
//******************************************
// ATARI 8-bit (400/800/XL/XE) MODULE
//******************************************
#ifdef ENABLE_ATARI8
// Atari 8-bit (400/800/XL/XE)
// Left Slot Cartridge Pinout
// 30P 2.54mm pitch
//
// RIGHT
// +------+
// PHI2 -| S 15 |- /CCTL
// R/W -| R 14 |- RD5
// L A10 -| P 13 |- +5V B
// A A11 -| N 12 |- /S5 O
// B D7 -| M 11 |- D6 T
// E D3 -| L 10 |- D0 T
// L A12 -| K 9 |- D1 O
// A9 -| J 8 |- D2 M
// S A8 -| H 7 |- D5
// I A7 -| F 6 |- D4 S
// D A6 -| E 5 |- A0 I
// E A5 -| D 4 |- A1 D
// A4 -| C 3 |- A2 E
// GND -| B 2 |- A3
// RD4 -| A 1 |- /S4
// +------+
// LEFT
//
// LABEL SIDE
//
// RD4 GND A4 A5 A6 A7 A8 A9 A12 D3 D7 A11 A10 R/W PHI2
// +-------------------------------------------------------------+
// | A B C D E F H J K L M N P R S |
// LEFT | | RIGHT
// | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
// +-------------------------------------------------------------+
// /S4 A3 A2 A1 A0 D4 D5 D2 D1 D0 D6 /S5 +5V RD5 /CCTL
//
// BOTTOM SIDE
//
// CONTROL PINS:
// RD4(PH0) - SNES RESET
// PHI2(PH1) - SNES CPUCLK
// /S5(PH3) - SNES /CS
// RD5(PH4) - SNES /IRQ
// R/W(PH5) - SNES /WR
// /S4(PH6) - SNES /RD
// /CCTL(PL0) - SNES A16
//******************************************
// DEFINES
//******************************************
#define DISABLE_S4 PORTH |= (1 << 6) // ROM SELECT $8000-$9FFF
#define ENABLE_S4 PORTH &= ~(1 << 6)
#define DISABLE_S5 PORTH |= (1 << 3) // ROM SELECT $A000-$BFFF
#define ENABLE_S5 PORTH &= ~(1 << 3)
#define DISABLE_CCTL PORTL |= (1 << 0) // CARTRIDGE CONTROL BLOCK $D500-$D5FF
#define ENABLE_CCTL PORTL &= ~(1 << 0)
//******************************************
// VARIABLES
//******************************************
byte ATARI8[] = {8,16,32,40,64,128};
byte atari8lo = 0; // Lowest Entry
byte atari8hi = 5; // Highest Entry
byte atari8size;
byte newatari8size;
boolean atari8right = 0; // 0 = LEFT Slot, 1 = RIGHT Slot
// EEPROM MAPPING
// 07 MAPPER [ATARI 8-BIT SLOT]
// 08 ROM SIZE
//******************************************
// MENU
//******************************************
// Base Menu
static const char atari8MenuItem3[] PROGMEM = "Read RIGHT ROM";
static const char* const menuOptionsATARI8[] PROGMEM = { FSTRING_SELECT_CART, FSTRING_READ_ROM, atari8MenuItem3, FSTRING_SET_SIZE, FSTRING_RESET };
void atari8Menu()
{
convertPgm(menuOptionsATARI8, 5);
uint8_t mainMenu = question_box(F("ATARI 8-BIT MENU"), menuOptions, 5, 0);
switch (mainMenu)
{
// Select Cart
case 0:
setCart_ATARI8();
setup_ATARI8();
break;
// Read LEFT Slot Cart
case 1:
sd.chdir("/");
atari8right = 0; // LEFT Slot
readROM_ATARI8();
sd.chdir("/");
break;
// Read RIGHT Slot Cart
case 2:
sd.chdir("/");
atari8right = 1; // RIGHT Slot
readROM_ATARI8();
sd.chdir("/");
break;
case 3:
// Set Size
setROMSize_ATARI8();
break;
case 4:
// reset
resetArduino();
break;
}
}
//******************************************
// SETUP
//******************************************
void setup_ATARI8()
{
// Request 5V
setVoltage(VOLTS_SET_5V);
// Set Address Pins to Output
// Atari 8-bit uses A0-A12 [A13-A23 UNUSED]
//A0-A7
DDRF = 0xFF;
//A8-A15
DDRK = 0xFF;
//A16-A23
DDRL = 0xFF; // Use A16 for /CCTL Output
// Set Control Pins to Output
// PHI2(PH1) /S5(PH3) R/W(PH5) /S4(PH6)
DDRH |= (1 << 1) | (1 << 3) | (1 << 5) | (1 << 6);
// Set RD4 & RD5 to Input
// RD4(PH0) RD5(PH4)
DDRH &= ~((1 << 0) | (1 << 4));
// Set TIME(PJ0) to Output (UNUSED)
DDRJ |= (1 << 0);
// Set Pins (D0-D7) to Input
DDRC = 0x00;
// Setting Control Pins to HIGH
// PHI2(PH1) /S5(PH3) R/W(PH5) /S4(PH6)
//PORTH |= (1 << 1) | (1 << 3) | (1 << 5) | (1 << 6);
// /S5(PH3) R/W(PH5) /S4(PH6)
PORTH |= (1 << 3) | (1 << 5) | (1 << 6);
// Set Unused Data Pins (PA0-PA7) to Output
DDRA = 0xFF;
// Set Unused Pins HIGH
PORTA = 0xFF;
PORTL = 0xFF; // A16-A23 (A16 used for /CCTL Output)
PORTJ |= (1 << 0); // TIME(PJ0)
checkStatus_ATARI8();
strcpy(romName, "ATARI");
mode = CORE_ATARI8;
}
//******************************************
// READ FUNCTIONS
//******************************************
uint8_t readData_ATARI8(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;
// Extended Delay
NOP;
NOP;
NOP;
NOP;
NOP;
NOP;
NOP;
NOP;
NOP;
NOP;
uint8_t ret = PINC;
NOP;
NOP;
NOP;
NOP;
NOP;
return ret;
}
void readSegment_ATARI8(uint16_t startaddr, uint16_t endaddr)
{
for (uint16_t addr = startaddr; addr < endaddr; addr += 512) {
for (int w = 0; w < 512; w++) {
uint8_t temp = readData_ATARI8(addr + w);
sdBuffer[w] = temp;
}
myFile.write(sdBuffer, 512);
}
}
void readBountyBobBank_ATARI8(uint16_t startaddr)
{
for (uint8_t w = 0; w < 4; w++) {
readData_ATARI8(startaddr + 0x0FF6 + w);
readSegment_ATARI8(startaddr, startaddr + 0x0E00);
// Split Read of Last 0x200 bytes
for (int x = 0; x < 0x1F6; x++) {
sdBuffer[x] = readData_ATARI8(startaddr + 0x0E00 + x);
}
myFile.write(sdBuffer, 502);
// Bank Registers 0xFF6-0xFF9
for (int y = 0; y < 4; y++){
readData_ATARI8(startaddr + 0x0FFF); // Reset Bank
sdBuffer[y] = readData_ATARI8(startaddr + 0x0FF6 + y);
}
// End of Bank 0x8FFA-0x8FFF
readData_ATARI8(startaddr + 0x0FFF); // Reset Bank
readData_ATARI8(startaddr + 0x0FF6 + w); // Set Bank
for (int z = 4; z < 10; z++) {
sdBuffer[z] = readData_ATARI8(startaddr + 0x0FF6 + z); // 0xFFA-0xFFF
}
myFile.write(sdBuffer, 10);
}
readData_ATARI8(startaddr + 0x0FFF); // Reset Bank
}
void bankSwitch_ATARI8(uint8_t bank)
{
// write to $D5XX using /CCTL
// CCTL sets upper 3 bits of 16-bit address to 110
// CCTL = [110] 1 0101 0000 0000 = $D500
ENABLE_CCTL;
// Set Address $D500
PORTF = 0x00; // A0-A7
PORTK = 0xD5; // A8-A12
NOP;
NOP;
NOP;
NOP;
NOP;
// Set Data to Output
DDRC = 0xFF;
// Set R/W to WRITE
PORTH &= ~(1 << 5);
// Set Bank
PORTC = bank;
NOP;
NOP;
NOP;
NOP;
NOP;
// Pulse Clock
// CPU CLOCK 1.7897725MHz(NTSC)/1.7734470MHz(PAL/SECAM)
// 1.7897725MHz = 1 cycle = 558.73023ns = 279.365115/279.365115
for (int i = 0; i < 2; i++) {
PORTH ^= (1 << 1);
// NOP (62.5ns) x 4 = 250ns = 0.25us
NOP;
NOP;
NOP;
NOP; // 4 NOPs = 4 x 62.5ns = 250ns x 2 = 500ns = 2 MHz
}
// Set R/W to READ
PORTH |= (1 << 5);
// Reset Data to Input
DDRC = 0x00;
DISABLE_CCTL;
}
//******************************************
// READ ROM
//******************************************
void readROM_ATARI8()
{
createFolderAndOpenFile("ATARI8", "ROM", romName, "bin");
// Store Slot Setting to EEPROM
EEPROM_writeAnything(7, atari8right); // 0 = LEFT, 1 = RIGHT
// ATARI 8-bit A12-A0 = 1 0000 0000 0000
// S4 [100]/S5 [101] are the upper 3 bits for 16-bit address
// S4 = [100] 1 1111 1111 1111 = $8000-$9FFF
// S5 = [101] 1 1111 1111 1111 = $A000-$BFFF
if (atari8right) { // RIGHT Slot Cartridge 8K
// Right slot carts are 8K mapped to $8000-$9FFF
// Right slot carts use /S4 assigned to Pin 12
// Pin 12 = RIGHT Slot /S4 = LEFT Slot /S5
ENABLE_S5;
readSegment_ATARI8(0x8000,0xA000); // 8K
DISABLE_S5;
// Correct Size to 8K
atari8size = 0; // 8K
EEPROM_writeAnything(8, atari8size);
}
else if (atari8size == 3) { // Bounty Bob Strikes Back 40K
ENABLE_S4;
// First 16KB (4KB x 4)
readBountyBobBank_ATARI8(0x8000);
// Second 16KB (4KB x 4)
readBountyBobBank_ATARI8(0x9000);
DISABLE_S4;
ENABLE_S5;
readSegment_ATARI8(0xA000, 0xC000); // +8K = 40K
DISABLE_S5;
}
else if (atari8size > 1) { // XE Carts 32K/64K/128K
// Bug Hunt and Lode Runner dump as 128K. Trim beginning 64K as both carts start from Bank 8.
int banks = (ATARI8[atari8size] / 8) - 1;
for (int x = 0; x < banks; x++) {
bankSwitch_ATARI8(x);
ENABLE_S4;
readSegment_ATARI8(0x8000,0xA000); // 8K
DISABLE_S4;
}
// Last Bank
ENABLE_S5;
readSegment_ATARI8(0xA000,0xC000); // +8K
DISABLE_S5;
}
else { // Standard LEFT Cart 8K/16K
if (atari8size == 1) {
// Add XE Bankswitch for Necromancer 16K
bankSwitch_ATARI8(0);
// Standard 16K
ENABLE_S4;
readSegment_ATARI8(0x8000,0xA000); // +8K = 16K
DISABLE_S4;
}
ENABLE_S5;
readSegment_ATARI8(0xA000,0xC000); // 8K
DISABLE_S5;
}
myFile.close();
printCRC(fileName, NULL, 0);
println_Msg(FS(FSTRING_EMPTY));
print_STR(press_button_STR, 1);
display_Update();
wait();
}
//******************************************
// ROM SIZE
//******************************************
#if (defined(ENABLE_OLED) || defined(ENABLE_LCD))
void printRomSize_ATARI8(int index)
{
display_Clear();
print_Msg(FS(FSTRING_ROM_SIZE));
println_Msg(ATARI8[index]);
}
#endif
void setROMSize_ATARI8()
{
byte newatari8size;
#if (defined(ENABLE_OLED) || defined(ENABLE_LCD))
display_Clear();
if (atari8lo == atari8hi)
newatari8size = atari8lo;
else {
newatari8size = navigateMenu(atari8lo, atari8hi, &printRomSize_ATARI8);
display.setCursor(0, 56); // Display selection at bottom
}
print_Msg(FS(FSTRING_ROM_SIZE));
print_Msg(ATARI8[newatari8size]);
println_Msg(F("KB"));
display_Update();
delay(1000);
#else
if (atari8lo == atari8hi)
newatari8size = atari8lo;
else {
setrom:
String sizeROM;
for (int i = 0; i < (atari8hi - atari8lo + 1); i++) {
Serial.print(F("Select ROM Size: "));
Serial.print(i);
Serial.print(F(" = "));
Serial.print(ATARI8[i + atari8lo]);
Serial.println(F("KB"));
}
Serial.print(F("Enter ROM Size: "));
while (Serial.available() == 0) {}
sizeROM = Serial.readStringUntil('\n');
Serial.println(sizeROM);
newatari8size = sizeROM.toInt() + atari8lo;
if (newatari8size > atari8hi) {
Serial.println(F("SIZE NOT SUPPORTED"));
Serial.println(FS(FSTRING_EMPTY));
goto setrom;
}
}
Serial.print(F("ROM Size = "));
Serial.print(ATARI8[newatari8size]);
Serial.println(F("KB"));
#endif
EEPROM_writeAnything(8, newatari8size);
atari8size = newatari8size;
}
void checkStatus_ATARI8()
{
EEPROM_readAnything(7, atari8right);
if (atari8right != 1) {
atari8right = 0; // default LEFT Slot
EEPROM_writeAnything(7, atari8right);
}
EEPROM_readAnything(8, atari8size);
if (atari8size > atari8hi) {
atari8size = 1; // default 16K
EEPROM_writeAnything(8, atari8size);
}
#if (defined(ENABLE_OLED) || defined(ENABLE_LCD))
display_Clear();
println_Msg(F("ATARI 8-BIT READER"));
println_Msg(FS(FSTRING_CURRENT_SETTINGS));
println_Msg(FS(FSTRING_EMPTY));
print_Msg(F("SLOT: "));
if (atari8right)
println_Msg(F("RIGHT"));
else
println_Msg(F("LEFT"));
print_Msg(FS(FSTRING_ROM_SIZE));
print_Msg(ATARI8[atari8size]);
println_Msg(F("KB"));
display_Update();
wait();
#else
Serial.print(FS(FSTRING_ROM_SIZE));
Serial.print(ATARI8[atari8size]);
Serial.println(F("KB"));
Serial.println(FS(FSTRING_EMPTY));
#endif
}
//******************************************
// CART SELECT CODE
//******************************************
void setCart_ATARI8()
{
//go to root
sd.chdir();
struct database_entry_mapper_size entry;
// Select starting letter
byte myLetter = starting_letter();
// Open database
if (myFile.open("atari8cart.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

321
Cart_Reader/BALLY.ino Normal file
View File

@ -0,0 +1,321 @@
//******************************************
// BALLY ASTROCADE MODULE
//******************************************
#ifdef ENABLE_BALLY
// Bally Astrocade
// Cartridge Pinout
// 26P 2.54mm pitch connector
//
// BOTTOM
// +-------+
// GND -| 1 |
// A7 -| 2 |
// A6 -| 3 |
// A5 -| 4 |
// A4 -| 5 |
// A3 -| 6 |
// A2 -| 7 |
// A1 -| 8 |
// A0 -| 9 |
// D0 -| 10 |
// D1 -| 11 |
// D2 -| 12 |
// GND -| 13 |
// D3 -| 14 |
// D4 -| 15 |
// D5 -| 16 |
// D6 -| 17 |
// D7 -| 18 |
// A11 -| 19 |
// A10 -| 20 |
// /ENABLE -| 21 |
// A12 -| 22 |
// A9 -| 23 |
// A8 -| 24 |
// VCC(+5V) -| 25 |
// GND -| 26 |
// +-------+
//
// TOP SIDE
// +-----------------------------------------------------------------------------------------------------------+
// LEFT | | RIGHT
// | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
// +-----------------------------------------------------------------------------------------------------------+
// GND A7 A6 A5 A4 A3 A2 A1 A0 D0 D1 D2 GND D3 D4 D5 D6 D7 A11 A10 /EN A12 A9 A8 +5V GND
//
// BOTTOM SIDE
// CONTROL PINS:
// /ENABLE(PH3) - SNES /CS
//******************************************
// VARIABLES
//******************************************
byte BALLY[] = {2,4,8};
byte ballylo = 0; // Lowest Entry
byte ballyhi = 2; // Highest Entry
byte ballysize;
byte newballysize;
// EEPROM MAPPING
// 08 ROM SIZE
//******************************************
// MENU
//******************************************
// Base Menu
static const char* const menuOptionsBALLY[] PROGMEM = { FSTRING_SELECT_CART, FSTRING_READ_ROM, FSTRING_SET_SIZE, FSTRING_RESET };
void ballyMenu()
{
convertPgm(menuOptionsBALLY, 4);
uint8_t mainMenu = question_box(F("BALLY ASTROCADE MENU"), menuOptions, 4, 0);
switch (mainMenu)
{
case 0:
// Select Cart
setCart_BALLY();
setup_BALLY();
break;
case 1:
// Read ROM
sd.chdir("/");
readROM_BALLY();
sd.chdir("/");
break;
case 2:
// Set Size
setROMSize_BALLY();
break;
case 3:
// reset
resetArduino();
break;
}
}
//******************************************
// SETUP
//******************************************
void setup_BALLY()
{
// Request 5V
setVoltage(VOLTS_SET_5V);
// Set Address Pins to Output
// Bally Astrocade uses A0-A12 [A13-A23 UNUSED]
//A0-A7
DDRF = 0xFF;
//A8-A15
DDRK = 0xFF;
//A16-A23
DDRL = 0xFF;
// Set Control Pins to Output
// ---(PH0) ---(PH1) /ENABLE(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
// ---(PH0) ---(PH1) /ENABLE(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_BALLY();
strcpy(romName, "BALLY");
mode = CORE_BALLY;
}
//******************************************
// READ FUNCTIONS
//******************************************
uint8_t readData_BALLY(uint16_t addr)
{
PORTF = addr & 0xFF; // A0-A7
PORTK = (addr >> 8) & 0xFF; // A8-A15
PORTC = 0xFF; // Input Pullup
PORTH &= ~(1 << 3); // /ENABLE LOW
NOP;
NOP;
NOP;
NOP;
NOP;
uint8_t ret = PINC;
PORTH |= (1 << 3); // /ENABLE HIGH
return ret;
}
void readSegment_BALLY(uint16_t startaddr, uint16_t endaddr)
{
for (uint16_t addr = startaddr; addr < endaddr; addr += 512) {
for (int w = 0; w < 512; w++) {
uint8_t temp = readData_BALLY(addr + w);
sdBuffer[w] = temp;
}
myFile.write(sdBuffer, 512);
}
}
//******************************************
// READ ROM
//******************************************
void readROM_BALLY()
{
createFolderAndOpenFile("BALLY", "ROM", romName, "bin");
readSegment_BALLY(0x0000,0x0800); // 2K
if (ballysize > 0) {
readSegment_BALLY(0x0800,0x1000); // +2K = 4K
if (ballysize > 1) {
readSegment_BALLY(0x1000,0x2000); // +4K = 8K
}
}
myFile.close();
printCRC(fileName, NULL, 0);
println_Msg(FS(FSTRING_EMPTY));
print_STR(press_button_STR, 1);
display_Update();
wait();
}
//******************************************
// ROM SIZE
//******************************************
#if (defined(ENABLE_OLED) || defined(ENABLE_LCD))
void printRomSize_BALLY(int index)
{
display_Clear();
print_Msg(FS(FSTRING_ROM_SIZE));
println_Msg(BALLY[index]);
}
#endif
void setROMSize_BALLY()
{
byte newballysize;
#if (defined(ENABLE_OLED) || defined(ENABLE_LCD))
display_Clear();
if (ballylo == ballyhi)
newballysize = ballylo;
else {
newballysize = navigateMenu(ballylo, ballyhi, &printRomSize_BALLY);
display.setCursor(0, 56); // Display selection at bottom
}
print_Msg(FS(FSTRING_ROM_SIZE));
print_Msg(BALLY[newballysize]);
println_Msg(F("KB"));
display_Update();
delay(1000);
#else
if (ballylo == ballyhi)
newballysize = ballylo;
else {
setrom:
String sizeROM;
for (int i = 0; i < (ballyhi - ballylo + 1); i++) {
Serial.print(F("Select ROM Size: "));
Serial.print(i);
Serial.print(F(" = "));
Serial.print(BALLY[i + ballylo]);
Serial.println(F("KB"));
}
Serial.print(F("Enter ROM Size: "));
while (Serial.available() == 0) {}
sizeROM = Serial.readStringUntil('\n');
Serial.println(sizeROM);
newballysize = sizeROM.toInt() + ballylo;
if (newballysize > ballyhi) {
Serial.println(F("SIZE NOT SUPPORTED"));
Serial.println(FS(FSTRING_EMPTY));
goto setrom;
}
}
Serial.print(F("ROM Size = "));
Serial.print(BALLY[newballysize]);
Serial.println(F("KB"));
#endif
EEPROM_writeAnything(8, newballysize);
ballysize = newballysize;
}
void checkStatus_BALLY()
{
EEPROM_readAnything(8, ballysize);
if (ballysize > ballyhi) {
ballysize = 0; // default 2K
EEPROM_writeAnything(8, ballysize);
}
#if (defined(ENABLE_OLED) || defined(ENABLE_LCD))
display_Clear();
println_Msg(F("BALLY ASTROCADE"));
println_Msg(FS(FSTRING_CURRENT_SETTINGS));
println_Msg(FS(FSTRING_EMPTY));
print_Msg(FS(FSTRING_ROM_SIZE));
print_Msg(BALLY[ballysize]);
println_Msg(F("KB"));
display_Update();
wait();
#else
Serial.print(FS(FSTRING_ROM_SIZE));
Serial.print(BALLY[ballysize]);
Serial.println(F("KB"));
Serial.println(FS(FSTRING_EMPTY));
#endif
}
//******************************************
// CART SELECT CODE
//******************************************
void setCart_BALLY()
{
//go to root
sd.chdir();
byte gameSize;
// Select starting letter
//byte myLetter = starting_letter();
// Open database
if (myFile.open("ballycart.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

View File

@ -4,8 +4,8 @@
This project represents a community-driven effort to provide This project represents a community-driven effort to provide
an easy to build and easy to modify cartridge dumper. an easy to build and easy to modify cartridge dumper.
Date: 2024-07-05 Date: 2024-07-08
Version: 13.5 Version: 14.0
SD lib: https://github.com/greiman/SdFat SD lib: https://github.com/greiman/SdFat
LCD lib: https://github.com/olikraus/u8g2 LCD lib: https://github.com/olikraus/u8g2
@ -21,10 +21,11 @@
MichlK - ROM Reader for Super Nintendo MichlK - ROM Reader for Super Nintendo
Jeff Saltzman - 4-Way Button Jeff Saltzman - 4-Way Button
Wayne and Layne - Video Game Shield menu Wayne and Layne - Video Game Shield menu
skaman - Cart ROM READER SNES ENHANCED, Famicom Cart Dumper, Coleco-, Intellivision, Virtual Boy, WSV, PCW, ARC, Atari 2600/5200/7800, ODY2, Fairchild, MSX, Pokemon Mini, C64, Vectrex modules skaman - Cart ROM READER SNES ENHANCED, Famicom Cart Dumper, 2600, 5200, 7800, ARC, ATARI8, BALLY, C64, COLV, FAIRCHILD,
INTV, LEAP, LJ, LJPRO, MSX, ODY2, PCW, POKEMINI, PV1000, PYUUTA, RCA, TI99, TRS80, VBOY, VECTREX, WSV, VIC20, VSMILE modules
Tamanegi_taro - PCE and Satellaview modules Tamanegi_taro - PCE and Satellaview modules
splash5 - GBSmart, Wonderswan, NGP and Super A'can modules splash5 - GBSmart, Wonderswan, NGP and Super A'can modules
partlyhuman - Casio Loopy module partlyhuman - Casio Loopy & Atari Lynx module
hkz & themanbehindthecurtain - N64 flashram commands hkz & themanbehindthecurtain - N64 flashram commands
Andrew Brown & Peter Den Hartog - N64 controller protocol Andrew Brown & Peter Den Hartog - N64 controller protocol
libdragon - N64 controller checksum functions libdragon - N64 controller checksum functions
@ -43,7 +44,7 @@
philenotfound, karimhadjsalem, nsx0r, ducky92, niklasweber, Lesserkuma, BacteriaMage, qufb, philenotfound, karimhadjsalem, nsx0r, ducky92, niklasweber, Lesserkuma, BacteriaMage, qufb,
vpelletier, Ancyker, mattiacci, RWeick, ButThouMust, partlyhuman, fakkuyuu, hxlnt, breyell, vpelletier, Ancyker, mattiacci, RWeick, ButThouMust, partlyhuman, fakkuyuu, hxlnt, breyell,
smesgr9000, joshman196, PsychoFox11, plaidpants, LuigiBlood, InvalidInterrupt smesgr9000, joshman196, PsychoFox11, plaidpants, LuigiBlood, InvalidInterrupt
And to nocash for figuring out the secrets of the SFC Nintendo Power cartridge. And to nocash for figuring out the secrets of the SFC Nintendo Power cartridge.
This program is free software: you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
@ -458,7 +459,7 @@ uint32_t calculateCRC(char* fileName, char* folder, unsigned long offset) {
/****************************************** /******************************************
CRC Functions for Atari, Fairchild, Ody2, Arc, etc. modules CRC Functions for Atari, Fairchild, Ody2, Arc, etc. modules
*****************************************/ *****************************************/
#if (defined(ENABLE_ODY2) || defined(ENABLE_ARC) || defined(ENABLE_FAIRCHILD) || defined(ENABLE_MSX) || defined(ENABLE_POKE) || defined(ENABLE_2600) || defined(ENABLE_5200) || defined(ENABLE_7800) || defined(ENABLE_C64) || defined(ENABLE_VECTREX) || defined(ENABLE_NES) || defined(ENABLE_LYNX)) #if (defined(ENABLE_ODY2) || defined(ENABLE_ARC) || defined(ENABLE_FAIRCHILD) || defined(ENABLE_MSX) || defined(ENABLE_POKE) || defined(ENABLE_2600) || defined(ENABLE_5200) || defined(ENABLE_7800) || defined(ENABLE_C64) || defined(ENABLE_VECTREX) || defined(ENABLE_NES) || defined(ENABLE_LYNX) || defined(ENABLE_ATARI8) || defined(ENABLE_BALLY) || defined(ENABLE_LEAP) || defined(ENABLE_LJ) || defined(ENABLE_LJPRO) || defined(ENABLE_PV1000) || defined(ENABLE_PYUUTA) || defined(ENABLE_RCA) || defined(ENABLE_TI99) || defined(ENABLE_TRS80) || defined(ENABLE_VIC20) || defined(ENABLE_VSMILE))
void printCRC(char* checkFile, uint32_t* crcCopy, unsigned long offset) { void printCRC(char* checkFile, uint32_t* crcCopy, unsigned long offset) {
uint32_t crc = calculateCRC(checkFile, folder, offset); uint32_t crc = calculateCRC(checkFile, folder, offset);
@ -658,7 +659,7 @@ boolean compareCRC(const char* database, uint32_t crc32sum, boolean renamerom, i
//****************************************** //******************************************
// Math Functions // Math Functions
//****************************************** //******************************************
#if (defined(ENABLE_NES) || defined(ENABLE_MSX) || defined(ENABLE_GBX)) #if (defined(ENABLE_NES) || defined(ENABLE_MSX) || defined(ENABLE_GBX) || defined(ENABLE_TRS80))
int int_pow(int base, int exp) { // Power for int int int_pow(int base, int exp) { // Power for int
int result = 1; int result = 1;
while (exp) { while (exp) {
@ -737,7 +738,11 @@ void seek_first_letter_in_database(FsFile& database, byte myLetter) {
#endif #endif
} }
#if (defined(ENABLE_ARC) || defined(ENABLE_FAIRCHILD) || defined(ENABLE_VECTREX)) #if ( \
defined(ENABLE_ARC) || defined(ENABLE_FAIRCHILD) || defined(ENABLE_VECTREX) || defined(ENABLE_BALLY) || \
defined(ENABLE_PV1000) || defined(ENABLE_PYUUTA) || defined(ENABLE_RCA) || defined(ENABLE_TRS80) || \
defined(ENABLE_LEAP) || defined(ENABLE_LJ) || defined(ENABLE_VSMILE)\
)
// read single digit data line as byte // read single digit data line as byte
void readDataLineSingleDigit(FsFile& database, void* byteData) { void readDataLineSingleDigit(FsFile& database, void* byteData) {
// Read rom size // Read rom size
@ -748,7 +753,10 @@ void readDataLineSingleDigit(FsFile& database, void* byteData) {
} }
#endif #endif
#if (defined(ENABLE_ODY2) || defined(ENABLE_5200) || defined(ENABLE_7800) || defined(ENABLE_C64)) #if ( \
defined(ENABLE_ODY2) || defined(ENABLE_5200) || defined(ENABLE_7800) || defined(ENABLE_C64) || \
defined(ENABLE_VIC20)|| defined(ENABLE_ATARI8)\
)
struct database_entry_mapper_size { struct database_entry_mapper_size {
byte gameMapper; byte gameMapper;
byte gameSize; byte gameSize;
@ -881,7 +889,10 @@ boolean checkCartSelection(FsFile& database, void (*readData)(FsFile&, void*), v
# if ( \ # if ( \
defined(ENABLE_ODY2) || defined(ENABLE_ARC) || defined(ENABLE_FAIRCHILD) || defined(ENABLE_MSX) || \ defined(ENABLE_ODY2) || defined(ENABLE_ARC) || defined(ENABLE_FAIRCHILD) || defined(ENABLE_MSX) || \
defined(ENABLE_POKE) || defined(ENABLE_2600) || defined(ENABLE_5200) || defined(ENABLE_7800) || \ defined(ENABLE_POKE) || defined(ENABLE_2600) || defined(ENABLE_5200) || defined(ENABLE_7800) || \
defined(ENABLE_C64) || defined(ENABLE_VECTREX) || defined(ENABLE_NES) || defined(ENABLE_GBX) \ defined(ENABLE_C64) || defined(ENABLE_VECTREX) || defined(ENABLE_NES) || defined(ENABLE_GBX) || \
defined(ENABLE_BALLY) || defined(ENABLE_PV1000) || defined(ENABLE_PYUUTA) || defined(ENABLE_RCA) || \
defined(ENABLE_TRS80) || defined(ENABLE_VIC20) || defined(ENABLE_LEAP) || defined(ENABLE_LJ) || \
defined(ENABLE_VSMILE)|| defined(ENABLE_TI99) || defined(ENABLE_ATARI8)\
) )
void printInstructions() { void printInstructions() {
println_Msg(FS(FSTRING_EMPTY)); println_Msg(FS(FSTRING_EMPTY));
@ -1095,9 +1106,21 @@ constexpr char modeItem24[] PROGMEM = "Atari 5200";
constexpr char modeItem25[] PROGMEM = "Atari 7800"; constexpr char modeItem25[] PROGMEM = "Atari 7800";
constexpr char modeItem26[] PROGMEM = "Atari Lynx"; constexpr char modeItem26[] PROGMEM = "Atari Lynx";
constexpr char modeItem27[] PROGMEM = "Vectrex"; constexpr char modeItem27[] PROGMEM = "Vectrex";
constexpr char modeItem28[] PROGMEM = "Flashrom Programmer"; constexpr char modeItem28[] PROGMEM = "Atari 8-bit";
constexpr char modeItem29[] PROGMEM = "Self Test (3V)"; constexpr char modeItem29[] PROGMEM = "Bally Astrocade";
constexpr char modeItem30[] PROGMEM = "About"; constexpr char modeItem30[] PROGMEM = "Bandai LJ";
constexpr char modeItem31[] PROGMEM = "Bandai LJ Pro";
constexpr char modeItem32[] PROGMEM = "Casio PV-1000";
constexpr char modeItem33[] PROGMEM = "Commodore VIC-20";
constexpr char modeItem34[] PROGMEM = "LF Leapster (3V)";
constexpr char modeItem35[] PROGMEM = "RCA Studio II";
constexpr char modeItem36[] PROGMEM = "TI-99";
constexpr char modeItem37[] PROGMEM = "Tomy Pyuuta";
constexpr char modeItem38[] PROGMEM = "TRS-80";
constexpr char modeItem39[] PROGMEM = "Vtech V.Smile (3V)";
constexpr char modeItem40[] PROGMEM = "Flashrom Programmer";
constexpr char modeItem41[] PROGMEM = "Self Test (3V)";
constexpr char modeItem42[] PROGMEM = "About";
static const char* const modeOptions[] PROGMEM = { static const char* const modeOptions[] PROGMEM = {
#ifdef ENABLE_GBX #ifdef ENABLE_GBX
@ -1181,14 +1204,49 @@ static const char* const modeOptions[] PROGMEM = {
#ifdef ENABLE_VECTREX #ifdef ENABLE_VECTREX
modeItem27, modeItem27,
#endif #endif
#ifdef ENABLE_FLASH #ifdef ENABLE_ATARI8
modeItem28, modeItem28,
#endif #endif
#ifdef ENABLE_SELFTEST #ifdef ENABLE_BALLY
modeItem29, modeItem29,
#endif #endif
#ifdef ENABLE_LJ
modeItem30, modeItem30,
FSTRING_RESET #endif
#ifdef ENABLE_LJPRO
modeItem31,
#endif
#ifdef ENABLE_PV1000
modeItem32,
#endif
#ifdef ENABLE_VIC20
modeItem33,
#endif
#ifdef ENABLE_LEAP
modeItem34,
#endif
#ifdef ENABLE_RCA
modeItem35,
#endif
#ifdef ENABLE_TI99
modeItem36,
#endif
#ifdef ENABLE_PYUUTA
modeItem37,
#endif
#ifdef ENABLE_TRS80
modeItem38,
#endif
#ifdef ENABLE_VSMILE
modeItem39,
#endif
#ifdef ENABLE_FLASH
modeItem40,
#endif
#ifdef ENABLE_SELFTEST
modeItem41,
#endif
modeItem42, FSTRING_RESET
}; };
uint8_t pageMenu(const __FlashStringHelper* question, const char* const* menuStrings, uint8_t entryCount, uint8_t default_choice = 0) { uint8_t pageMenu(const __FlashStringHelper* question, const char* const* menuStrings, uint8_t entryCount, uint8_t default_choice = 0) {
@ -1397,7 +1455,7 @@ void mainMenu() {
setup_LYNX(); setup_LYNX();
return lynxMenu(); return lynxMenu();
break; break;
#endif #endif
#ifdef ENABLE_VECTREX #ifdef ENABLE_VECTREX
case SYSTEM_MENU_VECTREX: case SYSTEM_MENU_VECTREX:
@ -1406,6 +1464,90 @@ void mainMenu() {
break; break;
#endif #endif
#ifdef ENABLE_ATARI8
case SYSTEM_MENU_ATARI8:
setup_ATARI8();
return atari8Menu();
break;
#endif
#ifdef ENABLE_BALLY
case SYSTEM_MENU_BALLY:
setup_BALLY();
return ballyMenu();
break;
#endif
#ifdef ENABLE_LJ
case SYSTEM_MENU_LJ:
setup_LJ();
return ljMenu();
break;
#endif
#ifdef ENABLE_LJPRO
case SYSTEM_MENU_LJPRO:
setup_LJPRO();
return ljproMenu();
break;
#endif
#ifdef ENABLE_PV1000
case SYSTEM_MENU_PV1000:
setup_PV1000();
return pv1000Menu();
break;
#endif
#ifdef ENABLE_VIC20
case SYSTEM_MENU_VIC20:
setup_VIC20();
return vic20Menu();
break;
#endif
#ifdef ENABLE_LEAP
case SYSTEM_MENU_LEAP:
setup_LEAP();
return leapMenu();
break;
#endif
#ifdef ENABLE_RCA
case SYSTEM_MENU_RCA:
setup_RCA();
return rcaMenu();
break;
#endif
#ifdef ENABLE_TI99
case SYSTEM_MENU_TI99:
setup_TI99();
return ti99Menu();
break;
#endif
#ifdef ENABLE_PYUUTA
case SYSTEM_MENU_PYUUTA:
setup_PYUUTA();
return pyuutaMenu();
break;
#endif
#ifdef ENABLE_TRS80
case SYSTEM_MENU_TRS80:
setup_TRS80();
return trs80Menu();
break;
#endif
#ifdef ENABLE_VSMILE
case SYSTEM_MENU_VSMILE:
setup_VSMILE();
return vsmileMenu();
break;
#endif
#ifdef ENABLE_FLASH #ifdef ENABLE_FLASH
case SYSTEM_MENU_FLASH: case SYSTEM_MENU_FLASH:
# ifdef ENABLE_VSELECT # ifdef ENABLE_VSELECT
@ -3608,6 +3750,42 @@ void loop() {
#endif #endif
#ifdef ENABLE_GPC #ifdef ENABLE_GPC
case CORE_GPC: return gpcMenu(); case CORE_GPC: return gpcMenu();
#endif
#ifdef ENABLE_ATARI8
case CORE_ATARI8: return atari8Menu();
#endif
#ifdef ENABLE_BALLY
case CORE_BALLY: return ballyMenu();
#endif
#ifdef ENABLE_LJ
case CORE_LJ: return ljMenu();
#endif
#ifdef ENABLE_LJPRO
case CORE_LJPRO: return ljproMenu();
#endif
#ifdef ENABLE_PV1000
case CORE_PV1000: return pv1000Menu();
#endif
#ifdef ENABLE_VIC20
case CORE_VIC20: return vic20Menu();
#endif
#ifdef ENABLE_LEAP
case CORE_LEAP: return leapMenu();
#endif
#ifdef ENABLE_RCA
case CORE_RCA: return rcaMenu();
#endif
#ifdef ENABLE_TI99
case CORE_TI99: return ti99Menu();
#endif
#ifdef ENABLE_PYUUTA
case CORE_PYUUTA: return pyuutaMenu();
#endif
#ifdef ENABLE_TRS80
case CORE_TRS80: return trs80Menu();
#endif
#ifdef ENABLE_VSMILE
case CORE_VSMILE: return vsmileMenu();
#endif #endif
case CORE_MAX: return resetArduino(); case CORE_MAX: return resetArduino();
} }

View File

@ -96,6 +96,34 @@
/****/ /****/
/* [ Atari 8-bit -------------------------------------------------- ]
*/
//#define ENABLE_ATARI8
/****/
/* [ Bally Astrocade ---------------------------------------------- ]
*/
//#define ENABLE_BALLY
/****/
/* [ Bandai Little Jammer ----------------------------------------- ]
*/
//#define ENABLE_LJ
/****/
/* [ Bandai Little Jammer Pro ------------------------------------- ]
*/
//#define ENABLE_LJPRO
/****/
/* [ Benesse Pocket Challenge W ----------------------------------- ] /* [ Benesse Pocket Challenge W ----------------------------------- ]
*/ */
@ -103,10 +131,10 @@
/****/ /****/
/* [ C64 --------------------------------------------------- ] /* [ Casio PV-1000 ------------------------------------------------ ]
*/ */
//#define ENABLE_C64 //#define ENABLE_PV1000
/****/ /****/
@ -117,6 +145,20 @@
/****/ /****/
/* [ Commodore 64 ------------------------------------------------- ]
*/
//#define ENABLE_C64
/****/
/* [ Commodore VIC-20 --------------------------------------------- ]
*/
//#define ENABLE_VIC20
/****/
/* [ Emerson Arcadia 2001 ----------------------------------------- ] /* [ Emerson Arcadia 2001 ----------------------------------------- ]
*/ */
@ -153,6 +195,13 @@
/****/ /****/
/* [ LeapFrog Leapster -------------------------------------------- ]
*/
//#define ENABLE_LEAP
/****/
/* [ Neo Geo Pocket ----------------------------------------------- ] /* [ Neo Geo Pocket ----------------------------------------------- ]
*/ */
@ -181,7 +230,7 @@
/****/ /****/
/* [ MSX ------------------------------------------- ] /* [ MSX ---------------------------------------------------------- ]
*/ */
//#define ENABLE_MSX //#define ENABLE_MSX
@ -195,13 +244,20 @@
/****/ /****/
/* [ Pokemon Mini -------------------------------------- ] /* [ Pokemon Mini ------------------------------------------------- ]
*/ */
//#define ENABLE_POKE //#define ENABLE_POKE
/****/ /****/
/* [ RCA Studio II ------------------------------------------------ ]
*/
//#define ENABLE_RCA
/****/
/* [ Sega Master System/Mark III/Game Gear/SG-1000 ---------------- ] /* [ Sega Master System/Mark III/Game Gear/SG-1000 ---------------- ]
*/ */
@ -251,7 +307,28 @@
/****/ /****/
/* [ Vectrex --------------------------------------------------- ] /* [ Texas Instruments TI-99 -------------------------------------- ]
*/
//#define ENABLE_TI99
/****/
/* [ Tomy Pyuuta -------------------------------------------------- ]
*/
//#define ENABLE_PYUUTA
/****/
/* [ TRS-80 Color Computer ---------------------------------------- ]
*/
//#define ENABLE_TRS80
/****/
/* [ Vectrex ------------------------------------------------------ ]
*/ */
//#define ENABLE_VECTREX //#define ENABLE_VECTREX
@ -265,6 +342,13 @@
/****/ /****/
/* [ Vtech V.Smile ------------------------------------------------ ]
*/
//#define ENABLE_VSMILE
/****/
/* [ Watara Supervision ------------------------------------------- ] /* [ Watara Supervision ------------------------------------------- ]
*/ */

1052
Cart_Reader/LEAP.ino Normal file

File diff suppressed because it is too large Load Diff

356
Cart_Reader/LJ.ino Normal file
View File

@ -0,0 +1,356 @@
//******************************************
// LITTLE JAMMER MODULE
//******************************************
#ifdef ENABLE_LJ
// Little Jammer
// Cartridge Pinout
// 48P 1.25mm pitch connector
//
// FORM FACTOR IS SAME AS BANDAI WONDERSWAN/BENESSE POCKET CHALLENGE V2/LITTLE JAMMER PRO
// WIRING IS COMPLETELY DIFFERENT!
//
// LEFT SIDE
// 1 VSS (GND)
// 2 A-1
// 3 A0
// 4 A1
// 5 A2
// 6 A3
// 7 A4
// 8 A5
// 9 A6
// 10 A7
// 11 A8
// 12 A9
// 13 A10
// 14 A11
// 15 A12
// 16 A13
// 17 A14
// 18 A15
// 19 A16
// 20 A17
// 21 A18
// 22 A19
// 23 A20
// 24 VCC (+5V)
// 25 VCC (+5V)
// 26 D0
// 27 D1
// 28 D2
// 29 D3
// 30 D4
// 31 D5
// 32 D6
// 33 D7
// 34 /WE
// 35 /RESET
// 36 /CE
// 37 /OE
// 38 VSS (GND)
// 39 NC
// 40 NC
// 41 NC
// 42 NC
// 43 NC
// 44 NC
// 45 NC
// 46 NC
// 47 VSS (GND)
// 48 VSS (GND)
// RIGHT SIDE
// CONTROL PINS:
// /RESET(PH0) - SNES RESET
// /CE(PH3) - SNES /CS
// /WE(PH5) - SNES /WR
// /OE(PH6) - SNES /RD
// LITTLE JAMMER DIRECT ADDRESSING
// 1 1111 1111 1111 1111 1111
// 1 F F F F F = 0x1FFFFF
// Size = 0x200000 = 2MB
//
// A20 connection on Pin 23 = 0x400000 = 4MB
// 11 1111 1111 1111 1111 1111
// 3 F F F F F = 0x3FFFFF
// Size = 0x400000 = 4MB
//******************************************
// VARIABLES
//******************************************
byte LJ[] = {1,2,4};
byte ljlo = 0; // Lowest Entry
byte ljhi = 2; // Highest Entry
byte ljsize;
byte newljsize;
boolean ljflashfound = false;
byte ljbytecheck;
// EEPROM MAPPING
// 08 ROM SIZE
//******************************************
// MENU
//******************************************
// Base Menu
static const char* const menuOptionsLJ[] PROGMEM = { FSTRING_SELECT_CART, FSTRING_READ_ROM, FSTRING_SET_SIZE, FSTRING_RESET };
void ljMenu()
{
convertPgm(menuOptionsLJ, 4);
uint8_t mainMenu = question_box(F("LITTLE JAMMER MENU"), menuOptions, 4, 0);
switch (mainMenu)
{
// Select Cart
case 0:
setCart_LJ();
setup_LJ();
break;
// Read ROM
case 1:
sd.chdir("/");
readROM_LJ();
sd.chdir("/");
break;
// Set Size
case 2:
setROMSize_LJ();
break;
// Reset
case 3:
resetArduino();
break;
}
}
//******************************************
// SETUP
//******************************************
void setup_LJ()
{
// Request 5V
setVoltage(VOLTS_SET_5V);
// Set Address Pins to Output
// LITTLE JAMMER uses A(-1)-A19 wired to A0-A20 [A21-A23 UNUSED]
//A0-A7
DDRF = 0xFF;
//A8-A15
DDRK = 0xFF;
//A16-A23
DDRL = 0xFF;
// Set Control Pins to Output
// /RST(PH0) ---(PH1) /CE(PH3) ---(PH4) /WR(PH5) /OE(PH6)
DDRH |= (1 << 0) | (1 << 1) | (1 << 3) | (1 << 4) | (1 << 5) | (1 << 6);
// Set TIME(PJ0) to Output (UNUSED)
DDRJ |= (1 << 0);
// Set Pins (D0-D7) to Input
DDRC = 0x00;
// Setting Control Pins to HIGH
// /RST(PH0) ---(PH1) /CE(PH3) ---(PH4) /WR(PH5) /OE(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;
PORTJ |= (1 << 0); // TIME(PJ0)
checkStatus_LJ();
strcpy(romName, "LJ");
mode = CORE_LJ;
}
//******************************************
// READ FUNCTIONS
//******************************************
uint8_t readData_LJ(uint32_t addr)
{
PORTF = addr & 0xFF; // A(-1)-A6
PORTK = (addr >> 8) & 0xFF; // A7-A14
PORTL = (addr >> 16) & 0xFF; // A15-A20
NOP;
NOP;
// switch /CE(PH3) to LOW
PORTH &= ~(1 << 3);
// switch /OE(PH6) to LOW
PORTH &= ~(1 << 6);
NOP;
NOP;
uint8_t ret = PINC;
// switch /CE(PH3) and /OE(PH6) to HIGH
PORTH |= (1 << 3) | (1 << 6);
return ret;
}
void readSegment_LJ(uint32_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_LJ(addr + w);
sdBuffer[w] = temp;
}
myFile.write(sdBuffer, 512);
}
}
//******************************************
// READ ROM
//******************************************
void readROM_LJ()
{
createFolderAndOpenFile("LJ", "ROM", romName, "bin");
// Maximum Direct Address Size is 4MB
readSegment_LJ(0x000000,0x100000); // 1MB
if (ljsize > 0) // 2MB/4MB
{
readSegment_LJ(0x100000,0x200000); // +1MB = 2MB
if (ljsize > 1) // 4MB
{
readSegment_LJ(0x200000,0x400000); // +2MB = 4MB
}
}
myFile.close();
printCRC(fileName, NULL, 0);
println_Msg(FS(FSTRING_EMPTY));
print_STR(press_button_STR, 1);
display_Update();
wait();
}
//******************************************
// ROM SIZE
//******************************************
#if (defined(ENABLE_OLED) || defined(ENABLE_LCD))
void printRomSize_LJ(int index)
{
display_Clear();
print_Msg(FS(FSTRING_ROM_SIZE));
println_Msg(LJ[index]);
}
#endif
void setROMSize_LJ()
{
byte newljsize;
#if (defined(ENABLE_OLED) || defined(ENABLE_LCD))
display_Clear();
if (ljlo == ljhi)
newljsize = ljlo;
else {
newljsize = navigateMenu(ljlo, ljhi, &printRomSize_LJ);
display.setCursor(0, 56); // Display selection at bottom
}
print_Msg(FS(FSTRING_ROM_SIZE));
print_Msg(LJ[newljsize]);
println_Msg(F("KB"));
display_Update();
delay(1000);
#else
if (ljlo == ljhi)
newljsize = ljlo;
else {
setrom:
String sizeROM;
for (int i = 0; i < (ljhi - ljlo + 1); i++) {
Serial.print(F("Select ROM Size: "));
Serial.print(i);
Serial.print(F(" = "));
Serial.print(LJ[i + ljlo]);
Serial.println(F("KB"));
}
Serial.print(F("Enter ROM Size: "));
while (Serial.available() == 0) {}
sizeROM = Serial.readStringUntil('\n');
Serial.println(sizeROM);
newljsize = sizeROM.toInt() + ljlo;
if (newljsize > ljhi) {
Serial.println(F("SIZE NOT SUPPORTED"));
Serial.println(FS(FSTRING_EMPTY));
goto setrom;
}
}
Serial.print(F("ROM Size = "));
Serial.print(LJ[newljsize]);
Serial.println(F("KB"));
#endif
EEPROM_writeAnything(8, newljsize);
ljsize = newljsize;
}
void checkStatus_LJ()
{
EEPROM_readAnything(8, ljsize);
if (ljsize > ljhi) {
ljsize = 1; // default 2M
EEPROM_writeAnything(8, ljsize);
}
#if (defined(ENABLE_OLED) || defined(ENABLE_LCD))
display_Clear();
println_Msg(F("LITTLE JAMMER"));
println_Msg(FS(FSTRING_CURRENT_SETTINGS));
println_Msg(FS(FSTRING_EMPTY));
print_Msg(FS(FSTRING_ROM_SIZE));
print_Msg(LJ[ljsize]);
println_Msg(F("MB"));
display_Update();
wait();
#else
Serial.print(FS(FSTRING_ROM_SIZE));
Serial.print(LJ[ljsize]);
Serial.println(F("MB"));
Serial.println(FS(FSTRING_EMPTY));
#endif
}
//******************************************
// CART SELECT CODE
//******************************************
void setCart_LJ()
{
//go to root
sd.chdir();
byte gameSize;
// Select starting letter
//byte myLetter = starting_letter();
// Open database
if (myFile.open("ljcart.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

554
Cart_Reader/LJPRO.ino Normal file
View File

@ -0,0 +1,554 @@
//******************************************
// LITTLE JAMMER PRO MODULE
//******************************************
#ifdef ENABLE_LJPRO
// Little Jammer Pro
// Cartridge Pinout
// 48P 1.25mm pitch connector
//
// FORM FACTOR IS SAME AS BANDAI WONDERSWAN/BENESSE POCKET CHALLENGE V2/LITTLE JAMMER
// WIRING IS COMPLETELY DIFFERENT!
//
// LEFT SIDE
// 1 GND
// 2 GND
// 3 S1 (GND)
// 4 S2 (GND)
// 5 U1_WP#/ACC
// 6 U1_SCLK
// 7 U1_SCLK
// 8 U1_SI
// 9 U1_SI
// 10 U1_SO/PO7
// 11 U1_SO/PO7
// 12 U1_PO6
// 13 U1_PO5
// 14 U1_PO4
// 15 U1_PO3
// 16 U1_PO2
// 17 U1_PO1
// 18 U1_PO0
// 19 U1_CS#
// 20 U1_CS#
// 21 U1_HOLD#
// 22 U1_HOLD#
// 23 VCC (+3V)
// 24 VCC (+3V)
// 25 VCC (+3V)
// 26 VCC (+3V)
// 27 U2_SCLK
// 28 U2_SCLK
// 29 U2_SI
// 30 U2_SI
// 31 U2_SO/PO7
// 32 U2_SO/PO7
// 33 U2_PO6
// 34 U2_PO5
// 35 U2_PO4
// 36 U2_PO3
// 37 U2_PO2
// 38 U2_PO1
// 39 U2_PO0
// 40 U2_CS#
// 41 U2_CS#
// 42 U2_HOLD#
// 43 U2_HOLD#
// 44 U2_WP#/ACC
// 45 S3 (GND)
// 46 S4 (GND)
// 47 GND
// 48 GND
// RIGHT SIDE
// CONTROL PINS:
// U1_HOLD# (PH4) - SNES /IRQ
// U1_CS# (PK0) - SNES A8
// U1_SI (PK1) - SNES A9
// U1_WP#/ACC (PK2) - SNES A10
//
// U2_HOLD# (PH0) - SNES RESET
// U2_SI (PH3) - SNES /CS
// U2_WP#/ACC (PH5) - SNES /WR
// U2_CS# (PH6) - SNES /RD
//
// S1 (PK4) - SNES A12
// S2 (PK5) - SNES A13
// S3 (PK6) - SNES A14
// S4 (PK7) - SNES A15
// COMBINE U1_SCLK + U2_SCLK INTO SINGLE SCLK
// SCLK(PH1) - SNES CPUCLK
// DATA PINS:
// U1 D0-D7 (PORTF)
// U2 D0-D7 (PORTC)
// NOTES:
// HOLD# NOT USED FOR PARALLEL MODE - PULLED UP TO VCC ON CARTS
// WP#/ACC PULLED DOWN TO GND ON CARTS
//******************************************
// DEFINES
//******************************************
#define CS1_LOW PORTK &= ~(1 << 0)
#define CS1_HIGH PORTK |= (1 << 0)
#define CS2_LOW PORTH &= ~(1 << 6)
#define CS2_HIGH PORTH |= (1 << 6)
//******************************************
// VARIABLES
//******************************************
byte LJPRO[] = {2,4,6,8};
byte ljprolo = 0; // Lowest Entry
byte ljprohi = 3; // Highest Entry
byte ljprosize;
byte newljprosize;
char mnfID[3];
char deviceID[5];
boolean ljproflash1found = false;
boolean ljproflash2found = false;
byte ljproflash1size;
byte ljproflash2size;
// EEPROM MAPPING
// 08 ROM SIZE
//******************************************
// MENU
//******************************************
// Base Menu
static const char* const menuOptionsLJPRO[] PROGMEM = { FSTRING_READ_ROM, FSTRING_SET_SIZE, FSTRING_RESET };
// U1_HOLD#(PH4) - SNES /IRQ
// U1_CS# - SNES A8
// U1_WP#/ACC - SNES A9
// U1_SI - SNES A10
//
// U2_HOLD#(PH0) - SNES RESET
// U2_SI(PH3) - SNES /CS
// U2_WP#/ACC(PH5) - SNES /WR
// U2_CS#(PH6) - SNES /RD
void ljproMenu()
{
convertPgm(menuOptionsLJPRO, 3);
uint8_t mainMenu = question_box(F("LITTLE JAMMER PRO"), menuOptions, 3, 0);
switch (mainMenu)
{
case 0:
// Read ROM
sd.chdir("/");
readROM_LJPRO();
sd.chdir("/");
break;
case 1:
// Set Size
setROMSize_LJPRO();
break;
case 2:
// reset
resetArduino();
break;
}
}
//******************************************
// SETUP
//******************************************
void setup_LJPRO()
{
// Request 3.3V
setVoltage(VOLTS_SET_3V3);
// LITTLE JAMMER PRO uses Serial Flash
// Set Data Pins to Input
DDRF = 0x00; // U1 Data
DDRC = 0x00; // U2 Data
// Set Unused Address Pins to Output
DDRL = 0xFF;
// Set Control Pins to Output
// U2_HLD(PH0) SCLK(PH1) U2_SI(PH3) U1_HLD(PH4) U2_WP(PH5) U2_CS(PH6)
DDRH |= (1 << 0) | (1 << 1) | (1 << 3) | (1 << 4) | (1 << 5) | (1 << 6);
// U1_CS(PK0) U1_SI(PK1) U1_WP(PK2) --------
DDRK |= (1 << 0) | (1 << 1) | (1 <<2) | (1 << 3);
// FLASH Configuration Pins to Input
// S1(PK4) S2(PK5) S3(PK6) S4(PK7)
DDRK &= ~((1 << 4) | (1 << 5) | (1 << 6) | (1 << 7));
// Set TIME(PJ0) to Output (UNUSED)
DDRJ |= (1 << 0);
// Setting Control Pins to HIGH
// U2_HLD(PH0) SCLK(PH1) U2_SI(PH3) U1_HLD(PH4) U2_WP(PH5) U2_CS(PH6)
PORTH |= (1 << 0) | (1 << 1) | (1 << 3) | (1 << 4) | (1 << 5) | (1 << 6);
// U1_CS(PK0) U1_SI(PK1) U1_WP(PK2) -------- S1(PK4) S2(PK5) S3(PK6) S4(PK7)
PORTK |= (1 << 0) | (1 << 1) | (1 << 2) | (1 << 3) | (1 << 4) | (1 << 5) | (1 << 6) | (1 << 7);
// Set Unused Data Pins (PA0-PA7) to Output
DDRA = 0xFF;
// Set Unused Pins HIGH
PORTA = 0xFF;
PORTJ |= (1 << 0); // TIME(PJ0)
checkStatus_LJPRO();
strcpy(romName, "LJPRO");
mode = CORE_LJPRO;
}
//******************************************
// SERIAL MODE
//******************************************
// 25L1605/25L3205
// Default Serial Mode
void sendSerial_U1(uint8_t data)
{
for (int i = 0; i < 8; i++) {
PORTH &= ~(1 << 1); // SCLK LOW
if ((data >> 7) & 0x1) { // Bit is HIGH
PORTK |= (1 << 1); // U1_SI HIGH;
}
else {
PORTK &= ~(1 << 1); // U1_SI LOW;
}
PORTH |= (1 << 1); // SCLK HIGH
// rotate to the next bit
data <<= 1;
}
}
void sendSerial_U2(uint8_t data)
{
for (int i = 0; i < 8; i++) {
PORTH &= ~(1 << 1); // SCLK LOW
if ((data >> 7) & 0x1) { // Bit is HIGH
PORTH |= (1 << 3); // U2_SI HIGH;
}
else {
PORTH &= ~(1 << 3); // U2_SI LOW;
}
PORTH |= (1 << 1); // SCLK HIGH
// rotate to the next bit
data <<= 1;
}
}
uint8_t readSerial_U1()
{
bool serBits[9];
for (byte i = 0; i < 8; i++) {
pulseClock_LJPRO(1);
serBits[i] = (PINF >> 7) & 0x1;
}
byte tempdata = serBits[0] << 7 | serBits[1] << 6 | serBits[2] << 5 | serBits[3] << 4 | serBits[4] << 3 | serBits[5] << 2 | serBits[6] << 1 | serBits[7];
return tempdata;
}
uint8_t readSerial_U2()
{
bool serBits[9];
for (byte i = 0; i < 8; i++) {
pulseClock_LJPRO(1);
serBits[i] = (PINC >> 7) & 0x1;
}
byte tempdata = serBits[0] << 7 | serBits[1] << 6 | serBits[2] << 5 | serBits[3] << 4 | serBits[4] << 3 | serBits[5] << 2 | serBits[6] << 1 | serBits[7];
return tempdata;
}
//******************************************
// PARALLEL MODE
//******************************************
// 25L1605/25L3205
// Parallel Mode - Command 0x55
// SCLK Frequency 1.2MHz (Cycle 833.33ns)
// READ 0x03
// WRITE 0x02
void pulseClock_LJPRO(unsigned int times)
{
for (unsigned int i = 0; i < (times * 2); i++) {
// Switch the clock pin to 0 if it's 1 and 0 if it's 1
PORTH ^= (1 << 1);
// without the delay the clock pulse would be 1.5us and 666kHz
//__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t"));
}
}
// Send one byte of data to Serial FLASH [Parallel Mode]
void sendData_U1(byte data)
{
DDRF = 0xFF; // U1 Data Output
PORTF = data;
pulseClock_LJPRO(8);
DDRF = 0x00; // U1 Data Input
}
void sendData_U2(byte data)
{
DDRC = 0xFF; // U2 Data Output
PORTC = data;
pulseClock_LJPRO(8);
DDRC = 0x00; // U2 Data Input
}
void readData_U1(uint32_t startaddr, uint32_t endaddr)
{
for (uint32_t addr = startaddr; addr < endaddr; addr += 512) {
for (int x = 0; x < 512; x++) {
pulseClock_LJPRO(1);
sdBuffer[x] = PINF;
}
myFile.write(sdBuffer, 512);
}
}
void readData_U2(uint32_t startaddr, uint32_t endaddr)
{
for (uint32_t addr = startaddr; addr < endaddr; addr += 512) {
for (int x = 0; x < 512; x++) {
pulseClock_LJPRO(1);
sdBuffer[x] = PINC;
}
myFile.write(sdBuffer, 512);
}
}
// RDID
// Manufacturer 0xC2
// Memory Density 0x20
// Device ID 0x15 [25L1605]/0x16 [25L3205]
// REMS
// Manufacturer 0xC2
// Device ID 0x14 [25L1605]/0x15 [25L3205]
void readID_U1() // Parallel Mode
{
CS1_LOW; // U1 LOW
sendSerial_U1(0x9F); // RDID Command
pulseClock_LJPRO(1);
byte id0 = PINF; // 0xC2
pulseClock_LJPRO(1);
byte id1 = PINF; // 0x20
pulseClock_LJPRO(1);
byte id2 = PINF; // 0x15 [MX25L1605]/0x16 [MX25L3205]
CS1_HIGH; // U1 HIGH
// Flash ID
sprintf(mnfID, "%02X", id0);
sprintf(deviceID, "%02X%02X", id1, id2);
// println_Msg(mnfID);
// println_Msg(deviceID);
// display_Update();
if(strcmp(deviceID, "2015") == 0) { // MX25L1605
ljproflash1found = 1;
ljproflash1size = 2;
display_Clear();
println_Msg(F("U1 MX25L1605 FOUND"));
display_Update();
}
else if (strcmp(deviceID, "2016") == 0) { // MX25L3205
ljproflash1found = 1;
ljproflash1size = 4;
display_Clear();
println_Msg(F("U1 MX25L3205 FOUND"));
display_Update();
}
}
void readID_U2() // Parallel Mode
{
CS2_LOW; // U2 LOW
sendSerial_U2(0x9F); // RDID Command
pulseClock_LJPRO(1);
byte id0 = PINC; // 0xC2
pulseClock_LJPRO(1);
byte id1 = PINC; // 0x20
pulseClock_LJPRO(1);
byte id2 = PINC; // 0x15 [MX25L1605]/0x16 [MX25L3205]
pulseClock_LJPRO(1);
CS2_HIGH; // U2 HIGH
// Flash ID
sprintf(mnfID, "%02X", id0);
sprintf(deviceID, "%02X%02X", id1, id2);
// println_Msg(mnfID);
// println_Msg(deviceID);
// display_Update();
if(strcmp(deviceID, "2015") == 0) { // MX25L1605
ljproflash2found = 1;
ljproflash2size = 2;
println_Msg(F("U2 MX25L1605 FOUND"));
display_Update();
}
else if (strcmp(deviceID, "2016") == 0) { // MX25L3205
ljproflash2found = 1;
ljproflash2size = 4;
println_Msg(F("U2 MX25L3205 FOUND"));
display_Update();
}
}
//******************************************
// READ ROM
//******************************************
void readROM_LJPRO()
{
createFolderAndOpenFile("LJPRO", "ROM", romName, "bin");
// Little Jammer Pro PCB B1043-02A
// Footprints for two 25L1605/25L3205 chips
// Test carts only have one 25L1605 (2MB) installed
// PCB could possibly install two 25L3205 chips (2x4MB = 8MB)
// Set U1 FLASH to Parallel Mode
CS1_LOW; // U1 LOW
sendSerial_U1(0x55); // Parallel Mode
CS1_HIGH; // U1 HIGH
// Read ID
readID_U1();
// Set U2 FLASH to Parallel Mode
CS2_LOW; // U2 LOW
sendSerial_U2(0x55); // Parallel Mode
CS2_HIGH; // U2 HIGH
// Read ID
readID_U2();
// Read U1
println_Msg(F("Reading U1..."));
display_Update();
CS1_LOW; // U1 LOW
DDRF = 0x00; // U1 Data Input
sendSerial_U1(0x03); // Read Array (Parallel)
sendSerial_U1(0x00); // Address A23-A16
sendSerial_U1(0x00); // Address A15-A8
sendSerial_U1(0x00); // Address A7-A0
readData_U1(0x000000, 0x200000);
if (ljproflash1size == 4) { // 4MB
readData_U1(0x200000, 0x400000);
}
CS1_HIGH; // U1 HIGH
if (ljproflash2found) {
// Read U2
println_Msg(F("Reading U2..."));
display_Update();
CS2_LOW; // U2 LOW
DDRC = 0x00; // U2 Data Input
sendSerial_U2(0x03); // Read Array (Parallel)
sendSerial_U2(0x00); // Address A23-A16
sendSerial_U2(0x00); // Address A15-A8
sendSerial_U2(0x00); // Address A7-A0
readData_U2(0x000000, 0x200000);
if (ljproflash2size == 4) { // 4MB
readData_U2(0x200000, 0x400000);
}
CS2_HIGH; // U2 HIGH
}
myFile.close();
printCRC(fileName, NULL, 0);
println_Msg(FS(FSTRING_EMPTY));
print_STR(press_button_STR, 1);
display_Update();
wait();
}
//******************************************
// ROM SIZE
//******************************************
#if (defined(ENABLE_OLED) || defined(ENABLE_LCD))
void printRomSize_LJPRO(int index)
{
display_Clear();
print_Msg(FS(FSTRING_ROM_SIZE));
println_Msg(LJPRO[index]);
}
#endif
void setROMSize_LJPRO()
{
byte newljprosize;
#if (defined(ENABLE_OLED) || defined(ENABLE_LCD))
display_Clear();
if (ljprolo == ljprohi)
newljprosize = ljprolo;
else {
newljprosize = navigateMenu(ljprolo, ljprohi, &printRomSize_LJPRO);
display.setCursor(0, 56); // Display selection at bottom
}
print_Msg(FS(FSTRING_ROM_SIZE));
print_Msg(LJPRO[newljprosize]);
println_Msg(F("KB"));
display_Update();
delay(1000);
#else
if (ljprolo == ljprohi)
newljprosize = ljprolo;
else {
setrom:
String sizeROM;
for (int i = 0; i < (ljprohi - ljprolo + 1); i++) {
Serial.print(F("Select ROM Size: "));
Serial.print(i);
Serial.print(F(" = "));
Serial.print(LJPRO[i + ljprolo]);
Serial.println(F("KB"));
}
Serial.print(F("Enter ROM Size: "));
while (Serial.available() == 0) {}
sizeROM = Serial.readStringUntil('\n');
Serial.println(sizeROM);
newljprosize = sizeROM.toInt() + ljprolo;
if (newljprosize > ljprohi) {
Serial.println(F("SIZE NOT SUPPORTED"));
Serial.println(FS(FSTRING_EMPTY));
goto setrom;
}
}
Serial.print(F("ROM Size = "));
Serial.print(LJPRO[newljprosize]);
Serial.println(F("KB"));
#endif
EEPROM_writeAnything(8, newljprosize);
ljprosize = newljprosize;
}
void checkStatus_LJPRO()
{
EEPROM_readAnything(8, ljprosize);
if (ljprosize > ljprohi) {
ljprosize = 0; // default 2M
EEPROM_writeAnything(8, ljprosize);
}
#if (defined(ENABLE_OLED) || defined(ENABLE_LCD))
display_Clear();
println_Msg(F("LITTLE JAMMER PRO"));
println_Msg(FS(FSTRING_CURRENT_SETTINGS));
println_Msg(FS(FSTRING_EMPTY));
print_Msg(FS(FSTRING_ROM_SIZE));
print_Msg(LJPRO[ljprosize]);
println_Msg(F("MB"));
display_Update();
wait();
#else
Serial.print(FS(FSTRING_ROM_SIZE));
Serial.print(LJPRO[ljprosize]);
Serial.println(F("MB"));
Serial.println(FS(FSTRING_EMPTY));
#endif
}
#endif

View File

@ -49,7 +49,7 @@
* String Constants * String Constants
**/ **/
// Firmware Version // Firmware Version
constexpr char PROGMEM FSTRING_VERSION[] = "V13.5"; constexpr char PROGMEM FSTRING_VERSION[] = "V14.0";
// Universal // Universal
constexpr char PROGMEM FSTRING_RESET[] = "Reset"; constexpr char PROGMEM FSTRING_RESET[] = "Reset";

View File

@ -227,6 +227,42 @@ enum CORES: uint8_t {
# endif # endif
# ifdef ENABLE_GPC # ifdef ENABLE_GPC
CORE_GPC, CORE_GPC,
# endif
# ifdef ENABLE_ATARI8
CORE_ATARI8,
# endif
# ifdef ENABLE_BALLY
CORE_BALLY,
# endif
# ifdef ENABLE_LJ
CORE_LJ,
# endif
# ifdef ENABLE_LJPRO
CORE_LJPRO,
# endif
# ifdef ENABLE_PV1000
CORE_PV1000,
# endif
# ifdef ENABLE_VIC20
CORE_VIC20,
# endif
# ifdef ENABLE_LEAP
CORE_LEAP,
# endif
# ifdef ENABLE_RCA
CORE_RCA,
# endif
# ifdef ENABLE_TI99
CORE_TI99,
# endif
# ifdef ENABLE_PYUUTA
CORE_PYUUTA,
# endif
# ifdef ENABLE_TRS80
CORE_TRS80,
# endif
# ifdef ENABLE_VSMILE
CORE_VSMILE,
# endif # endif
CORE_MAX // Always last CORE_MAX // Always last
}; };
@ -313,6 +349,42 @@ enum SYSTEM_MENU: uint8_t {
# if defined(ENABLE_VECTREX) # if defined(ENABLE_VECTREX)
SYSTEM_MENU_VECTREX, SYSTEM_MENU_VECTREX,
# endif # endif
# if defined(ENABLE_ATARI8)
SYSTEM_MENU_ATARI8,
# endif
# if defined(ENABLE_BALLY)
SYSTEM_MENU_BALLY,
# endif
# if defined(ENABLE_LJ)
SYSTEM_MENU_LJ,
# endif
# if defined(ENABLE_LJPRO)
SYSTEM_MENU_LJPRO,
# endif
# if defined(ENABLE_PV1000)
SYSTEM_MENU_PV1000,
# endif
# if defined(ENABLE_VIC20)
SYSTEM_MENU_VIC20,
# endif
# if defined(ENABLE_LEAP)
SYSTEM_MENU_LEAP,
# endif
# if defined(ENABLE_RCA)
SYSTEM_MENU_RCA,
# endif
# if defined(ENABLE_TI99)
SYSTEM_MENU_TI99,
# endif
# if defined(ENABLE_PYUUTA)
SYSTEM_MENU_PYUUTA,
# endif
# if defined(ENABLE_TRS80)
SYSTEM_MENU_TRS80,
# endif
# if defined(ENABLE_VSMILE)
SYSTEM_MENU_VSMILE,
# endif
# if defined(ENABLE_FLASH) # if defined(ENABLE_FLASH)
SYSTEM_MENU_FLASH, SYSTEM_MENU_FLASH,
# endif # endif
@ -391,4 +463,4 @@ extern long configGetLong(const __FlashStringHelper* key, int onFail = 0);
#include "ClockedSerial.h" #include "ClockedSerial.h"
#endif /* OSCR_H_ */ #endif /* OSCR_H_ */

324
Cart_Reader/PV1000.ino Normal file
View File

@ -0,0 +1,324 @@
//******************************************
// CASIO PV-1000/PV-2000 MODULE
//******************************************
#ifdef ENABLE_PV1000
// Casio PV-1000/PV-2000
// Cartridge Pinout
// 36P 2.54mm pitch connector
//
// FRONT BACK
// SIDE SIDE
// +---------+
// VCC -| B01 A01 |- GND
// NC -| B02 A02 |- NC
// A14 -| B03 A03 |- A15
// A12 -| B04 A04 |- A13
// A10 -| B05 A05 |- A11
// A8 -| B06 A06 |- A9
// A6 -| B07 A07 |- A7
// A4 -| B08 A08 |- A5
// A2 -| B09 A09 |- A3
// A0 -| B10 A10 |- A1
// D6 -| B11 A11 |- D7
// D4 -| B12 A12 |- D5
// D2 -| B13 A13 |- D3
// D0 -| B14 A14 |- D1
// /CS1 -| B15 A15 |- /CS2
// /WR -| B16 A16 |- /RD
// CON -| B17 A17 |- /IORQ
// VCC -| B18 A18 |- GND
// +---------+
//
// BACK
// GND NC A15 A13 A11 A9 A7 A5 A3 A1 D7 D5 D3 D1 /CS2 /RD /IO GND
// +-------------------------------------------------------------------------+
// | A01 A02 A03 A04 A05 A06 A07 A08 A09 A10 A11 A12 A13 A14 A15 A16 A17 A18 |
// LEFT | | RIGHT
// | B01 B02 B03 B04 B05 B06 B07 B08 B09 B10 B11 B12 B13 B14 B15 B16 B17 B18 |
// +-------------------------------------------------------------------------+
// VCC NC A14 A12 A10 A8 A6 A4 A2 A0 D6 D4 D2 D0 /CS1 /WR CON VCC
// FRONT
// CONTROL PINS:
// /CS2(PH3) - SNES /CS
// /CS1(PH4) - SNES /IRQ
// /WR(PH5) - SNES /WR
// /RD(PH6) - SNES /RD
//******************************************
// VARIABLES
//******************************************
byte PV1000[] = {8,16};
byte pv1000lo = 0; // Lowest Entry
byte pv1000hi = 1; // Highest Entry
byte pv1000size;
byte newpv1000size;
// EEPROM MAPPING
// 08 ROM SIZE
//******************************************
// MENU
//******************************************
// Base Menu
static const char* const menuOptionsPV1000[] PROGMEM = { FSTRING_SELECT_CART, FSTRING_READ_ROM, FSTRING_SET_SIZE, FSTRING_RESET };
void pv1000Menu()
{
convertPgm(menuOptionsPV1000, 4);
uint8_t mainMenu = question_box(F("PV-1000 MENU"), menuOptions, 4, 0);
switch (mainMenu)
{
case 0:
// Select Cart
setCart_PV1000();
setup_PV1000();
break;
case 1:
// Read ROM
sd.chdir("/");
readROM_PV1000();
sd.chdir("/");
break;
case 2:
// Set Size
setROMSize_PV1000();
break;
case 3:
// reset
resetArduino();
break;
}
}
//******************************************
// SETUP
//******************************************
void setup_PV1000()
{
// Request 5V
setVoltage(VOLTS_SET_5V);
// Set Address Pins to Output
// PV-1000 uses A0-A15 [A16-A23 UNUSED]
//A0-A7
DDRF = 0xFF;
//A8-A15
DDRK = 0xFF;
//A16-A23
DDRL = 0xFF;
// Set Control Pins to Output
// ---(PH0) ---(PH1) /CS2(PH3) /CS1(PH4) /WR(PH5) /RD(PH6)
DDRH |= (1 << 0) | (1 << 1) | (1 << 3) | (1 << 4) | (1 << 5) | (1 << 6);
// Set TIME(PJ0) to Output (UNUSED)
DDRJ |= (1 << 0);
// Set Pins (D0-D7) to Input
DDRC = 0x00;
// Setting Control Pins to HIGH
// ---(PH0) ---(PH1) /CS2(PH3) /CS1(PH4) /WR(PH5) /RD(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_PV1000();
strcpy(romName, "PV1000");
mode = CORE_PV1000;
}
//******************************************
// READ FUNCTIONS
//******************************************
uint8_t readData_PV1000(uint16_t addr)
{
PORTF = addr & 0xFF; // A0-A7
PORTK = (addr >> 8) & 0xFF; // A8-A13
NOP;
NOP;
NOP;
NOP;
NOP;
// Set /RD to LOW
PORTH &= ~(1 << 6); // /RD LOW (ENABLE)
NOP;
NOP;
NOP;
uint8_t ret = PINC;
// Pull /RD to HIGH
PORTH |= (1 << 6); // /RD HIGH (DISABLE)
return ret;
}
void readSegment_PV1000(uint32_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_PV1000(addr + w);
sdBuffer[w] = temp;
}
myFile.write(sdBuffer, 512);
}
}
//******************************************
// READ ROM
//******************************************
void readROM_PV1000()
{
createFolderAndOpenFile("PV1000", "ROM", romName, "bin");
if (pv1000size == 0) { // 8K
PORTH &= ~(1 << 4); // /CS1(PH4) LOW
readSegment_PV1000(0x0000,0x2000); // 8K
PORTH |= (1 << 4); // /CS1(PH4) HIGH
}
else { // 16K
PORTH &= ~(1 << 3); // /CS2(PH3) LOW
readSegment_PV1000(0x0000,0x4000); // 16K
PORTH |= (1 << 3); // /CS2(PH3) HIGH
}
myFile.close();
printCRC(fileName, NULL, 0);
println_Msg(FS(FSTRING_EMPTY));
print_STR(press_button_STR, 1);
display_Update();
wait();
}
//******************************************
// ROM SIZE
//******************************************
#if (defined(ENABLE_OLED) || defined(ENABLE_LCD))
void printRomSize_PV1000(int index)
{
display_Clear();
print_Msg(FS(FSTRING_ROM_SIZE));
println_Msg(PV1000[index]);
}
#endif
void setROMSize_PV1000()
{
byte newpv1000size;
#if (defined(ENABLE_OLED) || defined(ENABLE_LCD))
display_Clear();
if (pv1000lo == pv1000hi)
newpv1000size = pv1000lo;
else {
newpv1000size = navigateMenu(pv1000lo, pv1000hi, &printRomSize_PV1000);
display.setCursor(0, 56); // Display selection at bottom
}
print_Msg(FS(FSTRING_ROM_SIZE));
print_Msg(PV1000[newpv1000size]);
println_Msg(F("KB"));
display_Update();
delay(1000);
#else
if (pv1000lo == pv1000hi)
newpv1000size = pv1000lo;
else {
setrom:
String sizeROM;
for (int i = 0; i < (pv1000hi - pv1000lo + 1); i++) {
Serial.print(F("Select ROM Size: "));
Serial.print(i);
Serial.print(F(" = "));
Serial.print(PV1000[i + pv1000lo]);
Serial.println(F("KB"));
}
Serial.print(F("Enter ROM Size: "));
while (Serial.available() == 0) {}
sizeROM = Serial.readStringUntil('\n');
Serial.println(sizeROM);
newpv1000size = sizeROM.toInt() + pv1000lo;
if (newpv1000size > pv1000hi) {
Serial.println(F("SIZE NOT SUPPORTED"));
Serial.println(FS(FSTRING_EMPTY));
goto setrom;
}
}
Serial.print(F("ROM Size = "));
Serial.print(PV1000[newpv1000size]);
Serial.println(F("KB"));
#endif
EEPROM_writeAnything(8, newpv1000size);
pv1000size = newpv1000size;
}
void checkStatus_PV1000()
{
EEPROM_readAnything(8, pv1000size);
if (pv1000size > pv1000hi) {
pv1000size = 0; // default 8K
EEPROM_writeAnything(8, pv1000size);
}
#if (defined(ENABLE_OLED) || defined(ENABLE_LCD))
display_Clear();
println_Msg(F("CASIO PV-1000"));
println_Msg(FS(FSTRING_CURRENT_SETTINGS));
println_Msg(FS(FSTRING_EMPTY));
print_Msg(FS(FSTRING_ROM_SIZE));
print_Msg(PV1000[pv1000size]);
println_Msg(F("KB"));
display_Update();
wait();
#else
Serial.print(FS(FSTRING_ROM_SIZE));
Serial.print(PV1000[pv1000size]);
Serial.println(F("KB"));
Serial.println(FS(FSTRING_EMPTY));
#endif
}
//******************************************
// CART SELECT CODE
//******************************************
void setCart_PV1000()
{
//go to root
sd.chdir();
byte gameSize;
// Select starting letter
//byte myLetter = starting_letter();
// Open database
if (myFile.open("pv1000cart.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

327
Cart_Reader/PYUUTA.ino Normal file
View File

@ -0,0 +1,327 @@
//******************************************
// TOMY PYUUTA MODULE
//******************************************
#ifdef ENABLE_PYUUTA
// Tomy Pyuuta
// Cartridge Pinout
// 36P 2.54mm pitch connector
//
// FRONT BACK
// SIDE SIDE
// +--------+
// GND -| 2 1 |- GND
// /RESET -| 4 3 |- D7
// J1-6 -| 6 5 |- D6
// A15/CRUOUT -| 8 7 |- D5
// A13 -| 10 9 |- D4
// A12 -| 12 11 |- D3
// A11 -| 14 13 |- D2
// A10 -| 16 15 |- D1
// A9 -| 18 17 |- D0
// A8 -| 20 19 |- VCC
// A7 -| 22 21 |- /CS1
// A3 -| 24 23 |- A14
// A6 -| 26 25 |- A2
// A5 -| 28 27 |- A1
// A4 -| 30 29 |- /DBIN
// /WE/CPUCLK -| 32 31 |- A0
// /INT4 /EC -| 34 33 |- SOUND
// CRUIN -| 36 35 |- /CS0
// +--------+
//
// BACK
// /CS0 SND A0 /DB A1 A2 A14 /CS1 VCC D0 D1 D2 D3 D4 D5 D6 D7 GND
// +----------------------------------------------------------------------------+
// | 35 33 31 29 27 25 23 21 19 17 15 13 11 9 7 5 3 1 |
// LEFT | | RIGHT
// | 36 34 32 30 28 26 24 22 20 18 16 14 12 10 8 6 4 2 |
// +----------------------------------------------------------------------------+
// CRIN /INT /WE A4 A5 A6 A3 A7 A8 A9 A10 A11 A12 A13 A15 J1-6 /RST GND
// FRONT
// CONTROL PINS:
// /RESET(PH0) - SNES RESET
// /CS0(PH3) - SNES /CS
// /DBIN(PH4) - SNES /IRQ
// /CS1(PH6) - SNES /RD
// NOTE: PYUUTA ADDRESS AND DATA BUS ARE BIG-ENDIAN
// LEAST SIGNIFICANT IS BIT 7 AND MOST SIGNIFICANT IS BIT 0
// PCB ADAPTER WIRED FOR DIFFERENCE
//******************************************
// VARIABLES
//******************************************
byte PYUUTA[] = {8,16,32};
byte pyuutalo = 0; // Lowest Entry
byte pyuutahi = 2; // Highest Entry
byte pyuutasize;
byte newpyuutasize;
// EEPROM MAPPING
// 08 ROM SIZE
//******************************************
// MENU
//******************************************
// Base Menu
static const char* const menuOptionsPYUUTA[] PROGMEM = { FSTRING_SELECT_CART, FSTRING_READ_ROM, FSTRING_SET_SIZE, FSTRING_RESET };
void pyuutaMenu()
{
convertPgm(menuOptionsPYUUTA, 4);
uint8_t mainMenu = question_box(F("TOMY PYUUTA MENU"), menuOptions, 4, 0);
switch (mainMenu)
{
case 0:
// Select Cart
setCart_PYUUTA();
setup_PYUUTA();
break;
case 1:
// Read ROM
sd.chdir("/");
readROM_PYUUTA();
sd.chdir("/");
break;
case 2:
// Set Size
setROMSize_PYUUTA();
break;
case 3:
// reset
resetArduino();
break;
}
}
//******************************************
// SETUP
//******************************************
void setup_PYUUTA()
{
// Request 5V
setVoltage(VOLTS_SET_5V);
// Set Address Pins to Output
// PYUUTA uses A0-A15 [A16-A23 UNUSED]
//A0-A7
DDRF = 0xFF;
//A8-A15
DDRK = 0xFF;
//A16-A23
DDRL = 0xFF;
// Set Control Pins to Output
// /RST(PH0) ---(PH1) /CS0(PH3) /DBIN(PH4) ---(PH5) /CS1(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
// /RST(PH0) ---(PH1) /CS0(PH3) /DBIN(PH4) ---(PH5) /CS1(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_PYUUTA();
strcpy(romName, "PYUUTA");
mode = CORE_PYUUTA;
}
//******************************************
// READ FUNCTIONS
//******************************************
uint8_t readData_PYUUTA(uint16_t addr)
{
PORTF = addr & 0xFF; // A0-A7
PORTK = (addr >> 8) & 0xFF; // A8-A15
NOP;
NOP;
NOP;
NOP;
NOP;
uint8_t ret = PINC;
return ret;
}
void readSegment_PYUUTA(uint32_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_PYUUTA(addr + w);
sdBuffer[w] = temp;
}
myFile.write(sdBuffer, 512);
}
}
//******************************************
// READ ROM
//******************************************
void readROM_PYUUTA()
{
createFolderAndOpenFile("PYUUTA", "ROM", romName, "bin");
//8K $8000-$9FFF
//16K $8000-$BFFF
//32K $4000-$BFFF
PORTH &= ~(1 << 4); // /DBIN(PH4) LOW
if (pyuutasize > 1) { // 32K [3D CARTS]
PORTH &= ~(1 << 6); // /CS1(PH6) LOW
readSegment_PYUUTA(0x4000,0x8000); // +16K = 32K
PORTH |= (1 << 6); // /CS1(PH6) HIGH
}
PORTH &= ~(1 << 3); // /CS0(PH3) LOW
readSegment_PYUUTA(0x8000,0xA000); // 8K
PORTH |= (1 << 3); // /CS0(PH3) HIGH
if (pyuutasize > 0) { // 16K
PORTH &= ~(1 << 3); // /CS0(PH3) LOW
readSegment_PYUUTA(0xA000,0xC000); // +8K = 16K
PORTH |= (1 << 3); // /CS0(PH3) HIGH
}
PORTH |= (1 << 4); // /DBIN(PH4) HIGH
myFile.close();
printCRC(fileName, NULL, 0);
println_Msg(FS(FSTRING_EMPTY));
print_STR(press_button_STR, 1);
display_Update();
wait();
}
//******************************************
// ROM SIZE
//******************************************
#if (defined(ENABLE_OLED) || defined(ENABLE_LCD))
void printRomSize_PYUUTA(int index)
{
display_Clear();
print_Msg(FS(FSTRING_ROM_SIZE));
println_Msg(PYUUTA[index]);
}
#endif
void setROMSize_PYUUTA()
{
byte newpyuutasize;
#if (defined(ENABLE_OLED) || defined(ENABLE_LCD))
display_Clear();
if (pyuutalo == pyuutahi)
newpyuutasize = pyuutalo;
else {
newpyuutasize = navigateMenu(pyuutalo, pyuutahi, &printRomSize_PYUUTA);
display.setCursor(0, 56); // Display selection at bottom
}
print_Msg(FS(FSTRING_ROM_SIZE));
print_Msg(PYUUTA[newpyuutasize]);
println_Msg(F("KB"));
display_Update();
delay(1000);
#else
if (pyuutalo == pyuutahi)
newpyuutasize = pyuutalo;
else {
setrom:
String sizeROM;
for (int i = 0; i < (pyuutahi - pyuutalo + 1); i++) {
Serial.print(F("Select ROM Size: "));
Serial.print(i);
Serial.print(F(" = "));
Serial.print(PYUUTA[i + pyuutalo]);
Serial.println(F("KB"));
}
Serial.print(F("Enter ROM Size: "));
while (Serial.available() == 0) {}
sizeROM = Serial.readStringUntil('\n');
Serial.println(sizeROM);
newpyuutasize = sizeROM.toInt() + pyuutalo;
if (newpyuutasize > pyuutahi) {
Serial.println(F("SIZE NOT SUPPORTED"));
Serial.println(FS(FSTRING_EMPTY));
goto setrom;
}
}
Serial.print(F("ROM Size = "));
Serial.print(PYUUTA[newpyuutasize]);
Serial.println(F("KB"));
#endif
EEPROM_writeAnything(8, newpyuutasize);
pyuutasize = newpyuutasize;
}
void checkStatus_PYUUTA()
{
EEPROM_readAnything(8, pyuutasize);
if (pyuutasize > pyuutahi) {
pyuutasize = 0; // default 8K
EEPROM_writeAnything(8, pyuutasize);
}
#if (defined(ENABLE_OLED) || defined(ENABLE_LCD))
display_Clear();
println_Msg(F("TOMY PYUUTA"));
println_Msg(FS(FSTRING_CURRENT_SETTINGS));
println_Msg(FS(FSTRING_EMPTY));
print_Msg(FS(FSTRING_ROM_SIZE));
print_Msg(PYUUTA[pyuutasize]);
println_Msg(F("KB"));
display_Update();
wait();
#else
Serial.print(FS(FSTRING_ROM_SIZE));
Serial.print(PYUUTA[pyuutasize]);
Serial.println(F("KB"));
Serial.println(FS(FSTRING_EMPTY));
#endif
}
//******************************************
// CART SELECT CODE
//******************************************
void setCart_PYUUTA()
{
//go to root
sd.chdir();
byte gameSize;
// Select starting letter
//byte myLetter = starting_letter();
// Open database
if (myFile.open("pyuutacart.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

327
Cart_Reader/RCA.ino Normal file
View File

@ -0,0 +1,327 @@
//******************************************
// RCA STUDIO II MODULE
//******************************************
#ifdef ENABLE_RCA
// RCA Studio II
// Cartridge Pinout
// 22P 3.96mm pitch connector
//
// FRONT
// +-------+
// D7 -| 1 |
// D6 -| 2 |
// D5 -| 3 |
// D4 -| 4 |
// D3 -| 5 |
// ROM_DISABLE -| 6 |
// GND -| 7 |
// D2 -| 8 |
// D1 -| 9 |
// D0 -| 10 |
// A0 -| 11 |
// A1 -| 12 |
// A2 -| 13 |
// A3 -| 14 |
// VCC(+5V) -| 15 |
// A4 -| 16 |
// A5 -| 17 |
// A6 -| 18 |
// TPA -| 19 |
// A7 -| 20 |
// /MRD -| 21 |
// ROMCS -| 22 |
// +-------+
//
// BACK SIDE
// +-------------------------------------------------------------------------------------------+
// LEFT | | RIGHT
// | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
// +-------------------------------------------------------------------------------------------+
// D7 D6 D5 D4 D3 DIS GND D2 D1 D0 A0 A1 A2 A3 +5V A4 A5 A6 TPA A7 /MRD CS
//
// FRONT SIDE
// CONTROL PINS:
// /MRD(PH3) - SNES /CS
// TPA(PH6) - SNES /RD
//******************************************
// VARIABLES
//******************************************
byte RCA[] = {1,2};
byte rcalo = 0; // Lowest Entry
byte rcahi = 1; // Highest Entry
byte rcasize;
byte newrcasize;
// EEPROM MAPPING
// 08 ROM SIZE
//******************************************
// MENU
//******************************************
// Base Menu
static const char* const menuOptionsRCA[] PROGMEM = { FSTRING_SELECT_CART, FSTRING_READ_ROM, FSTRING_SET_SIZE, FSTRING_RESET };
void rcaMenu()
{
convertPgm(menuOptionsRCA, 4);
uint8_t mainMenu = question_box(F("RCA STUDIO II MENU"), menuOptions, 4, 0);
switch (mainMenu)
{
case 0:
// Select Cart
setCart_RCA();
setup_RCA();
break;
case 1:
// Read ROM
sd.chdir("/");
readROM_RCA();
sd.chdir("/");
break;
case 2:
// Set Size
setROMSize_RCA();
break;
case 3:
// reset
resetArduino();
break;
}
}
//******************************************
// SETUP
//******************************************
void setup_RCA()
{
// Request 5V
setVoltage(VOLTS_SET_5V);
// Set Address Pins to Output
// RCA Studio II uses A0-A7 [A8-A23 UNUSED]
//A0-A7
DDRF = 0xFF;
//A8-A15
DDRK = 0xFF;
//A16-A23
DDRL = 0xFF;
// Set Control Pins to Output
// ---(PH0) ---(PH1) /MRD(PH3) ---(PH4) ---(PH5) TPA(PH6)
DDRH |= (1 << 0) | (1 << 1) | (1 << 3) | (1 << 4) | (1 << 5) | (1 << 6);
// Set TIME(PJ0) to Output (UNUSED)
DDRJ |= (1 << 0);
// Set Pins (D0-D7) to Input
DDRC = 0x00;
// Setting Control Pins to HIGH
// ---(PH0) ---(PH1) /MRD(PH3) ---(PH4) ---(PH5) TPA(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;
PORTK = 0xFF; // A8-A15
PORTL = 0xFF; // A16-A23
PORTJ |= (1 << 0); // TIME(PJ0)
checkStatus_RCA();
strcpy(romName, "RCA");
mode = CORE_RCA;
}
//******************************************
// READ FUNCTIONS
//******************************************
uint8_t readData_RCA(uint16_t addr)
{
// Setup TPA + /MRD
PORTH &= ~(1 << 6); // TPA LOW
delayMicroseconds(4);
PORTH |= (1 << 3); // /MRD HIGH;
delayMicroseconds(4);
// Set HIGH Address
PORTF = (addr >> 8) & 0xFF;
delayMicroseconds(4);
// Latch HIGH Address
PORTH |= (1 << 6); // TPA HIGH
delayMicroseconds(4);
PORTH &= ~(1 << 3); // /MRD LOW
delayMicroseconds(4);
// Switch TPA LOW
PORTH &= ~(1 << 6); // TPA LOW
delayMicroseconds(4);
// Set LOW Address
PORTF = addr & 0xFF;
delayMicroseconds(4);
uint8_t ret = PINC;
// Reset /MRD
PORTH |= (1 << 3); // /MRD HIGH;
return ret;
}
void readSegment_RCA(uint16_t startaddr, uint16_t endaddr)
{
for (uint16_t addr = startaddr; addr < endaddr; addr += 512) {
for (int w = 0; w < 512; w++) {
uint8_t temp = readData_RCA(addr + w);
sdBuffer[w] = temp;
}
myFile.write(sdBuffer, 512);
}
}
//******************************************
// READ ROM
//******************************************
void readROM_RCA()
{
createFolderAndOpenFile("RCA", "ROM", romName, "bin");
readSegment_RCA(0x0400,0x0600); // 512B
if (rcasize > 0)
readSegment_RCA(0x0600,0x0800); // +512B = 1K
myFile.close();
printCRC(fileName, NULL, 0);
println_Msg(FS(FSTRING_EMPTY));
print_STR(press_button_STR, 1);
display_Update();
wait();
}
//******************************************
// ROM SIZE
//******************************************
#if (defined(ENABLE_OLED) || defined(ENABLE_LCD))
void printRomSize_RCA(int index)
{
display_Clear();
print_Msg(FS(FSTRING_ROM_SIZE));
println_Msg(RCA[index]);
}
#endif
void setROMSize_RCA()
{
byte newrcasize;
#if (defined(ENABLE_OLED) || defined(ENABLE_LCD))
display_Clear();
if (rcalo == rcahi)
newrcasize = rcalo;
else {
newrcasize = navigateMenu(rcalo, rcahi, &printRomSize_RCA);
display.setCursor(0, 56); // Display selection at bottom
}
print_Msg(FS(FSTRING_ROM_SIZE));
print_Msg(RCA[newrcasize]);
println_Msg(F("KB"));
display_Update();
delay(1000);
#else
if (rcalo == rcahi)
newrcasize = rcalo;
else {
setrom:
String sizeROM;
for (int i = 0; i < (rcahi - rcalo + 1); i++) {
Serial.print(F("Select ROM Size: "));
Serial.print(i);
Serial.print(F(" = "));
Serial.print(RCA[i + rcalo]);
Serial.println(F("KB"));
}
Serial.print(F("Enter ROM Size: "));
while (Serial.available() == 0) {}
sizeROM = Serial.readStringUntil('\n');
Serial.println(sizeROM);
newrcasize = sizeROM.toInt() + rcalo;
if (newrcasize > rcahi) {
Serial.println(F("SIZE NOT SUPPORTED"));
Serial.println(FS(FSTRING_EMPTY));
goto setrom;
}
}
Serial.print(F("ROM Size = "));
Serial.print(RCA[newrcasize]);
Serial.println(F("KB"));
#endif
EEPROM_writeAnything(8, newrcasize);
rcasize = newrcasize;
}
void checkStatus_RCA()
{
EEPROM_readAnything(8, rcasize);
if (rcasize > rcahi) {
rcasize = 1; // default 1024B
EEPROM_writeAnything(8, rcasize);
}
#if (defined(ENABLE_OLED) || defined(ENABLE_LCD))
display_Clear();
println_Msg(F("RCA STUDIO II"));
println_Msg(FS(FSTRING_CURRENT_SETTINGS));
println_Msg(FS(FSTRING_EMPTY));
print_Msg(FS(FSTRING_ROM_SIZE));
print_Msg(RCA[rcasize] * 512);
println_Msg(F("B"));
display_Update();
wait();
#else
Serial.print(FS(FSTRING_ROM_SIZE));
Serial.print(RCA[rcasize] * 512);
Serial.println(F("B"));
Serial.println(FS(FSTRING_EMPTY));
#endif
}
//******************************************
// CART SELECT CODE
//******************************************
void setCart_RCA()
{
//go to root
sd.chdir();
byte gameSize;
// Select starting letter
//byte myLetter = starting_letter();
// Open database
if (myFile.open("rcacart.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

1071
Cart_Reader/TI99.ino Normal file

File diff suppressed because it is too large Load Diff

398
Cart_Reader/TRS80.ino Normal file
View File

@ -0,0 +1,398 @@
//******************************************
// TRS-80 COLOR COMPUTER MODULE
//******************************************
#ifdef ENABLE_TRS80
// TRS-80
// Color Computer
// Cartridge Pinout
// 40P 2.54mm pitch connector
//
// TOP BOTTOM
// SIDE SIDE
// +-------+
// NC -| 1 2 |- NC
// /HALT -| 3 4 |- /NMI
// /RESET -| 5 6 |- E
// Q -| 7 8 |- /CART
// +5V -| 9 10 |- D0
// D1 -| 11 12 |- D2
// D3 -| 13 14 |- D4
// D5 -| 15 16 |- D6
// D7 -| 17 18 |- R/W
// A0 -| 19 20 |- A1
// A2 -| 21 22 |- A3
// A4 -| 23 24 |- A5
// A6 -| 25 26 |- A7
// A8 -| 27 28 |- A9
// A10 -| 29 30 |- A11
// A12 -| 31 32 |- /CTS
// GND -| 33 34 |- GND
// SND -| 35 36 |- /SCS
// A13 -| 37 38 |- A14
// A15 -| 39 40 |- /SLENB
// +-------+
//
// TOP
// A15 A13 SND GND A12 A10 A8 A6 A4 A2 A0 D7 D5 D3 D1 +5V Q /RST /HLT NC
// +-----------------------------------------------------------------------------------------------+
// | 39 37 35 33 31 29 27 25 23 21 19 17 15 13 11 9 7 5 3 1 |
// LEFT | | RIGHT
// | 40 38 36 34 32 30 28 26 24 22 20 18 16 14 12 10 8 6 4 2 |
// +-----------------------------------------------------------------------------------------------+
// /SLB A14 /SCS GND /CTS A11 A9 A7 A5 A3 A1 RW D6 D4 D2 D0 /CRT E /NMI NC
// BOTTOM
// CONTROL PINS:
// /RESET(PH0) - SNES RESET
// E(PH1) - SNES CPUCLK
// /CTS(PH3) - SNES /CS
// /SCS(PH4) - SNES /IRQ
// R/W(PH5) - SNES /WR
// NOTE: CARTS CONNECT /CART TO Q
//******************************************
// VARIABLES
//******************************************
byte TRS80[] = {2,4,8,10,16,32,64,128};
byte trs80lo = 0; // Lowest Entry
byte trs80hi = 7; // Highest Entry
byte trs80size;
byte newtrs80size;
// EEPROM MAPPING
// 08 ROM SIZE
//******************************************
// MENU
//******************************************
// Base Menu
static const char* const menuOptionsTRS80[] PROGMEM = { FSTRING_SELECT_CART, FSTRING_READ_ROM, FSTRING_SET_SIZE, FSTRING_RESET };
void trs80Menu()
{
convertPgm(menuOptionsTRS80, 4);
uint8_t mainMenu = question_box(F("TRS-80 MENU"), menuOptions, 4, 0);
switch (mainMenu)
{
case 0:
// Select Cart
setCart_TRS80();
setup_TRS80();
break;
case 1:
// Read ROM
sd.chdir("/");
readROM_TRS80();
sd.chdir("/");
break;
case 2:
// Set Size
setROMSize_TRS80();
break;
case 3:
// reset
resetArduino();
break;
}
}
//******************************************
// SETUP
//******************************************
void setup_TRS80()
{
// Request 5V
setVoltage(VOLTS_SET_5V);
// Set Address Pins to Output
// TRS-80 uses A0-A15 [A16-A23 UNUSED]
//A0-A7
DDRF = 0xFF;
//A8-A15
DDRK = 0xFF;
//A16-A23
DDRL = 0xFF;
// Set Control Pins to Output
// /RST(PH0) E(PH1) /CTS(PH3) /SCS(PH4) R/W(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
// /RST(PH0) E(PH1) /CTS(PH3) /SCS(PH4) R/W(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_TRS80();
strcpy(romName, "TRS80");
mode = CORE_TRS80;
}
//******************************************
// READ FUNCTIONS
//******************************************
uint8_t readData_TRS80(uint16_t addr)
{
PORTF = addr & 0xFF; // A0-A7
PORTK = (addr >> 8) & 0xFF; // A8-A15
// Set /CTS to LOW
PORTH &= ~(1 << 3); // /CTS LOW
NOP;
NOP;
NOP;
NOP;
NOP;
uint8_t ret = PINC;
// Pull /CTS to HIGH
PORTH |= (1 << 3); // /CTS HIGH
return ret;
}
void readSegment_TRS80(uint32_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_TRS80(addr + w);
sdBuffer[w] = temp;
}
myFile.write(sdBuffer, 512);
}
}
//******************************************
// BANKSWITCH
//******************************************
// Bankswitch is a combination of IC1 74LS175 (Quad Latch) and IC3 74LS10 (NAND Gate)
// IC1 latches D0-D3 using /RESET and control (CP) from IC3
// IC3 controls latch into IC1 using CP output based on R/W, E and /SCS
// IC3 CP LOW only when R/W LOW, /SCS LOW, and E HIGH
void bankSwitch_TRS80(uint16_t addr, uint8_t data)
{
PORTF = addr & 0xFF; // A0-A7
PORTK = (addr >> 8) & 0xFF; // A8-A15
NOP;
NOP;
NOP;
NOP;
NOP;
DDRC = 0xFF; // Set to Output
PORTC = data;
NOP;
NOP;
NOP;
NOP;
NOP;
// SET CP (LATCH INPUT INTO 74LS175) TO LOW
PORTH &= ~(1 << 4); // /SCS(PH4) LOW
PORTH &= ~(1 << 5); // R/W(PH5) LOW = WRITE
// Pulse E to Latch Data
PORTH &= ~(1 << 1); // E(PH1) LOW
NOP;
PORTH |= (1 << 1); // E(PH1) HIGH
NOP;
// SET CP TO HIGH
PORTH |= (1 << 4); // /SCS(PH5) HIGH
PORTH |= (1 << 5); // R/W(PH5) HIGH = READ
DDRC = 0x00; // Reset to Input
}
//******************************************
// READ ROM
//******************************************
void readROM_TRS80()
{
createFolderAndOpenFile("TRS80", "ROM", romName, "ccc");
// Set /RESET to LOW
PORTH &= ~(1 << 0); // /RESET LOW
delay(100);
// Set /RESET to HIGH
PORTH |= (1 << 0); // /RESET HIGH
// Set R/W to READ
PORTH |= (1 << 5); // R/W HIGH
if (trs80size > 5) { // Bankswitch Carts - Predator 64K/Robocop 128K
// Predator 64K = (2^6) / 16 = 4
// Robocop 128K = (2^7) / 16 = 8
int banks = (int_pow(2, trs80size)) / 16;
for (int x = 0; x < banks; x++) {
bankSwitch_TRS80(0xFF40, x); // Bankswitch
readSegment_TRS80(0xC000, 0x10000); // 16K * 8 = 128K
}
}
else { // Normal Carts 2K/4K/8K/10K/16K/32K
readSegment_TRS80(0xC000,0xC800); // 2K
if (trs80size > 0) {
readSegment_TRS80(0xC800,0xD000); // +2K = 4K
if (trs80size > 1) {
readSegment_TRS80(0xD000,0xE000); // +4K = 8K
if (trs80size > 2) {
readSegment_TRS80(0xE000,0xE800); // +2K = 10K
if (trs80size > 3) {
readSegment_TRS80(0xE800,0x10000); // +6K = 16K
if (trs80size == 5) { // 32K
// Second Chip Select - Switch to Upper 16K (Mind-Roll)
PORTH &= ~(1 << 4); // /SCS LOW
NOP; NOP; NOP; NOP; NOP;
PORTH |= (1 << 4); // /SCS HIGH
readSegment_TRS80(0x8000,0xC000); // +16K = 32K
}
}
}
}
}
}
myFile.close();
printCRC(fileName, NULL, 0);
println_Msg(FS(FSTRING_EMPTY));
print_STR(press_button_STR, 1);
display_Update();
wait();
}
//******************************************
// ROM SIZE
//******************************************
#if (defined(ENABLE_OLED) || defined(ENABLE_LCD))
void printRomSize_TRS80(int index)
{
display_Clear();
print_Msg(FS(FSTRING_ROM_SIZE));
println_Msg(TRS80[index]);
}
#endif
void setROMSize_TRS80()
{
byte newtrs80size;
#if (defined(ENABLE_OLED) || defined(ENABLE_LCD))
display_Clear();
if (trs80lo == trs80hi)
newtrs80size = trs80lo;
else {
newtrs80size = navigateMenu(trs80lo, trs80hi, &printRomSize_TRS80);
display.setCursor(0, 56); // Display selection at bottom
}
print_Msg(FS(FSTRING_ROM_SIZE));
print_Msg(TRS80[newtrs80size]);
println_Msg(F("KB"));
display_Update();
delay(1000);
#else
if (trs80lo == trs80hi)
newtrs80size = trs80lo;
else {
setrom:
String sizeROM;
for (int i = 0; i < (trs80hi - trs80lo + 1); i++) {
Serial.print(F("Select ROM Size: "));
Serial.print(i);
Serial.print(F(" = "));
Serial.print(TRS80[i + trs80lo]);
Serial.println(F("KB"));
}
Serial.print(F("Enter ROM Size: "));
while (Serial.available() == 0) {}
sizeROM = Serial.readStringUntil('\n');
Serial.println(sizeROM);
newtrs80size = sizeROM.toInt() + trs80lo;
if (newtrs80size > trs80hi) {
Serial.println(F("SIZE NOT SUPPORTED"));
Serial.println(FS(FSTRING_EMPTY));
goto setrom;
}
}
Serial.print(F("ROM Size = "));
Serial.print(TRS80[newtrs80size]);
Serial.println(F("KB"));
#endif
EEPROM_writeAnything(8, newtrs80size);
trs80size = newtrs80size;
}
void checkStatus_TRS80()
{
EEPROM_readAnything(8, trs80size);
if (trs80size > trs80hi) {
trs80size = 5; // default 32K
EEPROM_writeAnything(8, trs80size);
}
#if (defined(ENABLE_OLED) || defined(ENABLE_LCD))
display_Clear();
println_Msg(F("TRS-80 COLOR COMPUTER"));
println_Msg(FS(FSTRING_CURRENT_SETTINGS));
println_Msg(FS(FSTRING_EMPTY));
print_Msg(FS(FSTRING_ROM_SIZE));
print_Msg(TRS80[trs80size]);
println_Msg(F("KB"));
display_Update();
wait();
#else
Serial.print(FS(FSTRING_ROM_SIZE));
Serial.print(TRS80[trs80size];
Serial.println(F("KB"));
Serial.println(FS(FSTRING_EMPTY));
#endif
}
//******************************************
// CART SELECT CODE
//******************************************
void setCart_TRS80()
{
//go to root
sd.chdir();
byte gameSize;
// Select starting letter
//byte myLetter = starting_letter();
// Open database
if (myFile.open("trs80cart.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

576
Cart_Reader/VIC20.ino Normal file
View File

@ -0,0 +1,576 @@
//******************************************
// COMMODORE VIC-20 MODULE
//******************************************
#ifdef ENABLE_VIC20
// Commodore VIC-20
// Cartridge Pinout
// 44P 3.96mm pitch connector
//
// FRONT BACK
// SIDE SIDE
// +-------+
// GND -| 1 A |- GND
// D0 -| 2 B |- A0
// D1 -| 3 C |- A1
// D2 -| 4 D |- A2
// D3 -| 5 E |- A3
// D4 -| 6 F |- A4
// D5 -| 7 H |- A5
// D6 -| 8 J |- A6
// D7 -| 9 K |- A7
// /BLK1 -| 10 L |- A8
// /BLK2 -| 11 M |- A9
// /BLK3 -| 12 N |- A10
// /BLK5 -| 13 P |- A11
// /RAM1 -| 14 R |- A12
// /RAM2 -| 15 S |- A13
// /RAM3 -| 16 T |- IO2
// VR/W -| 17 U |- IO3
// CR/W -| 18 V |- PHI2
// IRQ -| 19 W |- /NMI
// NC -| 20 X |- /RESET
// +5V -| 21 Y |- NC
// GND -| 22 Z |- GND
// +-------+
//
// BACK
// GND NC /RST /NMI PH2 I3 I2 A13 A12 A11 A10 A9 A8 A7 A6 A5 A4 A3 A2 A1 A0 GND
// +-------------------------------------------------------------------------------+
// | Z Y X W V U T S R P N M L K J H F E D C B A |
// LEFT | | RIGHT
// | 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 |
// +-------------------------------------------------------------------------------+
// GND +5V NC IRQ CRW VRW /R3 /R2 /R1 /B5 /B3 /B2 /B1 D7 D6 D5 D4 D3 D2 D1 D0 GND
// FRONT
// CONTROL PINS:
// /BLK1(PH3) - SNES /CS - [$2000-$3FFF]
// /BLK2(PH4) - SNES /IRQ - [$4000-$5FFF]
// /BLK3(PH5) - SNES /WR - [$6000-$7FFF]
// /BLK5(PH6) - SNES /RD - [$A000-$BFFF]
//******************************************
// VARIABLES
//******************************************
byte VIC20MAP[] = {
0x20, // 0x2000
0x24, // 0x2000/0x4000
0x2A, // 0x2000/0xA000
0x46, // 0x4000/0x6000 - Adventure Games
0x60, // 0x6000
0x6A, // 0x6000/0xA000 - Standard 16K
0x70, // 0x7000
0xA0, // 0xA000 - Standard 8K
0xB0 // 0xB000
};
byte vic20mapcount = 9;
byte vic20mapselect;
byte vic20maplo = 0; // Lowest Entry
byte vic20maphi = 8; // Highest Entry
byte vic20map = 0;
byte newvic20map;
byte VIC20SIZE[] = {
0x20, // 2K/0K 0x800
0x40, // 4K/0K 0x1000
0x80, // 8K/0K 0x2000
0x44, // 4K/4K 0x1000/0x1000
0x48, // 4K/8K 0x1000/0x2000
0x84, // 8K/4K 0x2000/0x1000
0x88 // 8K/8K 0x2000/0x2000
};
byte vic20lo = 0; // Lowest Entry
byte vic20hi = 6; // Highest Entry
byte vic20size;
byte newvic20size;
//byte VIC20[] = {2,4,8};
//byte vic20lo = 0; // Lowest Entry
//byte vic20hi = 2; // Highest Entry
//byte vic20size;
//byte newvic20size;
// EEPROM MAPPING
// 07 MAPPER
// 08 ROM SIZE
//******************************************
// MENU
//******************************************
// Base Menu
static const char* const menuOptionsVIC20[] PROGMEM = { FSTRING_SELECT_CART, FSTRING_READ_ROM, FSTRING_SET_SIZE, FSTRING_RESET };
void vic20Menu()
{
convertPgm(menuOptionsVIC20, 4);
uint8_t mainMenu = question_box(F("VIC-20 MENU"), menuOptions, 4, 0);
switch (mainMenu)
{
case 0:
// Select Cart
setCart_VIC20();
setup_VIC20();
break;
case 1:
// Read ROM
sd.chdir("/");
CreateROMFolder_VIC20();
readROM_VIC20();
FinishROMFolder_VIC20();
sd.chdir("/");
break;
case 2:
// Set ROM Map + Size
setROMMap_VIC20();
setROMSize_VIC20();
break;
case 3:
// reset
resetArduino();
break;
}
}
//******************************************
// SETUP
//******************************************
void setup_VIC20()
{
// Request 5V
setVoltage(VOLTS_SET_5V);
// Set Address Pins to Output
// VIC-20 uses A0-A13 [A14-A23 UNUSED]
//A0-A7
DDRF = 0xFF;
//A8-A15
DDRK = 0xFF;
//A16-A23
DDRL = 0xFF;
// Set Control Pins to Output
// /RST(PH0) ---(PH1) /BLK1(PH3) /BLK2(PH4) /BLK3(PH5) /BLK5(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
// /RST(PH0) ---(PH1) /BLK1(PH3) /BLK2(PH4) /BLK3(PH5) /BLK5(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_VIC20();
strcpy(romName, "VIC20");
mode = CORE_VIC20;
}
//******************************************
// READ FUNCTIONS
//******************************************
uint8_t readData_VIC20(uint16_t addr)
{
PORTF = addr & 0xFF; // A0-A7
PORTK = (addr >> 8) & 0xFF; // A8-A13
NOP;
NOP;
NOP;
NOP;
NOP;
uint8_t ret = PINC;
return ret;
}
void readSegment_VIC20(uint32_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_VIC20(addr + w);
sdBuffer[w] = temp;
}
myFile.write(sdBuffer, 512);
}
}
//******************************************
// ROM FOLDER
//******************************************
void CreateROMFolder_VIC20()
{
sd.chdir();
EEPROM_readAnything(0, foldern);
sprintf(folder, "VIC20/ROM/%d", foldern);
sd.mkdir(folder, true);
sd.chdir(folder);
}
void FinishROMFolder_VIC20()
{
foldern += 1;
EEPROM_writeAnything(0, foldern); // FOLDER #
sd.chdir();
}
//******************************************
// READ ROM
//******************************************
void readROM_VIC20()
{
display_Clear();
print_Msg(F("Saving to "));
print_Msg(folder);
println_Msg(F("/..."));
display_Update();
byte rommap = 0;
byte romsize = 0;
// Split into Individual ROM Files
for (int x = 0; x < 2; x++) { // ROM0/ROM1
if (x == 1) {
if ((VIC20MAP[vic20map] & 0x0F) == 0)
break;
rommap = ((VIC20MAP[vic20map] & 0x0F) << 4);
romsize = VIC20SIZE[vic20size] & 0x0F;
}
else {
rommap = VIC20MAP[vic20map] & 0xF0;
romsize = ((VIC20SIZE[vic20size] & 0xF0) >> 4);
}
snprintf(fileName, sizeof(fileName), "%s.%x", romName, rommap);
// open file on sdcard
if (!myFile.open(fileName, O_RDWR | O_CREAT))
print_FatalError(F("Can't create file on SD"));
if (rommap == 0x20) { // BLK1
PORTH &= ~(1 << 3); // BLK1(PH3) LOW
readSegment_VIC20(0x2000,0x3000); // 4K
if (romsize == 8)
readSegment_VIC20(0x3000,0x4000); // +4K = 8K
PORTH |= (1 << 3); // BLK1(PH3) HIGH
}
else if (rommap == 0x40) { // BLK2
PORTH &= ~(1 << 4); // BLK2(PH4) LOW
readSegment_VIC20(0x4000,0x5000); // 4K
if (romsize == 8)
readSegment_VIC20(0x5000,0x6000); // +4K = 8K
PORTH |= (1 << 4); // BLK2(PH4) HIGH
}
else if (rommap == 0x60) { // BLK3
PORTH &= ~(1 << 5); // BLK3(PH5) LOW
readSegment_VIC20(0x6000,0x7000); // 4K
if (romsize == 8)
readSegment_VIC20(0x7000,0x8000); // +4K = 8K
PORTH |= (1 << 5); // BLK3(PH5) HIGH
}
else if (rommap == 0x70) { // BLK3 UPPER HALF
PORTH &= ~(1 << 5); // BLK3(PH5) LOW
readSegment_VIC20(0x7000,0x8000);
PORTH |= (1 << 5); // BLK3(PH5) HIGH
}
else if (rommap == 0xA0) { // BLK5
PORTH &= ~(1 << 6); // BLK5(PH6) LOW
readSegment_VIC20(0xA000,0xA800); // 2K
if (romsize > 2) {
readSegment_VIC20(0xA800,0xB000); // +2K = 4K
if (romsize > 4)
readSegment_VIC20(0xB000,0xC000); // +4K = 8K
}
PORTH |= (1 << 6); // BLK5(PH6) HIGH
}
else if (rommap == 0xB0) { // BLK5 UPPER HALF
PORTH &= ~(1 << 6); // BLK5(PH6) LOW
readSegment_VIC20(0xB000,0xB800); // 2K
if (romsize > 2)
readSegment_VIC20(0xB800,0xC000); // +2K = 4K
PORTH |= (1 << 6); // BLK5(PH6) HIGH
}
myFile.close();
print_Msg(F("ROM"));
print_Msg(x);
print_Msg(FS(FSTRING_SPACE));
printCRC(fileName, NULL, 0);
}
println_Msg(FS(FSTRING_EMPTY));
print_STR(press_button_STR, 1);
display_Update();
wait();
}
//******************************************
// ROM SIZE
//******************************************
void setROMSize_VIC20()
{
#if (defined(ENABLE_OLED) || defined(ENABLE_LCD))
display_Clear();
if (vic20lo == vic20hi)
newvic20size = vic20lo;
else {
int b = 0;
int i = vic20lo;
while (1) {
display_Clear();
print_Msg(F("ROM0 Size: "));
println_Msg((VIC20SIZE[i] & 0xF0) >> 4);
print_Msg(F("ROM1 Size: "));
println_Msg(VIC20SIZE[i] & 0x0F);
println_Msg(FS(FSTRING_EMPTY));
println_Msg(F("Press to Change"));
println_Msg(F("Hold to Select"));
display_Update();
b = checkButton();
if (b == 2) { // Previous (doubleclick)
if (i == vic20lo)
i = vic20hi;
else
i--;
}
if (b == 1) { // Next (press)
if (i == vic20hi)
i = vic20lo;
else
i++;
}
if (b == 3) { // Long Press - Execute (hold)
newvic20size = i;
break;
}
}
display.setCursor(0, 48); // Display selection at bottom
}
print_Msg(F("ROM0 SIZE "));
print_Msg((VIC20SIZE[newvic20size] & 0xF0) >> 4);
println_Msg(F("KB"));
print_Msg(F("ROM1 SIZE "));
print_Msg(VIC20SIZE[newvic20size] & 0x0F);
println_Msg(F("KB"));
display_Update();
delay(1000);
#else
if (vic20lo == vic20hi)
newvic20size = vic20lo;
else {
setrom:
String sizeROM;
for (int i = 0; i < (vic20hi - vic20lo + 1); i++) {
Serial.print(F("Select ROM Size: "));
Serial.print(i);
Serial.print(F(" = "));
Serial.print((VIC20SIZE[i + vic20lo] & 0xF0) >> 4);
Serial.print(F("KB/"));
Serial.print(VIC20SIZE[i + vic20lo] & 0x0F);
Serial.println(F("KB"));
}
Serial.print(F("Enter ROM Size: "));
while (Serial.available() == 0) {}
sizeROM = Serial.readStringUntil('\n');
Serial.println(sizeROM);
newvic20size = sizeROM.toInt() + vic20lo;
if (newvic20size > vic20hi) {
Serial.println(F("SIZE NOT SUPPORTED"));
Serial.println(FS(FSTRING_EMPTY));
goto setrom;
}
}
Serial.print(F("ROM0 Size = "));
Serial.print((VIC20SIZE[newvic20size] & 0xF0) >> 4);
Serial.println(F("KB"));
Serial.print(F("ROM1 Size = "));
Serial.print(VIC20SIZE[newvic20size] & 0x0F);
Serial.println(F("KB"));
#endif
EEPROM_writeAnything(8, newvic20size);
vic20size = newvic20size;
}
void checkStatus_VIC20()
{
EEPROM_readAnything(7, vic20map);
EEPROM_readAnything(8, vic20size);
if (vic20map > 8) {
vic20map = 7; // default 0xA000
EEPROM_writeAnything(7, vic20map);
}
if (vic20size > vic20hi) {
vic20size = 2; // default 8K
EEPROM_writeAnything(8, vic20size);
}
#if (defined(ENABLE_OLED) || defined(ENABLE_LCD))
display_Clear();
println_Msg(F("COMMODORE VIC-20"));
println_Msg(FS(FSTRING_CURRENT_SETTINGS));
println_Msg(FS(FSTRING_EMPTY));
print_Msg(F("ROM MAP: "));
println_Msg(VIC20MAP[vic20map], HEX);
print_Msg(F("ROM0 SIZE: "));
print_Msg((VIC20SIZE[vic20size] & 0xF0) >> 4);
println_Msg(F("KB"));
print_Msg(F("ROM1 SIZE: "));
print_Msg(VIC20SIZE[vic20size] & 0x0F);
println_Msg(F("KB"));
display_Update();
wait();
#else
Serial.print(F("CURRENT ROM MAP: "));
Serial.println(VIC20MAP[vic20map]);
Serial.print(F("CURRENT ROM0 SIZE: "));
Serial.print((VIC20SIZE[vic20size] & 0xF0) >> 4);
Serial.println(F("KB"));
Serial.print(F("CURRENT ROM1 SIZE: "));
Serial.print(VIC20SIZE[vic20size] & 0x0F);
Serial.println(F("KB"));
Serial.println(FS(FSTRING_EMPTY));
#endif
}
//******************************************
// SET ROM MAP
//******************************************
void setROMMap_VIC20()
{
#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 /* ENABLE_OLED | ENABLE_LCD */
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 /* ENABLE_OLED | ENABLE_LCD */
if (buttonVal1 == HIGH) { // Button Released
// Correct Overshoot
if (i == 0)
i = vic20mapcount - 1;
else
i--;
break;
}
display_Clear();
print_Msg(F("ROM Map: "));
vic20mapselect = VIC20MAP[i];
println_Msg(vic20mapselect, HEX);
if (i == (vic20mapcount - 1))
i = 0;
else
i++;
delay(250);
}
}
while (1) {
display_Clear();
print_Msg(F("ROM Map: "));
vic20mapselect = VIC20MAP[i];
println_Msg(vic20mapselect, HEX);
println_Msg(FS(FSTRING_EMPTY));
println_Msg(F("Press to Change"));
println_Msg(F("Hold to Select"));
display_Update();
b = checkButton();
if (b == 2) { // Previous ROM Map (doubleclick)
if (i == 0)
i = vic20mapcount - 1;
else
i--;
}
if (b == 1) { // Next ROM Map (press)
if (i == (vic20mapcount - 1))
i = 0;
else
i++;
}
if (b == 3) { // Long Press - Execute (hold)
newvic20map = i;
break;
}
}
display.setCursor(0, 56);
print_Msg(F("ROM MAP "));
print_Msg(vic20mapselect, HEX);
println_Msg(F(" SELECTED"));
display_Update();
delay(1000);
#else
String newmap;
Serial.println(F("ROM MAP:"));
Serial.println(F("0 = 0x2000"));
Serial.println(F("1 = 0x2000/0x4000"));
Serial.println(F("2 = 0x2000/0xA000"));
Serial.println(F("3 = 0x4000/0x6000"));
Serial.println(F("4 = 0x6000"));
Serial.println(F("5 = 0x6000/0xA000"));
Serial.println(F("6 = 0x7000"));
Serial.println(F("7 = 0xA000"));
Serial.println(F("8 = 0xB000"));
Serial.print(F("Enter Mapper [0-8]: "));
while (Serial.available() == 0) {}
newmap = Serial.readStringUntil('\n');
Serial.println(newmap);
newvic20map = newmap.toInt();
#endif
EEPROM_writeAnything(7, newvic20map);
vic20map = newvic20map;
}
//******************************************
// CART SELECT CODE
//******************************************
void setCart_VIC20()
{
//go to root
sd.chdir();
struct database_entry_mapper_size entry;
// Select starting letter
byte myLetter = starting_letter();
// Open database
if (myFile.open("vic20cart.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

365
Cart_Reader/VSMILE.ino Normal file
View File

@ -0,0 +1,365 @@
//******************************************
// VSMILE MODULE
//******************************************
#ifdef ENABLE_VSMILE
// V.Smile
// Cartridge pinout
// 48P 2.54mm pitch connector
//
// FRONT BACK
// SIDE SIDE
// +---------+
// VCC -| 25 1 |- WE
// RAMCS -| 26 2 |- OE
// VCC -| 27 3 |- GND
// CSB2 -| 28 4 |- D3
// D2 -| 29 5 |- D4
// D1 -| 30 6 |- D5
// D0 -| 31 7 |- D6
// D7 -| 32 8 |- D11
// D10 -| 33 9 |- D12
// D9 -| 34 10 |- D13
// D8 -| 35 11 |- D15
// D14 -| 36 12 |- A1
// A17 -| 37 13 |- A2
// A3 -| 38 14 |- A4
// |---------|
// A5 -| 39 15 |- A6
// A7 -| 40 16 |- A8
// A18 -| 41 17 |- A19
// A9 -| 42 18 |- A10
// A11 -| 43 19 |- A12
// A13 -| 44 20 |- A14
// A15 -| 45 21 |- A16
// A20 -| 46 22 |- A21
// A22 -| 47 23 |- GND
// CSB1 -| 48 24 |- VCC
// +---------+
//
// DATA D0-D7 - PORTC
// DATA D8-D15 - PORTA
// ADDR A1-A8 - PORTF
// ADDR A9-A16 - PORTK
// ADDR A17-A22 - PORTL
// CONTROL PINS - PORTH
//******************************************
// DEFINES
//******************************************
#define OE_HIGH PORTH |= (1<<3) // SNES /CART
#define OE_LOW PORTH &= ~(1<<3)
#define CSB1_HIGH PORTH |= (1<<6) // SNES /RD
#define CSB1_LOW PORTH &= ~(1<<6)
#define CSB2_HIGH PORTH |= (1<<4) // SNES /IRQ
#define CSB2_LOW PORTH &= ~(1<<4)
//******************************************
// VARIABLES
//******************************************
byte VSMILE[] = {4,6,8,16};
byte vsmilelo = 0; // Lowest Entry
byte vsmilehi = 3; // Highest Entry
byte vsmilesize;
byte newvsmilesize;
// EEPROM MAPPING
// 08 ROM SIZE
//******************************************
// MENU
//******************************************
// Base Menu
static const char* const menuOptionsVSMILE[] PROGMEM = { FSTRING_SELECT_CART, FSTRING_READ_ROM, FSTRING_SET_SIZE, FSTRING_RESET };
void vsmileMenu()
{
convertPgm(menuOptionsVSMILE, 4);
uint8_t mainMenu = question_box(F("V.SMILE MENU"), menuOptions, 4, 0);
// wait for user choice to come back from the question box menu
switch (mainMenu) {
// Select Cart
case 0:
setCart_VSMILE();
setup_VSMILE();
break;
// Read ROM
case 1:
sd.chdir("/");
readROM_VSMILE();
sd.chdir("/");
break;
// Set Size
case 2:
setROMSize_VSMILE();
break;
// Reset
case 3:
resetArduino();
break;
}
}
//******************************************
// SETUP
//******************************************
void setup_VSMILE()
{
// Request 3.3V
setVoltage(VOLTS_SET_3V3);
// Control Pins OE(PH3), CSB2(PH4), CSB1(PH6)
DDRH = 0x58; // 0b01011000 - CSB1, CSB2, OE [OUTPUT] - Unused Pins [INPUT]
PORTH = 0xFF; // 0b11111111 - CSB1, CSB2, OE [HIGH] - Unused Pins [HIGH]
// Address Pins
DDRF = 0xFF; // Address A1-A8 [OUTPUT]
DDRK = 0xFF; // Address A9-A16 [OUTPUT]
DDRL = 0x3F; // Address A17-A22 [OUTPUT] 0b00111111
// Data Pins
DDRC = 0x00; // D0-D7 [INPUT]
DDRA = 0x00; // D8-D15 [INPUT]
checkStatus_VSMILE();
strcpy(romName, "VSMILE");
mode = CORE_VSMILE;
}
//******************************************
// READ FUNCTIONS
//******************************************
// Max Single ROM Size 0x800000 (Highest WORD Address = 0x3FFFFF)
word read_rom_word_VSMILE(unsigned long address)
{
PORTL = (address >> 16) & 0xFF;
PORTK = (address >> 8) & 0xFF;
PORTF = address & 0xFF;
_delay_us(1); // Need longer delay
CSB2_HIGH;
CSB1_LOW;
OE_LOW;
unsigned char data1 = PINC;
unsigned char data2 = PINA;
word data = (data1 << 8) | (data2);
OE_HIGH;
CSB1_HIGH;
return data;
}
// VSMILE 2ND EPOXY CHIP [+2MB]
// CSB2 LOW ONLY
word read_rom2_word_VSMILE(unsigned long address)
{
PORTL = (address >> 16) & 0xFF;
PORTK = (address >> 8) & 0xFF;
PORTF = address & 0xFF;
_delay_us(1); // Need longer delay
CSB1_HIGH;
CSB2_LOW;
OE_LOW;
_delay_us(1); // Need longer delay
unsigned char data1 = PINC;
unsigned char data2 = PINA;
word data = (data1 << 8) | (data2);
OE_HIGH;
CSB2_HIGH;
return data;
}
// VSMILE MOTION 16MB 2ND CHIP [+8MB]
// CSB1 + CSB2 LOW
word read_rom3_word_VSMILE(unsigned long address)
{
PORTL = (address >> 16) & 0xFF;
PORTK = (address >> 8) & 0xFF;
PORTF = address & 0xFF;
CSB1_LOW;
CSB2_LOW;
OE_LOW;
unsigned char data1 = PINC;
unsigned char data2 = PINA;
word data = (data1 << 8) | (data2);
OE_HIGH;
CSB1_HIGH;
CSB2_HIGH;
return data;
}
//******************************************
// READ ROM
//******************************************
void readROM_VSMILE()
{
createFolderAndOpenFile("VSMILE", "ROM", romName, "bin");
for (unsigned long address = 0; address < 0x200000; address += 256) { // 4MB
for (unsigned int x = 0; x < 256; x++) {
word tempword = read_rom_word_VSMILE(address + x); // CSB1 LOW [CSB2 HIGH]
sdBuffer[x * 2] = (tempword >> 0x8) & 0xFF;
sdBuffer[(x * 2) + 1] = tempword & 0xFF;
}
myFile.write(sdBuffer, 512);
}
if (vsmilesize == 1) { // 6MB - 2 EPOXY CHIPS [4MB + 2MB] Alphabet Park/Care Bears
for (unsigned long address = 0; address < 0x100000; address += 256) { // +2MB HIGH = 6MB
for (unsigned int x = 0; x < 256; x++) {
word tempword = read_rom2_word_VSMILE(address + x); // CSB2 LOW [CSB1 HIGH]
sdBuffer[x * 2] = (tempword >> 0x8) & 0xFF;
sdBuffer[(x * 2) + 1] = tempword & 0xFF;
}
myFile.write(sdBuffer, 512);
}
}
else if (vsmilesize > 1) { // Normal 8MB
for (unsigned long address = 0x200000; address < 0x400000; address += 256) { // +4MB = 8MB
for (unsigned int x = 0; x < 256; x++) {
word tempword = read_rom_word_VSMILE(address + x); // CSB1 LOW [CSB2 HIGH]
sdBuffer[x * 2] = (tempword >> 0x8) & 0xFF;
sdBuffer[(x * 2) + 1] = tempword & 0xFF;
}
myFile.write(sdBuffer, 512);
}
if (vsmilesize > 2) { // Motion 16MB [8MB + 8MB] - Cars 2/Shrek Forever After/Super WHY!/Toy Story 3
for (unsigned long address = 0; address < 0x400000; address += 256) { // +8MB HIGH = 16MB
for (unsigned int x = 0; x < 256; x++) {
word tempword = read_rom3_word_VSMILE(address + x); // CSB1 + CSB2 LOW
sdBuffer[x * 2] = (tempword >> 0x8) & 0xFF;
sdBuffer[(x * 2) + 1] = tempword & 0xFF;
}
myFile.write(sdBuffer, 512);
}
}
}
myFile.close();
printCRC(fileName, NULL, 0);
println_Msg(FS(FSTRING_EMPTY));
print_STR(press_button_STR, 1);
display_Update();
wait();
}
//******************************************
// ROM SIZE
//******************************************
#if (defined(ENABLE_OLED) || defined(ENABLE_LCD))
void printRomSize_VSMILE(int index)
{
display_Clear();
print_Msg(FS(FSTRING_ROM_SIZE));
println_Msg(VSMILE[index]);
}
#endif
void setROMSize_VSMILE()
{
byte newvsmilesize;
#if (defined(ENABLE_OLED) || defined(ENABLE_LCD))
display_Clear();
if (vsmilelo == vsmilehi)
newvsmilesize = vsmilelo;
else {
newvsmilesize = navigateMenu(vsmilelo, vsmilehi, &printRomSize_VSMILE);
display.setCursor(0, 56); // Display selection at bottom
}
print_Msg(FS(FSTRING_ROM_SIZE));
print_Msg(VSMILE[newvsmilesize]);
println_Msg(F("KB"));
display_Update();
delay(1000);
#else
if (vsmilelo == vsmilehi)
newvsmilesize = vsmilelo;
else {
setrom:
String sizeROM;
for (int i = 0; i < (vsmilehi - vsmilelo + 1); i++) {
Serial.print(F("Select ROM Size: "));
Serial.print(i);
Serial.print(F(" = "));
Serial.print(VSMILE[i + vsmilelo]);
Serial.println(F("KB"));
}
Serial.print(F("Enter ROM Size: "));
while (Serial.available() == 0) {}
sizeROM = Serial.readStringUntil('\n');
Serial.println(sizeROM);
newvsmilesize = sizeROM.toInt() + vsmilelo;
if (newvsmilesize > vsmilehi) {
Serial.println(F("SIZE NOT SUPPORTED"));
Serial.println(FS(FSTRING_EMPTY));
goto setrom;
}
}
Serial.print(F("ROM Size = "));
Serial.print(VSMILE[newvsmilesize]);
Serial.println(F("KB"));
#endif
EEPROM_writeAnything(8, newvsmilesize);
vsmilesize = newvsmilesize;
}
void checkStatus_VSMILE()
{
EEPROM_readAnything(8, vsmilesize);
if (vsmilesize > vsmilehi) {
vsmilesize = 2; // default 8M
EEPROM_writeAnything(8, vsmilesize);
}
#if (defined(ENABLE_OLED) || defined(ENABLE_LCD))
display_Clear();
println_Msg(F("V.SMILE READER"));
println_Msg(FS(FSTRING_CURRENT_SETTINGS));
println_Msg(FS(FSTRING_EMPTY));
print_Msg(FS(FSTRING_ROM_SIZE));
print_Msg(VSMILE[vsmilesize]);
println_Msg(F("MB"));
display_Update();
wait();
#else
Serial.print(FS(FSTRING_ROM_SIZE));
Serial.print(VSMILE[vsmilesize]);
Serial.println(F("MB"));
Serial.println(FS(FSTRING_EMPTY));
#endif
}
//******************************************
// CART SELECT CODE
//******************************************
void setCart_VSMILE()
{
//go to root
sd.chdir();
byte gameSize;
// Select starting letter
//byte myLetter = starting_letter();
// Open database
if (myFile.open("vsmilecart.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

View File

@ -339,3 +339,135 @@ cart size:
3 = 16K 3 = 16K
4 = 32K 4 = 32K
5 = 64K 5 = 64K
## ballycart.txt
romsize
0 = 2K
1 = 4K
2 = 8K
## pv1000cart.txt
romsize
0 = 8K
1 = 16K
## pyuutacart.txt
romsize
0 = 8K
1 = 16K
2 = 32K
## rcacart.txt
romsize
0 = 512B
1 = 1024B (1K)
## trs80cart.txt
romsize
0 = 2K
1 = 4K
2 = 8K
3 = 10K
4 = 16K
5 = 32K
6 = 64K
7 = 128K
## vic20cart.txt (rommap,romsize)
rommap
upper nibble = ROM0 {0x20,0x40,0x60,0x70,0xA0,0xB0}
lower nibble = ROM1 {0x40,0x60,0xA0}
0 = 0x20 = 0x2000
1 = 0x24 = 0x2000/0x4000
2 = 0x2A = 0x2000/0xA000
3 = 0x46 = 0x4000/0x6000
4 = 0x60 = 0x6000
5 = 0x6A = 0x6000/0xA000
6 = 0x70 = 0x7000
7 = 0xA0 = 0xA000
8 = 0xB0 = 0xB000
romsize
upper nibble = ROM0 {2,4,8}
lower nibble = ROM1 {0,4,8}
0 = 0x20 = 2K/0K 0x800
1 = 0x40 = 4K/0K 0x1000
2 = 0x80 = 8K/0K 0x2000
3 = 0x44 = 4K/4K 0x1000/0x1000
4 = 0x48 = 4K/8K 0x1000/0x2000
5 = 0x84 = 8K/4K 0x2000/0x1000
6 = 0x88 = 8K/8K 0x2000/0x2000
## ti99cart.txt (mapper,gromsize,grommap,romsize)
mapper
0 = Normal Carts
1 = MBX
2 = TI-CALC [UNTESTED]
gromsize
0 = 0K
1 = 6K
2 = 12K
3 = 18K
4 = 24K
5 = 30K
grommap
Map corresponding bits
GROM# BITMAP HEX DEC
3 = 0000 1000 = 08 = 8
4 = 0001 0000 = 10 = 16
5 = 0010 0000 = 20 = 32
7 = 1000 0000 = 80 = 128
34 = 0001 1000 = 18 = 24
35 = 0010 1000 = 28 = 40
45 = 0011 0000 = 30 = 48
56 = 0110 0000 = 60 = 96
67 = 1100 0000 = C0 = 192
345 = 0011 1000 = 38 = 56
356 = 0110 1000 = 68 = 104
456 = 0111 0000 = 70 = 112
3456 = 0111 1000 = 78 = 120
3457 = 1011 1000 = B8 = 184
3467 = 1101 1000 = D8 = 216
34567 = 1111 1000 = F8 = 248
romsize
0 = 0K
1 = 4K
2 = 8K
3 = 12K
4 = 16K
## leapster.txt
romsize
0 = 4K
1 = 8K
2 = 16K
## vsmilecart.txt
romsize
0 = 4K
1 = 6K
2 = 8K
3 = 16K
## ljcart.txt
romsize
0 = 1M
1 = 2M
2 = 4M
## atari8cart.txt (slot,romsize)
slot
0 = left slot
1 = right slot
romsize
0 = 8K
1 = 16K
2 = 32K
3 = 40K
4 = 64K
5 = 128K

946
sd/atari8cart.txt Normal file
View File

@ -0,0 +1,946 @@
1400 Super SALT
0,1
3-D Tic-Tac-Toe
0,0
400/800 SALT
0,0
600xl/800xl SALT
0,1
810 Diagnostic Cartridge
0,0
Abracadabra
0,1
ACE-80XL
1,1
Ace of Aces
0,5
Action!
0,1
Adventure Creator
0,1
Airball
0,5
Alf in the Color Caves
0,1
Alien Ambush
0,0
Alien Garden
0,0
Alpha Shield
0,0
Alphabet Zoo
0,0
Ant Eater
0,0
Archon
0,2
Assembler Editor
0,0
AST
0,0
AST 2000
0,1
Asteroids
0,0
Astro Chase
0,1
Astro Grover
0,1
Atari BASIC
0,0
Atari LOGO
0,1
AtariArtist
0,1
AtariGraphics
0,1
AtariLab Light Module
0,1
Atarilab Temperature Module
0,1
AtariSchreiber
0,1
AtariTexte
0,1
AtariWriter
0,1
Atlantis
0,0
Attack at EP-CYG-4
0,1
Attack of the Mutant Camels
0,0
Ballblazer
0,4
Barnyard Blaster
0,5
Baseball
0,1
BASIC
0,0
Basic XE
0,1
Basic XL
0,1
Basketball
0,0
BattleZone
0,4
BC's Quest for Tires
0,1
Beamrider
0,1
BearJam
0,0
Big Bird's Funhouse
0,1
Big Bird's Special Delivery
0,1
Blue Max
0,2
Boulder Dash
0,1
Boulders and Bombs
0,0
Bounty Bob Strikes Back!
0,3
Bristles
0,1
Buck Rogers
0,1
Bug Hunt
0,4
Captain Beeble
0,1
Carnival Massacre
0,1
Castle Hassle
0,1
Castles and Keys
0,1
Caverns of Mars
0,1
Centipede
0,0
Chess
0,0
Chicken
0,0
Chiffres et des Lettres
0,1
Choplifter!
0,1
Choplifter! (XE)
0,4
Claim Jumper
0,1
Cloudburst
0,0
CocoNotes
0,1
Compu=Prompt
0,0
Computer Chess
0,0
Computer War
0,1
Computrac 4000-8000
0,1
Congo Bongo
0,1
Conquest of the Crown
0,1
Cosmic Life
0,0
CPS Super SALT 400/800/XL
0,1
Crime Buster
0,5
Crossbow
0,5
CrossFire
0,0
Crystal Castles
0,2
Da' Fuzz
0,0
Dance Fantasy
0,0
Dark Chambers
0,4
David's Midnight Magic
0,4
Decathlon
0,1
Defender
0,1
Delta Drawing
0,0
Deluxe Invaders
0,0
Demon Attack
0,0
Desert Falcon
0,4
Designer's Pencil
0,1
Diamond Graphic OS
0,4
Diamond Mine
0,1
Dig Dug
0,1
Direct Access
0,1
Donkey Kong
0,1
Donkey Kong Jr.
0,1
Dreadnaught Factor
0,0
Droids
0,0
DT-80
1,0
Ducks Ahoy!
0,1
E.T. Phone Home!
0,1
Eastern Front 1941
0,1
Edit 6502
0,0
Editor Assembler
0,0
Educational System
0,0
Embargo
0,0
Ernie's Magic Shapes
0,1
Espial
0,1
Expando-Vision
0,0
Express!
0,4
FaceMaker
0,0
Fantastic Voyage
0,0
Fast Eddie
0,0
Fight Night
0,5
Final Legacy
0,1
Final Orbit
0,0
Firebird
0,0
Flapper
0,1
Flight Simulator II
0,5
Flip and Flop
0,1
Food Fight
0,2
Fort Apocalypse
0,1
Fortune Hunter
0,0
Fraction Fever
0,0
Frogger
0,0
Frogger II
0,1
Fun with Art
0,1
Galaxian
0,0
Gateway To Apshai
0,1
GATO Submarine Simulation
0,5
Gold Mine
0,0
Gorf
0,0
Gridrunner
0,0
Gyruss
0,1
H.E.R.O.
0,1
Halftime Battlin' Bands
0,1
Ham Text
0,0
Hamsoft / Amtor
0,0
Hard Hat Willy
0,1
Hardball!
0,4
Homebase Electronic Banking
0,0
Hypnotic Land
0,1
In-Store Demonstration
0,1
INFO-soft
0,1
Info/Gen
0,0
Into the Eagle's Nest
0,2
James Bond 007
0,1
Jawbreaker II
0,0
Journey to the Planets
0,1
Joust
0,1
Jumbo Jet Pilot
0,1
Jumpman Junior
0,1
Jungle Hunt
0,1
K-Razy Antiks
0,0
K-Razy Kritters
0,0
K-Razy Shoot Out
0,0
K-Star Patrol
0,0
Kaboom!
0,0
Karateka
0,5
Keystone Kapers
0,0
Kickback
0,0
Kids on Keys
0,0
KinderComp
0,0
Koala Painter
0,1
Learning Phone
0,0
Learning with Leeper
0,1
Leo's 'Lectric Paintbrush
0,0
Letter Perfect
0,0
Linking Logic
0,0
Lode Runner
0,4
Logic Levels
0,0
LogicMaster
0,0
M*A*S*H
0,0
MAC-65
0,1
Magic Dump II
1,0
Major League Hockey
0,0
Mario Bros.
0,4
Master Type
0,1
Math Encounter
0,0
Math Mileage
0,0
Math Works
0,0
Matterhorn
0,1
MegaMania
0,0
Memory Manor
0,0
Microcalc XE
0,2
Microfiler
0,0
MicroIllustrator
0,1
MicroMaestro
0,0
Microprinter System
0,0
Microsoft BASIC II
0,1
Millipede
0,1
Miner 2049er
0,1
Missile Command
0,0
Mogul Maniac
0,1
Monkey Wrench
1,0
Monkey Wrench II
1,0
Monster Maze
0,0
Moon Patrol
0,1
Mountain King
0,0
Movie Musical Madness
0,1
Mr. Cool
0,0
Mr. TNT
0,0
Ms. Pac-Man
0,1
Multi Fischa
0,0
Music Composer
0,0
Necromancer
0,1
Night Strike!
0,0
Oil's Well
0,1
One-on-One
0,2
Orc Attack
0,1
Ozzy's Orchard
0,1
Pac-Man
0,0
Paddle Jitter Test
0,1
Pastfinder
0,1
Peanut Butter Panic
0,0
Pengo
0,1
Picnic Paranoia
0,1
PILOT
0,0
Pitfall!
0,0
Pitfall II
0,1
Pitstop
0,1
PLATO
0,0
PlatterMania
0,0
Pocket Modem Software
0,0
Pole Position
0,1
Pool 400
0,0
Popeye
0,1
Porky's
0,1
Powerstar
0,1
Princess and the Frog
0,0
Pronto
0,1
Protector II
0,1
Q*bert
0,0
Qix
0,0
Rack 'em Up!
0,1
Rally Speedway
0,1
RealSports Football
0,1
Rescue on Fractalus!
0,4
River Raid
0,0
River Rescue
0,1
Robotron 2084
0,1
Sea Chase
0,0
Sea Horse Hide 'n Seek
0,1
Seafox
0,1
Serpentine
0,0
Sesame Street Letter-Go-Round
0,1
Shamus
0,1
Silicon Warrior
0,1
Sky Writer
0,1
Slime
0,1
Smart Terminal
0,0
Soccer
0,0
Space Invaders
0,0
Space Journey
0,1
Space Shuttle
0,1
Spark Bugs
0,0
Sparta DOS X
0,4
Spectraview II
0,1
Speedway Blast
0,0
Spider City
0,0
Springer
0,1
Spy Hunter
0,1
Star Maze
0,1
Star Raiders
0,0
Star Raiders II
0,2
Star Trek
0,1
Star Wars The Arcade Game
0,1
Star Wars Return of the Jedi
0,0
Starion
0,1
Story Machine
0,1
Submarine Commander
0,1
Summer Games
0,5
Super Breakout
0,0
Super Cobra
0,0
Super E-Burner
0,0
Super Sketch Graphics Master
0,0
Super Zaxxon
0,1
Survival of the Fittest
0,0
Synassembler
0,0
Tamlilan
0,1
Target
0,1
Telelink I
0,0
Telelink II
0,0
Tennis
0,1
Test Atari 65-130XE
0,0
Thera-Med Zahnschutz-Spiel
0,0
Thunderfox
0,4
Timebound
0,1
Topper
0,1
Track & Field
0,1
Trion
0,1
Turbo System
0,0
Turmoil
0,0
Twin Pack
0,0
Typo Attack
0,0
Typo
0,0
Up 'n Down
0,1
Up for Grabs
0,0
Video Easel
0,0
Video Poker Card Game
0,1
VisiCopy III
0,0
Webster
0,0
Weltraumkolonie
0,0
Whiz Kid
0,0
Wilcox Message Display
0,0
Wizard of Wor
0,1
Worm War 1
0,0
Writer's Tool
0,0
Zaxxon
0,1
Zenji
0,0
Zone Ranger
0,1
Zybex
0,4

103
sd/ballycart.txt Normal file
View File

@ -0,0 +1,103 @@
280 Zzzap + Dodgem
0
Amazing Maze + Tic-Tac-Toe
0
Artillery Duel
1
Astro Battle
1
Bally BASIC
1
Bally Pin
1
Biorhythm
1
Blackjack +2
1
Blast Droids
1
Brickyard + Clowns
1
Cosmic Raiders
2
Dog Patch
0
Elementary Math + Bingo Math
0
Football
1
Galactic Invasion
1
Galaxian
1
Grand Prix + Demolition Derby
1
ICBM Attack
1
Incredible Wizard
2
Letter Match +2
1
Machine Language Manager
0
Ms. Candyman
1
Muncher
2
Panzer Attack + Red Baron
1
Pirate's Chase
1
Sea Devil
1
Seawolf + Missile
0
Sneaky Snake
1
Solar Conqueror
2
Space Fortress
1
Space Invaders
1
Star Battle
0
Tornado Baseball +3
1
Treasure Cove
2

217
sd/leapster.txt Normal file
View File

@ -0,0 +1,217 @@
1st Grade
1
2nd Grade
1
Animal Genius
1
Backyardigans
1
Batman Multiply, Divide and Conquer
1
Batman Strength in Numbers
1
Bratz World
1
Cars
1
Cars Supercharged
1
Cars 2
1
Clifford The Big Red Dog
1
Cosmic Math
0
Crayola Art Adventure
1
Creature Create
1
Digging for Dinosaurs
1
Disney Fairies
1
Disney Princess
1
Disney Princess Enchanted Learning
1
Disney Princess Worlds of Enchantment
1
Disney-Pixar Collection
1
Dora the Explorer Animal Rescuer
1
Dora the Explorer Camping Adventure
1
Dora the Explorer Pinata Party
0
Dora the Explorer Wildlife Rescue
1
Finding Nemo
1
Foster's Home for Imaginary Friends
1
Get Puzzled!
1
Go Diego Go!
1
I Spy Challenger
1
I Spy Treasure Hunt
1
Incredibles
1
Kindergarten
1
Learning with Leap
1
Letter Factory
2
Letterpillar
0
Letters on the Loose
1
Madagascar
1
Math Baseball
1
Math Missions
1
Mr. Pencil's Learn to Draw & Write
1
My Amusement Park
1
NASCAR
1
nihao kai-lan
1
Noddy
1
Number Raiders
0
Numbers on the Run
1
OutWit!
1
Penguins of Madagascar
1
Pet Pals
1
Princess and the Frog
1
Ratatouille
1
Reading with Phonics
1
Rock the World
1
School House Rock! America Rock
2
School House Rock! Grammar Rock
2
Scooby Doo!
1
Scooby Doo! Spooky Snacks!
0
Sonic X
1
Spider-Man
1
SpongeBob SquarePants Saves the Day
1
SpongeBob SquarePants Through The Wormhole
0
Star Wars Jedi Math
1
Star Wars Jedi Reading
1
Talking WORDS Factory
2
Tangled
1
Thomas & Friends
1
Top-Secret Personal Beeswax
1
Toy Story 3
1
Up
1
Wall-E
1
Wolverine and the X-Men
1
Word Chasers
0

109
sd/ljcart.txt Normal file
View File

@ -0,0 +1,109 @@
70's Rock&Pops Selection Vol. 5
1
Asahi PRIME TIME Selection
0
Ballad Selection Vol 3
1
Basic Selection
1
BigBand Selection Vol. 10
1
BossaNova Selection Vol. 4
1
Cinema Selection Camel Package Vol. 7
1
Cinema Selection Navy Package Vol. 6
1
Cinema Selection Olive Package Vol. 8
1
Classical Jazz Selection Emerald Package Vol. 12
1
Classical Jazz Selection Sapphire Package vol. 13
1
DESKTOP JAM Basic Selection
1
Disco Hits Selection
1
Forever Rock & Pops Selection Vol. 11
1
Healing Selection
1
High Note Selection
1
LIMITED S Edition
1
Latin Selection
1
Lighted Nights Selection
1
Little Jammer Selection
1
LITTLE JAMMER SELECTION-1
1
NIKKA Selection
0
Owner's Club Selection
1
Owner's Club Selection2 Christmas Limited
1
Owner's Club Selection3 Jazz Ballad
1
Owner's Club Selection4 SAVOY Collection
0
Owner's Club Welcome Selection
1
Relaxing Selection Vol. 2
1
Rhythm Jam
1
STRIPES LIMITED Selection
1
Standard Selection Vol. 1
1
SwingJournal Selection
1
TVCM HITS! Wine and JAZZ&POPS Selection Vol. 9
1
TeaTime Selection Vol. 14
0
Wonderful Christmas Selection
0
Youth Song Selection Vol. 15
0

72
sd/pv1000cart.txt Normal file
View File

@ -0,0 +1,72 @@
Amidar
0
Dig Dug
1
Dirty Chameleon
0
Excite Mahjong
1
Excite Mahjong 2
1
Exciting Jockey
1
Fighting Bug
0
Front Line
0
Galaga
0
Mr. Packn
0
Naughty Boy
0
Pachinko - UFO
1
Pooyan (PV1000)
0
Pooyan (PV2000)
1
Rakugaki Special
1
Real Number Basic
1
Roc'n Rope
0
Ski Command
1
Space Panic
0
Super Cobra
0
Turpin
0
Tutankham
0
Warp & Warp
0
0

97
sd/pyuutacart.txt Normal file
View File

@ -0,0 +1,97 @@
4-nin Mahjong
1
0
Baseball [3D]
2
19
Battle Fighter [3D]
2
20
Bermuda Triangle
0
26
Bombman
0
23
Car-azy Racer
1
Cave Crawlers
0
Deep Six
0
Don Pan
0
Frogger
0
Guttang Gottong
0
Hyperspace
0
Jungler
0
Loco-Motion
0
Marine Adventure
0
Maze Patrol
0
Mickey Athletic Land
0
Mission Attack
0
Monster Inn
0
Mystery Gold
0
Mr. Do!
1
Night Flight
0
Pooyan
0
Rescue Copter [3D]
2
Saurusland
0
Scramble
0
Super Bike
1
Torpedo Terror
0
Traffic Jam
0
Triple Command
0
TRON
0
Turpin
0

49
sd/rcacart.txt Normal file
View File

@ -0,0 +1,49 @@
Baseball
1
Biorhythm
1
Blackjack
1
Concentration Match
1
Demonstration Cartridge
1
Fun with Numbers
0
Gunfighter + Moonship Battle
1
Pinball
1
Space War
0
Speedway + Tag (Europe)
1
Speedway + Tag (USA)
0
Star Wars
1
Tennis + Squash
0
TV Bingo
1
TV School House I
0
TV School House II - Math Fun
1

835
sd/ti99cart.txt Normal file
View File

@ -0,0 +1,835 @@
4A DOS
0,0,000,2
4A Flyer
0,0,000,2
99 Home Sentry
0,0,000,2
Accounting Assistant
0,5,248,0
Activity Accountant
0,3,056,0
Addition
0,2,040,0
Addition and Subtraction 1
0,3,056,0
Addition and Subtraction 2
0,3,056,0
Addition and Subtraction 3
0,4,120,0
Adventure
0,1,008,0
Alien Addition
0,2,024,0
Alligator Mix
0,2,024,0
Alpiner
0,4,120,1
A-Maze-Ing
0,1,008,0
Ambulance
0,0,000,2
Ant Colony
0,0,000,2
Ant-Eater
0,0,000,2
Attendance Recorder
0,5,248,0
Barrage
0,0,000,4
Beginning Grammar
0,2,024,0
Beyond Parsec
0,0,000,2
Beyond Space
0,0,000,2
Bigfoot
1,1,008,4
Black Hole
0,0,000,2
Blackjack and Poker
0,1,008,0
Blasto
0,1,008,0
Boxer
0,0,000,2
Break Thru
0,0,000,2
Buck Rogers
0,2,024,2
Burger Builder
0,0,000,2
Burgertime
0,2,024,2
Car Wars
0,1,008,0
Card Sharp
0,1,008,0
Centipede
0,0,000,2
Championship Baseball
1,3,056,4
Chicken Coop
0,0,000,2
Chisholm Trail
0,1,008,2
Class Data Recorder
0,5,248,0
Computer Math Games I
0,4,120,2
Computer Math Games II
0,3,056,0
Computer Math Games III
0,4,120,0
Computer Math Games IV
0,4,120,0
Computer Math Games VI
0,2,024,0
Computer War
0,0,000,4
Congo Bongo
0,2,024,2
Connect Four
0,1,016,0
Console Writer
0,0,000,2
Course Manager
0,5,248,0
Crossfire
0,1,008,2
Data Base Management System v2.0
0,0,000,2
Decimal Deli 2
0,4,120,0
Decimals
0,3,056,0
Defender
0,0,000,2
Demolition Division
0,2,024,0
Demonstration
0,4,120,0
Diagnostic
0,1,008,0
Diagnostic (FRA)
0,2,024,0
Dig Dug
0,0,000,4
Disk Fixer
0,0,000,2
Disk Fixer v2.0
0,0,000,2
Disk Manager
0,2,024,0
Disk Manager 1
0,2,024,0
Disk Manager 2
0,2,024,0
Disk Manager 3
0,2,024,0
Division
0,2,024,0
Donkey Kong
0,0,000,4
Dragon Mix
0,2,024,1
Driving Demon
0,0,000,2
D-Station I
0,0,000,2
D-Station II
0,0,000,2
E.T.
0,2,024,4
E.T. In His Adventure at Sea
0,5,248,2
Early Learning Fun
0,2,024,0
Early LOGO Learning Fun
0,1,008,2
Early Reading
0,5,248,0
Editor/Assembler
0,1,008,0
Edu-Pack
0,0,000,2
Electrifying Fractions 2
0,4,120,0
Equations
0,2,024,0
Escape
0,0,000,2
Extended Basic
0,4,120,3
Face Chase
0,0,000,2
Facemaker
0,2,024,2
Fantastic Fractions 1
0,3,112,0
Fantasy
0,5,248,2
Fathom
0,3,056,2
fig FORTH
0,0,000,2
Football
0,2,024,0
Fractional Numbers
0,3,104,0
Frog Jump
0,2,024,0
Frog Stickers
0,0,000,2
Frogger
0,1,128,2
Germ Patrol
0,5,248,2
Gestion Privee
0,3,056,0
Hangman
0,1,032,0
Hen Pecked
0,0,000,2
Henhouse
0,0,000,2
Home Financial Decisions
0,2,024,0
Homework Helper+
0,0,000,2
Honey Hunt
1,3,056,4
Hopper
0,1,008,2
Household Budget Management
0,2,024,0
Hunt The Wumpus
0,1,008,0
Hustle
0,1,008,0
I'm hiding
1,2,024,4
Integers
0,2,024,0
Introduction to Plant Genetics
0,4,120,2
Jawbreaker II
0,1,008,2
Jeu d'Echecs
0,4,120,1
Jumpy
0,0,000,4
Jungle Hunt
0,0,000,4
Junkman Junior
0,0,000,4
Key to Spanish 1/2
0,5,248,2
Key to Spanish 3/4
0,5,248,2
Key to Spanish 5/6
0,5,248,2
King of the Castle
0,0,000,2
Laws of Arithmetic
0,2,040,0
Link v0.99
0,0,000,2
M.A.S.H
0,3,056,2
Mancala
0,5,248,2
Measurement Formulas
0,5,248,4
Meteor Belt
1,1,008,4
Meteor Multiplication
0,2,024,0
Micro Pinball 2
0,0,000,4
Micro Tennis
0,0,000,4
Microsoft Multiplan
0,5,248,0
Microsurgeon
0,3,056,2
Midnite Mason
0,0,000,2
Milliken Manager
0,5,248,0
Milton Bradley Gamevision
0,5,248,0
Mini Memory
0,1,008,1
Miniwriter II
0,0,000,2
Minus Mission
0,2,024,0
Moon Mine
0,5,248,2
Moon Patrol
0,0,000,4
Moonsweeper
0,3,056,2
Mousk-Attack
0,4,120,2
Ms. Pac-Man
0,0,000,4
Multiplication
0,2,040,0
Munch Man
0,1,008,1
Munch Man II
0,0,000,2
Munchmobile
0,3,056,2
Music Maker
0,3,056,0
Music SDA
0,3,056,0
Nature's Way
0,0,000,2
Number Bowling
0,2,024,0
Number Magic
0,1,008,0
Number Magic (MULTI)
0,2,024,0
Number Readiness
0,2,024,0
Numeration 1
0,4,120,0
Numeration 2
0,3,056,0
Othello
0,1,008,1
Pac-Man
0,0,000,4
Paint 'N Print A
0,0,000,2
Paint 'N Print C
0,0,000,2
Parsec
0,3,056,2
Payroll Assistant
0,5,248,0
Percents
0,5,248,0
Peripheral Diagnostic Module
0,0,000,2
Personal Real Estate
0,4,120,0
Personal Record Keeping
0,4,120,0
Personal Record Keeping (GER/ITA)
0,5,248,0
Personal Report Generator (ENG/GER)
0,2,024,0
Peter Pan's Space Odyssey
0,5,248,2
Physical Fitness
0,2,024,0
Picnic Paranoia
0,0,000,4
Picture Parts
0,2,096,0
Pinocchio's Great Escape
0,5,248,2
Plato Interpreter
0,4,120,2
Pole Position
0,0,000,4
Popeye
0,2,192,2
Princess and Frog
0,0,000,2
Pro Typer
0,0,000,2
Protector II
0,0,000,4
Pyramid Puzzler
0,2,096,0
Q-Bert
0,1,128,2
Rabbit Trail
0,0,000,2
Reading Adventures
0,5,248,0
Reading Cheers
0,5,248,0
Reading Fun
0,5,248,0
Reading On
0,5,248,0
Reading Power
0,5,248,0
Reading Rainbows
0,5,248,0
Reading Trail
0,5,248,0
Reading Wonders
0,5,248,0
Return to Pirate's Isle
0,5,248,2
Robotron:2084
0,0,000,4
Romox Demo
0,0,000,2
Rotor Raiders
0,0,000,2
Salary Planner
0,4,120,0
Schachmeister
0,4,120,1
Schnoz-ola
0,0,000,2
Scholastic Spelling Level 3
0,5,248,1
Scholastic Spelling Level 4
0,5,248,1
Scholastic Spelling Level 5
0,5,248,4
Scholastic Spelling Level 6
0,5,248,4
School Mailer
0,4,120,0
Securities Analysis
0,4,120,0
Sewermania
1,2,024,4
Shamus
0,0,000,4
Shanghai
0,0,000,2
Simon Says
0,1,008,0
Slymoids
0,1,008,2
SMU Electrical Engineering Library
0,2,024,0
Sneggit
0,1,008,2
Soccer
0,2,024,0
Sorgan II
0,0,000,4
Soundtrack Trolley
1,1,008,4
Space Bandits
1,2,024,4
Space Journey
0,2,096,0
Space Patrol
0,0,000,2
Speech Editor
0,1,008,0
Speed Reading A
0,0,000,2
Speed Reading B
0,0,000,2
Spy's Demise
0,0,000,2
St. Nick
0,1,008,2
Star Gazer I
0,0,000,2
Star Gazer II
0,0,000,2
Star Gazer III
0,0,000,2
Star Maze
0,2,024,0
Star Runner
0,0,000,4
Star Trek
0,2,024,2
Star Wars
0,0,000,2
Statistics
0,5,248,0
Statistik
0,5,248,0
Story Machine v1.4
0,2,048,2
Strike Three!
0,0,000,4
Subtraction
0,2,024,0
Sudoku
0,0,000,2
Super Demon Attack
0,3,056,2
Super Duper v1.1
0,0,000,2
Super Sketch Model G2400
0,0,000,2
Super Sort
0,0,000,2
Super Storm
0,0,000,4
Superfly
1,2,024,4
SuperSpace II
0,1,008,0
T.I. Toad
0,0,000,2
Tax Investment Record Keeping
0,4,120,2
Tennis
0,0,000,4
Terminal Emulator I
0,2,024,0
Terminal Emulator II
0,4,216,1
Terry Turtle's Adventure
1,3,056,4
Testtrainer 1
0,2,024,0
The Attack
0,1,008,0
The Castle (Preview)
0,0,000,2
TI Invaders
0,1,008,1
TI LOGO
0,4,120,0
TI LOGO II
0,3,056,2
TI LOGO II (GER)
0,4,120,2
TI LOGO II (ITA)
0,4,184,2
TI Planner
0,0,000,2
TI-CALC
2,1,008,4
TI-IBM Copier
0,0,000,2
Tile Breaker
0,0,000,2
TI-Writer
0,1,008,0
Tombstone City
0,1,008,1
Topper
0,0,000,2
Touch Typing Tutor
0,3,056,0
Treasure Island
0,3,056,2
Tunnels of Doom
0,5,248,0
Typo II
0,0,000,2
Typoman
0,0,000,2
UCSD Pascal Development System
0,1,008,2
VAT Accounting
0,4,120,0
Verb Viper
0,2,024,0
Video Chess
0,4,120,1
Video Games 1
0,2,024,0
Video Games 2
0,1,008,0
Video Vegas
0,0,000,2
Video-Graphs
0,1,008,0
Von Drake's Molecular Mission
0,5,248,2
Weight Control and Nutrition
0,5,248,1
Win with Decimals 1
0,4,120,0
Wing War
0,3,056,2
Word Invasion
0,2,024,0
Word Radar
0,1,008,1
Yahtzee
0,1,008,0
Zero Zap
0,1,128,0

328
sd/trs80cart.txt Normal file
View File

@ -0,0 +1,328 @@
7 Card Stud
2
A Mazing World of Malcom Mortar
4
Androne
2
Appliance and Light Controller
4
Arkanoid (Coco 1-2)
4
Arkanoid (Coco 3)
5
Art Gallery
1
Atom
4
Audio Spectrum Analyzer
0
Backgammon
1
BASIC AID
0
Bingo Math
1
Bridge Tutor I
2
Bustout
1
Canyon Climber
2
Castle Guard
1
Castle of Tharoggad
4
Checker King
1
Clowns & Balloons
2
Coco Tuner
1
Color Baseball
2
Color Computer Disk BASIC
2
Color Cubes
1
Color File
1
Color File II
4
Color Forth
3
Color Logo
2
Color Robot Battle
2
Color Scripsit
2
Color Scripsit II
4
Crosswords
1
Cyrus World Class Chess
4
Deluxe RS-232 Program Pak
1
Demolition Derby
2
Demon Attack
4
Diagnostics
0
Diagnostics v2.0
0
Dino Wars
2
Direct Connect Modem Pak
2
DON-PAN
2
Doodle Bug (Computerware)
4
Doodle Bug (Computerware) (Buff/Green)
2
Doodle Bug (Dragon Data Ltd)
2
Doubleback
1
Downland
2
Dragon Fire
4
Dungeons of Daggorath
2
EDTASM+
4
Facemaker
2
Football
2
Fraction Fever
2
Galactic Attack
1
GFL Championship Football II
5
Gin Champion
2
Gomoku-Renju
2
Graphic Pak
4
Handyman
1
JDOS v1.08/v1.10/v1.11
2
JDOS v1.23
4
Kids on Keys
2
Kindercomp
2
Math Tutor
4
Mega-Bug
2
Micro Chess v2.0
2
Micro Painter
1
Microbes
1
Mind-Roll
5
Monster Maze
1
Music
1
Orchestra 90-CC
2
Panic Button
2
Personal Finance
2
Personal Finance II
2
Pinball
1
Polaris
1
Poltergeist
2
Popcorn
0
Predator
6
Project Nebula
2
Quasar Commander
1
RAD Warrior
5
Rampage!
5
Reactoid
1
Robocop
7
Roman Checkers
2
SDS80C
2
Shanghai
4
Shooting Gallery
2
Silpheed (Coco 1-2)
4
Silpheed (Coco 3)
5
Skiing
2
Slay the Nereis
2
Soko-Ban
4
Space Assault
1
Spectaculator
2
Spidercide
1
Springster
4
Starblaze
2
Stellar Lifeline
2
Super Logo
4
Super Pitfall
5
Temple of ROM
2
Tennis
1
Tetris
4
Thexder
4
TypeMate
4
Typing Tutor
1
Videotex
0
Wildcatting
1

718
sd/vic20cart.txt Normal file
View File

@ -0,0 +1,718 @@
A World at War
7,2
A.E.
5,6
Adventureland
3,6
Aggressor
7,2
Alien
7,2
Alien Blitz
7,1
Alien Sidestep
7,1
Alphabet Zoo
5,6
Amazing Maze
7,1
Amidar
7,2
Amok!
7,1
Ape Escape
7,2
Apple Panic
5,3
Arachnoid
5,6
Arcadia
7,2
Artillery Duel
5,6
Assam - Assembler
7,2
Astroblitz
7,1
Atlantis
7,1
Attack of the Mutant Camels
7,2
Avenger
7,2
Baldor's Castle
1,5
Bandits
7,2
Bank Robber
7,2
Battle Zone
5,6
Black Hole
7,1
Bridge 20
5,6
Buck Rogers
5,6
Bug Crusher
7,1
BUTI - Basic UTIlity
7,1
Cannonball Blitz
2,4
Capture the Flag
7,2
Car Race
7,2
Cassette Turbo
7,1
Catch-a-Snatch
7,2
Cave-In
7,2
CBM BASIC v4.0
7,1
CBM BASIC v5.0
7,2
Centipede
2,6
Choplifter
7,2
Chuck Norris Superkicks
7,2
Close Encounters
7,1
Cloudburst
7,1
Clowns
7,2
ComBASIC
8,1
Commodore Artist
7,1
Computer War
7,2
Congo Bongo
7,2
Cosmic Cruncher
7,2
Cosmic Jailbreak
7,2
Crater Raider
7,1
Creepy Corridors
7,2
Crossfire
7,2
Cyclon
7,2
Dancing Bear
2,6
Data 20 Display Manager
7,0
Deadly Duck
7,1
Deadly Skies
7,1
Defender
5,6
Demon Attack
7,1
D'Fuse
7,2
Dig Dug
2,6
Donkey Kong
2,6
Dot Gobbler
7,1
Dragonfire
7,2
Droids
7,2
E.T.
7,2
ExBasic Level II
7,2
Face Maker
7,2
Fast Eddie
7,2
Final Orbit + Bumper Bash
7,2
Flipper 1.0
7,2
Frogger
7,2
Frogman
7,2
Fun with Music
7,2
Galaxian
7,2
Garden Wars
7,2
Ghost Manor
7,2
Gold Fever
7,1
Gorf
7,2
Gridrunner
7,1
Handy Toolkit
7,2
HesMon v1.1
7,1
HesWriter v1.1
7,2
HiRes Toolkit
8,1
Home Baby Sitter II
7,2
Household Finance
7,2
IEEE-488
8,0
IFR: Flight Simulator
7,2
In The Chips
5,6
Jawbreaker II
7,2
Jelly Monster v.1
7,2
Jelly Monster v.2
7,2
Jungle Hunt
5,6
Jupiter Lander
7,2
Key-Quest
7,2
Kids on Keys
7,2
Kindercomp
5,6
K-Razy Antiks
5,6
K-Star Patrol
5,6
Laser Zone
7,2
Lode Runner
5,6
Lunar Leeper
2,4
Machine Language Monitor
0,1
Mastertype
5,6
Maze
7,2
Medieval Joust
7,2
Meteor Run
7,2
Mine Madness
7,2
Miner 2049er
7,2
Mission Impossible
3,6
Mobile Attack
7,2
Mole Attack
7,2
Money Wars
7,2
Monster Maze
7,2
Moon Patrol
5,6
Mosquito Infestation
7,1
Motocross Racer
7,2
Mountain King
5,6
Ms. Pac-Man
5,6
Mutant Herd
7,2
Number Crunch
7,2
Number Nabber & Shape Grabber
7,2
Omega Race
7,2
Outworld (NTSC)
5,3
Outworld (PAL)
7,2
Pac-Man
7,2
Paratrooper
7,2
Personal Finance
7,2
PET Loader
7,2
Pharaoh's Curse
5,6
Pinball
5,6
Pinball Spectacular
5,6
Pipes
7,2
Pirate's Cove
3,6
Poker
7,2
Polaris
7,2
Pole Position
5,6
Predator
7,2
Princess and Frog
7,2
Programmer's Aid Cartridge
6,1
Protector
7,2
Q*bert
7,2
Quackers
7,2
Quick Brown Fox
4,2
Radar Rat Race
7,2
Raid on Fort Knox
7,2
Rally-X
7,2
Rat Hotel
7,2
Renaissance
5,3
River Rescue
7,2
Road Race
7,2
Robin Hood
7,2
Robot Panic
7,2
Robotron: 2084
5,4
SamMON
0,2
Sargon II Chess
7,2
Satellite and Meteorites! (NTSC)
5,3
Satellite and Meteorites! (PAL)
7,2
Satellite Patrol
7,1
Scorpion
7,2
Scram 20
7,1
Screen Master
7,1
Sea Wolf
7,2
Seafox
5,6
Serpentine
7,2
Shamus
7,2
Sir Lancelot
7,2
Skibbereen
7,1
Skyblazer
5,6
Slot
7,2
Snake Byte
7,1
Space Ric-o-Shay
7,1
Space Snake
7,2
Speed Math & Bingo Math
7,2
Spider City
7,1
Spider of Mars (NTSC)
7,2
Spider of Mars (PAL)
5,3
Spike's Peak
7,2
Spills & Fills
7,2
Springer
5,6
Squish 'em
5,6
Star Battle
7,2
Star Post
7,2
Star Trek
7,2
Story Machine
5,5
Sub Chase
7,1
Sub Commander
5,4
Super Amok
7,2
Super Expander
7,1
Super Slot
7,2
Super Smash
7,2
Synthesound
7,2
Tank Atak
7,2
Tank Wars
7,1
Terraguard
7,1
The Count
3,6
The Fourth Encounter
7,2
The Sky is Falling
7,2
Threshold
7,2
Titan
7,2
Tomarc the Barbarian
7,2
Tooth Invaders
7,2
Topper
7,2
Trashman
5,3
Turmoil
7,2
Turtle Graphics
7,2
Tutankham
7,2
Type Attack
7,2
Typo
7,2
VC Extra
7,2
VC Song-Cartridge
7,2
VIC 20 Diagnostic Cartridge
7,1
VIC 20 Micromon v1.2
8,1
VIC 20 Mikro Assembler
5,3
VIC Color Test
7,0
VIC Forth v1.0
7,2
VIC Forth v1.1
7,2
VIC Graph
7,2
VIC Menagerie
7,2
VIC Music Composer
7,2
VIC Stat
7,2
VIC Super Lander
7,2
Vic Tool
8,0
VICKIT 1
8,0
VICKIT 2
8,1
VICKIT 3
8,1
VICKIT 4
7,1
VICKIT 5
8,1
VICterm 40
7,1
Video Vermin
7,2
Videomania
7,1
Visible Solar System
7,2
Voodoo Castle
3,6
Wacky Waiters
7,2
Waterloo BASIC
7,1
Witch Way
7,2
Wordcraft 20
5,6
Write Now!
7,2

223
sd/vsmilecart.txt Normal file
View File

@ -0,0 +1,223 @@
A Day On The Farm
2
Action Mania
2
Adventures of Little Red Riding Hood
2
Aladdin
2
Alphabet Park Adventure
2
Alphabet Park Adventure (6MB)
1
Baby Einstein
2
Backyardigans
2
Bailey Goes To Town
2
Barney
2
Batman
2
Blue's Clues
2
Bob the Builder
2
Care Bears
2
Care Bears (6MB)
1
Cars
2
Cars 2
3
Cinderella
2
Cranium
2
Discovery with Baby Mickey and Friends
2
Disney Fairies
2
Disney's Little Einsteins
2
Dora The Explorer
2
Elmo's World
2
Finding Nemo
2
Go Diego Go!
2
Handy Manny
2
Kung Fu Panda
2
Learn and Discover Home
2
Learnin' Wheels
2
Lil' Bratz
2
Lion King
2
Little Mermaid
2
Mickey Mouse
2
Mickey Mouse Clubhouse
2
Monsters vs. Aliens
2
Mother Goose
2
My Pet Puppy
2
Nascar Academy
2
Ni Hao Kai Lan
2
Noah's Ark Animal Adventure
2
Noddy
2
Pooh's Hundred Acre Wood Adventure
2
Princess and the Frog
2
Ratatouille
2
Scooby-Doo!
2
Sesame Street
2
Shrek
2
Shrek Forever After
3
Shrek the Third
2
Snow Park Challenge
2
Soccer Challenge
2
Spider-Man & Friends
2
Spongebob Squarepants
2
Super WHY!
3
Superman
2
Teletubbies
2
Thomas & Friends
2
Toy Story 2
2
Toy Story 3
2
Toy Story 3 (Motion)
3
Up
2
V.Smile Art Studio
0
V.Smile Jamming Gym Class
2
V.Smile PC Pal Island
2
V.Smile Smart Keyboard
2
Wall-E
2
Whiz Kid Wheels
2
Wiggles
2
Wild Waves
2
Winnie The Pooh
2
Wonder Pets!
2
Wow! Wow! Wubbzy!
2
Zayzoo
2