V19I: Added writing of GBA 4K eeprom save games

This commit is contained in:
sanni 2016-10-15 16:24:12 +02:00 committed by GitHub
parent 337c29abeb
commit 00f5dcdc1a
2 changed files with 194 additions and 24 deletions

View File

@ -2,8 +2,8 @@
Cartridge Reader for Arduino Mega2560 Cartridge Reader for Arduino Mega2560
Author: sanni Author: sanni
Date: 2016-10-14 Date: 2016-10-15
Version: V19H Version: V19I
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
@ -17,7 +17,7 @@
Jeff Saltzman - 4-Way Button Jeff Saltzman - 4-Way Button
Wayne and Layne - Video-Game-Shield menu Wayne and Layne - Video-Game-Shield menu
skaman - SNES enhancements and SA1 sram support skaman - SNES enhancements and SA1 sram support
nocash - Nintendo Power commands and lots of other info nocash - Nintendo Power and GBA Eeprom commands and lots of other info
crazynation - N64 bus timing crazynation - N64 bus timing
hkz/themanbehindthecurtain - N64 flashram commands hkz/themanbehindthecurtain - N64 flashram commands
jago85 - help with N64 stuff jago85 - help with N64 stuff
@ -34,7 +34,7 @@
YamaArashi - GBA flashrom bank switch command YamaArashi - GBA flashrom bank switch command
**********************************************************************************/ **********************************************************************************/
char ver[5] = "V19H"; char ver[5] = "V19I";
/****************************************** /******************************************
Define Output Define Output
@ -201,7 +201,7 @@ int foldern;
char folder[24]; char folder[24];
// Array that holds the data // Array that holds the data
byte sdBuffer[512]; byte sdBuffer[1024];
//****************************************** //******************************************
// Bitmaps // Bitmaps

View File

@ -6,7 +6,6 @@
Variables Variables
*****************************************/ *****************************************/
char calcChecksumStr[5]; char calcChecksumStr[5];
byte cartBuffer[512];
boolean readType; boolean readType;
const int nintendoLogo[] PROGMEM = { const int nintendoLogo[] PROGMEM = {
@ -180,7 +179,18 @@ void gbaMenu() {
display_Clear(); display_Clear();
sd.chdir("/"); sd.chdir("/");
// 4K EEPROM // 4K EEPROM
print_Error(F("Not supported yet"), false); writeEeprom_GBA(4);
writeErrors = verifyEEP_GBA(4);
if (writeErrors == 0) {
println_Msg(F("Verified OK"));
display_Update();
}
else {
print_Msg(F("Error: "));
print_Msg(writeErrors);
println_Msg(F(" bytes "));
print_Error(F("did not verify."), false);
}
setROM_GBA(); setROM_GBA();
break; break;
@ -189,6 +199,18 @@ void gbaMenu() {
sd.chdir("/"); sd.chdir("/");
// 64K EEPROM // 64K EEPROM
print_Error(F("Not supported yet"), false); print_Error(F("Not supported yet"), false);
/*writeEeprom_GBA(64);
writeErrors = verifyEEP_GBA(64);
if (writeErrors == 0) {
println_Msg(F("Verified OK"));
display_Update();
}
else {
print_Msg(F("Error: "));
print_Msg(writeErrors);
println_Msg(F(" bytes "));
print_Error(F("did not verify."), false);
}*/
setROM_GBA(); setROM_GBA();
break; break;
@ -455,7 +477,7 @@ int testHeader() {
// Set address to start of rom // Set address to start of rom
setAddress_GBA(0); setAddress_GBA(0);
// Read header into array sequentially // Read header into array sequentially
readSeq_GBA(cartBuffer, 192); readSeq_GBA(sdBuffer, 192);
// Reset ports or the 1st maskrom byte on eeprom carts won't be read correctly // Reset ports or the 1st maskrom byte on eeprom carts won't be read correctly
setROM_GBA(); setROM_GBA();
@ -468,7 +490,7 @@ int testHeader() {
setAddress_GBA(0); setAddress_GBA(0);
// Read Header into array in random access mode // Read Header into array in random access mode
readRand_GBA(0, cartBuffer, 192); readRand_GBA(0, sdBuffer, 192);
logoErrors = checkLogo(); logoErrors = checkLogo();
if (logoErrors == 0) { if (logoErrors == 0) {
@ -485,7 +507,7 @@ int testHeader() {
int checkLogo() { int checkLogo() {
int errors = 0; int errors = 0;
for (int currByte = 0x4; currByte < 0xA0; currByte++) { for (int currByte = 0x4; currByte < 0xA0; currByte++) {
if (pgm_read_byte(&nintendoLogo[currByte]) != cartBuffer[currByte]) { if (pgm_read_byte(&nintendoLogo[currByte]) != sdBuffer[currByte]) {
errors++; errors++;
} }
} }
@ -502,16 +524,16 @@ void getCartInfo_GBA() {
} }
else { else {
// Get cart ID // Get cart ID
cartID[0] = char(cartBuffer[0xAC]); cartID[0] = char(sdBuffer[0xAC]);
cartID[1] = char(cartBuffer[0xAD]); cartID[1] = char(sdBuffer[0xAD]);
cartID[2] = char(cartBuffer[0xAE]); cartID[2] = char(sdBuffer[0xAE]);
cartID[3] = char(cartBuffer[0xAF]); cartID[3] = char(sdBuffer[0xAF]);
// Dump name into 8.3 compatible format // Dump name into 8.3 compatible format
byte myByte = 0; byte myByte = 0;
byte myLength = 0; byte myLength = 0;
for (int addr = 0xA0; addr <= 0xAB; addr++) { for (int addr = 0xA0; addr <= 0xAB; addr++) {
myByte = cartBuffer[addr]; myByte = sdBuffer[addr];
if (((char(myByte) >= 48 && char(myByte) <= 57) || (char(myByte) >= 65 && char(myByte) <= 122)) && myLength < 8) { if (((char(myByte) >= 48 && char(myByte) <= 57) || (char(myByte) >= 65 && char(myByte) <= 122)) && myLength < 8) {
romName[myLength] = char(myByte); romName[myLength] = char(myByte);
myLength++; myLength++;
@ -519,15 +541,15 @@ void getCartInfo_GBA() {
} }
// Get ROM version // Get ROM version
romVersion = cartBuffer[0xBC]; romVersion = sdBuffer[0xBC];
// Get Checksum as string // Get Checksum as string
sprintf(checksumStr, "%02X", cartBuffer[0xBD]); sprintf(checksumStr, "%02X", sdBuffer[0xBD]);
// Calculate Checksum // Calculate Checksum
int calcChecksum = 0x00; int calcChecksum = 0x00;
for (int n = 0xA0; n < 0xBD; n++) { for (int n = 0xA0; n < 0xBD; n++) {
calcChecksum -= cartBuffer[n]; calcChecksum -= sdBuffer[n];
} }
calcChecksum = (calcChecksum - 0x19) & 0xFF; calcChecksum = (calcChecksum - 0x19) & 0xFF;
// Turn into string // Turn into string
@ -1219,7 +1241,7 @@ void writeFLASH_GBA (boolean browseFile, unsigned long flashSize, uint32_t pos)
} }
} }
// Check if the SRAM was written without any error // Check if the Flashrom was written without any error
void verifyFLASH_GBA(unsigned long flashSize, uint32_t pos) { void verifyFLASH_GBA(unsigned long flashSize, uint32_t pos) {
// Output a HIGH signal on CS_ROM(PH3) WE_FLASH(PH5) // Output a HIGH signal on CS_ROM(PH3) WE_FLASH(PH5)
PORTH |= (1 << 3) | (1 << 5); PORTH |= (1 << 3) | (1 << 5);
@ -1276,6 +1298,46 @@ void verifyFLASH_GBA(unsigned long flashSize, uint32_t pos) {
/****************************************** /******************************************
GBA Eeprom SAVE Functions GBA Eeprom SAVE Functions
*****************************************/ *****************************************/
// Write eeprom from file
void writeEeprom_GBA(word eepSize) {
// Launch Filebrowser
filePath[0] = '\0';
sd.chdir("/");
fileBrowser("Select eep file");
// Create filepath
sprintf(filePath, "%s/%s", filePath, fileName);
display_Clear();
print_Msg(F("Writing eeprom..."));
display_Update();
//open file on sd card
if (myFile.open(filePath, O_READ)) {
// Fill romBuffer
myFile.read(sdBuffer, 512);
for (word i = 0; i < eepSize * 16; i += 64) {
// Disable interrupts for more uniform clock pulses
noInterrupts();
// Write 512 bytes
writeBlock_EEP(i, eepSize);
interrupts();
// Wait
delayMicroseconds(200);
}
// Close the file:
myFile.close();
println_Msg(F("done"));
display_Update();
}
else {
println_Msg(F("Error"));
print_Error(F("File doesnt exist"), false);
}
}
// Read eeprom to file // Read eeprom to file
void readEeprom_GBA(word eepSize) { void readEeprom_GBA(word eepSize) {
// Get name, add extension and convert to char array for sd lib // Get name, add extension and convert to char array for sd lib
@ -1322,13 +1384,13 @@ void readEeprom_GBA(word eepSize) {
if (i != 0) if (i != 0)
myFile.seekCur(i * 64); myFile.seekCur(i * 64);
// Write sdBuffer to file // Write sdBuffer to file
myFile.write(cartBuffer, 512); myFile.write(sdBuffer, 512);
} }
myFile.close(); myFile.close();
} }
// Send address as bits to eeprom // Send address as bits to eeprom
void setAddress_EEP(word currAddr, word numBits) { void send_GBA(word currAddr, word numBits) {
for (word addrBit = numBits; addrBit > 0; addrBit--) { for (word addrBit = numBits; addrBit > 0; addrBit--) {
// If you want the k-th bit of n, then do // If you want the k-th bit of n, then do
// (n & ( 1 << k )) >> k // (n & ( 1 << k )) >> k
@ -1351,6 +1413,87 @@ void setAddress_EEP(word currAddr, word numBits) {
} }
} }
// Write 512K eeprom block
void writeBlock_EEP(word startAddr, word eepSize) {
// Setup
// Set CS_ROM(PH3) WR(PH5) RD(PH6) to Output
DDRH |= (1 << 3) | (1 << 5) | (1 << 6);
// Set A0(PF0) to Output
DDRF |= (1 << 0);
// Set A23/D7(PC7) to Output
DDRC |= (1 << 7);
// Set CS_ROM(PH3) WR(PH5) RD(PH6) to High
PORTH |= (1 << 3) | (1 << 5) | (1 << 6);
// Set A0(PF0) to High
PORTF |= (1 << 0);
// Set A23/D7(PC7) to High
PORTC |= (1 << 7);
__asm__("nop\n\t""nop\n\t");
// Write 64*8=512 bytes
for (word currAddr = startAddr; currAddr < startAddr + 64; currAddr++) {
// Set CS_ROM(PH3) to LOW
PORTH &= ~ (1 << 3);
// Send write request "10"
// Set A0(PF0) to High
PORTF |= (1 << 0);
// Set WR(PH5) to LOW
PORTH &= ~ (1 << 5);
// Set WR(PH5) to High
PORTH |= (1 << 5);
// Set A0(PF0) to LOW
PORTF &= ~ (1 << 0);
// Set WR(PH5) to LOW
PORTH &= ~ (1 << 5);
// Set WR(PH5) to High
PORTH |= (1 << 5);
// Send either 6 or 14 bit address
if (eepSize == 4) {
send_GBA(currAddr, 6);
}
else {
send_GBA(currAddr, 14);
}
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");
// Send data
for (byte currByte = 0; currByte < 8; currByte++) {
send_GBA(sdBuffer[currAddr * 8 + currByte], 8);
}
// Send stop bit
// Set A0(PF0) to LOW
PORTF &= ~ (1 << 0);
// Set WR(PH5) to LOW
PORTH &= ~ (1 << 5);
// WR(PH5) to High
PORTH |= (1 << 5);
// Set CS_ROM(PH3) to High
PORTH |= (1 << 3);
// Wait until done
// Set A0(PF0) to Input
DDRF &= ~ (1 << 0);
do {
// Set CS_ROM(PH3) RD(PH6) to LOW
PORTH &= ~((1 << 3) | (1 << 6));
// Set CS_ROM(PH3) RD(PH6) to High
PORTH |= (1 << 3) | (1 << 6);
}
while ((PINF & 0x1) == 0);
// Set A0(PF0) to Output
DDRF |= (1 << 0);
}
}
// Reads 512 bytes from eeprom // Reads 512 bytes from eeprom
void readBlock_EEP(word startAddress, word eepSize) { void readBlock_EEP(word startAddress, word eepSize) {
// Setup // Setup
@ -1389,10 +1532,10 @@ void readBlock_EEP(word startAddress, word eepSize) {
// Send either 6 or 14 bit address // Send either 6 or 14 bit address
if (eepSize == 4) { if (eepSize == 4) {
setAddress_EEP(currAddr, 6); send_GBA(currAddr, 6);
} }
else { else {
setAddress_EEP(currAddr, 14); send_GBA(currAddr, 14);
} }
// Send stop bit // Send stop bit
@ -1445,11 +1588,38 @@ void readBlock_EEP(word startAddress, word eepSize) {
// OR 8 bits into one byte for a total of 8 bytes // OR 8 bits into one byte for a total of 8 bytes
for (byte j = 0; j < 64; j += 8) { for (byte j = 0; j < 64; j += 8) {
cartBuffer[((currAddr - startAddress) * 8) + (j / 8)] = tempBits[0 + j] << 7 | tempBits[1 + j] << 6 | tempBits[2 + j] << 5 | tempBits[3 + j] << 4 | tempBits[4 + j] << 3 | tempBits[5 + j] << 2 | tempBits[6 + j] << 1 | tempBits[7 + j]; sdBuffer[((currAddr - startAddress) * 8) + (j / 8)] = tempBits[0 + j] << 7 | tempBits[1 + j] << 6 | tempBits[2 + j] << 5 | tempBits[3 + j] << 4 | tempBits[4 + j] << 3 | tempBits[5 + j] << 2 | tempBits[6 + j] << 1 | tempBits[7 + j];
} }
} }
} }
// Check if the SRAM was written without any error
unsigned long verifyEEP_GBA(word eepSize) {
unsigned long wrError = 0;
//open file on sd card
if (!myFile.open(filePath, O_READ)) {
print_Error(F("SD Error"), true);
}
// Fill sd Buffer
for (word i = 0; i < eepSize * 16; i += 64) {
// Disable interrupts for more uniform clock pulses
noInterrupts();
readBlock_EEP(i, eepSize);
interrupts();
}
// Compare
for (int c = 0; c < eepSize * 16; c++) {
if (sdBuffer[c] != myFile.read()) {
wrError++;
}
}
myFile.close();
return wrError;
}
//****************************************** //******************************************
// End of File // End of File
//****************************************** //******************************************