mirror of
https://github.com/sanni/cartreader.git
synced 2024-11-15 01:15:06 +01:00
e61ac414d8
* Reduced PROGMEM / DRAM usage slightly (Using defaults w/HW5: Before -> 214,668 bytes / 5,757 bytes; After -> 213,414 bytes / 5,751 bytes) * Optimized some menu options and calls * Added more string constants and implemented them where found. * Fixed some stylization * Constants should always be uppercase. * Features should use the `ENABLE_<feature name>` format. * Options for features should use the `OPTION_<feature name>_<option name>` format. * Added ENUMs for more clarity and better type checking. * Moved some defines over to `constexpr` and `const` types. These are preferred over preprocessor constants when not intended for use with `#if` and other preprocessor language.
735 lines
18 KiB
C++
735 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
|
|
|
|
uint32_t rom_size;
|
|
boolean multipack;
|
|
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)
|
|
|
|
strcpy(romName, "PCW");
|
|
|
|
mode = CORE_PCW;
|
|
}
|
|
|
|
//******************************************
|
|
// MENU
|
|
//******************************************
|
|
static const char* const menuOptionsPCW[] PROGMEM = { FSTRING_READ_ROM, FSTRING_READ_SAVE, FSTRING_WRITE_SAVE, FSTRING_RESET };
|
|
|
|
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("/");
|
|
check_multi_PCW();
|
|
if (multipack)
|
|
readMultiROM_PCW();
|
|
else
|
|
readSingleROM_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;
|
|
}
|
|
|
|
//******************************************
|
|
// SINGLE-PACK FUNCTIONS
|
|
//******************************************
|
|
|
|
uint32_t detect_rom_size_PCW(void) {
|
|
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;
|
|
}
|
|
|
|
void readSingleROM_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(FS(FSTRING_EMPTY));
|
|
|
|
// Create file
|
|
strcpy(fileName, romName);
|
|
strcat(fileName, ".pcw");
|
|
EEPROM_readAnything(0, foldern);
|
|
sprintf(folder, "PCW/ROM/%d", foldern);
|
|
sd.mkdir(folder, true);
|
|
sd.chdir(folder);
|
|
|
|
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(FS(FSTRING_EMPTY));
|
|
print_STR(press_button_STR, 1);
|
|
display_Update();
|
|
wait();
|
|
}
|
|
|
|
//******************************************
|
|
// MULTI-PACK FUNCTIONS
|
|
//******************************************
|
|
|
|
// 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
|
|
|
|
void check_multi_PCW() {
|
|
// init variables
|
|
read_setup_PCW();
|
|
multipack = 0;
|
|
bank0 = 0;
|
|
bank1 = 0;
|
|
|
|
byte tempbyte = read_rom_byte_PCW(0x3FFC); // Check for a bank 0 switch value
|
|
if (tempbyte) {
|
|
bank0 = tempbyte; // Store bank 0 switch value
|
|
tempbyte = read_rom_byte_PCW(0x3FFD); // Check for a bank 1 switch value
|
|
if (tempbyte) {
|
|
bank1 = tempbyte; // Store bank 1 switch value
|
|
if (!read_rom_byte_PCW(0x3FFB) && !read_rom_byte_PCW(0x3FFF)) { // Check for 00s
|
|
multipack = 1; // Flag as multi-pack
|
|
display_Clear();
|
|
if ((bank0 == 0x28) && (bank1 == 0x2E)) // 2MB multi-pack cart
|
|
rom_size = 0x200000;
|
|
else if ((bank0 == 0x20) && (bank1 == 0x31)) // 4MB multi-pack cart
|
|
rom_size = 0x400000;
|
|
else { // Warn for unknown bank switch values, size set to 4MB
|
|
println_Msg(F("Warning: Unknown cart size"));
|
|
rom_size = 0x400000;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
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;
|
|
|
|
for (unsigned int x = 0; x < 40; x++)
|
|
__asm__("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);
|
|
}
|
|
}
|
|
|
|
void readMultiROM_PCW() {
|
|
print_Msg(F("READING "));
|
|
print_Msg(rom_size / 1024 / 1024);
|
|
print_Msg("MB MULTI-PACK");
|
|
println_Msg(FS(FSTRING_EMPTY));
|
|
|
|
// Create file
|
|
strcpy(fileName, romName);
|
|
strcat(fileName, ".pcw");
|
|
EEPROM_readAnything(0, foldern);
|
|
sprintf(folder, "PCW/ROM/%d", foldern);
|
|
sd.mkdir(folder, true);
|
|
sd.chdir(folder);
|
|
|
|
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);
|
|
|
|
// Lower Half
|
|
read_setup_PCW();
|
|
switchBank_PCW(0);
|
|
for (unsigned long address = 0; address < (rom_size / 2); address += 512) {
|
|
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);
|
|
}
|
|
|
|
// Upper Half
|
|
read_setup_PCW();
|
|
switchBank_PCW(1);
|
|
for (unsigned long address = 0x200000; address < (0x200000 + (rom_size / 2)); address += 512) {
|
|
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();
|
|
|
|
// 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(FS(FSTRING_EMPTY));
|
|
print_STR(press_button_STR, 1);
|
|
display_Update();
|
|
wait();
|
|
}
|
|
|
|
//******************************************
|
|
// 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
|
|
//******************************************
|