mirror of
https://github.com/sanni/cartreader.git
synced 2024-12-25 04:21:53 +01:00
V20 Changed N64 timing a bit
Hopefully I didn't break anything :x
This commit is contained in:
parent
94a7337d22
commit
6bcdc9526c
@ -2,15 +2,15 @@
|
||||
Cartridge Reader for Arduino Mega2560
|
||||
|
||||
Author: sanni
|
||||
Date: 2017-01-12
|
||||
Version: V19L
|
||||
Date: 2017-01-29
|
||||
Version: V20
|
||||
|
||||
SD lib: https://github.com/greiman/SdFat
|
||||
LCD lib: https://github.com/adafruit/Adafruit_SSD1306
|
||||
Clockgen: https://github.com/etherkit/Si5351Arduino
|
||||
RGB Tools lib: https://github.com/joushx/Arduino-RGB-Tools
|
||||
|
||||
Compiled with Arduino 1.6.11
|
||||
Compiled with Arduino 1.8.0
|
||||
|
||||
Thanks to:
|
||||
MichlK - ROM-Reader for Super Nintendo
|
||||
@ -34,7 +34,7 @@
|
||||
YamaArashi - GBA flashrom bank switch command
|
||||
|
||||
**********************************************************************************/
|
||||
char ver[5] = "V19L";
|
||||
char ver[5] = "V20";
|
||||
|
||||
/******************************************
|
||||
Define Output
|
||||
|
@ -104,8 +104,8 @@ void setup_GB() {
|
||||
|
||||
// Set Data Pins (D0-D7) to Input
|
||||
DDRC = 0x00;
|
||||
// Enable Internal Pullups
|
||||
//PORTC = 0xFF;
|
||||
// Disable Internal Pullups
|
||||
PORTC = 0x00;
|
||||
|
||||
// Print start page
|
||||
getCartInfo_GB();
|
||||
@ -244,6 +244,12 @@ void setup_GB() {
|
||||
/******************************************
|
||||
Low level functions
|
||||
*****************************************/
|
||||
// Switch data pins to read
|
||||
void dataIn_GB() {
|
||||
// Set to Input
|
||||
DDRC = 0x00;
|
||||
}
|
||||
|
||||
byte readByte_GB(word myAddress) {
|
||||
PORTF = myAddress & 0xFF;
|
||||
PORTK = (myAddress >> 8) & 0xFF;
|
||||
@ -390,7 +396,7 @@ void readROM_GB() {
|
||||
dataOut();
|
||||
// Set ROM bank
|
||||
writeByte_GB(0x2100, y);
|
||||
dataIn();
|
||||
dataIn_GB();
|
||||
if (y > 1) {
|
||||
addr = 0x4000;
|
||||
}
|
||||
@ -525,7 +531,7 @@ void readSRAM_GB() {
|
||||
writeByte_GB(0x4000, bank);
|
||||
|
||||
// Read RAM
|
||||
dataIn();
|
||||
dataIn_GB();
|
||||
for (addr = 0xA000; addr <= endaddr; addr = addr + 64) {
|
||||
uint8_t readData[64];
|
||||
for (int i = 0; i < 64; i++) {
|
||||
@ -537,7 +543,7 @@ void readSRAM_GB() {
|
||||
dataOut();
|
||||
// Disable RAM
|
||||
writeByte_GB(0x0000, 0x00);
|
||||
dataIn();
|
||||
dataIn_GB();
|
||||
}
|
||||
else {
|
||||
print_Error(F("Cart has no SRAM"), false);
|
||||
@ -616,7 +622,7 @@ void writeSRAM_GB() {
|
||||
print_Error(F("Cart has no SRAM"), false);
|
||||
}
|
||||
// Set pins to input
|
||||
dataIn();
|
||||
dataIn_GB();
|
||||
|
||||
// Close the file:
|
||||
myFile.close();
|
||||
@ -665,7 +671,7 @@ unsigned long verifySRAM_GB() {
|
||||
writeByte_GB(0x4000, bank);
|
||||
|
||||
// Read RAM
|
||||
dataIn();
|
||||
dataIn_GB();
|
||||
for (addr = 0xA000; addr <= endaddr; addr = addr + 64) {
|
||||
//fill sdBuffer
|
||||
myFile.read(sdBuffer, 64);
|
||||
@ -679,7 +685,7 @@ unsigned long verifySRAM_GB() {
|
||||
dataOut();
|
||||
// Disable RAM
|
||||
writeByte_GB(0x0000, 0x00);
|
||||
dataIn();
|
||||
dataIn_GB();
|
||||
}
|
||||
// Close the file:
|
||||
myFile.close();
|
||||
@ -716,7 +722,7 @@ void writeFlash_GB() {
|
||||
romType = myFile.read();
|
||||
romSize = myFile.read();
|
||||
// Go back to file beginning
|
||||
myFile.seekCur(0);
|
||||
myFile.seekSet(0);
|
||||
|
||||
numBanks = 2; // Default 32K
|
||||
if (romSize == 1) {
|
||||
@ -759,8 +765,10 @@ void writeFlash_GB() {
|
||||
// Set data pins to output
|
||||
dataOut();
|
||||
|
||||
// Set ROM bank 1
|
||||
writeByte_GB(0x2100, 1);
|
||||
// Set ROM bank hi 0
|
||||
writeByte_GB(0x3000, 0);
|
||||
// Set ROM bank low 0
|
||||
writeByte_GB(0x2000, 0);
|
||||
delay(100);
|
||||
|
||||
// Reset flash
|
||||
@ -772,7 +780,7 @@ void writeFlash_GB() {
|
||||
writeByte_GB(0x2aa, 0x55);
|
||||
writeByte_GB(0x555, 0x90);
|
||||
|
||||
dataIn();
|
||||
dataIn_GB();
|
||||
|
||||
// Read the two id bytes into a string
|
||||
sprintf(flashid, "%02X%02X", readByte_GB(0), readByte_GB(1));
|
||||
@ -781,7 +789,7 @@ void writeFlash_GB() {
|
||||
println_Msg(F("MBM29F033C"));
|
||||
print_Msg(F("Banks: "));
|
||||
print_Msg(numBanks);
|
||||
println_Msg(F("/256"));
|
||||
println_Msg(F("/255"));
|
||||
display_Update();
|
||||
}
|
||||
else if (strcmp(flashid, "0141") == 0) {
|
||||
@ -821,7 +829,7 @@ void writeFlash_GB() {
|
||||
writeByte_GB(0x2aa, 0x55);
|
||||
writeByte_GB(0x555, 0x10);
|
||||
|
||||
dataIn();
|
||||
dataIn_GB();
|
||||
|
||||
// Read the status register
|
||||
byte statusReg = readByte_GB(0);
|
||||
@ -839,32 +847,25 @@ void writeFlash_GB() {
|
||||
println_Msg(F("Blankcheck"));
|
||||
display_Update();
|
||||
|
||||
unsigned int addr = 0;
|
||||
|
||||
// Read x number of banks
|
||||
for (int y = 1; y < numBanks; y++) {
|
||||
for (int currBank = 0; currBank < numBanks; currBank++) {
|
||||
// Blink led
|
||||
PORTB ^= (1 << 4);
|
||||
|
||||
dataOut();
|
||||
|
||||
// Set ROM bank
|
||||
writeByte_GB(0x2100, y);
|
||||
writeByte_GB(0x2000, currBank);
|
||||
dataIn();
|
||||
|
||||
if (y > 1) {
|
||||
addr = 0x4000;
|
||||
}
|
||||
|
||||
for (; addr <= 0x7FFF; addr += 512) {
|
||||
for (unsigned int currAddr = 0x4000; currAddr < 0x7FFF; currAddr += 512) {
|
||||
uint8_t readData[512];
|
||||
for (int i = 0; i < 512; i++) {
|
||||
readData[i] = readByte_GB(addr + i);
|
||||
for (int currByte = 0; currByte < 512; currByte++) {
|
||||
readData[currByte] = readByte_GB(currAddr + currByte);
|
||||
}
|
||||
for (int j = 0; j < 512; j++) {
|
||||
if (readData[j] != 0xFF) {
|
||||
println_Msg(F("Not empty"));
|
||||
display_Update();
|
||||
print_Error(F("Erase failed"), true);
|
||||
}
|
||||
}
|
||||
@ -875,42 +876,37 @@ void writeFlash_GB() {
|
||||
display_Update();
|
||||
|
||||
// Write flash
|
||||
addr = 0;
|
||||
dataOut();
|
||||
|
||||
for (int y = 1; y < numBanks; y++) {
|
||||
for (int currBank = 0; currBank < numBanks; currBank++) {
|
||||
// Blink led
|
||||
PORTB ^= (1 << 4);
|
||||
|
||||
// Set ROM bank
|
||||
writeByte_GB(0x2100, y);
|
||||
writeByte_GB(0x2000, currBank);
|
||||
|
||||
if (y > 1) {
|
||||
addr = 0x4000;
|
||||
}
|
||||
|
||||
for (; addr <= 0x7FFF; addr += 512) {
|
||||
for (unsigned int currAddr = 0x4000; currAddr < 0x7FFF; currAddr += 512) {
|
||||
myFile.read(sdBuffer, 512);
|
||||
|
||||
for (int c = 0; c < 512; c++) {
|
||||
for (int currByte = 0; currByte < 512; currByte++) {
|
||||
// Write command sequence
|
||||
writeByte_GB(0x555, 0xaa);
|
||||
writeByte_GB(0x2aa, 0x55);
|
||||
writeByte_GB(0x555, 0xa0);
|
||||
// Write current byte
|
||||
writeByte_GB(addr + c, sdBuffer[c]);
|
||||
writeByte_GB(currAddr + currByte, sdBuffer[currByte]);
|
||||
|
||||
// Set data pins to input
|
||||
dataIn();
|
||||
|
||||
// Switch CS(PH3) and RD(PH6) to LOW
|
||||
// Setting CS(PH3) and OE/RD(PH6) LOW
|
||||
PORTH &= ~((1 << 3) | (1 << 6));
|
||||
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t");
|
||||
|
||||
// Busycheck
|
||||
while ((PINC & 0x80) != (sdBuffer[c] & 0x80)) {
|
||||
// Busy check
|
||||
while ((PINC & 0x80) != (sdBuffer[currByte] & 0x80)) {
|
||||
}
|
||||
// Switch CS(PH3) and RD(PH6) to HIGH
|
||||
|
||||
// Switch CS(PH3) and OE/RD(PH6) to HIGH
|
||||
PORTH |= (1 << 3) | (1 << 6);
|
||||
|
||||
// Set data pins to output
|
||||
@ -918,14 +914,56 @@ void writeFlash_GB() {
|
||||
}
|
||||
}
|
||||
}
|
||||
// Set data pins to input again
|
||||
dataIn();
|
||||
|
||||
// Set data pins to input again
|
||||
dataIn_GB();
|
||||
|
||||
println_Msg(F("Verifying"));
|
||||
display_Update();
|
||||
|
||||
// Go back to file beginning
|
||||
myFile.seekSet(0);
|
||||
unsigned int addr = 0;
|
||||
writeErrors = 0;
|
||||
|
||||
// Verify flashrom
|
||||
for (int y = 1; y < numBanks; y++) {
|
||||
// Set ROM bank
|
||||
dataOut();
|
||||
writeByte_GB(0x2100, y);
|
||||
dataIn_GB();
|
||||
|
||||
// Blink led
|
||||
PORTB ^= (1 << 4);
|
||||
|
||||
if (y > 1) {
|
||||
addr = 0x4000;
|
||||
}
|
||||
|
||||
for (; addr <= 0x7FFF; addr = addr + 512) {
|
||||
// Fill sdBuffer
|
||||
myFile.read(sdBuffer, 512);
|
||||
// Compare
|
||||
for (int i = 0; i < 512; i++) {
|
||||
if (readByte_GB(addr + i) != sdBuffer[i]) {
|
||||
writeErrors++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Close the file:
|
||||
myFile.close();
|
||||
|
||||
println_Msg(F("Done"));
|
||||
display_Update();
|
||||
if (writeErrors == 0) {
|
||||
println_Msg(F("OK"));
|
||||
display_Update();
|
||||
}
|
||||
else {
|
||||
print_Msg(F("Error: "));
|
||||
print_Msg(writeErrors);
|
||||
println_Msg(F(" bytes "));
|
||||
print_Error(F("did not verify."), false);
|
||||
}
|
||||
}
|
||||
else {
|
||||
println_Msg(F("Can't open file"));
|
||||
|
@ -277,6 +277,9 @@ void setup_N64_Cart() {
|
||||
// Activate Internal Pullup Resistors
|
||||
//PORTH |= (1 << 4);
|
||||
|
||||
// Wait until all is stable
|
||||
delay(500);
|
||||
|
||||
// Print start page
|
||||
getCartInfo_N64();
|
||||
if (cartSize != 0) {
|
||||
@ -365,27 +368,33 @@ void setAddress_N64(unsigned long myAddress) {
|
||||
PORTF = myAdrHighOut & 0xFF;
|
||||
PORTK = (myAdrHighOut >> 8) & 0xFF;
|
||||
|
||||
// Leave ale_H and ale_L high for ~120ns
|
||||
// Leave ale_H high for additional 120ns
|
||||
__asm__("nop\n\t""nop\n\t");
|
||||
|
||||
// Pull ale_H(PC1) low
|
||||
PORTC &= ~(1 << 1);
|
||||
|
||||
// Leave address pins stable for a little bit
|
||||
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");
|
||||
|
||||
// Output low part to address pins
|
||||
PORTF = myAdrLowOut & 0xFF;
|
||||
PORTK = (myAdrLowOut >> 8) & 0xFF;
|
||||
|
||||
// Leave ale_L high for another ~110ns
|
||||
__asm__("nop\n\t""nop\n\t");
|
||||
// Leave ale_L high for ~180ns
|
||||
__asm__("nop\n\t""nop\n\t""nop\n\t");
|
||||
|
||||
// Pull ale_L(PC0) low
|
||||
PORTC &= ~(1 << 0);
|
||||
|
||||
// Wait ~1000ns before read
|
||||
__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""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");
|
||||
// Leave address pins stable for a little bit
|
||||
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");
|
||||
|
||||
// Set data pins to input
|
||||
adIn_N64();
|
||||
|
||||
// Wait ~600ns just to be sure address is set
|
||||
__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""nop\n\t""nop\n\t");
|
||||
}
|
||||
|
||||
// Read one word out of the cartridge
|
||||
@ -393,21 +402,15 @@ word readWord_N64() {
|
||||
// Pull read(PH6) low
|
||||
PORTH &= ~(1 << 6);
|
||||
|
||||
// Wait ~100ns
|
||||
__asm__("nop\n\t""nop\n\t");
|
||||
// Wait ~300ns
|
||||
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");
|
||||
|
||||
// Join bytes from PINF and PINK into a word
|
||||
word tempWord = ( ( PINK & 0xFF ) << 8 ) | ( PINF & 0xFF );
|
||||
|
||||
// Wait ~200ns
|
||||
__asm__("nop\n\t""nop\n\t""nop\n\t");
|
||||
|
||||
// Pull read(PH6) high
|
||||
PORTH |= (1 << 6);
|
||||
|
||||
// Wait ~60ns
|
||||
__asm__("nop\n\t");
|
||||
|
||||
return tempWord;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user