From 07a38f30c213a54890daab13d2a43eeee405d2a1 Mon Sep 17 00:00:00 2001 From: sanni Date: Fri, 9 Sep 2022 00:21:16 +0200 Subject: [PATCH] V9.7: Calculate block CRC during Controller Pak read --- Cart_Reader/Cart_Reader.ino | 6 +- Cart_Reader/N64.ino | 135 ++++++++++++++++++++++++++++-------- Cart_Reader/SMS.ino | 4 +- 3 files changed, 112 insertions(+), 33 deletions(-) diff --git a/Cart_Reader/Cart_Reader.ino b/Cart_Reader/Cart_Reader.ino index 43f5ba5..9fbaa2e 100644 --- a/Cart_Reader/Cart_Reader.ino +++ b/Cart_Reader/Cart_Reader.ino @@ -4,8 +4,8 @@ This project represents a community-driven effort to provide an easy to build and easy to modify cartridge dumper. - Date: 28.08.2022 - Version: 9.6 + Date: 09.09.2022 + Version: 9.7 SD lib: https://github.com/greiman/SdFat OLED lib: https://github.com/adafruit/Adafruit_SSD1306 @@ -59,7 +59,7 @@ **********************************************************************************/ -char ver[5] = "9.6"; +char ver[5] = "9.7"; //****************************************** // !!! CHOOSE HARDWARE VERSION !!! diff --git a/Cart_Reader/N64.ino b/Cart_Reader/N64.ino index 742cfcb..b4be100 100644 --- a/Cart_Reader/N64.ino +++ b/Cart_Reader/N64.ino @@ -22,9 +22,9 @@ bool tempBits[65]; int eepPages; // N64 Controller -// 256 bits of received Controller data -char N64_raw_dump[257]; -// Array that holds one Controller Pak block of 32 bytes +// 256 bits of received Controller data + 8 bit CRC +char N64_raw_dump[265]; +// Array that holds one Controller Pak block of 32 bytes data byte myBlock[33]; String rawStr = ""; // above char array read into a string struct { @@ -192,6 +192,7 @@ void n64ControllerMenu() { case 1: resetController(); + checkController(); display_Clear(); display_Update(); readMPK(); @@ -204,6 +205,7 @@ void n64ControllerMenu() { case 2: resetController(); + checkController(); display_Clear(); display_Update(); // Change to root @@ -605,26 +607,25 @@ static word addrCRC(word address) { return address | crc; } -// unused -//static byte dataCRC(byte * data) { -// byte ret = 0; -// for (byte i = 0; i <= 32; i++) { -// for (byte j = 7; j >= 0; j--) { -// int tmp = 0; -// if (ret & 0x80) { -// tmp = 0x85; -// } -// ret <<= 1; -// if ( i < 32 ) { -// if (data[i] & (0x01 << j)) { -// ret |= 0x1; -// } -// } -// ret ^= tmp; -// } -// } -// return ret; -//} +static uint8_t dataCRC( uint8_t *data ) { + uint8_t ret = 0; + for ( int i = 0; i <= 32; i++ ) { + for ( int j = 7; j >= 0; j-- ) { + int tmp = 0; + if ( ret & 0x80 ) { + tmp = 0x85; + } + ret <<= 1; + if ( i < 32 ) { + if ( data[i] & (0x01 << j) ) { + ret |= 0x1; + } + } + ret ^= tmp; + } + } + return ret; +} /****************************************** N64 Controller Protocol Functions @@ -1952,7 +1953,57 @@ void resetController() { delay(100); } -// read 32bytes from controller pak +// read 3 bytes from controller +void checkController() { + display_Clear(); + + // Check if line is HIGH + if (!N64_QUERY) + print_Error(F("Data line LOW"), true); + + // Send status command + unsigned char command[] = {0x0}; + + // don't want interrupts getting in the way + noInterrupts(); + N64_send(command, 1); + N64_stop(); + // read in data + N64_get(32); + // end of time sensitive code + interrupts(); + + // Empty N64_raw_dump into myBlock + for (word i = 0; i < 32; i += 8) { + boolean byteFlipped[9]; + + // Flip byte order + byteFlipped[0] = N64_raw_dump[i + 7]; + byteFlipped[1] = N64_raw_dump[i + 6]; + byteFlipped[2] = N64_raw_dump[i + 5]; + byteFlipped[3] = N64_raw_dump[i + 4]; + byteFlipped[4] = N64_raw_dump[i + 3]; + byteFlipped[5] = N64_raw_dump[i + 2]; + byteFlipped[6] = N64_raw_dump[i + 1]; + byteFlipped[7] = N64_raw_dump[i + 0]; + + // Join bits into one byte + unsigned char myByte = 0; + for (byte j = 0; j < 8; ++j) { + if (byteFlipped[j]) { + myByte |= 1 << j; + } + } + if ((i == 0) && (myByte != 0x05)) + print_Error(F("Controller not found"), true); + if ((i == 16) && (myByte != 0x01)) + print_Error(F("Controller Pak not found"), true); + if ((i == 16) && (myByte == 0x04)) + print_Error(F("CRC Error"), true); + } +} + +// read 32bytes from controller pak and calculate CRC void readBlock(word myAddress) { // Calculate the address CRC word myAddressCRC = addrCRC(myAddress); @@ -1970,8 +2021,8 @@ void readBlock(word myAddress) { N64_send(addressHigh, 1); N64_send(addressLow, 1); N64_stop(); - // read in data - N64_get(256); + // read in 32 byte data + 1 byte crc + N64_get(264); // end of time sensitive code interrupts(); @@ -1999,6 +2050,34 @@ void readBlock(word myAddress) { // Save byte into block array myBlock[i / 8] = myByte; } + + // Get CRC of block send + boolean byteFlipped[9]; + // Flip byte order + byteFlipped[0] = N64_raw_dump[256 + 7]; + byteFlipped[1] = N64_raw_dump[256 + 6]; + byteFlipped[2] = N64_raw_dump[256 + 5]; + byteFlipped[3] = N64_raw_dump[256 + 4]; + byteFlipped[4] = N64_raw_dump[256 + 3]; + byteFlipped[5] = N64_raw_dump[256 + 2]; + byteFlipped[6] = N64_raw_dump[256 + 1]; + byteFlipped[7] = N64_raw_dump[256 + 0]; + + unsigned char blockCRC = 0; + for (byte k = 0; k < 8; ++k) { + if (byteFlipped[k]) { + blockCRC |= 1 << k; + } + } + + // Calculate CRC of block received + unsigned char myCRC = dataCRC(&myBlock[0]); + + // Compare + if (blockCRC != myCRC) { + display_Clear(); + print_Error(F("CRC ERROR"), true); + } } // reads the MPK file to the sd card @@ -2052,7 +2131,7 @@ void readMPK() { sdBuffer[currBlock + currByte] = myBlock[currByte]; } - // Real N64 has about 627us pause between banks, loop takes 500us, add a bit extra delay + // Real N64 has about 627us pause between banks, add a bit extra delay if (currBlock < 479) delayMicroseconds(800); } @@ -2087,7 +2166,7 @@ boolean checkHeader(byte startAddress) { } } -// verifies if read was successful +// verifies if Controller Pak holds valid header data void checksumMPK() { println_Msg(F("")); print_Msg(F("Header...")); diff --git a/Cart_Reader/SMS.ino b/Cart_Reader/SMS.ino index c51fa9c..39630e4 100644 --- a/Cart_Reader/SMS.ino +++ b/Cart_Reader/SMS.ino @@ -404,7 +404,7 @@ void getCartInfo_SMS() { break; default: cartSize = 48 * 1024UL; - + // LED Error setColor_RGB(0, 0, 255); break; @@ -604,7 +604,7 @@ void readROM_SMS() { // Blink led blinkLED(); - + // Read 16KB from slot 2 which starts at 0x8000 for (word currBuffer = 0; currBuffer < bankSize; currBuffer += 512) { // Fill SD buffer