Last active
July 11, 2021 00:07
-
-
Save arpruss/59c943709e84d3b7dd4ed7faa187f2f5 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// simply read a 32k Gameboy cartridge | |
// public domain / CC0 | |
#define CHUNK_SIZE 16 | |
uint16_t address; | |
uint16_t globalChecksum; | |
uint16_t correctGlobalChecksum; | |
uint8_t headerChecksum; | |
uint8_t correctHeaderChecksum; | |
bool needToWarnHeaderChecksum = false; | |
const uint32_t aPins[15] = { PB8, PB9, PC13, PB7, PA0, PA1, PA2, PA3, | |
PA4, PA5, PA6, PA7, PB0, PB1, PB10 }; | |
const uint32_t dPins[8] = { PB4, PB3, PA9, PA8, PB15, PB14, PB13, PA10 }; // 5V tolerant | |
void setAddress(uint16_t address) { | |
uint16_t mask = 1; | |
for (unsigned bit = 0 ; bit < sizeof(aPins)/sizeof(*aPins) ; bit++, mask <<= 1) | |
digitalWrite(aPins[bit], (mask & address) ? 1 : 0); | |
} | |
uint8_t readByte() { | |
uint8_t out = 0; | |
uint8_t mask = 1; | |
for (unsigned bit = 0 ; mask ; bit++, mask <<= 1) | |
if (digitalRead(dPins[bit])) | |
out |= mask; | |
return out; | |
} | |
uint8_t simpleReadByte(uint16_t addr) { | |
setAddress(addr); | |
delayMicroseconds(1); | |
return readByte(); | |
} | |
void setup() { | |
for (int i=0;i<15;i++) | |
pinMode(aPins[i],OUTPUT); // maybe OUTPUT_PULLDOWN in some cases? | |
for (int i=0;i<8;i++) | |
pinMode(dPins[i],INPUT); | |
Serial.begin(); | |
delay(3000); | |
address = 0x0; | |
headerChecksum = 0; | |
globalChecksum = 0; | |
} | |
void loop() { | |
char buf[120]; | |
if (address >= 0x8000) { | |
sprintf(buf, "; header checksum: %02x (correct is: %02x)\n", headerChecksum, correctHeaderChecksum); | |
Serial.println(buf); | |
sprintf(buf, "; ROM checksum: %04x (correct is: %04x)\n", globalChecksum, correctGlobalChecksum); | |
Serial.println(buf); | |
while(1) ; | |
address = 0x7d00; | |
} | |
sprintf(buf, "%04x: ", (unsigned)address); | |
Serial.print(buf); | |
for (int i=0; i<CHUNK_SIZE; i++) { | |
uint8_t r = simpleReadByte(address); | |
sprintf(buf, "%02x", (unsigned)r); | |
Serial.print(buf); | |
if (0x134 <= address && address < 0x14d) { | |
headerChecksum -= r+1; | |
} | |
if (address != 0x14e && address != 0x14f) { | |
globalChecksum += r; | |
} | |
if (address == 0x14D) { | |
correctHeaderChecksum = r; | |
if (r != headerChecksum) | |
needToWarnHeaderChecksum = true; | |
} | |
else if (address == 0x14e) { | |
correctGlobalChecksum = (uint16_t)r << 8; | |
} | |
else if (address == 0x14f) { | |
correctGlobalChecksum |= r; | |
} | |
address++; | |
} | |
Serial.write('\n'); | |
if (needToWarnHeaderChecksum) { | |
sprintf(buf, "; header checksum mismatch: is %02x, should be %02x !\n", headerChecksum, correctHeaderChecksum); | |
Serial.print(buf); | |
needToWarnHeaderChecksum = false; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment