Upload Files
More info: Also added Pocket SNES PCB by Niltonn https://forum.arduino.cc/index.php?topic=158974.msg4381465#msg4381465
@ -2,15 +2,15 @@
|
|||||||
Cartridge Reader for Arduino Mega2560
|
Cartridge Reader for Arduino Mega2560
|
||||||
|
|
||||||
Author: sanni
|
Author: sanni
|
||||||
Date: 12.11.2019
|
Date: 27.11.2019
|
||||||
Version: 4.1
|
Version: 4.2
|
||||||
|
|
||||||
SD lib: https://github.com/greiman/SdFat
|
SD lib: https://github.com/greiman/SdFat
|
||||||
LCD lib: https://github.com/adafruit/Adafruit_SSD1306
|
LCD lib: https://github.com/adafruit/Adafruit_SSD1306
|
||||||
Clockgen: https://github.com/etherkit/Si5351Arduino
|
Clockgen: https://github.com/etherkit/Si5351Arduino
|
||||||
RGB Tools lib: https://github.com/joushx/Arduino-RGB-Tools
|
RGB Tools lib: https://github.com/joushx/Arduino-RGB-Tools
|
||||||
|
|
||||||
Compiled with Arduino 1.8.9 and Arduino AVR Boards Version 1.6.21
|
Compiled with Arduino 1.8.10
|
||||||
|
|
||||||
Thanks to:
|
Thanks to:
|
||||||
MichlK - ROM-Reader for Super Nintendo
|
MichlK - ROM-Reader for Super Nintendo
|
||||||
@ -43,7 +43,7 @@
|
|||||||
**********************************************************************************/
|
**********************************************************************************/
|
||||||
#include <SdFat.h>
|
#include <SdFat.h>
|
||||||
|
|
||||||
char ver[5] = "4.1";
|
char ver[5] = "4.2";
|
||||||
|
|
||||||
/******************************************
|
/******************************************
|
||||||
Options
|
Options
|
||||||
|
@ -283,7 +283,7 @@ void mdCartMenu() {
|
|||||||
print_Error(F("Cart has no EEPROM"), false);
|
print_Error(F("Cart has no EEPROM"), false);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 5:
|
case 5:
|
||||||
// For multi-game carts
|
// For multi-game carts
|
||||||
// Set reset pin to output (PH0)
|
// Set reset pin to output (PH0)
|
||||||
|
@ -1314,14 +1314,14 @@ setram:
|
|||||||
// Mapper 4 includes both MMC3 AND MMC6
|
// Mapper 4 includes both MMC3 AND MMC6
|
||||||
// RAM is mapped differently between MMC3 and MMC6
|
// RAM is mapped differently between MMC3 and MMC6
|
||||||
void checkMMC6() { // Detect MMC6 Carts - read PRG 0x3E00A ("STARTROPICS")
|
void checkMMC6() { // Detect MMC6 Carts - read PRG 0x3E00A ("STARTROPICS")
|
||||||
write_prg_byte(0x8000, 6); // PRG Bank 0 ($8000-$9FFF)
|
write_prg_byte(0x8000, 6); // PRG Bank 0 ($8000-$9FFF)
|
||||||
write_prg_byte(0x8001, 0x1F); // 0x3E000
|
write_prg_byte(0x8001, 0x1F); // 0x3E000
|
||||||
prgchk0 = read_prg_byte(0x800A);
|
prgchk0 = read_prg_byte(0x800A);
|
||||||
prgchk1 = read_prg_byte(0x800B);
|
prgchk1 = read_prg_byte(0x800B);
|
||||||
prgchk2 = read_prg_byte(0x800C);
|
prgchk2 = read_prg_byte(0x800C);
|
||||||
prgchk3 = read_prg_byte(0x800D);
|
prgchk3 = read_prg_byte(0x800D);
|
||||||
if ((prgchk0 == 0x53) && (prgchk1 == 0x54) && (prgchk2 == 0x41) && (prgchk3 == 0x52))
|
if ((prgchk0 == 0x53) && (prgchk1 == 0x54) && (prgchk2 == 0x41) && (prgchk3 == 0x52))
|
||||||
mmc6 = true; // MMC6 Cart
|
mmc6 = true; // MMC6 Cart
|
||||||
}
|
}
|
||||||
|
|
||||||
void checkStatus_NES() {
|
void checkStatus_NES() {
|
||||||
@ -2705,7 +2705,7 @@ void writeRAM() {
|
|||||||
case 0: // 2K/4K
|
case 0: // 2K/4K
|
||||||
for (word address = 0x0; address < (0x800 * ramsize); address += 512) { // 2K/4K
|
for (word address = 0x0; address < (0x800 * ramsize); address += 512) { // 2K/4K
|
||||||
sdFile.read(sdBuffer, 512);
|
sdFile.read(sdBuffer, 512);
|
||||||
for (int x = 0; x < 512; x++){
|
for (int x = 0; x < 512; x++) {
|
||||||
write_prg_byte(base + address + x, sdBuffer[x]); // SWITCH MUST BE IN OFF POSITION
|
write_prg_byte(base + address + x, sdBuffer[x]); // SWITCH MUST BE IN OFF POSITION
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2737,7 +2737,7 @@ void writeRAM() {
|
|||||||
write_prg_byte(0xA001, 0x30); // PRG RAM PROTECT - Enable reading/writing to RAM at $7000-$71FF
|
write_prg_byte(0xA001, 0x30); // PRG RAM PROTECT - Enable reading/writing to RAM at $7000-$71FF
|
||||||
for (word address = 0x1000; address < 0x1200; address += 512) { // 512B
|
for (word address = 0x1000; address < 0x1200; address += 512) { // 512B
|
||||||
sdFile.read(sdBuffer, 512);
|
sdFile.read(sdBuffer, 512);
|
||||||
for (int x = 0; x < 512; x++){
|
for (int x = 0; x < 512; x++) {
|
||||||
write_wram_byte(base + address + x, sdBuffer[x]);
|
write_wram_byte(base + address + x, sdBuffer[x]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2745,17 +2745,17 @@ void writeRAM() {
|
|||||||
write_prg_byte(0xA001, 0xC0); // PRG RAM PROTECT - Enable reading/writing to RAM at $7200-$73FF
|
write_prg_byte(0xA001, 0xC0); // PRG RAM PROTECT - Enable reading/writing to RAM at $7200-$73FF
|
||||||
for (word address = 0x1200; address < 0x1400; address += 512) { // 512B
|
for (word address = 0x1200; address < 0x1400; address += 512) { // 512B
|
||||||
sdFile.read(sdBuffer, 512);
|
sdFile.read(sdBuffer, 512);
|
||||||
for (int x = 0; x < 512; x++){
|
for (int x = 0; x < 512; x++) {
|
||||||
write_wram_byte(base + address + x, sdBuffer[x]);
|
write_wram_byte(base + address + x, sdBuffer[x]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
write_prg_byte(0x8000, 0x6); // PRG RAM DISABLE
|
write_prg_byte(0x8000, 0x6); // PRG RAM DISABLE
|
||||||
}
|
}
|
||||||
else { // MMC3 8K
|
else { // MMC3 8K
|
||||||
write_prg_byte(0xA001, 0x80); // PRG RAM CHIP ENABLE - Chip Enable, Allow Writes
|
write_prg_byte(0xA001, 0x80); // PRG RAM CHIP ENABLE - Chip Enable, Allow Writes
|
||||||
for (word address = 0; address < 0x2000; address += 512) { // 8K
|
for (word address = 0; address < 0x2000; address += 512) { // 8K
|
||||||
sdFile.read(sdBuffer, 512);
|
sdFile.read(sdBuffer, 512);
|
||||||
for (int x = 0; x < 512; x++){
|
for (int x = 0; x < 512; x++) {
|
||||||
write_prg_byte(base + address + x, sdBuffer[x]);
|
write_prg_byte(base + address + x, sdBuffer[x]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2821,7 +2821,7 @@ void writeRAM() {
|
|||||||
write_ram_byte(0xF800, 0x40); // PRG RAM WRITE ENABLE
|
write_ram_byte(0xF800, 0x40); // PRG RAM WRITE ENABLE
|
||||||
for (word address = 0; address < 0x2000; address += 512) { // 8K
|
for (word address = 0; address < 0x2000; address += 512) { // 8K
|
||||||
sdFile.read(sdBuffer, 512);
|
sdFile.read(sdBuffer, 512);
|
||||||
for (int x = 0; x < 512; x++){
|
for (int x = 0; x < 512; x++) {
|
||||||
write_prg_byte(base + address + x, sdBuffer[x]);
|
write_prg_byte(base + address + x, sdBuffer[x]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2834,7 +2834,7 @@ void writeRAM() {
|
|||||||
write_prg_byte(0x7EF9, 0xA3); // PRG RAM ENABLE 1
|
write_prg_byte(0x7EF9, 0xA3); // PRG RAM ENABLE 1
|
||||||
for (word address = 0x1F00; address < 0x2000; address += 512) { // PRG RAM 1K ($7F00-$7FFF)
|
for (word address = 0x1F00; address < 0x2000; address += 512) { // PRG RAM 1K ($7F00-$7FFF)
|
||||||
sdFile.read(sdBuffer, 128);
|
sdFile.read(sdBuffer, 128);
|
||||||
for (int x = 0; x < 128; x++){
|
for (int x = 0; x < 128; x++) {
|
||||||
write_prg_byte(base + address + x, sdBuffer[x]);
|
write_prg_byte(base + address + x, sdBuffer[x]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3139,7 +3139,7 @@ void NESmaker_ID() { // Read Flash ID
|
|||||||
write_prg_byte(0xAAAA, 0x55);
|
write_prg_byte(0xAAAA, 0x55);
|
||||||
write_prg_byte(0xC000, 0x01);
|
write_prg_byte(0xC000, 0x01);
|
||||||
write_prg_byte(0x9555, 0xF0); // Software ID Exit
|
write_prg_byte(0x9555, 0xF0); // Software ID Exit
|
||||||
if(strcmp(flashID, "BFB7") == 0) // SST 39SF040
|
if (strcmp(flashID, "BFB7") == 0) // SST 39SF040
|
||||||
flashfound = 1;
|
flashfound = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,14 +70,14 @@ void setup_WS()
|
|||||||
PORTG |= (1 << 5);
|
PORTG |= (1 << 5);
|
||||||
|
|
||||||
display_Clear();
|
display_Clear();
|
||||||
|
|
||||||
// unlock MMC
|
// unlock MMC
|
||||||
if (!unlockMMC2003_WS())
|
if (!unlockMMC2003_WS())
|
||||||
print_Error(F("Can't initial MMC"), true);
|
print_Error(F("Can't initial MMC"), true);
|
||||||
|
|
||||||
if (getCartInfo_WS() != 0xea)
|
if (getCartInfo_WS() != 0xea)
|
||||||
print_Error(F("Rom header read error"), true);
|
print_Error(F("Rom header read error"), true);
|
||||||
|
|
||||||
showCartInfo_WS();
|
showCartInfo_WS();
|
||||||
mode = mode_WS;
|
mode = mode_WS;
|
||||||
}
|
}
|
||||||
@ -92,70 +92,70 @@ void wsMenu()
|
|||||||
switch (mainMenu)
|
switch (mainMenu)
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
{
|
{
|
||||||
// Read Rom
|
// Read Rom
|
||||||
sd.chdir("/");
|
sd.chdir("/");
|
||||||
readROM_WS(filePath, FILEPATH_LENGTH);
|
readROM_WS(filePath, FILEPATH_LENGTH);
|
||||||
sd.chdir("/");
|
sd.chdir("/");
|
||||||
compareChecksum_WS(filePath);
|
compareChecksum_WS(filePath);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 1:
|
case 1:
|
||||||
{
|
|
||||||
// Read Save
|
|
||||||
sd.chdir("/");
|
|
||||||
switch (saveType)
|
|
||||||
{
|
{
|
||||||
case 0: println_Msg(F("No save for this game")); break;
|
// Read Save
|
||||||
case 1: readSRAM_WS(); break;
|
sd.chdir("/");
|
||||||
case 2: readEEPROM_WS(); break;
|
switch (saveType)
|
||||||
default: println_Msg(F("Unknow save type")); break;
|
{
|
||||||
|
case 0: println_Msg(F("No save for this game")); break;
|
||||||
|
case 1: readSRAM_WS(); break;
|
||||||
|
case 2: readEEPROM_WS(); break;
|
||||||
|
default: println_Msg(F("Unknow save type")); break;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 2:
|
case 2:
|
||||||
{
|
|
||||||
// Write Save
|
|
||||||
sd.chdir("/");
|
|
||||||
switch (saveType)
|
|
||||||
{
|
{
|
||||||
case 0: println_Msg(F("No save for this game")); break;
|
// Write Save
|
||||||
case 1:
|
sd.chdir("/");
|
||||||
|
switch (saveType)
|
||||||
{
|
{
|
||||||
writeSRAM_WS();
|
case 0: println_Msg(F("No save for this game")); break;
|
||||||
verifySRAM_WS();
|
case 1:
|
||||||
break;
|
{
|
||||||
|
writeSRAM_WS();
|
||||||
|
verifySRAM_WS();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 2:
|
||||||
|
{
|
||||||
|
writeEEPROM_WS();
|
||||||
|
verifyEEPROM_WS();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: println_Msg(F("Unknow save type")); break;
|
||||||
}
|
}
|
||||||
case 2:
|
|
||||||
{
|
break;
|
||||||
writeEEPROM_WS();
|
|
||||||
verifyEEPROM_WS();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: println_Msg(F("Unknow save type")); break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 4:
|
case 4:
|
||||||
{
|
{
|
||||||
writeWitchOS_WS();
|
writeWitchOS_WS();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
// reset
|
// reset
|
||||||
asm volatile (" jmp 0");
|
asm volatile (" jmp 0");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
println_Msg(F(""));
|
println_Msg(F(""));
|
||||||
println_Msg(F("Press Button..."));
|
println_Msg(F("Press Button..."));
|
||||||
|
|
||||||
display_Update();
|
display_Update();
|
||||||
wait();
|
wait();
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t getCartInfo_WS()
|
uint8_t getCartInfo_WS()
|
||||||
@ -163,7 +163,7 @@ uint8_t getCartInfo_WS()
|
|||||||
dataIn_WS();
|
dataIn_WS();
|
||||||
|
|
||||||
for (uint32_t i = 0; i < 16; i += 2)
|
for (uint32_t i = 0; i < 16; i += 2)
|
||||||
*((uint16_t*)(sdBuffer + i)) = readWord_WS(0xffff0 + i);
|
* ((uint16_t*)(sdBuffer + i)) = readWord_WS(0xffff0 + i);
|
||||||
|
|
||||||
wsGameChecksum = *(uint16_t*)(sdBuffer + 14);
|
wsGameChecksum = *(uint16_t*)(sdBuffer + 14);
|
||||||
wsWitch = false;
|
wsWitch = false;
|
||||||
@ -176,96 +176,96 @@ uint8_t getCartInfo_WS()
|
|||||||
// 256kbits sram
|
// 256kbits sram
|
||||||
case 0xe600: // BAN007
|
case 0xe600: // BAN007
|
||||||
case 0x8eed: // BANC16
|
case 0x8eed: // BANC16
|
||||||
{
|
{
|
||||||
sdBuffer[11] = 0x02;
|
sdBuffer[11] = 0x02;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// games missing 'COLOR' flag
|
// games missing 'COLOR' flag
|
||||||
case 0x26db: // SQRC01
|
case 0x26db: // SQRC01
|
||||||
case 0xbfdf: // SUMC07
|
case 0xbfdf: // SUMC07
|
||||||
{
|
|
||||||
sdBuffer[7] |= 0x01;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 0x7f73: // BAN030
|
|
||||||
{
|
|
||||||
// missing developerId and cartId
|
|
||||||
sdBuffer[6] = 0x01;
|
|
||||||
sdBuffer[8] = 0x30;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 0xeafd: //BANC33
|
|
||||||
{
|
|
||||||
// enable GPIO and set to LOW
|
|
||||||
dataOut_WS();
|
|
||||||
writeByte_WSPort(0xcc, 0x03);
|
|
||||||
writeByte_WSPort(0xcd, 0x00);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 0x0000:
|
|
||||||
{
|
|
||||||
// developerId/cartId/checksum are all filled with 0x00 in witch based games
|
|
||||||
dataIn_WS();
|
|
||||||
if (readWord_WS(0xf0000) == 0x4c45 && readWord_WS(0xf0002) == 0x5349 && readWord_WS(0xf0004) == 0x0041)
|
|
||||||
{
|
{
|
||||||
// check witch BIOS
|
sdBuffer[7] |= 0x01;
|
||||||
if (readWord_WS(0xfff5e) == 0x006c && readWord_WS(0xfff60) == 0x5b1b)
|
break;
|
||||||
{
|
}
|
||||||
// check flashchip
|
case 0x7f73: // BAN030
|
||||||
// should be a MBM29DL400TC
|
{
|
||||||
dataOut_WS();
|
// missing developerId and cartId
|
||||||
writeWord_WS(0x80aaa, 0xaaaa);
|
sdBuffer[6] = 0x01;
|
||||||
writeWord_WS(0x80555, 0x5555);
|
sdBuffer[8] = 0x30;
|
||||||
writeWord_WS(0x80aaa, 0x9090);
|
break;
|
||||||
|
}
|
||||||
dataIn_WS();
|
case 0xeafd: //BANC33
|
||||||
if (readWord_WS(0x80000) == 0x0004 && readWord_WS(0x80002) == 0x220c)
|
{
|
||||||
wsWitch = true;
|
// enable GPIO and set to LOW
|
||||||
|
dataOut_WS();
|
||||||
dataOut_WS();
|
writeByte_WSPort(0xcc, 0x03);
|
||||||
writeWord_WS(0x80000, 0xf0f0);
|
writeByte_WSPort(0xcd, 0x00);
|
||||||
dataIn_WS();
|
break;
|
||||||
|
}
|
||||||
// 7AC003
|
case 0x0000:
|
||||||
sdBuffer[6] = 0x7a;
|
{
|
||||||
sdBuffer[8] = 0x03;
|
// developerId/cartId/checksum are all filled with 0x00 in witch based games
|
||||||
}
|
dataIn_WS();
|
||||||
// check service menu
|
if (readWord_WS(0xf0000) == 0x4c45 && readWord_WS(0xf0002) == 0x5349 && readWord_WS(0xf0004) == 0x0041)
|
||||||
else if (readWord_WS(0xfff22) == 0x006c && readWord_WS(0xfff24) == 0x5b1b)
|
{
|
||||||
{
|
// check witch BIOS
|
||||||
if (readWord_WS(0x93246) == 0x4a2f && readWord_WS(0x93248) == 0x5353 && readWord_WS(0x9324a) == 0x2e32)
|
if (readWord_WS(0xfff5e) == 0x006c && readWord_WS(0xfff60) == 0x5b1b)
|
||||||
{
|
{
|
||||||
// jss2
|
// check flashchip
|
||||||
sdBuffer[6] = 0xff; // WWGP
|
// should be a MBM29DL400TC
|
||||||
sdBuffer[8] = 0x1a; // 2001A
|
dataOut_WS();
|
||||||
sdBuffer[7] = 0x01; // color only
|
writeWord_WS(0x80aaa, 0xaaaa);
|
||||||
|
writeWord_WS(0x80555, 0x5555);
|
||||||
if (readWord_WS(0x93e9c) == 0x4648 && readWord_WS(0x93e9e) == 0x0050)
|
writeWord_WS(0x80aaa, 0x9090);
|
||||||
{
|
|
||||||
// WWGP2001A3 -> HFP Version
|
dataIn_WS();
|
||||||
sdBuffer[9] = 0x03;
|
if (readWord_WS(0x80000) == 0x0004 && readWord_WS(0x80002) == 0x220c)
|
||||||
wsGameChecksum = 0x4870;
|
wsWitch = true;
|
||||||
}
|
|
||||||
else
|
dataOut_WS();
|
||||||
{
|
writeWord_WS(0x80000, 0xf0f0);
|
||||||
// TODO check other jss2 version
|
dataIn_WS();
|
||||||
}
|
|
||||||
}
|
// 7AC003
|
||||||
else if (readWord_WS(0xe4260) == 0x6b64 && readWord_WS(0xe4262) == 0x696e)
|
sdBuffer[6] = 0x7a;
|
||||||
{
|
sdBuffer[8] = 0x03;
|
||||||
// dknight
|
}
|
||||||
sdBuffer[6] = 0xff; // WWGP
|
// check service menu
|
||||||
sdBuffer[8] = 0x2b; // 2002B
|
else if (readWord_WS(0xfff22) == 0x006c && readWord_WS(0xfff24) == 0x5b1b)
|
||||||
sdBuffer[7] = 0x01; // color only
|
{
|
||||||
sdBuffer[9] = 0x00;
|
if (readWord_WS(0x93246) == 0x4a2f && readWord_WS(0x93248) == 0x5353 && readWord_WS(0x9324a) == 0x2e32)
|
||||||
wsGameChecksum = 0x8b1c;
|
{
|
||||||
}
|
// jss2
|
||||||
}
|
sdBuffer[6] = 0xff; // WWGP
|
||||||
|
sdBuffer[8] = 0x1a; // 2001A
|
||||||
|
sdBuffer[7] = 0x01; // color only
|
||||||
|
|
||||||
|
if (readWord_WS(0x93e9c) == 0x4648 && readWord_WS(0x93e9e) == 0x0050)
|
||||||
|
{
|
||||||
|
// WWGP2001A3 -> HFP Version
|
||||||
|
sdBuffer[9] = 0x03;
|
||||||
|
wsGameChecksum = 0x4870;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// TODO check other jss2 version
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (readWord_WS(0xe4260) == 0x6b64 && readWord_WS(0xe4262) == 0x696e)
|
||||||
|
{
|
||||||
|
// dknight
|
||||||
|
sdBuffer[6] = 0xff; // WWGP
|
||||||
|
sdBuffer[8] = 0x2b; // 2002B
|
||||||
|
sdBuffer[7] = 0x01; // color only
|
||||||
|
sdBuffer[9] = 0x00;
|
||||||
|
wsGameChecksum = 0x8b1c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
romType = (sdBuffer[7] & 0x01); // wsc only = 1
|
romType = (sdBuffer[7] & 0x01); // wsc only = 1
|
||||||
romVersion = sdBuffer[9];
|
romVersion = sdBuffer[9];
|
||||||
romSize = sdBuffer[10];
|
romSize = sdBuffer[10];
|
||||||
@ -291,7 +291,7 @@ uint8_t getCartInfo_WS()
|
|||||||
case 0x09: cartSize = 131072 * 128; break;
|
case 0x09: cartSize = 131072 * 128; break;
|
||||||
default: cartSize = 0; break;
|
default: cartSize = 0; break;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (sramSize)
|
switch (sramSize)
|
||||||
{
|
{
|
||||||
case 0x00: saveType = 0; sramSize = 0; break;
|
case 0x00: saveType = 0; sramSize = 0; break;
|
||||||
@ -317,7 +317,7 @@ void showCartInfo_WS()
|
|||||||
display_Clear();
|
display_Clear();
|
||||||
|
|
||||||
println_Msg(F("WS Cart Info"));
|
println_Msg(F("WS Cart Info"));
|
||||||
|
|
||||||
print_Msg(F("Game: "));
|
print_Msg(F("Game: "));
|
||||||
println_Msg(romName);
|
println_Msg(romName);
|
||||||
|
|
||||||
@ -344,8 +344,8 @@ void showCartInfo_WS()
|
|||||||
|
|
||||||
print_Msg(F("Checksum: "));
|
print_Msg(F("Checksum: "));
|
||||||
println_Msg(checksumStr);
|
println_Msg(checksumStr);
|
||||||
|
|
||||||
println_Msg(F("Press Button..."));
|
println_Msg(F("Press Button..."));
|
||||||
display_Update();
|
display_Update();
|
||||||
wait();
|
wait();
|
||||||
}
|
}
|
||||||
@ -368,11 +368,11 @@ void getDeveloperName(uint8_t id, char *buf, size_t length)
|
|||||||
case 0x28: devName = PSTR("SQR"); break;
|
case 0x28: devName = PSTR("SQR"); break;
|
||||||
case 0x31: devName = PSTR("VGD"); break;
|
case 0x31: devName = PSTR("VGD"); break;
|
||||||
// TODO add more developer
|
// TODO add more developer
|
||||||
|
|
||||||
// custom developerId
|
// custom developerId
|
||||||
case 0x7a: devName = PSTR("7AC"); break; // witch
|
case 0x7a: devName = PSTR("7AC"); break; // witch
|
||||||
case 0xff: devName = PSTR("WWGP"); break; // WWGP series (jss2, dknight)
|
case 0xff: devName = PSTR("WWGP"); break; // WWGP series (jss2, dknight)
|
||||||
|
|
||||||
// if not found, use id
|
// if not found, use id
|
||||||
default: snprintf(buf, length, "%02X", id); return;
|
default: snprintf(buf, length, "%02X", id); return;
|
||||||
}
|
}
|
||||||
@ -431,7 +431,7 @@ void readROM_WS(char *outPathBuf, size_t bufferSize)
|
|||||||
PORTB ^= (1 << 4);
|
PORTB ^= (1 << 4);
|
||||||
|
|
||||||
for (uint32_t w = 0; w < 512; w += 2)
|
for (uint32_t w = 0; w < 512; w += 2)
|
||||||
*((uint16_t*)(sdBuffer + w)) = readWord_WS(0x20000 + addr + w);
|
* ((uint16_t*)(sdBuffer + w)) = readWord_WS(0x20000 + addr + w);
|
||||||
|
|
||||||
myFile.write(sdBuffer, 512);
|
myFile.write(sdBuffer, 512);
|
||||||
}
|
}
|
||||||
@ -474,8 +474,8 @@ void readSRAM_WS()
|
|||||||
uint16_t end_bank = (bank_size >> 16); // 64KB per bank
|
uint16_t end_bank = (bank_size >> 16); // 64KB per bank
|
||||||
|
|
||||||
if (bank_size > 0x10000)
|
if (bank_size > 0x10000)
|
||||||
bank_size = 0x10000;
|
bank_size = 0x10000;
|
||||||
|
|
||||||
uint16_t bank = 0;
|
uint16_t bank = 0;
|
||||||
|
|
||||||
do
|
do
|
||||||
@ -494,7 +494,7 @@ void readSRAM_WS()
|
|||||||
for (uint32_t w = 0; w < 512; w++)
|
for (uint32_t w = 0; w < 512; w++)
|
||||||
sdBuffer[w] = readByte_WS(0x10000 + addr + w);
|
sdBuffer[w] = readByte_WS(0x10000 + addr + w);
|
||||||
|
|
||||||
myFile.write(sdBuffer, 512);
|
myFile.write(sdBuffer, 512);
|
||||||
}
|
}
|
||||||
} while (++bank < end_bank);
|
} while (++bank < end_bank);
|
||||||
|
|
||||||
@ -508,16 +508,16 @@ void verifySRAM_WS()
|
|||||||
{
|
{
|
||||||
print_Msg(F("Verifying... "));
|
print_Msg(F("Verifying... "));
|
||||||
display_Update();
|
display_Update();
|
||||||
|
|
||||||
if (myFile.open(filePath, O_READ))
|
if (myFile.open(filePath, O_READ))
|
||||||
{
|
{
|
||||||
uint32_t bank_size = (sramSize << 7);
|
uint32_t bank_size = (sramSize << 7);
|
||||||
uint16_t end_bank = (bank_size >> 16); // 64KB per bank
|
uint16_t end_bank = (bank_size >> 16); // 64KB per bank
|
||||||
uint16_t bank = 0;
|
uint16_t bank = 0;
|
||||||
uint32_t write_errors = 0;
|
uint32_t write_errors = 0;
|
||||||
|
|
||||||
if (bank_size > 0x10000)
|
if (bank_size > 0x10000)
|
||||||
bank_size = 0x10000;
|
bank_size = 0x10000;
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
@ -578,8 +578,8 @@ void writeSRAM_WS()
|
|||||||
uint16_t end_bank = (bank_size >> 16); // 64KB per bank
|
uint16_t end_bank = (bank_size >> 16); // 64KB per bank
|
||||||
|
|
||||||
if (bank_size > 0x10000)
|
if (bank_size > 0x10000)
|
||||||
bank_size = 0x10000;
|
bank_size = 0x10000;
|
||||||
|
|
||||||
uint16_t bank = 0;
|
uint16_t bank = 0;
|
||||||
dataOut_WS();
|
dataOut_WS();
|
||||||
do
|
do
|
||||||
@ -636,7 +636,7 @@ void readEEPROM_WS()
|
|||||||
|
|
||||||
uint32_t eepromSize = (sramSize << 7);
|
uint32_t eepromSize = (sramSize << 7);
|
||||||
uint32_t bufSize = (eepromSize < 512 ? eepromSize : 512);
|
uint32_t bufSize = (eepromSize < 512 ? eepromSize : 512);
|
||||||
|
|
||||||
for (uint32_t i = 0; i < eepromSize; i += bufSize)
|
for (uint32_t i = 0; i < eepromSize; i += bufSize)
|
||||||
{
|
{
|
||||||
for (uint32_t j = 0; j < bufSize; j += 2)
|
for (uint32_t j = 0; j < bufSize; j += 2)
|
||||||
@ -644,7 +644,7 @@ void readEEPROM_WS()
|
|||||||
// blink LED
|
// blink LED
|
||||||
if ((j & 0x1f) == 0x00)
|
if ((j & 0x1f) == 0x00)
|
||||||
PORTB ^= (1 << 4);
|
PORTB ^= (1 << 4);
|
||||||
|
|
||||||
generateEepromInstruction_WS(wsEepromShiftReg, 0x2, ((i + j) >> 1));
|
generateEepromInstruction_WS(wsEepromShiftReg, 0x2, ((i + j) >> 1));
|
||||||
|
|
||||||
dataOut_WS();
|
dataOut_WS();
|
||||||
@ -673,13 +673,13 @@ void verifyEEPROM_WS()
|
|||||||
{
|
{
|
||||||
print_Msg(F("Verifying... "));
|
print_Msg(F("Verifying... "));
|
||||||
display_Update();
|
display_Update();
|
||||||
|
|
||||||
if (myFile.open(filePath, O_READ))
|
if (myFile.open(filePath, O_READ))
|
||||||
{
|
{
|
||||||
uint32_t write_errors = 0;
|
uint32_t write_errors = 0;
|
||||||
uint32_t eepromSize = (sramSize << 7);
|
uint32_t eepromSize = (sramSize << 7);
|
||||||
uint32_t bufSize = (eepromSize < 512 ? eepromSize : 512);
|
uint32_t bufSize = (eepromSize < 512 ? eepromSize : 512);
|
||||||
|
|
||||||
for (uint32_t i = 0; i < eepromSize; i += bufSize)
|
for (uint32_t i = 0; i < eepromSize; i += bufSize)
|
||||||
{
|
{
|
||||||
myFile.read(sdBuffer, bufSize);
|
myFile.read(sdBuffer, bufSize);
|
||||||
@ -689,7 +689,7 @@ void verifyEEPROM_WS()
|
|||||||
// blink LED
|
// blink LED
|
||||||
if ((j & 0x1f) == 0x00)
|
if ((j & 0x1f) == 0x00)
|
||||||
PORTB ^= (1 << 4);
|
PORTB ^= (1 << 4);
|
||||||
|
|
||||||
generateEepromInstruction_WS(wsEepromShiftReg, 0x2, ((i + j) >> 1));
|
generateEepromInstruction_WS(wsEepromShiftReg, 0x2, ((i + j) >> 1));
|
||||||
|
|
||||||
dataOut_WS();
|
dataOut_WS();
|
||||||
@ -706,7 +706,7 @@ void verifyEEPROM_WS()
|
|||||||
write_errors++;
|
write_errors++;
|
||||||
|
|
||||||
if (readByte_WSPort(0xc5) != sdBuffer[j + 1])
|
if (readByte_WSPort(0xc5) != sdBuffer[j + 1])
|
||||||
write_errors++;
|
write_errors++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -723,7 +723,7 @@ void verifyEEPROM_WS()
|
|||||||
print_Msg(write_errors);
|
print_Msg(write_errors);
|
||||||
println_Msg(F(" bytes "));
|
println_Msg(F(" bytes "));
|
||||||
print_Error(F("did not verify."), false);
|
print_Error(F("did not verify."), false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -748,11 +748,11 @@ void writeEEPROM_WS()
|
|||||||
{
|
{
|
||||||
uint32_t eepromSize = (sramSize << 7);
|
uint32_t eepromSize = (sramSize << 7);
|
||||||
uint32_t bufSize = (eepromSize < 512 ? eepromSize : 512);
|
uint32_t bufSize = (eepromSize < 512 ? eepromSize : 512);
|
||||||
|
|
||||||
for (uint32_t i = 0; i < eepromSize; i += bufSize)
|
for (uint32_t i = 0; i < eepromSize; i += bufSize)
|
||||||
{
|
{
|
||||||
myFile.read(sdBuffer, bufSize);
|
myFile.read(sdBuffer, bufSize);
|
||||||
|
|
||||||
for (uint32_t j = 0; j < bufSize; j += 2)
|
for (uint32_t j = 0; j < bufSize; j += 2)
|
||||||
{
|
{
|
||||||
// blink LED
|
// blink LED
|
||||||
@ -760,7 +760,7 @@ void writeEEPROM_WS()
|
|||||||
PORTB ^= (1 << 4);
|
PORTB ^= (1 << 4);
|
||||||
|
|
||||||
generateEepromInstruction_WS(wsEepromShiftReg, 0x1, ((i + j) >> 1));
|
generateEepromInstruction_WS(wsEepromShiftReg, 0x1, ((i + j) >> 1));
|
||||||
|
|
||||||
dataOut_WS();
|
dataOut_WS();
|
||||||
writeByte_WSPort(0xc6, wsEepromShiftReg[0]);
|
writeByte_WSPort(0xc6, wsEepromShiftReg[0]);
|
||||||
writeByte_WSPort(0xc7, wsEepromShiftReg[1]);
|
writeByte_WSPort(0xc7, wsEepromShiftReg[1]);
|
||||||
@ -772,7 +772,9 @@ void writeEEPROM_WS()
|
|||||||
pulseCLK_WS(1 + 32 + 3);
|
pulseCLK_WS(1 + 32 + 3);
|
||||||
|
|
||||||
dataIn_WS();
|
dataIn_WS();
|
||||||
do { pulseCLK_WS(128); }
|
do {
|
||||||
|
pulseCLK_WS(128);
|
||||||
|
}
|
||||||
while ((readByte_WSPort(0xc8) & 0x02) == 0x00);
|
while ((readByte_WSPort(0xc8) & 0x02) == 0x00);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -921,7 +923,7 @@ boolean compareChecksum_WS(const char *wsFilePath)
|
|||||||
{
|
{
|
||||||
if (wsFilePath == NULL)
|
if (wsFilePath == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
println_Msg(F("Calculating Checksum"));
|
println_Msg(F("Calculating Checksum"));
|
||||||
display_Update();
|
display_Update();
|
||||||
|
|
||||||
@ -940,7 +942,7 @@ boolean compareChecksum_WS(const char *wsFilePath)
|
|||||||
myFile.seekCur(myFile.fileSize() - 131072);
|
myFile.seekCur(myFile.fileSize() - 131072);
|
||||||
calLength = 131072 - 512;
|
calLength = 131072 - 512;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (uint32_t i = 0; i < calLength; i += 512)
|
for (uint32_t i = 0; i < calLength; i += 512)
|
||||||
{
|
{
|
||||||
myFile.read(sdBuffer, 512);
|
myFile.read(sdBuffer, 512);
|
||||||
@ -960,7 +962,7 @@ boolean compareChecksum_WS(const char *wsFilePath)
|
|||||||
calLength = wsGameChecksum;
|
calLength = wsGameChecksum;
|
||||||
|
|
||||||
// don't know why formating string "%04X(%04X)" always output "xxxx(0000)"
|
// don't know why formating string "%04X(%04X)" always output "xxxx(0000)"
|
||||||
// so split into two snprintf
|
// so split into two snprintf
|
||||||
char result[11];
|
char result[11];
|
||||||
snprintf(result, 5, "%04X", calLength);
|
snprintf(result, 5, "%04X", calLength);
|
||||||
snprintf(result + 4, 11 - 4, "(%04X)", checksum);
|
snprintf(result + 4, 11 - 4, "(%04X)", checksum);
|
||||||
@ -998,7 +1000,7 @@ void writeByte_WSPort(uint8_t port, uint8_t data)
|
|||||||
// switch WE(PH5) to HIGH
|
// switch WE(PH5) to HIGH
|
||||||
PORTH |= (1 << 5);
|
PORTH |= (1 << 5);
|
||||||
NOP; NOP;
|
NOP; NOP;
|
||||||
|
|
||||||
// switch CART(PH3), MMC(PH4) to HIGH
|
// switch CART(PH3), MMC(PH4) to HIGH
|
||||||
PORTH |= ((1 << 3) | (1 << 4));
|
PORTH |= ((1 << 3) | (1 << 4));
|
||||||
}
|
}
|
||||||
@ -1019,7 +1021,7 @@ uint8_t readByte_WSPort(uint8_t port)
|
|||||||
|
|
||||||
// switch OE(PH6) to HIGH
|
// switch OE(PH6) to HIGH
|
||||||
PORTH |= (1 << 6);
|
PORTH |= (1 << 6);
|
||||||
|
|
||||||
// switch CART(PH3), MMC(PH4) to HIGH
|
// switch CART(PH3), MMC(PH4) to HIGH
|
||||||
PORTH |= ((1 << 3) | (1 << 4));
|
PORTH |= ((1 << 3) | (1 << 4));
|
||||||
|
|
||||||
@ -1034,7 +1036,7 @@ void writeWord_WS(uint32_t addr, uint16_t data)
|
|||||||
|
|
||||||
PORTC = data & 0xff;
|
PORTC = data & 0xff;
|
||||||
PORTA = (data >> 8);
|
PORTA = (data >> 8);
|
||||||
|
|
||||||
// switch CART(PH3) and WE(PH5) to LOW
|
// switch CART(PH3) and WE(PH5) to LOW
|
||||||
PORTH &= ~((1 << 3) | (1 << 5));
|
PORTH &= ~((1 << 3) | (1 << 5));
|
||||||
NOP;
|
NOP;
|
||||||
@ -1049,7 +1051,7 @@ uint16_t readWord_WS(uint32_t addr)
|
|||||||
PORTF = addr & 0xff;
|
PORTF = addr & 0xff;
|
||||||
PORTK = (addr >> 8) & 0xff;
|
PORTK = (addr >> 8) & 0xff;
|
||||||
PORTL = (addr >> 16) & 0x0f;
|
PORTL = (addr >> 16) & 0x0f;
|
||||||
|
|
||||||
// switch CART(PH3) and OE(PH6) to LOW
|
// switch CART(PH3) and OE(PH6) to LOW
|
||||||
PORTH &= ~((1 << 3) | (1 << 6));
|
PORTH &= ~((1 << 3) | (1 << 6));
|
||||||
NOP; NOP; NOP;
|
NOP; NOP; NOP;
|
||||||
@ -1059,7 +1061,7 @@ uint16_t readWord_WS(uint32_t addr)
|
|||||||
// switch CART(PH3) and OE(PH6) to HIGH
|
// switch CART(PH3) and OE(PH6) to HIGH
|
||||||
PORTH |= (1 << 3) | (1 << 6);
|
PORTH |= (1 << 3) | (1 << 6);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void writeByte_WS(uint32_t addr, uint8_t data)
|
void writeByte_WS(uint32_t addr, uint8_t data)
|
||||||
@ -1069,7 +1071,7 @@ void writeByte_WS(uint32_t addr, uint8_t data)
|
|||||||
PORTL = (addr >> 16) & 0x0f;
|
PORTL = (addr >> 16) & 0x0f;
|
||||||
|
|
||||||
PORTC = data;
|
PORTC = data;
|
||||||
|
|
||||||
// switch CART(PH3) and WE(PH5) to LOW
|
// switch CART(PH3) and WE(PH5) to LOW
|
||||||
PORTH &= ~((1 << 3) | (1 << 5));
|
PORTH &= ~((1 << 3) | (1 << 5));
|
||||||
NOP;
|
NOP;
|
||||||
@ -1084,7 +1086,7 @@ uint8_t readByte_WS(uint32_t addr)
|
|||||||
PORTF = addr & 0xff;
|
PORTF = addr & 0xff;
|
||||||
PORTK = (addr >> 8) & 0xff;
|
PORTK = (addr >> 8) & 0xff;
|
||||||
PORTL = (addr >> 16) & 0x0f;
|
PORTL = (addr >> 16) & 0x0f;
|
||||||
|
|
||||||
// switch CART(PH3) and OE(PH6) to LOW
|
// switch CART(PH3) and OE(PH6) to LOW
|
||||||
PORTH &= ~((1 << 3) | (1 << 6));
|
PORTH &= ~((1 << 3) | (1 << 6));
|
||||||
NOP; NOP; NOP;
|
NOP; NOP; NOP;
|
||||||
@ -1094,13 +1096,13 @@ uint8_t readByte_WS(uint32_t addr)
|
|||||||
// switch CART(PH3) and OE(PH6) to HIGH
|
// switch CART(PH3) and OE(PH6) to HIGH
|
||||||
PORTH |= (1 << 3) | (1 << 6);
|
PORTH |= (1 << 3) | (1 << 6);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void unprotectEEPROM()
|
void unprotectEEPROM()
|
||||||
{
|
{
|
||||||
generateEepromInstruction_WS(wsEepromShiftReg, 0x0, 0x3);
|
generateEepromInstruction_WS(wsEepromShiftReg, 0x0, 0x3);
|
||||||
|
|
||||||
dataOut_WS();
|
dataOut_WS();
|
||||||
writeByte_WSPort(0xc6, wsEepromShiftReg[0]);
|
writeByte_WSPort(0xc6, wsEepromShiftReg[0]);
|
||||||
writeByte_WSPort(0xc7, wsEepromShiftReg[1]);
|
writeByte_WSPort(0xc7, wsEepromShiftReg[1]);
|
||||||
@ -1125,7 +1127,7 @@ void generateEepromInstruction_WS(uint8_t *instruction, uint8_t opcode, uint16_t
|
|||||||
// 2bits ext cmd (from addr)
|
// 2bits ext cmd (from addr)
|
||||||
*ptr <<= 2;
|
*ptr <<= 2;
|
||||||
*ptr |= (addr & 0x0003);
|
*ptr |= (addr & 0x0003);
|
||||||
*ptr <<= (addr_bits - 2);
|
*ptr <<= (addr_bits - 2);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -1135,7 +1137,7 @@ void generateEepromInstruction_WS(uint8_t *instruction, uint8_t opcode, uint16_t
|
|||||||
// address bits
|
// address bits
|
||||||
*ptr <<= addr_bits;
|
*ptr <<= addr_bits;
|
||||||
*ptr |= (addr & ((1 << addr_bits) - 1));
|
*ptr |= (addr & ((1 << addr_bits) - 1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2003 MMC need to be unlock,
|
// 2003 MMC need to be unlock,
|
||||||
@ -1149,7 +1151,7 @@ boolean unlockMMC2003_WS()
|
|||||||
PORTH &= ~(1 << 0);
|
PORTH &= ~(1 << 0);
|
||||||
PORTE &= ~(1 << 3);
|
PORTE &= ~(1 << 3);
|
||||||
PORTH |= ((1 << 3) | (1 << 4) | (1 << 5) | (1 << 6));
|
PORTH |= ((1 << 3) | (1 << 4) | (1 << 5) | (1 << 6));
|
||||||
|
|
||||||
// switch RST(PH0) to HIGH
|
// switch RST(PH0) to HIGH
|
||||||
PORTH |= (1 << 0);
|
PORTH |= (1 << 0);
|
||||||
|
|
||||||
@ -1190,7 +1192,7 @@ boolean unlockMMC2003_WS()
|
|||||||
void pulseCLK_WS(uint8_t count)
|
void pulseCLK_WS(uint8_t count)
|
||||||
{
|
{
|
||||||
register uint8_t tic;
|
register uint8_t tic;
|
||||||
|
|
||||||
// about 384KHz, 50% duty cycle
|
// about 384KHz, 50% duty cycle
|
||||||
asm volatile
|
asm volatile
|
||||||
("L0_%=:\n\t"
|
("L0_%=:\n\t"
|
||||||
|
@ -12,7 +12,8 @@ Be sure to check the guides in the [Wiki](https://github.com/sanni/cartreader/wi
|
|||||||
- Easy to modify open-source code, write your own extensions and share them with others
|
- Easy to modify open-source code, write your own extensions and share them with others
|
||||||
|
|
||||||
#### Supported Systems:
|
#### Supported Systems:
|
||||||
- Reads NES and Famicom cartridges
|
- Reads NES, Famicom and Family Basic cartridges including save
|
||||||
|
- Supports Mapper 30/NESmaker and flashes INL NM30 boards
|
||||||
- Reads SNES roms and reads/writes save games from and to the SNES cartridge
|
- Reads SNES roms and reads/writes save games from and to the SNES cartridge
|
||||||
Supported cartridge types so far: LoRom, HiRom, ExHiRom, SuperFX, SuperFX2, SDD1, CX4, SPC7110, SA1 (last two chips need Adafruit Clock Generator)
|
Supported cartridge types so far: LoRom, HiRom, ExHiRom, SuperFX, SuperFX2, SDD1, CX4, SPC7110, SA1 (last two chips need Adafruit Clock Generator)
|
||||||
- Reads and writes SNES Satellaview 8M Memory packs
|
- Reads and writes SNES Satellaview 8M Memory packs
|
||||||
|
@ -1,34 +1,3 @@
|
|||||||
#### cartreader.zip is the main PCB, if you order it from [JLCPCB](https://jlcpcb.com/quote) you usually get a coupon displayed during the checkout for buying parts [from lcsc.com](https://github.com/sanni/cartreader/wiki/Needed-Parts). [Default settings](https://www.dropbox.com/s/06dnus50ikmsmya/pcb16.jpg?dl=0) are fine, just select the color you prefer and off you go. If this is your first order from JLCPCB you should only pay $2 for 5 PCBs.
|
#### cartreader.zip is the main PCB, if you order it from [JLCPCB](https://jlcpcb.com/quote) you usually get a coupon displayed during the checkout for buying parts [from lcsc.com](https://github.com/sanni/cartreader/wiki/Needed-Parts). [Default settings](https://www.dropbox.com/s/06dnus50ikmsmya/pcb16.jpg?dl=0) are fine, just select the color you prefer and off you go. If this is your first order from JLCPCB you should only pay $2 for 5 PCBs.
|
||||||
|
|
||||||
![image](https://dl.dropboxusercontent.com/s/ta7pjoxn9kirtan/v17pcb.png?dl=1)
|
![image](https://dl.dropboxusercontent.com/s/ta7pjoxn9kirtan/v17pcb.png?dl=1)
|
||||||
|
|
||||||
#### nes_adapter.zip is an add-on for reading NES carts, [PCB thickness needs to be changed to 1.2mm](https://dl.dropboxusercontent.com/s/va1c72073cqfy90/pcb12.jpg?dl=1), this is very important or else it won't fit into the SNES slot. You can order a 2.5mm 72pin NES slot [here](https://www.aliexpress.com/item/32827561164.html).
|
|
||||||
|
|
||||||
![image](https://dl.dropboxusercontent.com/s/z2atlcly642sewj/nes_adapter.png?dl=1)
|
|
||||||
|
|
||||||
#### famicom_adapter.zip is an add-on for reading Famicom carts, [PCB thickness needs to be changed to 1.2mm](https://dl.dropboxusercontent.com/s/va1c72073cqfy90/pcb12.jpg?dl=1), this is very important or else it won't fit into the SNES slot. You can order a 2.54mm 60pin Famicom slot [here](https://www.aliexpress.com/item/32827561249.html).
|
|
||||||
|
|
||||||
![image](https://dl.dropboxusercontent.com/s/w89ivzvuzk6hf5b/famicom_adapter.png?dl=1)
|
|
||||||
|
|
||||||
#### sms_adapter.zip is an add-on for reading Sega Master System carts. You can order a 2.54mm 50pin SMS slot [here](https://www.aliexpress.com/item/32818469880.html). The adapter is based on the [design by Raphnet](https://www.raphnet.net/electronique/sms_to_smd/index_en.php). For use with the Cart Reader ignore the SMD footprints on the PCB, the adapter does not need any components. I only bridged R5 to connect the reset line, although I'm not sure if this is even needed.
|
|
||||||
|
|
||||||
![image](https://dl.dropboxusercontent.com/s/r6lavgoaccjtrz7/sms_adapter.png?dl=1)
|
|
||||||
|
|
||||||
#### wonderswan_adapter.zip is an add-on for reading WonderSwan carts. [PCB thickness needs to be changed to 1.2mm](https://dl.dropboxusercontent.com/s/755249v8smcuoft/wonderswan_adapter.png?dl=1), this is very important or else it won't fit into the SNES slot. (Optional) Install C1 and C2 with 10uF/16v 1210 package tantalum capacitor.
|
|
||||||
|
|
||||||
![image](https://dl.dropboxusercontent.com/s/755249v8smcuoft/wonderswan_adapter.png?dl=1)
|
|
||||||
|
|
||||||
#### flash_adapter.zip is an add-on for writing flashroms like the 29F032, 29L3211, 29LV160, [PCB thickness needs to be changed to 1.2mm](https://dl.dropboxusercontent.com/s/va1c72073cqfy90/pcb12.jpg?dl=1), this is very important or else it won't fit into the SNES slot.
|
|
||||||
|
|
||||||
![image](https://dl.dropboxusercontent.com/s/afrfmiuwvmvg9px/flash_adapter.png?dl=1)
|
|
||||||
|
|
||||||
#### eprom_adapter.zip is an add-on for writing an 27C322 eprom, [PCB thickness needs to be changed to 1.2mm](https://www.dropbox.com/s/va1c72073cqfy90/pcb12.jpg?dl=0), this is very important or else it won't fit into the SNES slot.
|
|
||||||
|
|
||||||
![image](https://dl.dropboxusercontent.com/s/ldmtkjv7xsgtwyg/27c322_adapter.png?dl=1)
|
|
||||||
|
|
||||||
#### With the sd_adapter PCB you can transform the microSD module from the parts list into a full size SD module by desoldering all the components and soldering them to this PCB. This is optional since you can also just mount the microSD module as is.
|
|
||||||
|
|
||||||
![image](https://dl.dropboxusercontent.com/s/jcse9iaxm3bbuu6/sd_adapter.pngg?dl=1)
|
|
||||||
|
|
||||||
|
|
||||||
For [Oshpark](https://oshpark.com/) you need to [rename filename.GML to filename.GKO](https://www.dropbox.com/s/0rcvhalgeu11sf8/rename.jpg?dl=0) or it won't find the board outline. Oshpark is great for ordering the smaller PCBs but very expensive for larger boards.
|
|
Before Width: | Height: | Size: 33 KiB After Width: | Height: | Size: 33 KiB |
Before Width: | Height: | Size: 39 KiB After Width: | Height: | Size: 39 KiB |
30
pcb/adapters/README.md
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
#### nes_adapter.zip is an add-on for reading NES carts, [PCB thickness needs to be changed to 1.2mm](https://dl.dropboxusercontent.com/s/va1c72073cqfy90/pcb12.jpg?dl=1), this is very important or else it won't fit into the SNES slot. You can order a 2.5mm 72pin NES slot [here](https://www.aliexpress.com/item/32827561164.html).
|
||||||
|
|
||||||
|
![image](https://dl.dropboxusercontent.com/s/z2atlcly642sewj/nes_adapter.png?dl=1)
|
||||||
|
|
||||||
|
#### famicom_adapter.zip is an add-on for reading Famicom carts, [PCB thickness needs to be changed to 1.2mm](https://dl.dropboxusercontent.com/s/va1c72073cqfy90/pcb12.jpg?dl=1), this is very important or else it won't fit into the SNES slot. You can order a 2.54mm 60pin Famicom slot [here](https://www.aliexpress.com/item/32827561249.html).
|
||||||
|
|
||||||
|
![image](https://dl.dropboxusercontent.com/s/w89ivzvuzk6hf5b/famicom_adapter.png?dl=1)
|
||||||
|
|
||||||
|
#### sms_adapter.zip is an add-on for reading Sega Master System carts. You can order a 2.54mm 50pin SMS slot [here](https://www.aliexpress.com/item/32818469880.html). The adapter is based on the [design by Raphnet](https://www.raphnet.net/electronique/sms_to_smd/index_en.php). For use with the Cart Reader ignore the SMD footprints on the PCB, the adapter does not need any components. I only bridged R5 to connect the reset line, although I'm not sure if this is even needed.
|
||||||
|
|
||||||
|
![image](https://dl.dropboxusercontent.com/s/r6lavgoaccjtrz7/sms_adapter.png?dl=1)
|
||||||
|
|
||||||
|
#### wonderswan_adapter.zip is an add-on for reading WonderSwan carts. [PCB thickness needs to be changed to 1.2mm](https://dl.dropboxusercontent.com/s/755249v8smcuoft/wonderswan_adapter.png?dl=1), this is very important or else it won't fit into the SNES slot. (Optional) Install C1 and C2 with 10uF/16v 1210 package tantalum capacitor.
|
||||||
|
|
||||||
|
![image](https://dl.dropboxusercontent.com/s/755249v8smcuoft/wonderswan_adapter.png?dl=1)
|
||||||
|
|
||||||
|
#### flash_adapter.zip is an add-on for writing flashroms like the 29F032, 29L3211, 29LV160, [PCB thickness needs to be changed to 1.2mm](https://dl.dropboxusercontent.com/s/va1c72073cqfy90/pcb12.jpg?dl=1), this is very important or else it won't fit into the SNES slot.
|
||||||
|
|
||||||
|
![image](https://dl.dropboxusercontent.com/s/afrfmiuwvmvg9px/flash_adapter.png?dl=1)
|
||||||
|
|
||||||
|
#### eprom_adapter.zip is an add-on for writing an 27C322 eprom, [PCB thickness needs to be changed to 1.2mm](https://www.dropbox.com/s/va1c72073cqfy90/pcb12.jpg?dl=0), this is very important or else it won't fit into the SNES slot.
|
||||||
|
|
||||||
|
![image](https://dl.dropboxusercontent.com/s/ldmtkjv7xsgtwyg/27c322_adapter.png?dl=1)
|
||||||
|
|
||||||
|
#### With the sd_adapter PCB you can transform the microSD module from the parts list into a full size SD module by desoldering all the components and soldering them to this PCB. This is optional since you can also just mount the microSD module as is.
|
||||||
|
|
||||||
|
![image](https://dl.dropboxusercontent.com/s/jcse9iaxm3bbuu6/sd_adapter.pngg?dl=1)
|
||||||
|
|
||||||
|
|
||||||
|
For [Oshpark](https://oshpark.com/) you need to [rename filename.GML to filename.GKO](https://www.dropbox.com/s/0rcvhalgeu11sf8/rename.jpg?dl=0) or it won't find the board outline. Oshpark is great for ordering the smaller PCBs but very expensive for larger boards.
|
Before Width: | Height: | Size: 32 KiB After Width: | Height: | Size: 32 KiB |
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 42 KiB |
Before Width: | Height: | Size: 32 KiB After Width: | Height: | Size: 32 KiB |
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 17 KiB |
Before Width: | Height: | Size: 38 KiB After Width: | Height: | Size: 38 KiB |
0
pcb/wonderswan_adapter.zip → pcb/adapters/wonderswan_adapter.zip
Executable file → Normal file
Before Width: | Height: | Size: 89 KiB After Width: | Height: | Size: 89 KiB |
5
pcb/pocketsnes/README.md
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
#### pocketsnes.zip is a smaller variant of the Cart Reader PCB made by Niltonn. To order the PCB please refer to: https://docs.easyeda.com/en/PCB/Order-PCB
|
||||||
|
|
||||||
|
![image](https://dl.dropboxusercontent.com/s/g0bhixbcrzjuye8/pocketsnes.jpg?dl=1)
|
||||||
|
|
||||||
|
More info: https://forum.arduino.cc/index.php?topic=158974.msg4381465#msg4381465
|