Add support for Atari 5200/7800, C64, Vectrex (thx to skaman)

This commit is contained in:
sanni 2023-09-23 00:11:08 +02:00
parent b373b662d2
commit 559010079c
32 changed files with 69804 additions and 65118 deletions

929
Cart_Reader/5200.ino Normal file
View File

@ -0,0 +1,929 @@
//******************************************
// ATARI 5200 MODULE
//******************************************
#ifdef enable_5200
// Atari 5200
// Cartridge Pinout
// 36P 2.54mm pitch connector
//
// RIGHT
// +-------+
// INTERLOCK -| 18 19 |- A0
// A2 -| 17 20 |- A1
// L A5 -| 16 21 |- A3
// A A6 -| 15 22 |- A4 B
// B GND -| 14 23 |- GND O
// E GND -| 13 24 |- GND T
// L GND -| 12 25 |- GND T
// N/C -| 11 26 |- +5V O
// /ENABLE 4000-7FFF -| 10 27 |- A7 M
// /ENABLE 8000-BFFF -| 9 28 |- N/C
// D7 -| 8 29 |- A8 S
// S D6 -| 7 30 |- AUD I
// I D5 -| 6 31 |- A9 D
// D D4 -| 5 32 |- A13 E
// E D3 -| 4 33 |- A10
// D2 -| 3 34 |- A12
// D1 -| 2 35 |- A11
// D0 -| 1 36 |- INTERLOCK
// +-------+
// LEFT
//
// LABEL SIDE
//
// /EN /EN
// D0 D1 D2 D3 D4 D5 D6 D7 80 40 -- GND GND GND A6 A5 A2 INT
// +--------------------------------------------------------------------------+
// | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
// LEFT | | RIGHT
// | 36 35 34 33 32 31 30 29 28 27 26 25 24 23 22 21 20 19 |
// +--------------------------------------------------------------------------+
// INT A11 A12 A10 A13 A9 AUD A8 -- A7 +5V GND GND GND A4 A3 A1 A0
//
// BOTTOM SIDE
// CONTROL PINS:
// /4000(PH5) - SNES /WR
// /8000(PH6) - SNES /RD
//******************************************
// Defines
//******************************************
#define DISABLE_4000 PORTH |= (1 << 5) // ROM SELECT 4000-7FFF
#define ENABLE_4000 PORTH &= ~(1 << 5)
#define DISABLE_8000 PORTH |= (1 << 6) // ROM SELECT 8000-BFFF
#define ENABLE_8000 PORTH &= ~(1 << 6)
//******************************************
// Supported Mappers
//******************************************
// Supported Mapper Array
// Format = {mapper,romsizelo,romsizehi}
static const byte PROGMEM a5200mapsize[] = {
0, 0, 3, // Standard 4K/8K/16K/32K
1, 2, 2, // Two Chip 16K
2, 4, 4, // Bounty Bob Strikes Back 40K [UNTESTED]
};
byte a5200mapcount = 3; // (sizeof(a5200mapsize) / sizeof(a5200mapsize[0])) / 3;
byte a5200mapselect;
int a5200index;
byte a5200[] = { 4, 8, 16, 32, 40 };
byte a5200lo = 0; // Lowest Entry
byte a5200hi = 4; // Highest Entry
byte a5200mapper = 0;
byte new5200mapper;
byte a5200size;
byte new5200size;
// EEPROM MAPPING
// 07 MAPPER
// 08 ROM SIZE
//******************************************
// Menu
//******************************************
// Base Menu
static const char a5200MenuItem1[] PROGMEM = "Select Cart";
static const char a5200MenuItem2[] PROGMEM = "Read ROM";
static const char a5200MenuItem3[] PROGMEM = "Set Mapper + Size";
static const char* const menuOptions5200[] PROGMEM = { a5200MenuItem1, a5200MenuItem2, a5200MenuItem3, string_reset2 };
void setup_5200() {
// Request 5V
setVoltage(VOLTS_SET_5V);
// Set Address Pins to Output
// Atari 5200 uses A0-A13 [A14-A23 UNUSED]
//A0-A7
DDRF = 0xFF;
//A8-A15
DDRK = 0xFF;
//A16-A23
DDRL = 0xFF;
// Set Control Pins to Output
// ---(PH0) ---(PH1) ---(PH3) ---(PH4) /4000(PH5) /8000(PH6)
DDRH |= (1 << 0) | (1 << 1) | (1 << 3) | (1 << 4) | (1 << 5) | (1 << 6);
// Set TIME(PJ0) to Output (UNUSED)
DDRJ |= (1 << 0);
// Set Pins (D0-D7) to Input
DDRC = 0x00;
// Setting Control Pins to HIGH
// ---(PH0) ---(PH1) ---(PH3) ---(PH4) /4000(PH5) /8000(PH6)
PORTH |= (1 << 0) | (1 << 1) | (1 << 3) | (1 << 4) | (1 << 5) | (1 << 6);
// Set Unused Data Pins (PA0-PA7) to Output
DDRA = 0xFF;
// Set Unused Pins HIGH
PORTA = 0xFF;
PORTL = 0xFF; // A16-A23
PORTJ |= (1 << 0); // TIME(PJ0)
checkStatus_5200();
strcpy(romName, "ATARI");
mode = mode_5200;
}
void a5200Menu() {
convertPgm(menuOptions5200, 4);
uint8_t mainMenu = question_box(F("ATARI 5200 MENU"), menuOptions, 4, 0);
switch (mainMenu) {
case 0:
// Select Cart
setCart_5200();
wait();
setup_5200();
break;
case 1:
// Read ROM
sd.chdir("/");
readROM_5200();
sd.chdir("/");
break;
case 2:
// Set Mapper + Size
setMapper_5200();
checkMapperSize_5200();
setROMSize_5200();
break;
case 3:
// reset
resetArduino();
break;
}
}
//******************************************
// READ CODE
//******************************************
uint8_t readData_5200(uint16_t addr) // Add Input Pullup
{
PORTF = addr & 0xFF; // A0-A7
PORTK = (addr >> 8) & 0xFF; // A8-A13
NOP;
NOP;
NOP;
NOP;
NOP;
// DDRC = 0x00; // Set to Input
PORTC = 0xFF; // Input Pullup
NOP;
NOP;
NOP;
NOP;
NOP;
// Extended Delay for Vanguard
NOP;
NOP;
NOP;
NOP;
NOP;
NOP;
NOP;
NOP;
NOP;
NOP;
uint8_t ret = PINC;
NOP;
NOP;
NOP;
NOP;
NOP;
return ret;
}
void readSegment_5200(uint16_t startaddr, uint16_t endaddr) {
for (uint16_t addr = startaddr; addr < endaddr; addr += 512) {
for (int w = 0; w < 512; w++) {
uint8_t temp = readData_5200(addr + w);
sdBuffer[w] = temp;
}
myFile.write(sdBuffer, 512);
}
}
//******************************************
// READ ROM
//******************************************
void readROM_5200() {
strcpy(fileName, romName);
strcat(fileName, ".a52");
// create a new folder for storing rom file
EEPROM_readAnything(0, foldern);
sprintf(folder, "5200/ROM/%d", foldern);
sd.mkdir(folder, true);
sd.chdir(folder);
display_Clear();
print_STR(saving_to_STR, 0);
print_Msg(folder);
println_Msg(F("/..."));
display_Update();
// open file on sdcard
if (!myFile.open(fileName, O_RDWR | O_CREAT))
print_FatalError(sd_error_STR);
// write new folder number back to EEPROM
foldern++;
EEPROM_writeAnything(0, foldern);
// 5200 A13-A0 = 10 0000 0000 0000
switch (a5200mapper) {
case 0: // Standard 4KB/8KB/16KB/32KB
// Lower Half of 32K is at 0x4000
if (a5200size == 3) { // 32K
ENABLE_4000;
readSegment_5200(0x4000, 0x8000); // +16K = 32K
DISABLE_4000;
}
// 4K/8K/16K + Upper Half of 32K
ENABLE_8000;
if (a5200size > 1)
readSegment_5200(0x8000, 0xA000); // +8K = 16K
if (a5200size > 0)
readSegment_5200(0xA000, 0xB000); // +4K = 8K
// Base 4K
readSegment_5200(0xB000, 0xC000); // 4K
DISABLE_8000;
break;
case 1: // Two Chip 16KB
ENABLE_4000;
readSegment_5200(0x4000, 0x6000); // 8K
DISABLE_4000;
ENABLE_8000;
readSegment_5200(0x8000, 0xA000); // +8K = 16K
DISABLE_8000;
break;
case 2: // Bounty Bob Strikes Back 40KB [UNTESTED]
ENABLE_4000;
// First 16KB (4KB x 4)
for (int w = 0; w < 4; w++) {
readData_5200(0x4FF6 + w);
readSegment_5200(0x4000, 0x4E00);
// Split Read of Last 0x200 bytes
for (int x = 0; x < 0x1F6; x++) {
sdBuffer[x] = readData_5200(0x4E00 + x);
}
myFile.write(sdBuffer, 502);
// Bank Registers 0x4FF6-0x4FF9
for (int y = 0; y < 4; y++) {
readData_5200(0x4FFF); // Reset Bank
sdBuffer[y] = readData_5200(0x4FF6 + y);
}
// End of Bank 0x4FFA-0x4FFF
readData_5200(0x4FFF); // Reset Bank
readData_5200(0x4FF6 + w); // Set Bank
for (int z = 4; z < 10; z++) {
sdBuffer[z] = readData_5200(0x4FF6 + z); // 0x4FFA-0x4FFF
}
myFile.write(sdBuffer, 10);
}
readData_5200(0x4FFF); // Reset Bank
// Second 16KB (4KB x 4)
for (int w = 0; w < 4; w++) {
readData_5200(0x5FF6 + w);
readSegment_5200(0x5000, 0x5E00);
// Split Read of Last 0x200 bytes
for (int x = 0; x < 0x1F6; x++) {
sdBuffer[x] = readData_5200(0x5E00 + x);
}
myFile.write(sdBuffer, 502);
// Bank Registers 0x5FF6-0x5FF9
for (int y = 0; y < 4; y++) {
readData_5200(0x5FFF); // Reset Bank
sdBuffer[y] = readData_5200(0x5FF6 + y);
}
// End of Bank 0x5FFA-0x5FFF
readData_5200(0x5FFF); // Reset Bank
readData_5200(0x5FF6 + w); // Set Bank
for (int z = 4; z < 10; z++) {
sdBuffer[z] = readData_5200(0x5FF6 + z); // 0x5FFA-0x5FFF
}
myFile.write(sdBuffer, 10);
}
readData_5200(0x5FFF); // Reset Bank
DISABLE_4000;
ENABLE_8000;
readSegment_5200(0x8000, 0xA000); // +8K = 40K
DISABLE_8000;
break;
}
myFile.close();
unsigned long crcsize = a5200[a5200size] * 0x400;
calcCRC(fileName, crcsize, NULL, 0);
println_Msg(F(""));
// Prints string out of the common strings array either with or without newline
print_STR(press_button_STR, 1);
display_Update();
wait();
}
//******************************************
// ROM SIZE
//******************************************
void checkMapperSize_5200() {
for (int i = 0; i < a5200mapcount; i++) {
a5200index = i * 3;
byte mapcheck = pgm_read_byte(a5200mapsize + a5200index);
if (mapcheck == a5200mapper) {
a5200lo = pgm_read_byte(a5200mapsize + a5200index + 1);
a5200hi = pgm_read_byte(a5200mapsize + a5200index + 2);
break;
}
}
}
void setROMSize_5200() {
#if (defined(enable_OLED) || defined(enable_LCD))
display_Clear();
if (a5200lo == a5200hi)
new5200size = a5200lo;
else {
int b = 0;
int i = a5200lo;
display_Clear();
print_Msg(F("ROM Size: "));
println_Msg(a5200[i]);
println_Msg(F(""));
#if defined(enable_OLED)
print_STR(press_to_change_STR, 1);
print_STR(right_to_select_STR, 1);
#elif defined(enable_LCD)
print_STR(rotate_to_change_STR, 1);
print_STR(press_to_select_STR, 1);
#endif
display_Update();
while (1) {
b = checkButton();
if (b == 2) { // Previous (doubleclick)
if (i == a5200lo)
i = a5200hi;
else
i--;
// Only update display after input because of slow LCD library
display_Clear();
print_Msg(F("ROM Size: "));
println_Msg(a5200[i]);
println_Msg(F(""));
#if defined(enable_OLED)
print_STR(press_to_change_STR, 1);
print_STR(right_to_select_STR, 1);
#elif defined(enable_LCD)
print_STR(rotate_to_change_STR, 1);
print_STR(press_to_select_STR, 1);
#endif
display_Update();
}
if (b == 1) { // Next (press)
if (i == a5200hi)
i = a5200lo;
else
i++;
// Only update display after input because of slow LCD library
display_Clear();
print_Msg(F("ROM Size: "));
println_Msg(a5200[i]);
println_Msg(F(""));
#if defined(enable_OLED)
print_STR(press_to_change_STR, 1);
print_STR(right_to_select_STR, 1);
#elif defined(enable_LCD)
print_STR(rotate_to_change_STR, 1);
print_STR(press_to_select_STR, 1);
#endif
display_Update();
}
if (b == 3) { // Long Press - Execute (hold)
new5200size = i;
break;
}
}
display.setCursor(0, 56); // Display selection at bottom
}
print_Msg(F("ROM SIZE "));
print_Msg(a5200[new5200size]);
println_Msg(F("K"));
display_Update();
delay(1000);
#else
if (a5200lo == a5200hi)
new5200size = a5200lo;
else {
setrom:
String sizeROM;
for (int i = 0; i < (a5200hi - a5200lo + 1); i++) {
Serial.print(F("Select ROM Size: "));
Serial.print(i);
Serial.print(F(" = "));
Serial.print(a5200[i + a5200lo]);
Serial.println(F("K"));
}
Serial.print(F("Enter ROM Size: "));
while (Serial.available() == 0) {}
sizeROM = Serial.readStringUntil('\n');
Serial.println(sizeROM);
new5200size = sizeROM.toInt() + a5200lo;
if (new5200size > a5200hi) {
Serial.println(F("SIZE NOT SUPPORTED"));
Serial.println(F(""));
goto setrom;
}
}
Serial.print(F("ROM Size = "));
Serial.print(a5200[new5200size]);
Serial.println(F("K"));
#endif
EEPROM_writeAnything(8, new5200size);
a5200size = new5200size;
}
void checkStatus_5200() {
EEPROM_readAnything(7, a5200mapper);
EEPROM_readAnything(8, a5200size);
if (a5200mapper > 2) {
a5200mapper = 0; // default STANDARD
EEPROM_writeAnything(7, a5200mapper);
}
if (a5200size > 4) {
a5200size = 1; // default 8K
EEPROM_writeAnything(8, a5200size);
}
#if (defined(enable_OLED) || defined(enable_LCD))
display_Clear();
println_Msg(F("ATARI 5200 READER"));
println_Msg(F("CURRENT SETTINGS"));
println_Msg(F(""));
print_Msg(F("MAPPER: "));
println_Msg(a5200mapper);
if (a5200mapper == 0)
println_Msg(F("STANDARD"));
else if (a5200mapper == 1)
println_Msg(F("TWO CHIP"));
else if (a5200mapper == 2)
println_Msg(F("BOUNTY BOB"));
print_Msg(F("ROM SIZE: "));
print_Msg(a5200[a5200size]);
println_Msg(F("K"));
display_Update();
wait();
#else
Serial.print(F("MAPPER: "));
Serial.println(a5200mapper);
if (a5200mapper == 0)
Serial.println(F("STANDARD"));
else if (a5200mapper == 1)
Serial.println(F("TWO CHIP"));
else if (a5200mapper == 2)
Serial.println(F("BOUNTY BOB"));
Serial.print(F("ROM SIZE: "));
Serial.print(a5200[a5200size]);
Serial.println(F("K"));
Serial.println(F(""));
#endif
}
//******************************************
// SET MAPPER
//******************************************
void setMapper_5200() {
#if (defined(enable_OLED) || defined(enable_LCD))
int b = 0;
int i = 0;
// Check Button Status
#if defined(enable_OLED)
buttonVal1 = (PIND & (1 << 7)); // PD7
#elif defined(enable_LCD)
boolean buttonVal1 = (PING & (1 << 2)); //PG2
#endif
if (buttonVal1 == LOW) { // Button Pressed
while (1) { // Scroll Mapper List
#if defined(enable_OLED)
buttonVal1 = (PIND & (1 << 7)); // PD7
#elif defined(enable_LCD)
buttonVal1 = (PING & (1 << 2)); //PG2
#endif
if (buttonVal1 == HIGH) { // Button Released
// Correct Overshoot
if (i == 0)
i = a5200mapcount - 1;
else
i--;
break;
}
display_Clear();
print_Msg(F("Mapper: "));
a5200index = i * 3;
a5200mapselect = pgm_read_byte(a5200mapsize + a5200index);
println_Msg(a5200mapselect);
if (a5200mapselect == 0)
println_Msg(F("STANDARD"));
else if (a5200mapselect == 1)
println_Msg(F("TWO CHIP"));
else if (a5200mapselect == 2)
println_Msg(F("BOUNTY BOB"));
display_Update();
if (i == (a5200mapcount - 1))
i = 0;
else
i++;
delay(250);
}
}
display_Clear();
print_Msg(F("Mapper: "));
a5200index = i * 3;
a5200mapselect = pgm_read_byte(a5200mapsize + a5200index);
println_Msg(a5200mapselect);
if (a5200mapselect == 0)
println_Msg(F("STANDARD"));
else if (a5200mapselect == 1)
println_Msg(F("TWO CHIP"));
else if (a5200mapselect == 2)
println_Msg(F("BOUNTY BOB"));
println_Msg(F(""));
#if defined(enable_OLED)
print_STR(press_to_change_STR, 1);
print_STR(right_to_select_STR, 1);
#elif defined(enable_LCD)
print_STR(rotate_to_change_STR, 1);
print_STR(press_to_select_STR, 1);
#endif
display_Update();
while (1) {
b = checkButton();
if (b == 2) { // Previous Mapper (doubleclick)
if (i == 0)
i = a5200mapcount - 1;
else
i--;
// Only update display after input because of slow LCD library
display_Clear();
print_Msg(F("Mapper: "));
a5200index = i * 3;
a5200mapselect = pgm_read_byte(a5200mapsize + a5200index);
println_Msg(a5200mapselect);
if (a5200mapselect == 0)
println_Msg(F("STANDARD"));
else if (a5200mapselect == 1)
println_Msg(F("TWO CHIP"));
else if (a5200mapselect == 2)
println_Msg(F("BOUNTY BOB"));
println_Msg(F(""));
#if defined(enable_OLED)
print_STR(press_to_change_STR, 1);
print_STR(right_to_select_STR, 1);
#elif defined(enable_LCD)
print_STR(rotate_to_change_STR, 1);
print_STR(press_to_select_STR, 1);
#endif
display_Update();
}
if (b == 1) { // Next Mapper (press)
if (i == (a5200mapcount - 1))
i = 0;
else
i++;
// Only update display after input because of slow LCD library
display_Clear();
print_Msg(F("Mapper: "));
a5200index = i * 3;
a5200mapselect = pgm_read_byte(a5200mapsize + a5200index);
println_Msg(a5200mapselect);
if (a5200mapselect == 0)
println_Msg(F("STANDARD"));
else if (a5200mapselect == 1)
println_Msg(F("TWO CHIP"));
else if (a5200mapselect == 2)
println_Msg(F("BOUNTY BOB"));
println_Msg(F(""));
#if defined(enable_OLED)
print_STR(press_to_change_STR, 1);
print_STR(right_to_select_STR, 1);
#elif defined(enable_LCD)
print_STR(rotate_to_change_STR, 1);
print_STR(press_to_select_STR, 1);
#endif
display_Update();
}
if (b == 3) { // Long Press - Execute (hold)
new5200mapper = a5200mapselect;
break;
}
}
display.setCursor(0, 56);
print_Msg(F("MAPPER "));
print_Msg(new5200mapper);
println_Msg(F(" SELECTED"));
display_Update();
delay(1000);
#else
setmapper:
String newmap;
Serial.println(F("SUPPORTED MAPPERS:"));
Serial.println(F("0 = Standard 4K/8K/16K/32K"));
Serial.println(F("1 = Two Chip 16K"));
Serial.println(F("2 = Bounty Bob Strikes Back 40K"));
Serial.print(F("Enter Mapper [0-2]: "));
while (Serial.available() == 0) {}
newmap = Serial.readStringUntil('\n');
Serial.println(newmap);
a5200index = newmap.toInt() * 3;
new5200mapper = pgm_read_byte(a5200mapsize + a5200index);
#endif
EEPROM_writeAnything(7, new5200mapper);
a5200mapper = new5200mapper;
}
//******************************************
// CART SELECT CODE
//******************************************
FsFile a5200csvFile;
char a5200game[39]; // title
char a5200mm[3]; // mapper
char a5200rr[3]; // romsize
char a5200ll[4]; // linelength (previous line)
unsigned long a5200csvpos; // CSV File Position
char a5200cartCSV[] = "5200cart.txt"; // CSV List
char a5200csvEND[] = "EOF"; // CSV End Marker for scrolling
bool readLine_5200(FsFile& f, char* line, size_t maxLen) {
for (size_t n = 0; n < maxLen; n++) {
int c = f.read();
if (c < 0 && n == 0) return false; // EOF
if (c < 0 || c == '\n') {
line[n] = 0;
return true;
}
line[n] = c;
}
return false; // line too long
}
bool readVals_5200(char* a5200game, char* a5200mm, char* a5200rr, char* a5200ll) {
char line[44];
a5200csvpos = a5200csvFile.position();
if (!readLine_5200(a5200csvFile, line, sizeof(line))) {
return false; // EOF or too long
}
char* comma = strtok(line, ",");
int x = 0;
while (comma != NULL) {
if (x == 0)
strcpy(a5200game, comma);
else if (x == 1)
strcpy(a5200mm, comma);
else if (x == 2)
strcpy(a5200rr, comma);
else if (x == 3)
strcpy(a5200ll, comma);
comma = strtok(NULL, ",");
x += 1;
}
return true;
}
bool getCartListInfo_5200() {
bool buttonreleased = 0;
bool cartselected = 0;
#if (defined(enable_OLED) || defined(enable_LCD))
display_Clear();
println_Msg(F(" HOLD TO FAST CYCLE"));
display_Update();
#else
Serial.println(F("HOLD BUTTON TO FAST CYCLE"));
#endif
delay(2000);
#if defined(enable_OLED)
buttonVal1 = (PIND & (1 << 7)); // PD7
#elif defined(enable_LCD)
boolean buttonVal1 = (PING & (1 << 2)); //PG2
#endif
if (buttonVal1 == LOW) { // Button Held - Fast Cycle
while (1) { // Scroll Game List
while (readVals_5200(a5200game, a5200mm, a5200rr, a5200ll)) {
if (strcmp(a5200csvEND, a5200game) == 0) {
a5200csvFile.seek(0); // Restart
} else {
#if (defined(enable_OLED) || defined(enable_LCD))
display_Clear();
println_Msg(F("CART TITLE:"));
println_Msg(F(""));
println_Msg(a5200game);
display_Update();
#else
Serial.print(F("CART TITLE:"));
Serial.println(a5200game);
#endif
#if defined(enable_OLED)
buttonVal1 = (PIND & (1 << 7)); // PD7
#elif defined(enable_LCD)
buttonVal1 = (PING & (1 << 2)); //PG2
#endif
if (buttonVal1 == HIGH) { // Button Released
buttonreleased = 1;
break;
}
if (buttonreleased) {
buttonreleased = 0; // Reset Flag
break;
}
}
}
#if defined(enable_OLED)
buttonVal1 = (PIND & (1 << 7)); // PD7
#elif defined(enable_LCD)
buttonVal1 = (PING & (1 << 2)); //PG2
#endif
if (buttonVal1 == HIGH) // Button Released
break;
}
}
#if (defined(enable_OLED) || defined(enable_LCD))
display.setCursor(0, 56);
println_Msg(F("FAST CYCLE OFF"));
display_Update();
#else
Serial.println(F(""));
Serial.println(F("FAST CYCLE OFF"));
Serial.println(F("PRESS BUTTON TO STEP FORWARD"));
Serial.println(F("DOUBLE CLICK TO STEP BACK"));
Serial.println(F("HOLD TO SELECT"));
Serial.println(F(""));
#endif
while (readVals_5200(a5200game, a5200mm, a5200rr, a5200ll)) {
if (strcmp(a5200csvEND, a5200game) == 0) {
a5200csvFile.seek(0); // Restart
} else {
#if (defined(enable_OLED) || defined(enable_LCD))
display_Clear();
println_Msg(F("CART TITLE:"));
println_Msg(F(""));
println_Msg(a5200game);
display.setCursor(0, 48);
#if defined(enable_OLED)
print_STR(press_to_change_STR, 1);
print_STR(right_to_select_STR, 1);
#elif defined(enable_LCD)
print_STR(rotate_to_change_STR, 1);
print_STR(press_to_select_STR, 1);
#endif
display_Update();
#else
Serial.print(F("CART TITLE:"));
Serial.println(a5200game);
#endif
while (1) { // Single Step
int b = checkButton();
if (b == 1) { // Continue (press)
break;
}
if (b == 2) { // Reset to Start of List (doubleclick)
byte prevline = strtol(a5200ll, NULL, 10);
a5200csvpos -= prevline;
a5200csvFile.seek(a5200csvpos);
break;
}
if (b == 3) { // Long Press - Select Cart (hold)
new5200mapper = strtol(a5200mm, NULL, 10);
new5200size = strtol(a5200rr, NULL, 10);
EEPROM_writeAnything(7, new5200mapper);
EEPROM_writeAnything(8, new5200size);
cartselected = 1; // SELECTION MADE
#if (defined(enable_OLED) || defined(enable_LCD))
println_Msg(F("SELECTION MADE"));
display_Update();
#else
Serial.println(F("SELECTION MADE"));
#endif
break;
}
}
if (cartselected) {
cartselected = 0; // Reset Flag
return true;
}
}
}
#if (defined(enable_OLED) || defined(enable_LCD))
println_Msg(F(""));
println_Msg(F("END OF FILE"));
display_Update();
#else
Serial.println(F("END OF FILE"));
#endif
return false;
}
void checkCSV_5200() {
if (getCartListInfo_5200()) {
#if (defined(enable_OLED) || defined(enable_LCD))
display_Clear();
println_Msg(F("CART SELECTED"));
println_Msg(F(""));
println_Msg(a5200game);
display_Update();
// Display Settings
display.setCursor(0, 56);
print_Msg(F("CODE: M"));
print_Msg(new5200mapper);
print_Msg(F("/R"));
println_Msg(new5200size);
display_Update();
#else
Serial.println(F(""));
Serial.println(F("CART SELECTED"));
Serial.println(a5200game);
// Display Settings
Serial.print(F("CODE: M"));
Serial.print(new5200mapper);
Serial.print(F("/R"));
Serial.println(new5200size);
Serial.println(F(""));
#endif
} else {
#if (defined(enable_OLED) || defined(enable_LCD))
display.setCursor(0, 56);
println_Msg(F("NO SELECTION"));
display_Update();
#else
Serial.println(F("NO SELECTION"));
#endif
}
}
void checkSize_5200() {
EEPROM_readAnything(7, a5200mapper);
for (int i = 0; i < a5200mapcount; i++) {
a5200index = i * 3;
if (a5200mapper == pgm_read_byte(a5200mapsize + a5200index)) {
a5200size = pgm_read_byte(a5200mapsize + a5200index + 1);
EEPROM_writeAnything(8, a5200size);
break;
}
}
}
void setCart_5200() {
#if (defined(enable_OLED) || defined(enable_LCD))
display_Clear();
println_Msg(a5200cartCSV);
display_Update();
#endif
sd.chdir();
sprintf(folder, "5200/CSV");
sd.chdir(folder); // Switch Folder
a5200csvFile = sd.open(a5200cartCSV, O_READ);
if (!a5200csvFile) {
#if (defined(enable_OLED) || defined(enable_LCD))
display_Clear();
println_Msg(F("CSV FILE NOT FOUND!"));
display_Update();
#else
Serial.println(F("CSV FILE NOT FOUND!"));
#endif
while (1) {
if (checkButton() != 0)
setup_5200();
}
}
checkCSV_5200();
a5200csvFile.close();
}
#endif

