mirror of
https://github.com/sanni/cartreader.git
synced 2024-11-10 23:15:08 +01:00
V8.5 BETA: Add global log and GB database
Both are disabled in options.h by default since they push the RAM usage over the limit resulting in corrupted LCD output. Global log outputs all info to OSCR_LOG.txt in the root of the SD. no-intro calculates the CRC32 of a Gameboy ROM and if found in the database renames it to no-intro naming scheme.
This commit is contained in:
parent
a237f64470
commit
1c6d277e84
@ -4,8 +4,8 @@
|
||||
This project represents a community-driven effort to provide
|
||||
an easy to build and easy to modify cartridge dumper.
|
||||
|
||||
Date: 09.06.2022
|
||||
Version: 8.4
|
||||
Date: 11.06.2022
|
||||
Version: 8.5 BETA
|
||||
|
||||
SD lib: https://github.com/greiman/SdFat
|
||||
OLED lib: https://github.com/adafruit/Adafruit_SSD1306
|
||||
@ -19,7 +19,7 @@
|
||||
RTC lib: https://github.com/adafruit/RTClib
|
||||
Frequency lib: https://github.com/PaulStoffregen/FreqCount
|
||||
|
||||
Compiled with Arduino 1.8.16
|
||||
Compiled with Arduino 1.8.19
|
||||
|
||||
Thanks to:
|
||||
MichlK - ROM Reader for Super Nintendo
|
||||
@ -58,7 +58,7 @@
|
||||
|
||||
**********************************************************************************/
|
||||
|
||||
char ver[5] = "8.4";
|
||||
char ver[5] = "8.5B";
|
||||
|
||||
/******************************************
|
||||
Libraries
|
||||
@ -77,6 +77,9 @@ char ver[5] = "8.4";
|
||||
SdFs sd;
|
||||
FsFile myDir;
|
||||
FsFile myFile;
|
||||
#ifdef global_log
|
||||
FsFile myLog;
|
||||
#endif
|
||||
|
||||
// AVR Eeprom
|
||||
#include <EEPROM.h>
|
||||
@ -785,6 +788,12 @@ void setup() {
|
||||
print_Error(F("SD Error"), true);
|
||||
}
|
||||
|
||||
#ifdef global_log
|
||||
if (!myLog.open("OSCR_LOG.txt", O_RDWR | O_CREAT | O_APPEND)) {
|
||||
print_Error(F("SD Error"), true);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef RTC_installed
|
||||
// Start RTC
|
||||
RTCStart();
|
||||
@ -892,6 +901,9 @@ void print_Msg(const __FlashStringHelper *string) {
|
||||
#ifdef enable_serial
|
||||
Serial.print(string);
|
||||
#endif
|
||||
#ifdef global_log
|
||||
myLog.print(string);
|
||||
#endif
|
||||
}
|
||||
|
||||
void print_Msg(const char myString[]) {
|
||||
@ -906,8 +918,8 @@ void print_Msg(const char myString[]) {
|
||||
}
|
||||
// Newline
|
||||
display.setCursor(0, display.ty + 8);
|
||||
// Print remaining characters
|
||||
while (strPos < strlen(myString)) {
|
||||
// Print until end of display and ignore remaining characters
|
||||
while ((strPos < strlen(myString)) && (display.tx < 122)) {
|
||||
display.print(myString[strPos]);
|
||||
strPos++;
|
||||
}
|
||||
@ -922,6 +934,9 @@ void print_Msg(const char myString[]) {
|
||||
#ifdef enable_serial
|
||||
Serial.print(myString);
|
||||
#endif
|
||||
#ifdef global_log
|
||||
myLog.print(myString);
|
||||
#endif
|
||||
}
|
||||
|
||||
void print_Msg(long unsigned int message) {
|
||||
@ -934,6 +949,9 @@ void print_Msg(long unsigned int message) {
|
||||
#ifdef enable_serial
|
||||
Serial.print(message);
|
||||
#endif
|
||||
#ifdef global_log
|
||||
myLog.print(message);
|
||||
#endif
|
||||
}
|
||||
|
||||
void print_Msg(byte message, int outputFormat) {
|
||||
@ -946,6 +964,9 @@ void print_Msg(byte message, int outputFormat) {
|
||||
#ifdef enable_serial
|
||||
Serial.print(message, outputFormat);
|
||||
#endif
|
||||
#ifdef global_log
|
||||
myLog.print(message, outputFormat);
|
||||
#endif
|
||||
}
|
||||
|
||||
void print_Msg(String string) {
|
||||
@ -958,6 +979,9 @@ void print_Msg(String string) {
|
||||
#ifdef enable_serial
|
||||
Serial.print(string);
|
||||
#endif
|
||||
#ifdef global_log
|
||||
myLog.print(string);
|
||||
#endif
|
||||
}
|
||||
|
||||
void print_Msg_PaddedHexByte(byte message) {
|
||||
@ -976,10 +1000,9 @@ void print_Msg_PaddedHex32(unsigned long message) {
|
||||
print_Msg_PaddedHexByte((message >> 8) & 0xFF);
|
||||
print_Msg_PaddedHexByte((message >> 0) & 0xFF);
|
||||
}
|
||||
|
||||
void println_Msg(String string) {
|
||||
#ifdef enable_LCD
|
||||
print_Msg(string);
|
||||
display.print(string);
|
||||
display.setCursor(0, display.ty + 8);
|
||||
#endif
|
||||
#ifdef enable_OLED
|
||||
@ -988,11 +1011,14 @@ void println_Msg(String string) {
|
||||
#ifdef enable_serial
|
||||
Serial.println(string);
|
||||
#endif
|
||||
#ifdef global_log
|
||||
myLog.println(string);
|
||||
#endif
|
||||
}
|
||||
|
||||
void println_Msg(byte message, int outputFormat) {
|
||||
#ifdef enable_LCD
|
||||
print_Msg(message, outputFormat);
|
||||
display.print(message, outputFormat);
|
||||
display.setCursor(0, display.ty + 8);
|
||||
#endif
|
||||
#ifdef enable_OLED
|
||||
@ -1001,24 +1027,48 @@ void println_Msg(byte message, int outputFormat) {
|
||||
#ifdef enable_serial
|
||||
Serial.println(message, outputFormat);
|
||||
#endif
|
||||
#ifdef global_log
|
||||
myLog.println(message, outputFormat);
|
||||
#endif
|
||||
}
|
||||
|
||||
void println_Msg(const char message[]) {
|
||||
void println_Msg(const char myString[]) {
|
||||
#ifdef enable_LCD
|
||||
print_Msg(message);
|
||||
// test for word wrap
|
||||
if ((display.tx + strlen(myString) * 6) > 128) {
|
||||
int strPos = 0;
|
||||
// Print until end of display
|
||||
while (display.tx < 122) {
|
||||
display.print(myString[strPos]);
|
||||
strPos++;
|
||||
}
|
||||
// Newline
|
||||
display.setCursor(0, display.ty + 8);
|
||||
// Print until end of display and ignore remaining characters
|
||||
while ((strPos < strlen(myString)) && (display.tx < 122)) {
|
||||
display.print(myString[strPos]);
|
||||
strPos++;
|
||||
}
|
||||
}
|
||||
else {
|
||||
display.print(myString);
|
||||
}
|
||||
display.setCursor(0, display.ty + 8);
|
||||
#endif
|
||||
#ifdef enable_OLED
|
||||
display.println(message);
|
||||
display.println(myString);
|
||||
#endif
|
||||
#ifdef enable_serial
|
||||
Serial.println(message);
|
||||
Serial.println(myString);
|
||||
#endif
|
||||
#ifdef global_log
|
||||
myLog.println(myString);
|
||||
#endif
|
||||
}
|
||||
|
||||
void println_Msg(const __FlashStringHelper *string) {
|
||||
#ifdef enable_LCD
|
||||
print_Msg(string);
|
||||
display.print(string);
|
||||
display.setCursor(0, display.ty + 8);
|
||||
#endif
|
||||
#ifdef enable_OLED
|
||||
@ -1027,11 +1077,14 @@ void println_Msg(const __FlashStringHelper *string) {
|
||||
#ifdef enable_serial
|
||||
Serial.println(string);
|
||||
#endif
|
||||
#ifdef global_log
|
||||
myLog.println(string);
|
||||
#endif
|
||||
}
|
||||
|
||||
void println_Msg(long unsigned int message) {
|
||||
#ifdef enable_LCD
|
||||
print_Msg(message);
|
||||
display.print(message);
|
||||
display.setCursor(0, display.ty + 8);
|
||||
#endif
|
||||
#ifdef enable_OLED
|
||||
@ -1040,6 +1093,9 @@ void println_Msg(long unsigned int message) {
|
||||
#ifdef enable_serial
|
||||
Serial.println(message);
|
||||
#endif
|
||||
#ifdef global_log
|
||||
myLog.println(message);
|
||||
#endif
|
||||
}
|
||||
|
||||
void display_Update() {
|
||||
@ -1052,6 +1108,9 @@ void display_Update() {
|
||||
#ifdef enable_serial
|
||||
delay(100);
|
||||
#endif
|
||||
#ifdef global_log
|
||||
myLog.flush();
|
||||
#endif
|
||||
}
|
||||
|
||||
void display_Clear() {
|
||||
@ -1063,6 +1122,9 @@ void display_Clear() {
|
||||
display.clearDisplay();
|
||||
display.setCursor(0, 0);
|
||||
#endif
|
||||
#ifdef global_log
|
||||
myLog.println("");
|
||||
#endif
|
||||
}
|
||||
|
||||
unsigned char question_box(const __FlashStringHelper* question, char answers[7][20], int num_answers, int default_choice) {
|
||||
|
@ -299,7 +299,7 @@ void gbMenu() {
|
||||
// Change working dir to root
|
||||
sd.chdir("/");
|
||||
readROM_GB();
|
||||
compare_checksum_GB();
|
||||
compare_checksums_GB();
|
||||
break;
|
||||
|
||||
case 1:
|
||||
@ -313,6 +313,7 @@ void gbMenu() {
|
||||
else {
|
||||
print_Error(F("Cart has no Sram"), false);
|
||||
}
|
||||
println_Msg(F(""));
|
||||
break;
|
||||
|
||||
case 2:
|
||||
@ -340,13 +341,13 @@ void gbMenu() {
|
||||
else {
|
||||
print_Error(F("Cart has no Sram"), false);
|
||||
}
|
||||
println_Msg(F(""));
|
||||
break;
|
||||
|
||||
case 3:
|
||||
resetArduino();
|
||||
break;
|
||||
}
|
||||
println_Msg(F(""));
|
||||
println_Msg(F("Press Button..."));
|
||||
display_Update();
|
||||
wait();
|
||||
@ -372,8 +373,8 @@ void setup_GB() {
|
||||
|
||||
// Set Data Pins (D0-D7) to Input
|
||||
DDRC = 0x00;
|
||||
// Disable Internal Pullups
|
||||
//PORTC = 0x00;
|
||||
// Enable Internal Pullups
|
||||
PORTC = 0xFF;
|
||||
|
||||
delay(400);
|
||||
|
||||
@ -385,15 +386,12 @@ void setup_GB() {
|
||||
showCartInfo_GB();
|
||||
|
||||
// MMM01 initialize
|
||||
if (romType >= 11 && romType <= 13)
|
||||
{
|
||||
dataOut();
|
||||
if (romType >= 11 && romType <= 13) {
|
||||
writeByte_GB(0x3fff, 0x00);
|
||||
writeByte_GB(0x5fff, 0x40);
|
||||
writeByte_GB(0x7fff, 0x01);
|
||||
writeByte_GB(0x1fff, 0x3a);
|
||||
writeByte_GB(0x1fff, 0x7a);
|
||||
dataIn_GB();
|
||||
}
|
||||
}
|
||||
|
||||
@ -508,17 +506,14 @@ void showCartInfo_GB() {
|
||||
/******************************************
|
||||
Low level functions
|
||||
*****************************************/
|
||||
// Switch data pins to read
|
||||
void dataIn_GB() {
|
||||
// Set to Input
|
||||
DDRC = 0x00;
|
||||
// Pullups
|
||||
//PORTC = 0xFF;
|
||||
}
|
||||
|
||||
byte readByte_GB(word myAddress) {
|
||||
// Set address
|
||||
PORTF = myAddress & 0xFF;
|
||||
PORTK = (myAddress >> 8) & 0xFF;
|
||||
// Switch data pins to input
|
||||
DDRC = 0x00;
|
||||
// Enable pullups
|
||||
PORTC = 0xFF;
|
||||
|
||||
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t");
|
||||
|
||||
@ -539,11 +534,14 @@ byte readByte_GB(word myAddress) {
|
||||
}
|
||||
|
||||
void writeByte_GB(int myAddress, byte myData) {
|
||||
// Set address
|
||||
PORTF = myAddress & 0xFF;
|
||||
PORTK = (myAddress >> 8) & 0xFF;
|
||||
// Set data
|
||||
PORTC = myData;
|
||||
// Switch data pins to output
|
||||
DDRC = 0xFF;
|
||||
|
||||
// Arduino running at 16Mhz -> one nop = 62.5ns
|
||||
// Wait till output is stable
|
||||
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t");
|
||||
|
||||
@ -558,12 +556,21 @@ void writeByte_GB(int myAddress, byte myData) {
|
||||
|
||||
// Leave WR high for at least 50ns
|
||||
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t");
|
||||
|
||||
// Switch data pins to input
|
||||
DDRC = 0x00;
|
||||
// Enable pullups
|
||||
PORTC = 0xFF;
|
||||
}
|
||||
|
||||
// Triggers CS and CLK pin
|
||||
byte readByteSRAM_GB(word myAddress) {
|
||||
PORTF = myAddress & 0xFF;
|
||||
PORTK = (myAddress >> 8) & 0xFF;
|
||||
// Switch data pins to input
|
||||
DDRC = 0x00;
|
||||
// Enable pullups
|
||||
PORTC = 0xFF;
|
||||
|
||||
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t");
|
||||
|
||||
@ -594,9 +601,13 @@ byte readByteSRAM_GB(word myAddress) {
|
||||
|
||||
// Triggers CS and CLK pin
|
||||
void writeByteSRAM_GB(int myAddress, byte myData) {
|
||||
// Set address
|
||||
PORTF = myAddress & 0xFF;
|
||||
PORTK = (myAddress >> 8) & 0xFF;
|
||||
// Set data
|
||||
PORTC = myData;
|
||||
// Switch data pins to output
|
||||
DDRC = 0xFF;
|
||||
|
||||
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t");
|
||||
|
||||
@ -635,6 +646,11 @@ void writeByteSRAM_GB(int myAddress, byte myData) {
|
||||
|
||||
// Leave WR high for at least 50ns
|
||||
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t");
|
||||
|
||||
// Switch data pins to input
|
||||
DDRC = 0x00;
|
||||
// Enable pullups
|
||||
PORTC = 0xFF;
|
||||
}
|
||||
|
||||
/******************************************
|
||||
@ -642,9 +658,63 @@ void writeByteSRAM_GB(int myAddress, byte myData) {
|
||||
*****************************************/
|
||||
// Read Cartridge Header
|
||||
void getCartInfo_GB() {
|
||||
romType = readByte_GB(0x0147);
|
||||
romSize = readByte_GB(0x0148);
|
||||
sramSize = readByte_GB(0x0149);
|
||||
// Read Header into array
|
||||
for (int currByte = 0x100; currByte < 0x150; currByte++) {
|
||||
sdBuffer[currByte] = readByte_GB(currByte);
|
||||
}
|
||||
|
||||
/* Compare Nintendo logo against known checksum, 156 bytes starting at 0x04
|
||||
word logoChecksum = 0;
|
||||
for (int currByte = 0x104; currByte < 0x134; currByte++) {
|
||||
logoChecksum += sdBuffer[currByte];
|
||||
}
|
||||
|
||||
if (logoChecksum != 0x1546) {
|
||||
print_Error(F("STARTUP LOGO ERROR"), false);
|
||||
println_Msg(F(""));
|
||||
println_Msg(F(""));
|
||||
println_Msg(F(""));
|
||||
println_Msg(F("Press Button to"));
|
||||
println_Msg(F("ignore or powercycle"));
|
||||
println_Msg(F("to try again"));
|
||||
display_Update();
|
||||
wait();
|
||||
}
|
||||
*/
|
||||
|
||||
// Calculate header checksum
|
||||
byte headerChecksum = 0;
|
||||
for (int currByte = 0x134; currByte < 0x14D; currByte++) {
|
||||
headerChecksum = headerChecksum - sdBuffer[currByte] - 1;
|
||||
}
|
||||
|
||||
if (headerChecksum != sdBuffer[0x14D]) {
|
||||
// Read Header into array a second time
|
||||
for (int currByte = 0x100; currByte < 0x150; currByte++) {
|
||||
sdBuffer[currByte] = readByte_GB(currByte);
|
||||
}
|
||||
// Calculate header checksum a second time
|
||||
headerChecksum = 0;
|
||||
for (int currByte = 0x134; currByte < 0x14D; currByte++) {
|
||||
headerChecksum = headerChecksum - sdBuffer[currByte] - 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (headerChecksum != sdBuffer[0x14D]) {
|
||||
print_Error(F("HEADER CHECKSUM ERROR"), false);
|
||||
println_Msg(F(""));
|
||||
println_Msg(F(""));
|
||||
println_Msg(F(""));
|
||||
println_Msg(F("Press Button to"));
|
||||
println_Msg(F("ignore or clean"));
|
||||
println_Msg(F("cart and try again"));
|
||||
display_Update();
|
||||
wait();
|
||||
}
|
||||
|
||||
romType = sdBuffer[0x147];
|
||||
romSize = sdBuffer[0x148];
|
||||
sramSize = sdBuffer[0x149];
|
||||
|
||||
// ROM banks
|
||||
switch (romSize) {
|
||||
@ -710,18 +780,16 @@ void getCartInfo_GB() {
|
||||
}
|
||||
|
||||
// Get Checksum as string
|
||||
eepbit[6] = readByte_GB(0x014E);
|
||||
eepbit[7] = readByte_GB(0x014F);
|
||||
eepbit[6] = sdBuffer[0x14E];
|
||||
eepbit[7] = sdBuffer[0x14F];
|
||||
sprintf(checksumStr, "%02X%02X", eepbit[6], eepbit[7]);
|
||||
|
||||
// Get name
|
||||
byte myByte = 0;
|
||||
byte myLength = 0;
|
||||
|
||||
for (int addr = 0x0134; addr <= 0x13C; addr++) {
|
||||
myByte = readByte_GB(addr);
|
||||
if (((char(myByte) >= 48 && char(myByte) <= 57) || (char(myByte) >= 65 && char(myByte) <= 122)) && myLength < 15) {
|
||||
romName[myLength] = char(myByte);
|
||||
if (((char(sdBuffer[addr]) >= 48 && char(sdBuffer[addr]) <= 57) || (char(sdBuffer[addr]) >= 65 && char(sdBuffer[addr]) <= 122)) && myLength < 15) {
|
||||
romName[myLength] = char(sdBuffer[addr]);
|
||||
myLength++;
|
||||
}
|
||||
}
|
||||
@ -765,9 +833,6 @@ void readROM_GB() {
|
||||
draw_progressbar(0, totalProgressBar);
|
||||
|
||||
for (word currBank = 1; currBank < romBanks; currBank++) {
|
||||
// Switch data pins to output
|
||||
dataOut();
|
||||
|
||||
// Second bank starts at 0x4000
|
||||
if (currBank > 1) {
|
||||
romAddress = 0x4000;
|
||||
@ -808,9 +873,6 @@ void readROM_GB() {
|
||||
writeByte_GB(0x2000, currBank & 0x1F);
|
||||
}
|
||||
|
||||
// Switch data pins to intput
|
||||
dataIn_GB();
|
||||
|
||||
// Read banks and save to SD
|
||||
while (romAddress <= 0x7FFF) {
|
||||
for (int i = 0; i < 512; i++) {
|
||||
@ -834,9 +896,6 @@ unsigned int calc_checksum_GB (char* fileName, char* folder) {
|
||||
unsigned long i = 0;
|
||||
int c = 0;
|
||||
|
||||
if (strcmp(folder, "root") != 0)
|
||||
sd.chdir(folder);
|
||||
|
||||
// If file exists
|
||||
if (myFile.open(fileName, O_READ)) {
|
||||
//calcFilesize = myFile.fileSize() * 8 / 1024 / 1024; // unused
|
||||
@ -847,7 +906,6 @@ unsigned int calc_checksum_GB (char* fileName, char* folder) {
|
||||
}
|
||||
}
|
||||
myFile.close();
|
||||
sd.chdir();
|
||||
// Subtract checksum bytes
|
||||
calcChecksum -= eepbit[6];
|
||||
calcChecksum -= eepbit[7];
|
||||
@ -863,8 +921,8 @@ unsigned int calc_checksum_GB (char* fileName, char* folder) {
|
||||
}
|
||||
|
||||
// Compare checksum
|
||||
boolean compare_checksum_GB() {
|
||||
println_Msg(F("Calculating Checksum"));
|
||||
void compare_checksums_GB() {
|
||||
println_Msg(F("Calculating Checksum..."));
|
||||
display_Update();
|
||||
|
||||
strcpy(fileName, romName);
|
||||
@ -874,21 +932,105 @@ boolean compare_checksum_GB() {
|
||||
EEPROM_readAnything(0, foldern);
|
||||
sprintf(folder, "GB/ROM/%s/%d", romName, foldern - 1);
|
||||
|
||||
if (strcmp(folder, "root") != 0)
|
||||
sd.chdir(folder);
|
||||
|
||||
// Internal ROM checksum
|
||||
char calcsumStr[5];
|
||||
sprintf(calcsumStr, "%04X", calc_checksum_GB(fileName, folder));
|
||||
|
||||
if (strcmp(calcsumStr, checksumStr) == 0) {
|
||||
print_Msg(F("Result: "));
|
||||
println_Msg(calcsumStr);
|
||||
println_Msg(F("Checksum matches"));
|
||||
display_Update();
|
||||
return 1;
|
||||
print_Msg(F("Internal: "));
|
||||
print_Msg(calcsumStr);
|
||||
println_Msg(" -> OK");
|
||||
}
|
||||
else {
|
||||
print_Msg(F("Result: "));
|
||||
print_Msg(F("Internal: "));
|
||||
println_Msg(calcsumStr);
|
||||
print_Error(F("Checksum Error"), false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef no-intro
|
||||
//CRC32
|
||||
char crcStr[9];
|
||||
sprintf(crcStr, "%08lX", crcGB(fileName, folder));
|
||||
// Print checksum
|
||||
print_Msg("CRC32: ");
|
||||
print_Msg(crcStr);
|
||||
|
||||
//Search for CRC32 in file
|
||||
char gamename[50];
|
||||
char crc_search[9];
|
||||
|
||||
//go to root
|
||||
sd.chdir();
|
||||
if (myFile.open("gb.txt", O_READ)) {
|
||||
//Search for same CRC in list
|
||||
while (myFile.available()) {
|
||||
//Read 2 lines (game name and CRC)
|
||||
get_line(gamename, &myFile, 46);
|
||||
get_line(crc_search, &myFile, 9);
|
||||
skip_line(&myFile); //Skip every 3rd line
|
||||
|
||||
//if checksum search successful, rename the file and end search
|
||||
if (strcmp(crc_search, crcStr) == 0)
|
||||
{
|
||||
// Close the file:
|
||||
myFile.close();
|
||||
|
||||
print_Msg(" -> ");
|
||||
println_Msg(gamename);
|
||||
|
||||
// Rename file to no-intro
|
||||
sd.chdir(folder);
|
||||
if (myFile.open(fileName, O_READ)) {
|
||||
myFile.rename(gamename);
|
||||
// Close the file:
|
||||
myFile.close();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (strcmp(crc_search, crcStr) != 0)
|
||||
{
|
||||
println_Msg(" -> Not found");
|
||||
}
|
||||
}
|
||||
else {
|
||||
println_Msg("gb.txt not found");
|
||||
}
|
||||
#else
|
||||
println_Msg("");
|
||||
#endif
|
||||
|
||||
display_Update();
|
||||
//go to root
|
||||
sd.chdir();
|
||||
}
|
||||
|
||||
inline uint32_t updateCRC_GB(uint8_t ch, uint32_t crc) {
|
||||
uint32_t idx = ((crc) ^ (ch)) & 0xff;
|
||||
uint32_t tab_value = pgm_read_dword(crc_32_tab + idx);
|
||||
return tab_value ^ ((crc) >> 8);
|
||||
}
|
||||
|
||||
// Calculate rom's CRC32 from SD
|
||||
uint32_t crcGB(char* fileName, char* folder) {
|
||||
if (myFile.open(fileName, O_READ)) {
|
||||
uint32_t oldcrc32 = 0xFFFFFFFF;
|
||||
|
||||
for (unsigned long currByte = 0; currByte < (myFile.fileSize() / 512); currByte++) {
|
||||
myFile.read(sdBuffer, 512);
|
||||
for (int c = 0; c < 512; c++) {
|
||||
oldcrc32 = updateCRC_GB(sdBuffer[c], oldcrc32);
|
||||
}
|
||||
}
|
||||
// Close the file:
|
||||
myFile.close();
|
||||
return ~oldcrc32;
|
||||
}
|
||||
else {
|
||||
print_Error(F("File not found"), true);
|
||||
}
|
||||
}
|
||||
|
||||
@ -919,12 +1061,9 @@ void readSRAM_GB() {
|
||||
print_Error(F("SD Error"), true);
|
||||
}
|
||||
|
||||
dataIn_GB();
|
||||
|
||||
// MBC2 Fix
|
||||
readByte_GB(0x0134);
|
||||
|
||||
dataOut();
|
||||
if (romType <= 4 || (romType >= 11 && romType <= 13)) {
|
||||
writeByte_GB(0x6000, 1);
|
||||
}
|
||||
@ -934,11 +1073,9 @@ void readSRAM_GB() {
|
||||
|
||||
// Switch SRAM banks
|
||||
for (byte currBank = 0; currBank < sramBanks; currBank++) {
|
||||
dataOut();
|
||||
writeByte_GB(0x4000, currBank);
|
||||
|
||||
// Read SRAM
|
||||
dataIn_GB();
|
||||
for (word sramAddress = 0xA000; sramAddress <= lastByte; sramAddress += 64) {
|
||||
for (byte i = 0; i < 64; i++) {
|
||||
sdBuffer[i] = readByteSRAM_GB(sramAddress + i);
|
||||
@ -948,9 +1085,7 @@ void readSRAM_GB() {
|
||||
}
|
||||
|
||||
// Disable SRAM
|
||||
dataOut();
|
||||
writeByte_GB(0x0000, 0x00);
|
||||
dataIn_GB();
|
||||
|
||||
// Close the file:
|
||||
myFile.close();
|
||||
@ -975,14 +1110,9 @@ void writeSRAM_GB() {
|
||||
|
||||
//open file on sd card
|
||||
if (myFile.open(filePath, O_READ)) {
|
||||
// Set pins to input
|
||||
dataIn_GB();
|
||||
|
||||
// MBC2 Fix
|
||||
readByte_GB(0x0134);
|
||||
|
||||
dataOut();
|
||||
|
||||
// Enable SRAM for MBC1
|
||||
if (romType <= 4 || (romType >= 11 && romType <= 13)) {
|
||||
writeByte_GB(0x6000, 1);
|
||||
@ -1003,9 +1133,6 @@ void writeSRAM_GB() {
|
||||
// Disable SRAM
|
||||
writeByte_GB(0x0000, 0x00);
|
||||
|
||||
// Set pins to input
|
||||
dataIn_GB();
|
||||
|
||||
// Close the file:
|
||||
myFile.close();
|
||||
display_Clear();
|
||||
@ -1031,14 +1158,11 @@ unsigned long verifySRAM_GB() {
|
||||
// Variable for errors
|
||||
writeErrors = 0;
|
||||
|
||||
dataIn_GB();
|
||||
|
||||
// MBC2 Fix
|
||||
readByte_GB(0x0134);
|
||||
|
||||
// Check SRAM size
|
||||
if (lastByte > 0) {
|
||||
dataOut();
|
||||
if (romType <= 4) { // MBC1
|
||||
writeByte_GB(0x6000, 1); // Set RAM Mode
|
||||
}
|
||||
@ -1048,11 +1172,9 @@ unsigned long verifySRAM_GB() {
|
||||
|
||||
// Switch SRAM banks
|
||||
for (byte currBank = 0; currBank < sramBanks; currBank++) {
|
||||
dataOut();
|
||||
writeByte_GB(0x4000, currBank);
|
||||
|
||||
// Read SRAM
|
||||
dataIn_GB();
|
||||
for (word sramAddress = 0xA000; sramAddress <= lastByte; sramAddress += 64) {
|
||||
//fill sdBuffer
|
||||
myFile.read(sdBuffer, 64);
|
||||
@ -1063,10 +1185,8 @@ unsigned long verifySRAM_GB() {
|
||||
}
|
||||
}
|
||||
}
|
||||
dataOut();
|
||||
// Disable RAM
|
||||
writeByte_GB(0x0000, 0x00);
|
||||
dataIn_GB();
|
||||
}
|
||||
// Close the file:
|
||||
myFile.close();
|
||||
@ -1132,9 +1252,6 @@ void writeFlash29F_GB(byte MBC, boolean flashErase) {
|
||||
romBanks = 2;
|
||||
}
|
||||
|
||||
// Set data pins to output
|
||||
dataOut();
|
||||
|
||||
// Set ROM bank hi 0
|
||||
writeByte_GB(0x3000, 0);
|
||||
// Set ROM bank low 0
|
||||
@ -1150,8 +1267,6 @@ void writeFlash29F_GB(byte MBC, boolean flashErase) {
|
||||
writeByte_GB(0x2aa, 0x55);
|
||||
writeByte_GB(0x555, 0x90);
|
||||
|
||||
dataIn_GB();
|
||||
|
||||
// Read the two id bytes into a string
|
||||
sprintf(flashid, "%02X%02X", readByte_GB(0), readByte_GB(1));
|
||||
|
||||
@ -1196,7 +1311,6 @@ void writeFlash29F_GB(byte MBC, boolean flashErase) {
|
||||
display_Update();
|
||||
print_Error(F("Unknown flashrom"), true);
|
||||
}
|
||||
dataOut();
|
||||
|
||||
// Reset flash
|
||||
writeByte_GB(0x555, 0xf0);
|
||||
@ -1215,8 +1329,6 @@ void writeFlash29F_GB(byte MBC, boolean flashErase) {
|
||||
writeByte_GB(0x2aa, 0x55);
|
||||
writeByte_GB(0x555, 0x10);
|
||||
|
||||
// Set data pins to input
|
||||
dataIn_GB();
|
||||
// Read the status register
|
||||
byte statusReg = readByte_GB(0);
|
||||
// After a completed erase D7 will output 1
|
||||
@ -1234,11 +1346,8 @@ void writeFlash29F_GB(byte MBC, boolean flashErase) {
|
||||
// Blink led
|
||||
blinkLED();
|
||||
|
||||
dataOut();
|
||||
|
||||
// Set ROM bank
|
||||
writeByte_GB(0x2000, currBank);
|
||||
dataIn_GB();
|
||||
|
||||
for (unsigned int currAddr = 0x4000; currAddr < 0x7FFF; currAddr += 512) {
|
||||
for (int currByte = 0; currByte < 512; currByte++) {
|
||||
@ -1259,8 +1368,6 @@ void writeFlash29F_GB(byte MBC, boolean flashErase) {
|
||||
display_Update();
|
||||
|
||||
// Write flash
|
||||
dataOut();
|
||||
|
||||
word currAddr = 0;
|
||||
word endAddr = 0x3FFF;
|
||||
|
||||
@ -1292,9 +1399,6 @@ void writeFlash29F_GB(byte MBC, boolean flashErase) {
|
||||
// Write current byte
|
||||
writeByte_GB(currAddr + currByte, sdBuffer[currByte]);
|
||||
|
||||
// Set data pins to input
|
||||
dataIn_GB();
|
||||
|
||||
// Set OE/RD(PH6) LOW
|
||||
PORTH &= ~(1 << 6);
|
||||
|
||||
@ -1304,9 +1408,6 @@ void writeFlash29F_GB(byte MBC, boolean flashErase) {
|
||||
|
||||
// Switch OE/RD(PH6) to HIGH
|
||||
PORTH |= (1 << 6);
|
||||
|
||||
// Set data pins to output
|
||||
dataOut();
|
||||
}
|
||||
currAddr += 512;
|
||||
processedProgressBar += 512;
|
||||
@ -1320,8 +1421,6 @@ void writeFlash29F_GB(byte MBC, boolean flashErase) {
|
||||
display_Update();
|
||||
|
||||
// Write flash
|
||||
dataOut();
|
||||
|
||||
//Initialize progress bar
|
||||
uint32_t processedProgressBar = 0;
|
||||
uint32_t totalProgressBar = (uint32_t)(romBanks) * 16384;
|
||||
@ -1347,9 +1446,6 @@ void writeFlash29F_GB(byte MBC, boolean flashErase) {
|
||||
// Write current byte
|
||||
writeByte_GB(currAddr + currByte, sdBuffer[currByte]);
|
||||
|
||||
// Set data pins to input
|
||||
dataIn_GB();
|
||||
|
||||
// Set OE/RD(PH6) LOW
|
||||
PORTH &= ~(1 << 6);
|
||||
|
||||
@ -1359,9 +1455,6 @@ void writeFlash29F_GB(byte MBC, boolean flashErase) {
|
||||
|
||||
// Switch OE/RD(PH6) to HIGH
|
||||
PORTH |= (1 << 6);
|
||||
|
||||
// Set data pins to output
|
||||
dataOut();
|
||||
}
|
||||
processedProgressBar += 512;
|
||||
draw_progressbar(processedProgressBar, totalProgressBar);
|
||||
@ -1369,9 +1462,6 @@ void writeFlash29F_GB(byte MBC, boolean flashErase) {
|
||||
}
|
||||
}
|
||||
|
||||
// Set data pins to input again
|
||||
dataIn_GB();
|
||||
|
||||
print_Msg(F("Verifying..."));
|
||||
display_Update();
|
||||
|
||||
@ -1385,9 +1475,6 @@ void writeFlash29F_GB(byte MBC, boolean flashErase) {
|
||||
|
||||
// Read number of banks and switch banks
|
||||
for (word bank = 1; bank < romBanks; bank++) {
|
||||
// Switch data pins to output
|
||||
dataOut();
|
||||
|
||||
if (romType >= 5) { // MBC2 and above
|
||||
writeByte_GB(0x2100, bank); // Set ROM bank
|
||||
}
|
||||
@ -1397,9 +1484,6 @@ void writeFlash29F_GB(byte MBC, boolean flashErase) {
|
||||
writeByte_GB(0x2000, bank & 0x1F); // Set bits 0 & 4 (00011111) of ROM bank
|
||||
}
|
||||
|
||||
// Switch data pins to intput
|
||||
dataIn_GB();
|
||||
|
||||
if (bank > 1) {
|
||||
romAddress = 0x4000;
|
||||
}
|
||||
@ -1496,14 +1580,12 @@ void startCFIMode(boolean x16Mode) {
|
||||
void identifyCFI_GB() {
|
||||
// Reset flash
|
||||
display_Clear();
|
||||
dataOut();
|
||||
writeByte_GB(0x6000, 0); // Set ROM Mode
|
||||
writeByte_GB(0x2000, 0); // Set Bank to 0
|
||||
writeByte_GB(0x3000, 0);
|
||||
|
||||
startCFIMode(false); // Trying x8 mode first
|
||||
|
||||
dataIn_GB();
|
||||
display_Clear();
|
||||
// Try x8 mode first
|
||||
char cfiQRYx8[7];
|
||||
@ -1544,9 +1626,7 @@ void identifyCFI_GB() {
|
||||
return;
|
||||
}
|
||||
}
|
||||
dataIn_GB();
|
||||
flashBanks = 1 << (readByteCompensated(0x4E) - 14); // - flashX16Mode);
|
||||
dataOut();
|
||||
|
||||
// Reset flash
|
||||
writeByteCompensated(0xAAA, 0xf0);
|
||||
@ -1621,9 +1701,6 @@ bool writeCFI_GB() {
|
||||
resetArduino();
|
||||
}
|
||||
|
||||
// Set data pins to output
|
||||
dataOut();
|
||||
|
||||
// Set ROM bank hi 0
|
||||
writeByte_GB(0x3000, 0);
|
||||
// Set ROM bank low 0
|
||||
@ -1633,7 +1710,6 @@ bool writeCFI_GB() {
|
||||
// Reset flash
|
||||
writeByteCompensated(0xAAA, 0xf0);
|
||||
delay(100);
|
||||
dataOut();
|
||||
|
||||
// Reset flash
|
||||
writeByte_GB(0x555, 0xf0);
|
||||
@ -1650,8 +1726,6 @@ bool writeCFI_GB() {
|
||||
writeByteCompensated(0x555, 0x55);
|
||||
writeByteCompensated(0xAAA, 0x10);
|
||||
|
||||
dataIn_GB();
|
||||
|
||||
// Read the status register
|
||||
byte statusReg = readByte_GB(0);
|
||||
|
||||
@ -1673,11 +1747,8 @@ bool writeCFI_GB() {
|
||||
// Blink led
|
||||
blinkLED();
|
||||
|
||||
dataOut();
|
||||
|
||||
// Set ROM bank
|
||||
writeByte_GB(0x2000, currBank);
|
||||
dataIn_GB();
|
||||
|
||||
for (unsigned int currAddr = 0x4000; currAddr < 0x7FFF; currAddr += 512) {
|
||||
for (int currByte = 0; currByte < 512; currByte++) {
|
||||
@ -1696,8 +1767,6 @@ bool writeCFI_GB() {
|
||||
display_Update();
|
||||
|
||||
// Write flash
|
||||
dataOut();
|
||||
|
||||
word currAddr = 0;
|
||||
word endAddr = 0x3FFF;
|
||||
|
||||
@ -1727,9 +1796,6 @@ bool writeCFI_GB() {
|
||||
// Write current byte
|
||||
writeByte_GB(currAddr + currByte, sdBuffer[currByte]);
|
||||
|
||||
// Set data pins to input
|
||||
dataIn_GB();
|
||||
|
||||
// Setting CS(PH3) and OE/RD(PH6) LOW
|
||||
PORTH &= ~((1 << 3) | (1 << 6));
|
||||
|
||||
@ -1753,16 +1819,11 @@ bool writeCFI_GB() {
|
||||
PORTH |= (1 << 3) | (1 << 6);
|
||||
__asm__("nop\n\tnop\n\tnop\n\t"); // Waste a few CPU cycles to remove write errors
|
||||
|
||||
// Set data pins to output
|
||||
dataOut();
|
||||
}
|
||||
currAddr += 512;
|
||||
}
|
||||
}
|
||||
|
||||
// Set data pins to input again
|
||||
dataIn_GB();
|
||||
|
||||
display_Clear();
|
||||
println_Msg(F("Verifying"));
|
||||
display_Update();
|
||||
@ -1777,9 +1838,6 @@ bool writeCFI_GB() {
|
||||
|
||||
// Read number of banks and switch banks
|
||||
for (word bank = 1; bank < romBanks; bank++) {
|
||||
// Switch data pins to output
|
||||
dataOut();
|
||||
|
||||
if (romType >= 5) { // MBC2 and above
|
||||
writeByte_GB(0x2100, bank); // Set ROM bank
|
||||
}
|
||||
@ -1789,9 +1847,6 @@ bool writeCFI_GB() {
|
||||
writeByte_GB(0x2000, bank & 0x1F); // Set bits 0 & 4 (00011111) of ROM bank
|
||||
}
|
||||
|
||||
// Switch data pins to intput
|
||||
dataIn_GB();
|
||||
|
||||
if (bank > 1) {
|
||||
romAddress = 0x4000;
|
||||
}
|
||||
|
@ -62,6 +62,36 @@ boolean hasMenu;
|
||||
byte numGames;
|
||||
#endif
|
||||
|
||||
// Compare checksum
|
||||
boolean compare_checksum_GBS() {
|
||||
println_Msg(F("Calculating Checksum"));
|
||||
display_Update();
|
||||
|
||||
strcpy(fileName, romName);
|
||||
strcat(fileName, ".GB");
|
||||
|
||||
// last used rom folder
|
||||
EEPROM_readAnything(0, foldern);
|
||||
sprintf(folder, "GB/ROM/%s/%d", romName, foldern - 1);
|
||||
|
||||
char calcsumStr[5];
|
||||
sprintf(calcsumStr, "%04X", calc_checksum_GB(fileName, folder));
|
||||
|
||||
if (strcmp(calcsumStr, checksumStr) == 0) {
|
||||
print_Msg(F("Result: "));
|
||||
println_Msg(calcsumStr);
|
||||
println_Msg(F("Checksum matches"));
|
||||
display_Update();
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
print_Msg(F("Result: "));
|
||||
println_Msg(calcsumStr);
|
||||
print_Error(F("Checksum Error"), false);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
byte readByte_GBS(word myAddress) {
|
||||
PORTF = myAddress & 0xFF;
|
||||
PORTK = (myAddress >> 8) & 0xFF;
|
||||
@ -166,7 +196,7 @@ void gbSmartGameOptions()
|
||||
display_Clear();
|
||||
sd.chdir("/");
|
||||
readROM_GB();
|
||||
compare_checksum_GB();
|
||||
compare_checksum_GBS();
|
||||
break;
|
||||
}
|
||||
case 1: // Read SRAM
|
||||
@ -329,7 +359,7 @@ void gbSmartGetGames()
|
||||
|
||||
// check if contain menu
|
||||
hasMenu = true;
|
||||
dataIn_GB();
|
||||
dataIn();
|
||||
for (i = 0; i < 5; i++)
|
||||
{
|
||||
if (readByte_GBS(0x0134 + i) != menu_title[i])
|
||||
@ -349,7 +379,7 @@ void gbSmartGetGames()
|
||||
dataOut();
|
||||
writeByte_GB(0x2100, i);
|
||||
|
||||
dataIn_GB();
|
||||
dataIn();
|
||||
// read signature
|
||||
for (uint8_t j = 0x00; j < 0x30; j++)
|
||||
{
|
||||
@ -385,7 +415,7 @@ gb_smart_get_game_loop_end:;
|
||||
}
|
||||
else
|
||||
{
|
||||
dataIn_GB();
|
||||
dataIn();
|
||||
for (uint8_t j = 0; j < 15; j++)
|
||||
{
|
||||
myByte = readByte_GBS(0x0134 + j);
|
||||
@ -424,7 +454,7 @@ void gbSmartReadFlash()
|
||||
gbSmartRemapStartBank(0x00, gbSmartRomSizeGB, gbSmartSramSizeGB);
|
||||
|
||||
// dump fixed bank 0x00
|
||||
dataIn_GB();
|
||||
dataIn();
|
||||
for (uint16_t addr = 0x0000; addr <= 0x3fff; addr += 512)
|
||||
{
|
||||
for (uint16_t c = 0; c < 512; c++)
|
||||
@ -439,7 +469,7 @@ void gbSmartReadFlash()
|
||||
dataOut();
|
||||
writeByte_GB(0x2100, bank);
|
||||
|
||||
dataIn_GB();
|
||||
dataIn();
|
||||
for (uint16_t addr = 0x4000; addr <= 0x7fff; addr += 512)
|
||||
{
|
||||
for (uint16_t c = 0; c < 512; c++)
|
||||
@ -558,7 +588,7 @@ void gbSmartWriteFlashFromMyFile(uint32_t addr)
|
||||
gbSmartWriteFlashByte(addr + i, 0x00); // BCH should be 0x00
|
||||
|
||||
// waiting for finishing
|
||||
dataIn_GB();
|
||||
dataIn();
|
||||
while ((readByte_GBS(addr + i) & 0x80) == 0x00);
|
||||
}
|
||||
|
||||
@ -581,7 +611,7 @@ uint32_t gbSmartVerifyFlash()
|
||||
gbSmartRemapStartBank(0x00, gbSmartRomSizeGB, gbSmartSramSizeGB);
|
||||
|
||||
// verify bank 0x00
|
||||
dataIn_GB();
|
||||
dataIn();
|
||||
for (uint16_t addr = 0x0000; addr <= 0x3fff; addr += 512)
|
||||
{
|
||||
myFile.read(sdBuffer, 512);
|
||||
@ -599,7 +629,7 @@ uint32_t gbSmartVerifyFlash()
|
||||
dataOut();
|
||||
writeByte_GB(0x2100, bank);
|
||||
|
||||
dataIn_GB();
|
||||
dataIn();
|
||||
for (uint16_t addr = 0x4000; addr <= 0x7fff; addr += 512)
|
||||
{
|
||||
myFile.read(sdBuffer, 512);
|
||||
@ -626,7 +656,7 @@ byte gbSmartBlankCheckingFlash(uint8_t flash_start_bank)
|
||||
gbSmartRemapStartBank(flash_start_bank, gbSmartFlashSizeGB, gbSmartSramSizeGB);
|
||||
|
||||
// check first bank
|
||||
dataIn_GB();
|
||||
dataIn();
|
||||
for (uint16_t addr = 0x0000; addr <= 0x3fff; addr++)
|
||||
{
|
||||
if (readByte_GBS(addr) != 0xff)
|
||||
@ -639,7 +669,7 @@ byte gbSmartBlankCheckingFlash(uint8_t flash_start_bank)
|
||||
dataOut();
|
||||
writeByte_GB(0x2100, bank);
|
||||
|
||||
dataIn_GB();
|
||||
dataIn();
|
||||
for (uint16_t addr = 0x4000; addr <= 0x7fff; addr++)
|
||||
{
|
||||
if (readByte_GBS(addr) != 0xff)
|
||||
@ -667,7 +697,7 @@ void gbSmartEraseFlash(uint8_t flash_start_bank)
|
||||
gbSmartWriteFlashByte(0x0000, 0x20);
|
||||
gbSmartWriteFlashByte(0x0000, 0xd0);
|
||||
|
||||
dataIn_GB();
|
||||
dataIn();
|
||||
while ((readByte_GBS(0x0000) & 0x80) == 0x00);
|
||||
|
||||
// blink LED
|
||||
@ -682,7 +712,7 @@ void gbSmartEraseFlash(uint8_t flash_start_bank)
|
||||
gbSmartWriteFlashByte(0x4000, 0x20);
|
||||
gbSmartWriteFlashByte(0x4000, 0xd0);
|
||||
|
||||
dataIn_GB();
|
||||
dataIn();
|
||||
while ((readByte_GBS(0x4000) & 0x80) == 0x00);
|
||||
|
||||
// blink LED
|
||||
@ -730,7 +760,7 @@ void gbSmartRemapStartBank(uint8_t rom_start_bank, uint8_t rom_size, uint8_t sra
|
||||
// start set new base bank
|
||||
writeByte_GB(0x1000, 0xa5);
|
||||
|
||||
dataIn_GB();
|
||||
dataIn();
|
||||
rom_start_bank = gbSmartGetResizeParam(rom_size, sram_size);
|
||||
|
||||
dataOut();
|
||||
@ -740,7 +770,7 @@ void gbSmartRemapStartBank(uint8_t rom_start_bank, uint8_t rom_size, uint8_t sra
|
||||
writeByte_GB(0x2100, 0x01);
|
||||
}
|
||||
|
||||
dataIn_GB();
|
||||
dataIn();
|
||||
}
|
||||
|
||||
// Get magic number for 0x7000 register.
|
||||
|
@ -62,13 +62,21 @@
|
||||
// Use calibration data from snes_clk.txt
|
||||
// #define clockgen_calibration
|
||||
|
||||
// Write all info to log.txt in root dir
|
||||
//#define global_log
|
||||
|
||||
// Use Adafruit Clock Generator
|
||||
// #define clockgen_installed
|
||||
|
||||
//******************************************
|
||||
// GB OPTIONS
|
||||
//******************************************
|
||||
// Renames ROM if found in database (slow)
|
||||
//#define no-intro
|
||||
|
||||
//******************************************
|
||||
// N64 OPTIONS
|
||||
//******************************************
|
||||
// Read N64 Eeprom with Adadruit clockgen, CLK1 switch needs to be switch to ON
|
||||
// add // and disable CLK1 switch if you don't have the clockgen installed or if you want to read a repros save
|
||||
// #define clockgen_installed
|
||||
|
||||
// The CRC for N64 Roms will be calculated during dumping from memory instead of after dumping from SD card, not compatible to all Cart Readers
|
||||
// #define fastcrc
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user