Content.bin Part B decompresser
Jump to navigation
Jump to search
// Copyright 2008 Arcnor <arcnorj@yahoo.es>
// Licensed under the terms of the GNU GPL, version 2
// http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
#include <fstream>
#include <iostream>
using namespace std;
int Decompress(const char *fileBuf, const unsigned int bufSize, char **newBuffer, unsigned int &newSize) {
// Check if it's uncompressible
unsigned char tempbyte;
unsigned int header = 0;
if ((*(unsigned int *)fileBuf) == (*(unsigned int *)"LZ77")) {
// Some LZ77 files have a F7 byte after 'LZ77' that indicates size to be
// decompressed after it, and size of the compressed data. So, in the end,
// the header is 0x0A bytes long ;)
if ((unsigned char)fileBuf[4] == 0xF7)
header = 0x0A;
else
header = 0x04;
}
tempbyte = fileBuf[0 + header];
if (tempbyte != 0x10) {
throw -1;
}
// Take the 4 bytes (unlike NDS)
newSize = *(unsigned int *)&fileBuf[1 + header];
// New file buffer (1 byte bigger, in case we're decompressing text, to have it zero-terminated)
*newBuffer = new char[newSize + 1];
char *buffer = *newBuffer;
memset(buffer, 0x00, newSize);
// Command bit mask
unsigned char commandMask;
unsigned char commandSize;
unsigned int commandOffset;
unsigned int bufPos = 0;
unsigned int pos = 4 + header + 1;
while (pos < bufSize) {
commandMask = fileBuf[pos++];
for (int j = 0x80; j > 0; j = j >> 1) {
if (pos < bufSize) {
if ((commandMask & j) == 0) {
buffer[bufPos++] = fileBuf[pos++];
} else { // Command
commandSize = fileBuf[pos++];
commandOffset = (int)(unsigned char)fileBuf[pos++] | (int)(unsigned char)(commandSize & 0x0F) << 8;
commandSize = (commandSize >> 4) + 3;
// FIXME: When found a strange offset, just fill it with 'X'
if (commandOffset > bufPos) {
for (int k = 0; k < commandSize; k++) {
buffer[bufPos++] = 'X';
}
} else {
for (int k = 0; k < commandSize; k++) {
buffer[bufPos] = buffer[bufPos - commandOffset - 1];
bufPos++;
}
}
}
} else { // if (pos < bufsize)
break;
}
}
}
return 0;
}
int main(int argc, char *argv[]) {
if (argc < 2) {
cout << "Usage: " << argv[0] << " <XXXX_02_gameinfo.bin>" << endl;
return 1;
}
ifstream fin(argv[1], ifstream::in);
// Get buffer size
fin.seekg(0, ios_base::end);
unsigned int bufSize = (unsigned int)fin.tellg() - 0x20;
// Fill buffer
fin.seekg(0x20, ios_base::beg);
char *buf = new char[bufSize];
fin.read(buf, bufSize);
fin.close();
unsigned int newSize;
char *newBuf;
Decompress(buf, bufSize, &newBuf, newSize);
ofstream fout("DecompGameInfo.bin", ofstream::out);
fout.write(newBuf, newSize);
fout.close();
}