1021
Cart_Reader/7800.ino Normal file

File diff suppressed because it is too large Load Diff

1502
Cart_Reader/C64.ino Normal file

File diff suppressed because it is too large Load Diff

View File

@ -4,8 +4,8 @@
This project represents a community-driven effort to provide
an easy to build and easy to modify cartridge dumper.
Date: 2023-07-19
Version: 12.8
Date: 2023-09-22
Version: 12.9
SD lib: https://github.com/greiman/SdFat
LCD lib: https://github.com/olikraus/u8g2
@ -15,13 +15,13 @@
RTC lib: https://github.com/adafruit/RTClib
Frequency lib: https://github.com/PaulStoffregen/FreqCount
Compiled with Arduino IDE 2.1.1
Compiled with Arduino IDE 2.2.1
Thanks to:
MichlK - ROM Reader for Super Nintendo
Jeff Saltzman - 4-Way Button
Wayne and Layne - Video Game Shield menu
skaman - Cart ROM READER SNES ENHANCED, Famicom Cart Dumper, Coleco-, Intellivision, Virtual Boy, WSV, PCW, ARC, Atari, ODY2, Fairchild, MSX, Pokemon Mini modules
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
Tamanegi_taro - PCE and Satellaview modules
splash5 - GBSmart, Wonderswan, NGP and Super A'can modules
partlyhuman - Casio Loopy module
@ -39,7 +39,8 @@
jiyunomegami, splash5, Kreeblah, ramapcsx2, PsyK0p4T, Dakkaron, majorpbx, Pickle, sdhizumi,
Uzlopak, sakman55, Tombo89, scrap-a, borti4938, vogelfreiheit, CaitSith2, Modman,
philenotfound, karimhadjsalem, nsx0r, ducky92, niklasweber, Lesserkuma, BacteriaMage,
vpelletier, Ancyker, mattiacci, RWeick, joshman196, partlyhuman
vpelletier, Ancyker, mattiacci, RWeick, joshman196, partlyhuman, ButThouMust, hxlnt,
breyell
And to nocash for figuring out the secrets of the SFC Nintendo Power cartridge.
@ -252,6 +253,10 @@ void print_STR(byte string_number, boolean newline) {
#define mode_MSX 33
#define mode_POKE 34
#define mode_LOOPY 35
#define mode_C64 36
#define mode_5200 37
#define mode_7800 38
#define mode_VECTREX 39
// optimization-safe nop delay
#define NOP __asm__ __volatile__("nop\n\t")
@ -491,9 +496,9 @@ uint32_t calculateCRC(char* fileName, char* folder, int offset) {
}
/******************************************
CRC Functions for Atari, Fairchild, Ody2, Arc modules
CRC Functions for Atari, Fairchild, Ody2, Arc, etc. modules
*****************************************/
#if (defined(enable_ATARI) || defined(enable_ODY2) || defined(enable_ARC) || defined(enable_FAIRCHILD) || defined(enable_MSX) || defined(enable_POKE))
#if (defined(enable_ATARI) || defined(enable_ODY2) || defined(enable_ARC) || defined(enable_FAIRCHILD) || defined(enable_MSX) || defined(enable_POKE) || defined(enable_5200) || defined(enable_7800) || defined(enable_C64) || defined(enable_VECTREX))
inline uint32_t updateCRC(uint8_t ch, uint32_t crc) {
uint32_t idx = ((crc) ^ (ch)) & 0xff;
@ -885,12 +890,24 @@ static const char modeItem21[] PROGMEM = "Pokemon Mini (3V)";
#ifdef enable_LOOPY
static const char modeItem22[] PROGMEM = "Casio Loopy";
#endif
#ifdef enable_FLASH
static const char modeItem23[] PROGMEM = "Flashrom Programmer";
#ifdef enable_C64
static const char modeItem23[] PROGMEM = "Commodore 64";
#endif
static const char modeItem24[] PROGMEM = "Self Test (3V)";
static const char modeItem25[] PROGMEM = "About";
//static const char modeItem25[] PROGMEM = "Reset"; (stored in common strings array)
#ifdef enable_5200
static const char modeItem24[] PROGMEM = "Atari 5200";
#endif
#ifdef enable_7800
static const char modeItem25[] PROGMEM = "Atari 7800";
#endif
#ifdef enable_VECTREX
static const char modeItem26[] PROGMEM = "Vectrex";
#endif
#ifdef enable_FLASH
static const char modeItem27[] PROGMEM = "Flashrom Programmer";
#endif
static const char modeItem28[] PROGMEM = "Self Test (3V)";
static const char modeItem29[] PROGMEM = "About";
//static const char modeItem30[] PROGMEM = "Reset"; (stored in common strings array)
static const char* const modeOptions[] PROGMEM = {
#ifdef enable_GBX
modeItem1,
@ -958,10 +975,22 @@ static const char* const modeOptions[] PROGMEM = {
#ifdef enable_LOOPY
modeItem22,
#endif
#ifdef enable_FLASH
#ifdef enable_C64
modeItem23,
#endif
modeItem24, modeItem25, string_reset2
#ifdef enable_5200
modeItem24,
#endif
#ifdef enable_7800
modeItem25,
#endif
#ifdef enable_VECTREX
modeItem26,
#endif
#ifdef enable_FLASH
modeItem27,
#endif
modeItem28, modeItem29, string_reset2
};
// Count menu entries
@ -1033,6 +1062,18 @@ byte countMenuEntries() {
#ifdef enable_LOOPY
count++;
#endif
#ifdef enable_C64
count++;
#endif
#ifdef enable_5200
count++;
#endif
#ifdef enable_7800
count++;
#endif
#ifdef enable_VECTREX
count++;
#endif
#ifdef enable_FLASH
count++;
#endif
@ -1154,21 +1195,41 @@ unsigned char fixMenuOrder(unsigned char modeMenu) {
currentEntry++;
#endif
#if defined(enable_FLASH)
#if defined(enable_C64)
translationMatrix[currentEntry] = 22;
currentEntry++;
#endif
// Self Test
#if defined(enable_5200)
translationMatrix[currentEntry] = 23;
currentEntry++;
#endif
#if defined(enable_7800)
translationMatrix[currentEntry] = 24;
currentEntry++;
#endif
#if defined(enable_VECTREX)
translationMatrix[currentEntry] = 25;
currentEntry++;
#endif
#if defined(enable_FLASH)
translationMatrix[currentEntry] = 26;
currentEntry++;
#endif
// Self Test
translationMatrix[currentEntry] = 27;
currentEntry++;
// About
translationMatrix[currentEntry] = 24;
translationMatrix[currentEntry] = 28;
currentEntry++;
// Reset
translationMatrix[currentEntry] = 25;
translationMatrix[currentEntry] = 29;
currentEntry++;
return translationMatrix[modeMenu];
@ -1211,9 +1272,15 @@ void mainMenu() {
num_answers = menuCount - 14;
else
num_answers = 7;
} else { // currPage == 4
} else if (currPage == 4) {
option_offset = 21;
if (menuCount < 28)
num_answers = menuCount - 21;
else
num_answers = 7;
} else { // currPage == 5
option_offset = 28;
num_answers = menuCount - 28;
}
// Copy menuOptions out of progmem
convertPgm(modeOptions + option_offset, num_answers);
@ -1389,8 +1456,36 @@ void mainMenu() {
break;
#endif
#ifdef enable_FLASH
#ifdef enable_C64
case 22:
setup_C64();
c64Menu();
break;
#endif
#ifdef enable_5200
case 23:
setup_5200();
a5200Menu();
break;
#endif
#ifdef enable_7800
case 24:
setup_7800();
a7800Menu();
break;
#endif
#ifdef enable_VECTREX
case 25:
setup_VECTREX();
vectrexMenu();
break;
#endif
#ifdef enable_FLASH
case 26:
#ifdef ENABLE_VSELECT
setup_FlashVoltage();
#endif
@ -1399,16 +1494,16 @@ void mainMenu() {
#endif
#ifdef enable_selftest
case 23:
case 27:
selfTest();
break;
#endif
case 24:
case 28:
aboutScreen();
break;
case 25:
case 29:
resetArduino();
break;
@ -3590,7 +3685,26 @@ void loop() {
loopyMenu();
}
#endif
#ifdef enable_C64
else if (mode == mode_C64) {
c64Menu();
}
#endif
#ifdef enable_5200
else if (mode == mode_5200) {
a5200Menu();
}
#endif
#ifdef enable_7800
else if (mode == mode_7800) {
a7800Menu();
}
#endif
#ifdef enable_VECTREX
else if (mode == mode_VECTREX) {
vectrexMenu();
}
#endif
else {
display_Clear();
println_Msg(F("Menu Error"));

View File

@ -1,32 +1,32 @@
/********************************************************************
* Open Source Cartridge Reader *
Open Source Cartridge Reader
********************************************************************/
#ifndef CONFIG_H_
#define CONFIG_H_
/***** FIRMWARE CONFIGURATION **************************************
*
* Add or remove the "//" in front of items to toggle them.
*
* Disabled:
* //#define HW5
*
* Enabled:
* #define HW5
*
* Things in ** blocks like this are comments. Changing them doesn't
* affect the firmware that is flashed to your OSCR.
*
* If you only get a blank screen or "Press Button" message after
* flashing you have enabled too many modules.
*
Add or remove the "//" in front of items to toggle them.
Disabled:
//#define HW5
Enabled:
#define HW5
Things in ** blocks like this are comments. Changing them doesn't
affect the firmware that is flashed to your OSCR.
If you only get a blank screen or "Press Button" message after
flashing you have enabled too many modules.
********************************************************************/
/*==== HARDWARE VERSION ===========================================*/
/*
* Choose your hardware version:
Choose your hardware version:
*/
//#define HW5
@ -41,7 +41,7 @@
/*==== HARDWARE MODULES ===========================================*/
/* [ Automatic Voltage Selection ---------------------------------- ]
* Enable this if you have the VSELECT module.
Enable this if you have the VSELECT module.
*/
//#define ENABLE_VSELECT
@ -49,8 +49,8 @@
/****/
/* [ Clock Generator ---------------------------------------------- ]
* Enable this if you have the clock generator module. This will
* automatically be enabled if you selected HW2 or newer above.
Enable this if you have the clock generator module. This will
automatically be enabled if you selected HW2 or newer above.
*/
//#define clockgen_installed
@ -58,8 +58,8 @@
/****/
/* [ Real Time Clock ---------------------------------------------- ]
* Enable this if you have the RTC module. You can configure the
* type later in this file.
Enable this if you have the RTC module. You can configure the
type later in this file.
*/
//#define RTC_installed
@ -75,6 +75,20 @@
/****/
/* [ Atari 5200 --------------------------------------------------- ]
*/
//#define enable_5200
/****/
/* [ Atari 7800 --------------------------------------------------- ]
*/
//#define enable_7800
/****/
/* [ Benesse Pocket Challenge W ----------------------------------- ]
*/
@ -82,6 +96,13 @@
/****/
/* [ C64 --------------------------------------------------- ]
*/
//#define enable_C64
/****/
/* [ ColecoVision ------------------------------------------------- ]
*/
@ -106,7 +127,7 @@
/* [ Flashrom Programmer for SNES repros -------------------------- ]
*/
#define enable_FLASH
//#define enable_FLASH
//#define enable_FLASH16
/****/
@ -191,14 +212,14 @@
/* [ Super Famicom SF Memory Cassette ----------------------------- ]
*/
#define enable_SFM
//#define enable_SFM
/****/
/* [ Super Famicom Satellaview ------------------------------------ ]
*/
#define enable_SV
//#define enable_SV
/****/
@ -209,6 +230,13 @@
/****/
/* [ Vectrex --------------------------------------------------- ]
*/
//#define enable_VECTREX
/****/
/* [ Virtual Boy -------------------------------------------------- ]
*/
@ -247,10 +275,10 @@
/*==== FIRMWARE OPTIONS ===========================================*/
/* [ LCD: Background Color ---------------------------------------- ]
* Set the backlight color of the LCD if you have one.
*
* PARAMETERS:
* Green, Red, Blue
Set the backlight color of the LCD if you have one.
PARAMETERS:
Green, Red, Blue
*/
#define background_color 100, 0, 0
@ -258,12 +286,12 @@
/****/
/* [ 3.3V Stability Fix (3V3FIX) ---------------------------------- ]
* Enable this if you are having stability issues when using 3.3V,
* works best with VSELECT.
*
* If not using VSELECT, always turn the cart reader on with the
* voltage switch set to 5V and switch to 5V before selecting a
* cartridge from the menu.
Enable this if you are having stability issues when using 3.3V,
works best with VSELECT.
If not using VSELECT, always turn the cart reader on with the
voltage switch set to 5V and switch to 5V before selecting a
cartridge from the menu.
*/
//#define ENABLE_3V3FIX
@ -271,9 +299,9 @@
/****/
/* [ Updater ------------------------------------------------------ ]
* Disable this if you don't plan to/want to use the firmware
* updater utility. This setting is ignored on hardware versions
* other than HW5 and HW3.
Disable this if you don't plan to/want to use the firmware
updater utility. This setting is ignored on hardware versions
other than HW5 and HW3.
*/
#define ENABLE_UPDATER
@ -281,7 +309,7 @@
/****/
/* [ Self Test ---------------------------------------------------- ]
* Tests for shorts and other issues in your OSCR build.
Tests for shorts and other issues in your OSCR build.
*/
#define enable_selftest
@ -289,7 +317,7 @@
/****/
/* [ Logging ------------------------------------------------------ ]
* Write all info to OSCR_LOG.txt in root dir
Write all info to OSCR_LOG.txt in root dir
*/
#define global_log
@ -297,8 +325,8 @@
/****/
/* [ RTC: IC Type ------------------------------------------------- ]
* When the RTC module is installed, choose the type here. This
* setting is ignored if the RTC option is not enabled.
When the RTC module is installed, choose the type here. This
setting is ignored if the RTC option is not enabled.
*/
#define DS3231
@ -307,7 +335,7 @@
/****/
/* [ SNES Core/CLOCKGEN: Read Clock Generator Calibration Data ---- ]
* Toggle to use calibration data from snes_clk.txt
Toggle to use calibration data from snes_clk.txt
*/
//#define clockgen_calibration
@ -315,22 +343,22 @@
/****/
/* [ MegaDrive/Genesis Core: Compatibility Settings --------------- ]
* Allows you to create a text file on the SD card called
* "mdconf.txt" which you should place the following into:
*
* [segaSram16bit] N
*
* Where N is:
* 0: Output each byte once. Not supported by emulators. (default)
* 1: Duplicate each byte. Usable by Kega Fusion.
* 2: Same as 1 + pad with 0xFF so that the file size is 64KB.
Allows you to create a text file on the SD card called
"mdconf.txt" which you should place the following into:
[segaSram16bit] N
Where N is:
0: Output each byte once. Not supported by emulators. (default)
1: Duplicate each byte. Usable by Kega Fusion.
2: Same as 1 + pad with 0xFF so that the file size is 64KB.
*/
//#define use_md_conf
/*
* Alternatively, define it here by uncommenting and changing the
* following line. Setting both allows you to change the default.
Alternatively, define it here by uncommenting and changing the
following line. Setting both allows you to change the default.
*/
//#define DEFAULT_VALUE_segaSram16bit 0
@ -338,9 +366,9 @@
/****/
/* [ N64 Core: Fast CRC ------------------------------------------- ]
* Toggle so the CRC for N64 Roms will be calculated during dumping
* from memory instead of after dumping from SD card, not compatible
* with all Cart Readers
Toggle so the CRC for N64 Roms will be calculated during dumping
from memory instead of after dumping from SD card, not compatible
with all Cart Readers
*/
//#define fastcrc
@ -348,7 +376,7 @@
/****/
/* [ N64 Core: Log Summary ---------------------------------------- ]
* Enable to save a n64log.txt file with rom info in /N64/ROM
Enable to save a n64log.txt file with rom info in /N64/ROM
*/
//#define savesummarytotxt
@ -358,7 +386,7 @@
/*==== PROCESSING =================================================*/
/*
* You probably shouldn't change this stuff!
You probably shouldn't change this stuff!
*/
#if (defined(HW4) || defined(HW5))

View File

@ -1539,8 +1539,13 @@ bool getCartListInfo_MSX() {
println_Msg(F(""));
println_Msg(msxgame);
display.setCursor(0, 48);
println_Msg(F("Press to Change"));
println_Msg(F("Hold to Select"));
#if defined(enable_OLED)
print_STR(press_to_change_STR, 1);
print_STR(right_to_select_STR, 1);
#elif defined(enable_LCD)
print_STR(rotate_to_change_STR, 1);
print_STR(press_to_select_STR, 1);
#endif
display_Update();
#else
Serial.print(F("CART TITLE:"));

View File

@ -186,6 +186,9 @@ void snsMenu() {
#endif
resetArduino();
break;
default:
print_MissingModule(); // does not return
}
}

631
Cart_Reader/VECTREX.ino Normal file
View File

@ -0,0 +1,631 @@
//******************************************
// VECTREX MODULE
//******************************************
#ifdef enable_VECTREX
// Vectrex
// Cartridge Pinout
// 36P 2.54mm pitch connector
//
// RIGHT
// +-------+
// +5V -| 2 1 |- /HALT
// +5V -| 4 3 |- A7
// A8 -| 6 5 |- A6
// A9 -| 8 7 |- A5 B
// L A11 -| 10 9 |- A4 O
// A /OE -| 12 11 |- A3 T
// B A10 -| 14 13 |- A2 T
// E A15 -| 16 15 |- A1 O
// L D7 -| 18 17 |- A0 M
// D6 -| 20 19 |- D0
// S D5 -| 22 21 |- D1 S
// I D4 -| 24 23 |- D2 I
// D D3 -| 26 25 |- GND D
// E GND -| 28 27 |- GND E
// R/W -| 30 29 |- A12
// /CART -| 32 31 |- A13
// /NMI -| 34 33 |- A14
// /IRQ -| 36 35 |- PB6
// +-------+
// LEFT
//
// LABEL SIDE
//
// /IRQ /NMI /CART R/W GND D3 D4 D5 D6 D7 A15 A10 /OE A11 A9 A8 +5V +5V
// +-------------------------------------------------------------------------------------------+
// | 36 34 32 30 28 26 24 22 20 18 16 14 12 10 8 6 4 2 |
// LEFT | | RIGHT
// | 35 33 31 29 27 25 23 21 19 17 15 13 11 9 7 5 3 1 |
// +-------------------------------------------------------------------------------------------+
// PB6 A14 A13 A12 GND GND D2 D1 D0 A0 A1 A2 A3 A4 A5 A6 A7 /HALT
//
// BOTTOM SIDE
// CONTROL PINS:
// /OE(PH1) - SNES CPUCLK
// /CART(PH3) - SNES /CS
// PB6(PH5) - SNES /WR
// R/W(PH6) - SNES /RD
//******************************************
// Defines
//******************************************
#define CLK_ENABLE PORTH |= (1 << 1) // /E HIGH
#define CLK_DISABLE PORTH &= ~(1 << 1) // /E LOW
#define PB6_ENABLE PORTH |= (1 << 5) // PB6 HIGH
#define PB6_DISABLE PORTH &= ~(1 << 5) // PB6 LOW
byte VECTREX[] = { 4, 8, 12 };
byte vectrexlo = 0; // Lowest Entry
byte vectrexhi = 2; // Highest Entry
byte vectrexsize;
byte newvectrexsize;
// EEPROM MAPPING
// 08 ROM SIZE
//******************************************
// Menu
//******************************************
// Base Menu
static const char vectrexMenuItem1[] PROGMEM = "Select Cart";
static const char vectrexMenuItem2[] PROGMEM = "Read ROM";
static const char vectrexMenuItem3[] PROGMEM = "Set Size";
static const char* const menuOptionsVECTREX[] PROGMEM = { vectrexMenuItem1, vectrexMenuItem2, vectrexMenuItem3, string_reset2 };
void setup_VECTREX() {
// Request 5V
setVoltage(VOLTS_SET_5V);
// Set Address Pins to Output
// Vectrex uses A0-A15 [A16-A23 UNUSED]
//A0-A7
DDRF = 0xFF;
//A8-A15
DDRK = 0xFF;
//A16-A23
DDRL = 0xFF;
// Set Control Pins to Output
// ---(PH0) /OE(PH1) /CART(PH3) ---(PH4) PB6(PH5) R/W(PH6)
DDRH |= (1 << 0) | (1 << 1) | (1 << 3) | (1 << 4) | (1 << 5) | (1 << 6);
// Set TIME(PJ0) to Output (UNUSED)
DDRJ |= (1 << 0);
// Set Pins (D0-D7) to Input
DDRC = 0x00;
// Setting Control Pins to HIGH
// ---(PH0) /OE(PH1) /CART(PH3) ---(PH4) PB6(PH5) R/W(PH6)
PORTH |= (1 << 0) | (1 << 1) | (1 << 3) | (1 << 4) | (1 << 5) | (1 << 6);
// Set Unused Data Pins (PA0-PA7) to Output
DDRA = 0xFF;
// Set Unused Pins HIGH
PORTA = 0xFF;
PORTL = 0xFF; // A16-A23
PORTJ |= (1 << 0); // TIME(PJ0)
// Set /CART LOW
PORTH &= ~(1 << 3); // Enable Cart
// Set /OE LOW
PORTH &= ~(1 << 1); // Output Enable
checkStatus_VECTREX();
strcpy(romName, "VECTREX");
mode = mode_VECTREX;
}
void vectrexMenu() {
convertPgm(menuOptionsVECTREX, 4);
uint8_t mainMenu = question_box(F("VECTREX MENU"), menuOptions, 4, 0);
switch (mainMenu) {
case 0:
// Select Cart
setCart_VECTREX();
wait();
setup_VECTREX();
break;
case 1:
// Read ROM
sd.chdir("/");
readROM_VECTREX();
sd.chdir("/");
break;
case 2:
// Set Size
setROMSize_VECTREX();
break;
case 3:
// reset
resetArduino();
break;
}
}
//******************************************
// READ CODE
//******************************************
uint8_t readData_VECTREX(uint16_t addr) // Add Input Pullup
{
PORTF = addr & 0xFF; // A0-A7
PORTK = (addr >> 8) & 0xFF; // A8-A15
NOP;
NOP;
NOP;
NOP;
NOP;
PORTC = 0xFF; // Input Pullup
NOP;
NOP;
NOP;
NOP;
NOP;
NOP;
NOP;
NOP;
NOP;
NOP; // Added delay for better read
NOP;
NOP;
NOP;
NOP;
NOP;
uint8_t ret = PINC;
return ret;
}
void readSegment_VECTREX(uint16_t startaddr, uint16_t endaddr) {
for (uint16_t addr = startaddr; addr < endaddr; addr += 512) {
for (int w = 0; w < 512; w++) {
uint8_t temp = readData_VECTREX(addr + w);
sdBuffer[w] = temp;
}
myFile.write(sdBuffer, 512);
}
}
//******************************************
// READ ROM
//******************************************
void readROM_VECTREX() {
strcpy(fileName, romName);
strcat(fileName, ".vec");
// create a new folder for storing rom file
EEPROM_readAnything(0, foldern);
sprintf(folder, "VECTREX/ROM/%d", foldern);
sd.mkdir(folder, true);
sd.chdir(folder);
display_Clear();
print_STR(saving_to_STR, 0);
print_Msg(folder);
println_Msg(F("/..."));
display_Update();
// open file on sdcard
if (!myFile.open(fileName, O_RDWR | O_CREAT))
print_FatalError(sd_error_STR);
// write new folder number back to EEPROM
foldern++;
EEPROM_writeAnything(0, foldern);
PB6_DISABLE; // PB6 LOW - Switch Bank
// Standard Carts 4K/8K
readSegment_VECTREX(0x0000, 0x0400); // 1K
readSegment_VECTREX(0x0400, 0x0800); // +1K = 2K
readSegment_VECTREX(0x0800, 0x0C00); // +1K = 3K
readSegment_VECTREX(0x0C00, 0x1000); // +1K = 4K
if (vectrexsize > 0) {
readSegment_VECTREX(0x1000, 0x2000); // +4K = 8K
// Dark Tower 12K
if (vectrexsize > 1)
readSegment_VECTREX(0x2000, 0x3000); // +4K = 12K
// Oversize 32K Cart
if (vectrexsize > 2)
readSegment_VECTREX(0x3000, 0x8000); // +20K = 32K
// Oversize 64K Cart - PB6 Bankswitch
if (vectrexsize > 3) { // [UNTESTED]
PB6_ENABLE; // PB6 HIGH - Switch Bank
readSegment_VECTREX(0x0000, 0x8000); // +32K = 64K
PB6_DISABLE; // Reset PB6
}
}
myFile.close();
unsigned long crcsize = VECTREX[vectrexsize] * 0x400;
calcCRC(fileName, crcsize, NULL, 0);
println_Msg(F(""));
// Prints string out of the common strings array either with or without newline
print_STR(press_button_STR, 1);
display_Update();
wait();
}
//******************************************
// ROM SIZE
//******************************************
void setROMSize_VECTREX() {
#if (defined(enable_OLED) || defined(enable_LCD))
display_Clear();
if (vectrexlo == vectrexhi)
newvectrexsize = vectrexlo;
else {
int b = 0;
int i = vectrexlo;
display_Clear();
print_Msg(F("ROM Size: "));
println_Msg(VECTREX[i]);
println_Msg(F(""));
#if defined(enable_OLED)
print_STR(press_to_change_STR, 1);
print_STR(right_to_select_STR, 1);
#elif defined(enable_LCD)
print_STR(rotate_to_change_STR, 1);
print_STR(press_to_select_STR, 1);
#endif
display_Update();
while (1) {
b = checkButton();
if (b == 2) { // Previous (doubleclick)
if (i == vectrexlo)
i = vectrexhi;
else
i--;
display_Clear();
print_Msg(F("ROM Size: "));
println_Msg(VECTREX[i]);
println_Msg(F(""));
#if defined(enable_OLED)
print_STR(press_to_change_STR, 1);
print_STR(right_to_select_STR, 1);
#elif defined(enable_LCD)
print_STR(rotate_to_change_STR, 1);
print_STR(press_to_select_STR, 1);
#endif
display_Update();
}
if (b == 1) { // Next (press)
if (i == vectrexhi)
i = vectrexlo;
else
i++;
display_Clear();
print_Msg(F("ROM Size: "));
println_Msg(VECTREX[i]);
println_Msg(F(""));
#if defined(enable_OLED)
print_STR(press_to_change_STR, 1);
print_STR(right_to_select_STR, 1);
#elif defined(enable_LCD)
print_STR(rotate_to_change_STR, 1);
print_STR(press_to_select_STR, 1);
#endif
display_Update();
}
if (b == 3) { // Long Press - Execute (hold)
newvectrexsize = i;
break;
}
}
display.setCursor(0, 56); // Display selection at bottom
}
print_Msg(F("ROM SIZE "));
print_Msg(VECTREX[newvectrexsize]);
println_Msg(F("K"));
display_Update();
delay(1000);
#else
if (vectrexlo == vectrexhi)
newvectrexsize = vectrexlo;
else {
setrom:
String sizeROM;
for (int i = 0; i < (vectrexhi - vectrexlo + 1); i++) {
Serial.print(F("Select ROM Size: "));
Serial.print(i);
Serial.print(F(" = "));
Serial.print(VECTREX[i + vectrexlo]);
Serial.println(F("K"));
}
Serial.print(F("Enter ROM Size: "));
while (Serial.available() == 0) {}
sizeROM = Serial.readStringUntil('\n');
Serial.println(sizeROM);
newvectrexsize = sizeROM.toInt() + vectrexlo;
if (newvectrexsize > vectrexhi) {
Serial.println(F("SIZE NOT SUPPORTED"));
Serial.println(F(""));
goto setrom;
}
}
Serial.print(F("ROM Size = "));
Serial.print(VECTREX[newvectrexsize]);
Serial.println(F("K"));
#endif
EEPROM_writeAnything(8, newvectrexsize);
vectrexsize = newvectrexsize;
}
void checkStatus_VECTREX() {
EEPROM_readAnything(8, vectrexsize);
if (vectrexsize > 2) {
vectrexsize = 0; // default 4KB
EEPROM_writeAnything(8, vectrexsize);
}
#if (defined(enable_OLED) || defined(enable_LCD))
display_Clear();
println_Msg(F("VECTREX READER"));
println_Msg(F("CURRENT SETTINGS"));
println_Msg(F(""));
print_Msg(F("ROM SIZE: "));
print_Msg(VECTREX[vectrexsize]);
println_Msg(F("K"));
display_Update();
wait();
#else
Serial.print(F("ROM SIZE: "));
Serial.print(VECTREX[vectrexsize]);
Serial.println(F("K"));
Serial.println(F(""));
#endif
}
//******************************************
// CART SELECT CODE
//******************************************
FsFile vectrexcsvFile;
char vectrexgame[25]; // title
char vectrexrr[4]; // romsize
char vectrexll[4]; // linelength (previous line)
unsigned long vectrexcsvpos; // CSV File Position
char vectrexcartCSV[] = "vectrexcart.txt"; // CSV List
char vectrexcsvEND[] = "EOF"; // CSV End Marker for scrolling
bool readLine_VECTREX(FsFile& f, char* line, size_t maxLen) {
for (size_t n = 0; n < maxLen; n++) {
int c = f.read();
if (c < 0 && n == 0) return false; // EOF
if (c < 0 || c == '\n') {
line[n] = 0;
return true;
}
line[n] = c;
}
return false; // line too long
}
bool readVals_VECTREX(char* vectrexgame, char* vectrexrr, char* vectrexll) {
char line[31];
vectrexcsvpos = vectrexcsvFile.position();
if (!readLine_VECTREX(vectrexcsvFile, line, sizeof(line))) {
return false; // EOF or too long
}
char* comma = strtok(line, ",");
int x = 0;
while (comma != NULL) {
if (x == 0)
strcpy(vectrexgame, comma);
else if (x == 1)
strcpy(vectrexrr, comma);
else if (x == 2)
strcpy(vectrexll, comma);
comma = strtok(NULL, ",");
x += 1;
}
return true;
}
bool getCartListInfo_VECTREX() {
bool buttonreleased = 0;
bool cartselected = 0;
#if (defined(enable_OLED) || defined(enable_LCD))
display_Clear();
println_Msg(F(" HOLD TO FAST CYCLE"));
display_Update();
#else
Serial.println(F("HOLD BUTTON TO FAST CYCLE"));
#endif
delay(2000);
#if defined(enable_OLED)
buttonVal1 = (PIND & (1 << 7)); // PD7
#elif defined(enable_LCD)
boolean buttonVal1 = (PING & (1 << 2)); //PG2
#endif
if (buttonVal1 == LOW) { // Button Held - Fast Cycle
while (1) { // Scroll Game List
while (readVals_VECTREX(vectrexgame, vectrexrr, vectrexll)) {
if (strcmp(vectrexcsvEND, vectrexgame) == 0) {
vectrexcsvFile.seek(0); // Restart
} else {
#if (defined(enable_OLED) || defined(enable_LCD))
display_Clear();
println_Msg(F("CART TITLE:"));
println_Msg(F(""));
println_Msg(vectrexgame);
display_Update();
#else
Serial.print(F("CART TITLE:"));
Serial.println(vectrexgame);
#endif
#if defined(enable_OLED)
buttonVal1 = (PIND & (1 << 7)); // PD7
#elif defined(enable_LCD)
boolean buttonVal1 = (PING & (1 << 2)); //PG2
#endif
if (buttonVal1 == HIGH) { // Button Released
buttonreleased = 1;
break;
}
if (buttonreleased) {
buttonreleased = 0; // Reset Flag
break;
}
}
}
#if defined(enable_OLED)
buttonVal1 = (PIND & (1 << 7)); // PD7
#elif defined(enable_LCD)
boolean buttonVal1 = (PING & (1 << 2)); //PG2
#endif
if (buttonVal1 == HIGH) // Button Released
break;
}
}
#if (defined(enable_OLED) || defined(enable_LCD))
display.setCursor(0, 56);
println_Msg(F("FAST CYCLE OFF"));
display_Update();
#else
Serial.println(F(""));
Serial.println(F("FAST CYCLE OFF"));
Serial.println(F("PRESS BUTTON TO STEP FORWARD"));
Serial.println(F("DOUBLE CLICK TO STEP BACK"));
Serial.println(F("HOLD TO SELECT"));
Serial.println(F(""));
#endif
while (readVals_VECTREX(vectrexgame, vectrexrr, vectrexll)) {
if (strcmp(vectrexcsvEND, vectrexgame) == 0) {
vectrexcsvFile.seek(0); // Restart
} else {
#if (defined(enable_OLED) || defined(enable_LCD))
display_Clear();
println_Msg(F("CART TITLE:"));
println_Msg(F(""));
println_Msg(vectrexgame);
display.setCursor(0, 48);
#if defined(enable_OLED)
print_STR(press_to_change_STR, 1);
print_STR(right_to_select_STR, 1);
#elif defined(enable_LCD)
print_STR(rotate_to_change_STR, 1);
print_STR(press_to_select_STR, 1);
#endif
display_Update();
#else
Serial.print(F("CART TITLE:"));
Serial.println(vectrexgame);
#endif
while (1) { // Single Step
int b = checkButton();
if (b == 1) { // Continue (press)
break;
}
if (b == 2) { // Reset to Start of List (doubleclick)
byte prevline = strtol(vectrexll, NULL, 10);
vectrexcsvpos -= prevline;
vectrexcsvFile.seek(vectrexcsvpos);
break;
}
if (b == 3) { // Long Press - Select Cart (hold)
newvectrexsize = strtol(vectrexrr, NULL, 10);
EEPROM_writeAnything(8, newvectrexsize);
cartselected = 1; // SELECTION MADE
#if (defined(enable_OLED) || defined(enable_LCD))
println_Msg(F("SELECTION MADE"));
display_Update();
#else
Serial.println(F("SELECTION MADE"));
#endif
break;
}
}
if (cartselected) {
cartselected = 0; // Reset Flag
return true;
}
}
}
#if (defined(enable_OLED) || defined(enable_LCD))
println_Msg(F(""));
println_Msg(F("END OF FILE"));
display_Update();
#else
Serial.println(F("END OF FILE"));
#endif
return false;
}
void checkCSV_VECTREX() {
if (getCartListInfo_VECTREX()) {
#if (defined(enable_OLED) || defined(enable_LCD))
display_Clear();
println_Msg(F("CART SELECTED"));
println_Msg(F(""));
println_Msg(vectrexgame);
display_Update();
// Display Settings
display.setCursor(0, 56);
print_Msg(F("CODE: R"));
println_Msg(newvectrexsize);
display_Update();
#else
Serial.println(F(""));
Serial.println(F("CART SELECTED"));
Serial.println(vectrexgame);
// Display Settings
Serial.print(F("CODE: R"));
Serial.println(newvectrexsize);
Serial.println(F(""));
#endif
} else {
#if (defined(enable_OLED) || defined(enable_LCD))
display.setCursor(0, 56);
println_Msg(F("NO SELECTION"));
display_Update();
#else
Serial.println(F("NO SELECTION"));
#endif
}
}
void setCart_VECTREX() {
#if (defined(enable_OLED) || defined(enable_LCD))
display_Clear();
println_Msg(vectrexcartCSV);
display_Update();
#endif
sd.chdir();
sprintf(folder, "VECTREX/CSV");
sd.chdir(folder); // Switch Folder
vectrexcsvFile = sd.open(vectrexcartCSV, O_READ);
if (!vectrexcsvFile) {
#if (defined(enable_OLED) || defined(enable_LCD))
display_Clear();
println_Msg(F("CSV FILE NOT FOUND!"));
display_Update();
#else
Serial.println(F("CSV FILE NOT FOUND!"));
#endif
while (1) {
if (checkButton() != 0)
setup_VECTREX();
}
}
checkCSV_VECTREX();
vectrexcsvFile.close();
}
#endif

76
sd/5200cart.txt Normal file
View File

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

71
sd/7800cart.txt Normal file
View File

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

274
sd/c64cart.txt Normal file
View File

@ -0,0 +1,274 @@
128er Quickload,0,1,1,0
256K-EPROM-System,0,1,1,25
64 Doctor,0,1,1,28
64MON,0,1,1,20
Action Cartridge Plus,1,5,0,16
Action Replay Professional,1,5,0,32
Activision Decathlon,0,3,0,37
Adventure 1,0,3,0,31
Adventure 3,0,3,0,22
Adventure Creator,0,3,0,22
Aegean Voyage,0,3,0,28
After the War,17,7,1,24
Alf in the Color Caves,0,3,0,25
Alien Sidestep,0,1,0,33
Alpha Build,0,1,0,25
Alphabet Zoo,0,3,0,22
Arnie Armchair's Howzat Cricket Game,0,3,0,23
Astroblitz,0,1,0,47
Attack of the Mutant Camels,0,1,1,21
Avenger (MAX),0,1,2,38
BadLands,5,6,1,24
Batman,5,7,1,19
Battle Command,5,7,1,17
Battlezone,0,3,0,25
BC's Quest for Tires,0,3,0,21
Beamrider,0,3,0,31
Big Bird's Funhouse,0,3,0,20
Big Bird's Special Delivery,0,3,0,30
Black Box,0,3,0,38
Blueprint,0,3,0,20
Bowling (MAX),0,3,2,20
Bridge 64,0,3,0,24
Bubble Burst,0,3,0,20
Buck Rogers,0,3,0,23
Bug Crusher,0,1,0,22
C-64 Diagnostic,0,1,1,22
C-64 Import Test Diag,0,1,1,26
C64-FORTH,0,2,3,32
Calc Result Advanced,0,1,1,20
Castle Hassle,0,3,0,31
Centipede,0,1,0,24
Chase H.Q. II,5,8,0,20
Checkers,0,3,0,24
Choplifter!,0,3,0,19
Close Encounters of the Worst Kind,0,1,0,22
Clowns (MAX),0,1,2,45
Coccinelle cherche dessinateur,0,1,1,23
Coco-Notes,0,3,0,41
Colossus Chess +2,8,6,0,21
COMAL 80,21,6,0,28
Commodore 64 Diagnostic,0,1,1,20
Congo Bongo,0,3,0,34
Conrad Disk Booster,0,1,1,22
Cosmic Life,0,1,0,30
Crisis Mountain,0,3,0,22
Cyberball,5,7,1,26
Dance Fantasy,0,1,0,20
Dancing Feats,0,3,0,24
Defender,0,3,0,24
Dela S-4-Modul,0,1,1,19
Delta Drawing,0,3,0,25
Der Rechenlowe,11,3,0,24
Der Rechtschreiblowe,11,3,0,26
Designer's Pencil,0,3,0,32
Diamond Mine,0,3,0,28
Diary 64,0,1,1,23
Dig Dug,0,3,0,19
Doc'64,0,1,1,18
Donkey Kong,0,3,0,17
Dot Gobbler,0,1,0,22
Double Dragon (HES),19,7,1,22
Double Dragon (Ocean),5,7,1,31
Dragonsden,0,3,0,32
Ducks Ahoy!,0,3,0,21
Electronic Mailbox-64,0,1,1,22
Epyx Fast Load Cartridge,10,1,3,32
Ernie's Magic Shapes,0,3,0,36
Espial,0,3,0,31
ExBASIC Level II,0,1,1,17
Expert,6,1,3,27
Facemaker,0,1,0,17
Falconian Invaders,0,1,1,20
Fiendish Freddy's Big Top o' Fun +3,15,9,1,29
Final Cartridge,13,3,3,47
Final Cartridge III,3,6,3,27
Financial Advisor,0,1,1,30
Format- und Hardcopymodul,12,1,1,28
Fraction Fever,0,1,0,37
Frog Master,0,1,1,25
Frogger,0,3,0,22
Frogger +3,19,6,1,18
Frogger II,0,3,0,22
Galaxian,0,3,0,21
Galaxions +1,0,3,0,19
Gateway to Apshai,0,3,0,23
Ghostbusters,5,5,1,28
Gorf,0,3,0,23
Graf 64,0,1,1,15
Gridrunner,0,1,0,18
Gridrunner II,0,1,0,21
Gyruss,0,3,0,24
H.E.R.O.,0,3,0,17
Halftime Battlin' Bands,0,3,0,19
Happy-Packer,12,1,1,34
HES Mon 64,0,1,1,24
HES Writer 64,0,1,1,21
Hop Along Counting,0,1,0,24
Human Skeleton Tutorial,0,1,1,29
Hypra-Disk-Modul II,0,1,1,34
International Football,0,3,0,30
Jack Attack,0,3,0,33
James Bond 007,0,3,0,22
Jawbreaker,0,1,0,25
Juice!,0,3,0,21
Jukebox,0,1,0,17
Jumpman Junior,0,3,0,18
Jungle Hunt,0,3,0,25
Jupiter Lander (MAX),0,1,2,22
Kickman (MAX),0,1,2,31
Kids on Keys,0,1,0,24
Kindercomp,0,1,0,23
Kung-Fu Master,5,5,1,21
Laser Cycles,0,1,0,25
Lazarian,0,3,0,23
Lazer Zone,0,1,0,19
Leader Board,5,5,1,21
Learning with Leeper,0,3,0,23
LeMans (MAX),0,1,2,31
Linking Logic,0,3,0,23
Lode Runner,0,3,0,24
Logic Levels,0,3,0,22
Lunar Leeper,0,3,0,23
Magic Desk I,19,5,1,23
Magic Formel,14,6,3,24
Mario's Brewery,0,1,0,24
MasterType,0,3,0,26
Math Mileage,0,3,0,21
MAX BASIC (MAX),0,3,2,23
Maze Man,0,1,0,26
Maze Master,0,3,0,19
Memory Manor,0,1,0,22
MicroProse Soccer +2,7,7,0,23
Miner 2049er,0,3,0,31
MINI BASIC I (MAX),0,1,2,23
Minnesota Fat's Pool Challenger,0,1,0,29
Mole Attack (MAX),0,1,2,42
Money Wars (MAX),0,1,2,28
Moon Patrol,0,3,0,27
Moondust,0,1,1,22
Motor Mania,0,3,0,19
Mountain King,0,3,0,22
Movie Musical Madness,0,3,0,24
Mr. Cool,0,1,0,32
Mr. TNT,0,1,0,19
Ms. Pac-Man,0,3,0,18
Muistio 64,0,1,1,22
Music Composer (MAX),0,1,2,21
Music Machine (MAX),0,1,2,31
Myth,15,9,1,30
Narco Police,17,7,1,16
Navy SEALs,5,7,0,24
Ninja Remix,15,9,1,21
Nordic Power Action Cartridge,9,5,0,23
Nova Blast,0,3,0,40
Number Nabber Shape Grabber,0,1,1,21
Number Tumblers,0,1,0,38
Oil's Well,0,3,0,26
Omega Race,0,1,1,21
Omega Race (MAX),0,1,2,21
Pac-Man,0,1,0,27
Paint Brush,0,3,0,18
Pancho,0,3,0,22
Pang,5,7,1,17
Park Patrol,19,5,1,15
Pastfinder,0,3,0,23
Peanut Butter Panic,0,3,0,21
Pinball Spectacular (MAX),0,3,2,30
Pipes,0,1,0,36
Pit,0,1,0,16
Pitfall II,0,3,0,14
Pitfall!,0,1,1,21
Pitstop,0,3,0,19
Pole Position,0,3,0,18
Popeye,0,3,0,24
Power Cartridge,2,3,0,17
Princess and the Frog,0,3,0,26
Professional Skateboard Simulator +2,7,7,0,32
PS-64t,0,1,1,47
Q-bert,0,3,0,17
Rack 'em Up!,0,3,0,17
Radar Rat Race(MAX),0,1,2,23
Ranch,0,3,0,30
Retro Ball,0,1,1,16
REX-Ramfloppy,0,1,1,21
River Raid,0,3,0,24
Road Race (MAX),0,1,2,21
RoboCop 2,5,8,0,26
RoboCop 3,5,7,0,20
Robotron - 2084,0,3,0,20
Rootin' Tootin',0,3,0,26
Sales Cartridge,0,3,0,26
Sammy Lightfoot,0,3,0,26
Satan,17,7,1,26
Save New York,0,1,0,17
Sea Speller,0,1,0,24
Sea Wolf (MAX),0,1,2,22
Seafox,0,3,0,25
Seahorse Hide'n Seek,0,3,0,17
Serpentine,0,3,0,31
Sesame Street,0,3,0,21
Shadow of the Beast,5,8,0,24
Simons' BASIC,4,3,1,30
Solar Fox,0,3,0,24
Song Maker,0,1,0,20
Space Action,0,1,0,21
Space Gun,5,8,1,23
Space Ric-O-Shay,0,1,0,20
Space Shuttle,0,3,0,27
Speed Math & Bingo Math (MAX),0,1,2,24
Speedsaver $C000,0,0,2,40
Speedsaver Combi,0,1,1,27
Spitball,0,1,1,27
Spy Hunter,0,3,0,19
Star Post,0,1,1,21
Star Ranger,0,3,0,20
Star Trek,0,3,0,22
Star Wars,0,3,0,20
Stat 64,0,1,1,20
States and Capitals Tutorial,0,1,1,18
Stix,0,1,0,39
Story Machine,0,3,0,15
Super Alien (MAX),0,1,2,24
Super Expander 64,0,1,1,28
Super Sketch,0,1,1,28
Super Smash,0,1,1,23
Super Snapshot 5,20,6,3,22
Super Zaxxon,18,4,0,28
Tank Wars,0,1,0,24
Tapper,0,3,0,20
Teledata,0,1,1,17
Tennis,19,5,1,19
Tenpins,0,1,1,18
Tenpins +2,19,5,1,18
Terminator 2 +2,5,9,1,22
Threshold,0,1,0,26
Timebound,0,3,0,20
Toki,5,7,0,20
Tool-64,0,1,1,15
Tooth Invaders,0,3,0,18
Toy Bizarre,0,3,0,25
Trashman,0,1,0,22
Turbo Maze Man,0,1,0,19
Tyler's Dungeons,0,1,0,25
Ultrex Quadro Maze,0,1,1,27
Up & Add'Em,0,3,0,29
Up for Grabs,0,1,0,22
Up'n Down,0,3,0,23
Utah Counties Tutorial,0,1,1,20
VIC-Text 64,0,3,0,33
Viduzzles,0,3,0,22
Viking Raider,0,3,0,20
Vindicators,5,6,1,24
Visible Solar System (MAX),0,1,2,22
Warp Speed,16,3,3,37
Webster,0,3,0,22
Wizard of Id's Wiztype,0,3,0,18
Wizard of Wor,0,3,0,33
Wizard of Wor (MAX),0,1,2,24
Wonder Boy,5,6,1,30
Write Now! 64,0,3,0,21
Zaxxon,18,4,0,24
Zenji,0,3,0,18
Zone Ranger,0,3,0,16
EOF,0,0,0,0

32
sd/vectrexcart.txt Normal file
View File

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