Last active
January 26, 2026 04:46
-
-
Save sethmlarson/f22e7c10757fa969c10c1451b955787d to your computer and use it in GitHub Desktop.
Convert .dat files from "Sonic Mega Collection" on GameCube to .md Genesis ROMs
This file contains hidden or 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
| #include <fstream> | |
| #include <string> | |
| int processdata(unsigned char *InData, unsigned char *OutData, int filedatasize) // OutData=0 to get size | |
| { | |
| int CurrIn = 0x4; //Skip size | |
| int CurrOut = 0; | |
| while (CurrIn < filedatasize) | |
| { | |
| int Code = InData[CurrIn++]; | |
| for (int i = 0; (i < 8) && (CurrIn < filedatasize); i++) | |
| { | |
| if (Code & 1) | |
| { | |
| if (OutData) | |
| OutData[CurrOut] = InData[CurrIn]; | |
| CurrOut++; | |
| CurrIn++; | |
| } | |
| else | |
| { | |
| int OutDict = InData[CurrIn++]; | |
| int OutCnt = InData[CurrIn++]; | |
| OutDict |= ((OutCnt << 4) & 0xF00); | |
| OutCnt = (OutCnt & 0xF) + 2; | |
| OutDict |= (CurrOut & ~0xFFF); | |
| OutDict += 0x12; | |
| if (OutDict >= CurrOut) | |
| OutDict -= 0x1000; | |
| for (int j = 0; j <= OutCnt; j++) | |
| { | |
| if (OutData) | |
| OutData[CurrOut] = OutDict >= 0 ? OutData[OutDict] : 0; | |
| CurrOut++; | |
| OutDict++; | |
| } | |
| } | |
| Code >>= 1; | |
| } | |
| } | |
| return CurrOut; | |
| } | |
| int main(int argc, char* argv[]) | |
| { | |
| if (argc < 3) | |
| { | |
| printf("Wrong number of arguments\n"); | |
| return -1; | |
| } | |
| std::ifstream InFile(argv[1], std::ios::binary); | |
| printf("Decompressing %s to %s...\n", argv[1], argv[2]); | |
| InFile.seekg(0, std::ios::end); | |
| int filesize = InFile.tellg(); | |
| InFile.seekg(0, std::ios::beg); | |
| unsigned char *InData = new unsigned char[filesize]; | |
| InFile.read((char*)InData, filesize); | |
| int swapend = 0x702; | |
| if (filesize <= swapend) | |
| swapend = filesize-1; | |
| for (int i = 0; (3 * i) < swapend; i++) | |
| { | |
| char Tmp = InData[i]; | |
| InData[i] = InData[swapend - i]; | |
| InData[swapend - i] = Tmp; | |
| } | |
| int filedatasize = 0; | |
| for (int Curr = 0; Curr < 4; Curr++) | |
| { | |
| filedatasize <<= 8; | |
| filedatasize |= InData[3 - Curr]; | |
| } | |
| for (int i = 0; i < filedatasize; i++) | |
| InData[i] ^= 0x54; | |
| // Only calling to get the output size. Will be same as OutSize below. | |
| // Can skip this if using e.g. push_back() instead of unsigned char[] | |
| // or just set MaxBinSize large enough (max output file size). | |
| const int MaxBinSize = processdata(InData, 0, filedatasize); | |
| unsigned char* OutData = new unsigned char[MaxBinSize]; | |
| const int OutSize = processdata(InData, OutData, filedatasize); | |
| swapend = 156; | |
| for (int i = 0; i < OutSize; i += (swapend + 1)) | |
| { | |
| if (i + swapend >= OutSize) | |
| swapend = OutSize - i - 1; | |
| for (int j = 0; (j * 3) < swapend; j++) | |
| { | |
| char Tmp = OutData[i+j]; | |
| OutData[i+j] = OutData[i+swapend-j]; | |
| OutData[i+swapend-j] = Tmp; | |
| } | |
| } | |
| std::ofstream OutFile(argv[2], std::ios::binary); | |
| OutFile.write((char*)OutData, OutSize); | |
| delete[] InData; | |
| delete[] OutData; | |
| return 0; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment