mirror of
https://github.com/sanni/cartreader.git
synced 2024-11-27 15:04:15 +01:00
2cf7f5dbe7
The `setVoltage()` function should be called even when `ENABLE_VSELECT` is disabled because `ENABLE_3V3FIX` also uses it. There is no resource cost to do this as when both options are disabled the compiler will optimize this function out. This just "future proofs" the code so if that function ever does more it doesn't need updated everywhere. This applies to `setup_FlashVoltage()` as well. The changes to OSCR.cpp are just for code formatting and additional comments to clarify this.
744 lines
18 KiB
C++
744 lines
18 KiB
C++
//******************************************
|
|
// BENESSE POCKET CHALLENGE W MODULE
|
|
//******************************************
|
|
#ifdef enable_PCW
|
|
|
|
// Benesse Pocket Challenge W
|
|
// Cartridge Pinout
|
|
// 38P 1.27mm pitch connector
|
|
//
|
|
// CART CART
|
|
// TOP EDGE
|
|
// +---------+
|
|
// | 1 |-- VCC
|
|
// | 2 |-- GND
|
|
// | 3 |-- AD0 (A0 IN/D0 OUT)
|
|
// | 4 |-- AD1 (A1 IN/D1 OUT)
|
|
// | 5 |-- AD2 (A2 IN/D2 OUT)
|
|
// | 6 |-- AD3 (A3 IN/D3 OUT)
|
|
// | 7 |-- AD4 (A4 IN/D4 OUT)
|
|
// | 8 |-- AD5 (A5 IN/D5 OUT)
|
|
// | 9 |-- AD6 (A6 IN/D6 OUT)
|
|
// | 10 |-- AD7 (A7 IN/D7 OUT)
|
|
// | 11 |-- A08
|
|
// | 12 |-- A09
|
|
// | 13 |-- A10
|
|
// | 14 |-- A11
|
|
// | 15 |-- A12
|
|
// | 16 |-- A13
|
|
// | 17 |-- A14
|
|
// | 18 |-- A15
|
|
// | 19 |-- A16
|
|
// | 20 |-- A17
|
|
// | 21 |-- A18
|
|
// | 22 |-- A19
|
|
// | 23 |-- A20
|
|
// | 24 |-- A21
|
|
// | 25 |-- NC [CPU-INT2/T15(P47)]
|
|
// | 26 |-- 1B (7W00F) -> HIGH -+
|
|
// | 27 |-- 1A (7W00F) -> HIGH -+-> OE (ROM) = LOW
|
|
// | 28 |-- OE (LH5164A)
|
|
// | 29 |-- WE (LH5164A)
|
|
// | 30 |-- LE (HC573) [LATCH ENABLE FOR AD0-AD7]
|
|
// | 31 |-- NC [CPU-TO5(P43)]
|
|
// | 32 |-- NC [CPU-RESET]
|
|
// | 33 |-- VCC
|
|
// | 34 |-- GND
|
|
// | 35 |-- NC
|
|
// | 36 |-- NC [CPU-VCC]
|
|
// | 37 |-- NC [CONSOLE-GND]
|
|
// | 38 |-- NC
|
|
// +---------+
|
|
|
|
// CONTROL PINS:
|
|
// LE - (PH0) - PCW PIN 30 - SNES RST
|
|
// 1A - (PH3) - PCW PIN 27 - SNES /CS
|
|
// 1B - (PH4) - PCW PIN 26 - SNES /IRQ
|
|
// WE - (PH5) - PCW PIN 29 - SNES /WR
|
|
// OE - (PH6) - PCW PIN 28 - SNES /RD
|
|
|
|
// NOT CONNECTED:
|
|
// CLK(PH1) - N/C
|
|
|
|
// ADDRESS PINS:
|
|
// ADDR/DATA [AD0-AD7] - PORTC
|
|
// ADDR A8-A15 - PORTK
|
|
// ADDR A16-A21 - PORTL
|
|
|
|
//******************************************
|
|
// DEFINES
|
|
//******************************************
|
|
|
|
// CONTROL PINS - LE/1A/1B/WE/OE
|
|
#define LE_HIGH PORTH |= (1 << 0)
|
|
#define LE_LOW PORTH &= ~(1 << 0)
|
|
#define NAND_1A_HIGH PORTH |= (1 << 3)
|
|
#define NAND_1A_LOW PORTH &= ~(1 << 3)
|
|
#define NAND_1B_HIGH PORTH |= (1 << 4)
|
|
#define NAND_1B_LOW PORTH &= ~(1 << 4) // Built-in RAM + I/O
|
|
#define WE_HIGH PORTH |= (1 << 5)
|
|
#define WE_LOW PORTH &= ~(1 << 5)
|
|
#define OE_HIGH PORTH |= (1 << 6)
|
|
#define OE_LOW PORTH &= ~(1 << 6)
|
|
|
|
#define MODE_READ DDRC = 0 // [INPUT]
|
|
#define MODE_WRITE DDRC = 0xFF //[OUTPUT]
|
|
|
|
#define DATA_READ \
|
|
{ \
|
|
DDRC = 0; \
|
|
PORTC = 0xFF; \
|
|
} // [INPUT PULLUP]
|
|
#define ADDR_WRITE DDRC = 0xFF // [OUTPUT]
|
|
#define DETECTION_SIZE 64
|
|
|
|
boolean multipack = 0; // Multi-Pack Cart
|
|
byte bank0;
|
|
byte bank1;
|
|
|
|
//******************************************
|
|
// SETUP
|
|
//******************************************
|
|
|
|
void setup_PCW() {
|
|
// Request 5V
|
|
setVoltage(VOLTS_SET_5V);
|
|
|
|
// Set Address Pins to Output
|
|
//A8-A15
|
|
DDRK = 0xFF;
|
|
//A16-A21
|
|
DDRL = 0xFF;
|
|
|
|
// Set Control Pins to Output
|
|
// LE(PH0) --(PH1) 1A(PH3) 1B(PH4) WE(PH5) OE(PH6)
|
|
DDRH |= (1 << 0) | (1 << 1) | (1 << 3) | (1 << 4) | (1 << 5) | (1 << 6);
|
|
|
|
// Set TIME(PJ0) to Output (UNUSED)
|
|
DDRJ |= (1 << 0);
|
|
|
|
// Set Address/Data Pins AD0-AD7 (PC0-PC7) to Input
|
|
MODE_READ; // DDRC = 0
|
|
|
|
// Setting Control Pins to HIGH
|
|
// LE(PH0) ---(PH1) 1A(PH3) 1B(PH4) WE(PH5) OE(PH6)
|
|
PORTH |= (1 << 0) | (1 << 1) | (1 << 3) | (1 << 4) | (1 << 5) | (1 << 6);
|
|
|
|
// Set Unused Pins HIGH
|
|
PORTJ |= (1 << 0); // TIME(PJ0)
|
|
|
|
// Multi-Pack Cart Check
|
|
check_multi_PCW();
|
|
|
|
strcpy(romName, "PCW");
|
|
|
|
mode = mode_PCW;
|
|
}
|
|
|
|
//******************************************
|
|
// MENU
|
|
//******************************************
|
|
static const char pcwmenuItem1[] PROGMEM = "Read ROM";
|
|
static const char pcwmenuItem2[] PROGMEM = "Read SRAM";
|
|
static const char pcwmenuItem3[] PROGMEM = "Write SRAM";
|
|
static const char* const menuOptionsPCW[] PROGMEM = { pcwmenuItem1, pcwmenuItem2, pcwmenuItem3, string_reset2 };
|
|
|
|
void pcwMenu() {
|
|
convertPgm(menuOptionsPCW, 4);
|
|
uint8_t mainMenu = question_box(F(" POCKET CHALLENGE W"), menuOptions, 4, 0);
|
|
|
|
switch (mainMenu) {
|
|
case 0:
|
|
// Read ROM
|
|
sd.chdir("/");
|
|
if (multipack)
|
|
readMultiROM_PCW();
|
|
else
|
|
readROM_PCW();
|
|
sd.chdir("/");
|
|
break;
|
|
|
|
case 1:
|
|
// Read SRAM
|
|
sd.chdir("/");
|
|
display_Clear();
|
|
println_Msg(F("Reading SRAM..."));
|
|
display_Update();
|
|
readSRAM_PCW();
|
|
sd.chdir("/");
|
|
// Wait for user input
|
|
// Prints string out of the common strings array either with or without newline
|
|
print_STR(press_button_STR, 1);
|
|
display_Update();
|
|
wait();
|
|
break;
|
|
|
|
case 2:
|
|
// Write SRAM
|
|
sd.chdir("/");
|
|
fileBrowser(F("Select SRM file"));
|
|
display_Clear();
|
|
writeSRAM_PCW();
|
|
display_Clear();
|
|
writeErrors = verifySRAM_PCW();
|
|
if (writeErrors == 0) {
|
|
println_Msg(F("SRAM verified OK"));
|
|
display_Update();
|
|
} else {
|
|
print_STR(error_STR, 0);
|
|
print_Msg(writeErrors);
|
|
print_STR(_bytes_STR, 1);
|
|
print_Error(did_not_verify_STR);
|
|
}
|
|
break;
|
|
|
|
case 3:
|
|
// Reset
|
|
resetArduino();
|
|
break;
|
|
}
|
|
}
|
|
|
|
//******************************************
|
|
// LOW LEVEL FUNCTIONS
|
|
//******************************************
|
|
|
|
// Max ROM Size 0x400000 (Highest Address = 0x3FFFFF) - 3F FFFF
|
|
// NAND 1A + 1B HIGH = LOW = ROM Output Enabled
|
|
void read_setup_PCW() {
|
|
NAND_1A_HIGH;
|
|
NAND_1B_HIGH;
|
|
OE_HIGH;
|
|
WE_HIGH;
|
|
LE_LOW;
|
|
}
|
|
|
|
// READ ROM BYTE WITH ADDITIONAL DELAY
|
|
// NEEDED FOR PROBLEM CARTS TO SWITCH FROM ADDRESS TO DATA
|
|
unsigned char read_rom_byte_PCW(unsigned long address) {
|
|
PORTL = (address >> 16) & 0xFF;
|
|
PORTK = (address >> 8) & 0xFF;
|
|
// Latch Address on AD0-AD7
|
|
ADDR_WRITE;
|
|
LE_HIGH; // Latch Enable
|
|
PORTC = address & 0xFF; // A0-A7
|
|
LE_LOW; // Address Latched
|
|
__asm__("nop\n\t"
|
|
"nop\n\t");
|
|
// Read Data on AD0-AD7
|
|
OE_LOW;
|
|
DATA_READ;
|
|
delayMicroseconds(5); // 3+ Microseconds for Problem Carts
|
|
unsigned char data = PINC;
|
|
OE_HIGH;
|
|
|
|
return data;
|
|
}
|
|
|
|
// SRAM Size 0x8000 (Highest Address = 0x7FFF)
|
|
// NAND 1A LOW = SRAM Enabled [ROM DISABLED]
|
|
unsigned char read_ram_byte_1A_PCW(unsigned long address) {
|
|
NAND_1A_LOW;
|
|
PORTL = (address >> 16) & 0xFF;
|
|
PORTK = (address >> 8) & 0xFF;
|
|
// Latch Address on AD0-AD7
|
|
ADDR_WRITE;
|
|
LE_HIGH; // Latch Enable
|
|
PORTC = address & 0xFF; // A0-A7
|
|
LE_LOW; // Address Latched
|
|
__asm__("nop\n\t"
|
|
"nop\n\t"
|
|
"nop\n\t"
|
|
"nop\n\t"
|
|
"nop\n\t"
|
|
"nop\n\t");
|
|
// Read Data on AD0-AD7
|
|
OE_LOW;
|
|
DATA_READ;
|
|
__asm__("nop\n\t"
|
|
"nop\n\t"
|
|
"nop\n\t"
|
|
"nop\n\t"
|
|
"nop\n\t"
|
|
"nop\n\t");
|
|
unsigned char data = PINC;
|
|
OE_HIGH;
|
|
NAND_1A_HIGH;
|
|
__asm__("nop\n\t"
|
|
"nop\n\t"
|
|
"nop\n\t"
|
|
"nop\n\t"
|
|
"nop\n\t"
|
|
"nop\n\t");
|
|
|
|
return data;
|
|
}
|
|
|
|
// Toshiba TMP90C845A
|
|
// 0xFEC0-0xFFBF Built-in RAM (256 bytes)
|
|
// 0xFFC0-0xFFF7 Built-in I/O (56 bytes)
|
|
// 0xFF00-0xFFBF (192 byte area available in direct addressing mode)
|
|
// 0xFF18-0xFF68 (Micro DMA parameters (if used))
|
|
|
|
// TEST CODE TO READ THE CPU BUILT-IN RAM + I/O
|
|
// NAND 1B LOW = Built-In RAM + I/O Enabled [ROM DISABLED]
|
|
unsigned char read_ram_byte_1B_PCW(unsigned long address) {
|
|
NAND_1B_LOW;
|
|
PORTL = (address >> 16) & 0xFF;
|
|
PORTK = (address >> 8) & 0xFF;
|
|
// Latch Address on AD0-AD7
|
|
ADDR_WRITE;
|
|
LE_HIGH; // Latch Enable
|
|
PORTC = address & 0xFF; // A0-A7
|
|
LE_LOW; // Address Latched
|
|
__asm__("nop\n\t"
|
|
"nop\n\t"
|
|
"nop\n\t"
|
|
"nop\n\t"
|
|
"nop\n\t"
|
|
"nop\n\t");
|
|
// Read Data on AD0-AD7
|
|
OE_LOW;
|
|
DATA_READ;
|
|
__asm__("nop\n\t"
|
|
"nop\n\t"
|
|
"nop\n\t"
|
|
"nop\n\t"
|
|
"nop\n\t"
|
|
"nop\n\t");
|
|
unsigned char data = PINC;
|
|
OE_HIGH;
|
|
NAND_1B_HIGH;
|
|
__asm__("nop\n\t"
|
|
"nop\n\t"
|
|
"nop\n\t"
|
|
"nop\n\t"
|
|
"nop\n\t"
|
|
"nop\n\t");
|
|
|
|
return data;
|
|
}
|
|
|
|
// WRITE SRAM 32K
|
|
void write_ram_byte_1A_PCW(unsigned long address, unsigned char data) {
|
|
NAND_1A_LOW;
|
|
PORTL = (address >> 16) & 0xFF;
|
|
PORTK = (address >> 8) & 0xFF;
|
|
// Latch Address on AD0-AD7
|
|
ADDR_WRITE;
|
|
LE_HIGH; // Latch Enable
|
|
PORTC = address & 0xFF; // A0-A7
|
|
LE_LOW; // Address Latched
|
|
// Write Data on AD0-AD7 - WE LOW ~240-248ns
|
|
WE_LOW;
|
|
PORTC = data;
|
|
__asm__("nop\n\t"
|
|
"nop\n\t"
|
|
"nop\n\t"
|
|
"nop\n\t");
|
|
WE_HIGH;
|
|
NAND_1A_HIGH;
|
|
}
|
|
|
|
// WRITE CPU BUILT-IN RAM + I/O AREA
|
|
// MODIFIED TO MATCH WORKING BANK SWITCH ROUTINE
|
|
void write_ram_byte_1B_PCW(unsigned long address, unsigned char data) {
|
|
NAND_1A_LOW;
|
|
NAND_1A_HIGH;
|
|
NAND_1B_LOW;
|
|
PORTL = (address >> 16) & 0xFF;
|
|
PORTK = (address >> 8) & 0xFF;
|
|
// Latch Address on AD0-AD7
|
|
ADDR_WRITE;
|
|
LE_HIGH; // Latch Enable
|
|
PORTC = address & 0xFF; // A0-A7
|
|
LE_LOW; // Address Latched
|
|
// Write Data on AD0-AD7 - WE LOW ~740ns
|
|
WE_LOW;
|
|
PORTC = data;
|
|
__asm__("nop\n\t"
|
|
"nop\n\t"
|
|
"nop\n\t"
|
|
"nop\n\t"
|
|
"nop\n\t");
|
|
__asm__("nop\n\t"
|
|
"nop\n\t"
|
|
"nop\n\t"
|
|
"nop\n\t"
|
|
"nop\n\t");
|
|
WE_HIGH;
|
|
NAND_1B_HIGH;
|
|
}
|
|
|
|
//==============================================================================
|
|
// Overload Multi-Pack Bank Switch
|
|
//
|
|
// Known Multi-Pack Carts (Yellow Label Carts)
|
|
// 0BD400 [PS] (2MB Version)
|
|
// 0BD400 [PS] (4MB Version)
|
|
// 0BF400 [PL]
|
|
// 1BF400 [PZ]
|
|
// 8BD400 [CR]
|
|
// 8BF400 [LP]
|
|
// 9BF400 [SLP] (Undumped)
|
|
|
|
// Per Overload, identify multi-pack cart by reading 0x3FFA-0x3FFE
|
|
// Multi-Pack carts are non-zero
|
|
// 0x3FFA - Current Cartridge Bank
|
|
// 0x3FFC - Value to Switch to Cartridge Bank 0
|
|
// 0x3FFD - Value to Switch to Cartridge Bank 1
|
|
// 0x3FFE - Last Value written to 0xFFFF
|
|
|
|
// Bank Settings for 2MB
|
|
// Write 0x28 to 0xFFFF to read 1st half of ROM
|
|
// Write 0x2E to 0xFFFF to read 2nd half of ROM
|
|
|
|
// Bank Settings for 4MB
|
|
// Write 0x20 to 0xFFFF to read 1st half of ROM
|
|
// Write 0x31 to 0xFFFF to read 2nd half of ROM
|
|
|
|
// MULTI-PACK CART CHECK
|
|
void check_multi_PCW() {
|
|
read_setup_PCW();
|
|
byte tempbyte = read_rom_byte_PCW(0x3FFC); // Bank 0 Switch
|
|
if (tempbyte) {
|
|
bank0 = tempbyte; // Store Bank 0 Switch
|
|
tempbyte = read_rom_byte_PCW(0x3FFD); // Bank 1 Switch
|
|
if (tempbyte) {
|
|
bank1 = tempbyte; // Store Bank 1 Switch
|
|
// Check for 00s
|
|
tempbyte = read_rom_byte_PCW(0x3FFB); // Should be 00
|
|
if (!tempbyte) {
|
|
tempbyte = read_rom_byte_PCW(0x3FFF); // Should be 00
|
|
if (!tempbyte)
|
|
multipack = 1; // Flag Multi-Cart
|
|
else {
|
|
bank0 = 0;
|
|
bank1 = 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void write_bank_byte_PCW(unsigned char data) {
|
|
NAND_1A_LOW;
|
|
NAND_1A_HIGH;
|
|
NAND_1B_LOW;
|
|
// Write to Address 0xFFFF
|
|
PORTL = 0x00;
|
|
PORTK = 0xFF; // A8-A15
|
|
// Latch Address on AD0-AD7
|
|
ADDR_WRITE;
|
|
LE_HIGH; // Latch Enable
|
|
PORTC = 0xFF; // A0-A7
|
|
LE_LOW; // Address Latched
|
|
// Write Data on AD0-AD7 - WE LOW ~728-736ns
|
|
WE_LOW;
|
|
PORTC = data;
|
|
__asm__("nop\n\t"
|
|
"nop\n\t"
|
|
"nop\n\t"
|
|
"nop\n\t"
|
|
"nop\n\t");
|
|
__asm__("nop\n\t"
|
|
"nop\n\t"
|
|
"nop\n\t"
|
|
"nop\n\t"
|
|
"nop\n\t");
|
|
WE_HIGH;
|
|
NAND_1B_HIGH;
|
|
}
|
|
|
|
void switchBank_PCW(int bank) {
|
|
if (bank == 1) { // Upper Half
|
|
write_bank_byte_PCW(bank1);
|
|
} else { // Lower Half (default)
|
|
write_bank_byte_PCW(bank0);
|
|
}
|
|
}
|
|
|
|
//******************************************
|
|
// READ ROM FUNCTIONS
|
|
//******************************************
|
|
|
|
void readROM_PCW() {
|
|
// Setup read mode
|
|
read_setup_PCW();
|
|
|
|
// Detect rom size
|
|
uint32_t rom_size = detect_rom_size_PCW();
|
|
display_Clear();
|
|
print_Msg(F("READING "));
|
|
print_Msg(rom_size / 1024 / 1024);
|
|
print_Msg("MB SINGLE-PACK");
|
|
println_Msg(F(""));
|
|
display_Update();
|
|
|
|
// Create file
|
|
strcpy(fileName, romName);
|
|
strcat(fileName, ".pcw");
|
|
EEPROM_readAnything(0, foldern);
|
|
sprintf(folder, "PCW/ROM/%d", foldern);
|
|
sd.mkdir(folder, true);
|
|
sd.chdir(folder);
|
|
|
|
print_STR(saving_to_STR, 0);
|
|
print_Msg(folder);
|
|
println_Msg(F("/..."));
|
|
display_Update();
|
|
|
|
foldern = foldern + 1;
|
|
EEPROM_writeAnything(0, foldern);
|
|
|
|
if (!myFile.open(fileName, O_RDWR | O_CREAT)) {
|
|
print_FatalError(sd_error_STR);
|
|
}
|
|
|
|
// Init progress bar
|
|
uint32_t progress = 0;
|
|
draw_progressbar(0, rom_size);
|
|
|
|
for (unsigned long address = 0; address < rom_size; address += 512) { // 4MB
|
|
for (unsigned int x = 0; x < 512; x++) {
|
|
sdBuffer[x] = read_rom_byte_PCW(address + x);
|
|
}
|
|
myFile.write(sdBuffer, 512);
|
|
progress += 512;
|
|
draw_progressbar(progress, rom_size);
|
|
}
|
|
myFile.flush();
|
|
myFile.close();
|
|
|
|
// Compare CRC32 to database and rename ROM if found
|
|
// Arguments: database name, precalculated crc string or 0 to calculate, rename rom or not, starting offset
|
|
compareCRC("pcw.txt", 0, 1, 0);
|
|
|
|
// Wait for user input
|
|
println_Msg(F(""));
|
|
// Prints string out of the common strings array either with or without newline
|
|
print_STR(press_button_STR, 1);
|
|
display_Update();
|
|
wait();
|
|
}
|
|
|
|
void readMultiROM_PCW() {
|
|
strcpy(fileName, romName);
|
|
strcat(fileName, ".pcw");
|
|
|
|
EEPROM_readAnything(0, foldern);
|
|
sprintf(folder, "PCW/ROM/%d", foldern);
|
|
sd.mkdir(folder, true);
|
|
sd.chdir(folder);
|
|
|
|
display_Clear();
|
|
print_STR(saving_to_STR, 0);
|
|
print_Msg(folder);
|
|
println_Msg(F("/..."));
|
|
display_Update();
|
|
|
|
foldern = foldern + 1;
|
|
EEPROM_writeAnything(0, foldern);
|
|
|
|
if (!myFile.open(fileName, O_RDWR | O_CREAT)) {
|
|
print_FatalError(sd_error_STR);
|
|
}
|
|
|
|
display_Clear();
|
|
println_Msg(F("READING MULTI-PACK"));
|
|
println_Msg(F(""));
|
|
display_Update();
|
|
|
|
// Init progress bar
|
|
uint32_t progress = 0;
|
|
draw_progressbar(0, 0x400000);
|
|
|
|
read_setup_PCW();
|
|
// Lower Half
|
|
switchBank_PCW(0);
|
|
for (unsigned long address = 0; address < 0x200000; address += 512) { // 2MB
|
|
for (unsigned int x = 0; x < 512; x++) {
|
|
sdBuffer[x] = read_rom_byte_PCW(address + x);
|
|
}
|
|
myFile.write(sdBuffer, 512);
|
|
progress += 512;
|
|
draw_progressbar(progress, 0x400000);
|
|
}
|
|
|
|
read_setup_PCW();
|
|
// Upper Half
|
|
switchBank_PCW(1);
|
|
for (unsigned long address = 0x200000; address < 0x400000; address += 512) { // 2MB
|
|
for (unsigned int x = 0; x < 512; x++) {
|
|
sdBuffer[x] = read_rom_byte_PCW(address + x);
|
|
}
|
|
myFile.write(sdBuffer, 512);
|
|
progress += 512;
|
|
draw_progressbar(progress, 0x400000);
|
|
}
|
|
|
|
myFile.flush();
|
|
myFile.close();
|
|
// Reset Bank
|
|
switchBank_PCW(0);
|
|
|
|
// Compare CRC32 to database and rename ROM if found
|
|
// Arguments: database name, precalculated crc string or 0 to calculate, rename rom or not, starting offset
|
|
compareCRC("pcw.txt", 0, 1, 0);
|
|
|
|
// Wait for user input
|
|
println_Msg(F(""));
|
|
// Prints string out of the common strings array either with or without newline
|
|
print_STR(press_button_STR, 1);
|
|
display_Update();
|
|
wait();
|
|
}
|
|
|
|
uint32_t detect_rom_size_PCW(void) {
|
|
uint32_t rom_size;
|
|
uint8_t read_byte;
|
|
uint8_t current_byte;
|
|
uint8_t detect_1m, detect_2m;
|
|
|
|
//Initialize variables
|
|
detect_1m = 0;
|
|
detect_2m = 0;
|
|
|
|
//Confirm where mirror address starts from (1MB, 2MB or 4MB)
|
|
for (current_byte = 0; current_byte < DETECTION_SIZE; current_byte++) {
|
|
if ((current_byte != detect_1m) && (current_byte != detect_2m)) {
|
|
//If none matched, size is 4MB
|
|
break;
|
|
}
|
|
|
|
read_byte = read_rom_byte_PCW(current_byte);
|
|
|
|
if (current_byte == detect_1m) {
|
|
if (read_rom_byte_PCW(0x100000 + current_byte) == read_byte) {
|
|
detect_1m++;
|
|
}
|
|
}
|
|
if (current_byte == detect_2m) {
|
|
if (read_rom_byte_PCW(0x200000 + current_byte) == read_byte) {
|
|
detect_2m++;
|
|
}
|
|
}
|
|
}
|
|
|
|
//ROM size detection
|
|
if (detect_1m == DETECTION_SIZE) {
|
|
rom_size = 0x100000;
|
|
} else if (detect_2m == DETECTION_SIZE) {
|
|
rom_size = 0x200000;
|
|
} else {
|
|
rom_size = 0x400000;
|
|
}
|
|
|
|
return rom_size;
|
|
}
|
|
|
|
//******************************************
|
|
// SRAM FUNCTIONS
|
|
//******************************************
|
|
|
|
void readSRAM_PCW() { // readSRAM_1A()
|
|
strcpy(fileName, romName);
|
|
strcat(fileName, ".srm");
|
|
|
|
EEPROM_readAnything(0, foldern);
|
|
sprintf(folder, "PCW/SAVE/%d", foldern);
|
|
sd.mkdir(folder, true);
|
|
sd.chdir(folder);
|
|
|
|
foldern = foldern + 1;
|
|
EEPROM_writeAnything(0, foldern);
|
|
|
|
if (!myFile.open(fileName, O_RDWR | O_CREAT)) {
|
|
print_FatalError(sd_error_STR);
|
|
}
|
|
display_Clear();
|
|
read_setup_PCW();
|
|
for (unsigned long address = 0x0; address < 0x8000; address += 512) { // 32K
|
|
for (unsigned int x = 0; x < 512; x++) {
|
|
sdBuffer[x] = read_ram_byte_1A_PCW(address + x);
|
|
}
|
|
myFile.write(sdBuffer, 512);
|
|
}
|
|
myFile.flush();
|
|
myFile.close();
|
|
print_Msg(F("Saved to "));
|
|
print_Msg(folder);
|
|
println_Msg(F("/"));
|
|
display_Update();
|
|
// calcCRC(fileName, 0x8000, NULL, 0); // 32K
|
|
}
|
|
|
|
// SRAM
|
|
void writeSRAM_PCW() {
|
|
sprintf(filePath, "%s/%s", filePath, fileName);
|
|
println_Msg(F("Writing..."));
|
|
println_Msg(filePath);
|
|
display_Update();
|
|
|
|
if (myFile.open(filePath, O_READ)) {
|
|
sd.chdir();
|
|
sprintf(filePath, "%s/%s", filePath, fileName);
|
|
display_Clear();
|
|
println_Msg(F("Writing File: "));
|
|
println_Msg(filePath);
|
|
println_Msg(fileName);
|
|
display_Update();
|
|
//open file on sd card
|
|
if (myFile.open(filePath, O_READ)) {
|
|
read_setup_PCW();
|
|
for (unsigned int address = 0x0; address < 0x8000; address += 512) { // 32K
|
|
myFile.read(sdBuffer, 512);
|
|
for (unsigned int x = 0; x < 512; x++) {
|
|
write_ram_byte_1A_PCW(address + x, sdBuffer[x]);
|
|
}
|
|
}
|
|
myFile.close();
|
|
print_STR(done_STR, 1);
|
|
display_Update();
|
|
} else {
|
|
print_FatalError(sd_error_STR);
|
|
}
|
|
} else {
|
|
print_FatalError(sd_error_STR);
|
|
}
|
|
display_Clear();
|
|
}
|
|
|
|
unsigned long verifySRAM_PCW() {
|
|
writeErrors = 0;
|
|
|
|
if (myFile.open(filePath, O_READ)) {
|
|
read_setup_PCW();
|
|
for (unsigned int address = 0x0; address < 0x8000; address += 512) { // 32K
|
|
for (unsigned int x = 0; x < 512; x++) {
|
|
byte myByte = read_ram_byte_1A_PCW(address + x);
|
|
sdBuffer[x] = myByte;
|
|
}
|
|
for (int i = 0; i < 512; i++) {
|
|
if (myFile.read() != sdBuffer[i]) {
|
|
writeErrors++;
|
|
}
|
|
}
|
|
}
|
|
myFile.close();
|
|
} else {
|
|
print_FatalError(sd_error_STR);
|
|
}
|
|
|
|
return writeErrors;
|
|
}
|
|
|
|
// avoid warnings
|
|
#undef MODE_READ
|
|
#undef MODE_WRITE
|
|
|
|
#endif
|
|
//******************************************
|
|
// End of File
|
|
//******************************************
|