新FF14は海外だとARRの略称なんですなあ、という事でだらだらと海外サイトを見ていたら、新FF14のデータ解析についてのスレッドがあって中々興味深く(0x08と0x02がヘッダとか)、もっと探せば解析完了したのがありそうだと更に探すと、
というForumを発見。
ついでにC言語のソースもあったので、ちょっと試すとバグはあるものの動作したので、ソースを見ながらsqpackのフォーマットを大体理解してBugFix。
試した所、どうやら内部データを見る所まではできる模様。解析した人すごいな。indexファイル側で制御してるっぽい感じだけど。
修正版ソースは以下の通り。コピペしてフリーのコンパイラとライブラリで動作する筈。日本語はUTF-8なので、文字コードさえ間違わなければ内容が大体読める感じ。
以下 parse.cpp
#include <stdio.h> #include <string.h> #include "zlib.h" int decompress(char* outBuf, int buffSize, char * pInBuf, int size) { int result; int inRes; z_stream c_stream; c_stream.zalloc = Z_NULL; c_stream.zfree = Z_NULL; c_stream.opaque = Z_NULL; c_stream.next_out = (Bytef *)outBuf; c_stream.avail_out = (uInt)buffSize; c_stream.next_in = (Bytef *)pInBuf; c_stream.avail_in = (uInt)size; result = inflateInit(&c_stream); if (!result) { inRes = inflate(&c_stream, Z_FINISH); if (inRes == 1) { result = inflateEnd(&c_stream); } else { inflateEnd(&c_stream); if(inRes != 2 && (inRes != -5 || size)) { result = inRes; } else { result = -3; } } } return result; } int Adler32(char* bytes, int size) { const int a32mod = 65521; int s1 = 1, s2 = 0; for(int i = 0; i < size; i++) { int b = bytes[i]; s1 = (s1 + b) % a32mod; s2 = (s2 + s1) % a32mod; } return (int)((s2 << 16) + s1); } int main(int argc, char* argv[]) { //FILE* fp = fopen(argv[1], "rb"); FILE* fp = fopen("030000.win32.dat0", "rb"); char * data; int fname; fseek(fp, 0, SEEK_END); int size = ftell(fp); rewind(fp); data = new char[size]; fread(data, sizeof(char), size, fp); fclose(fp); const int find = 0x80; const int find2 = 0x02; for(int i = 0; i < size; i++) { if((*(int*)(data + i) == find) && *(int*)(data + i + 4) == find2) { int found = i + 0x88; int headerPos = i; fname = i; int totalUncompressedSize = *(int*)(data + i + 0x08); int totalFrames = *(int*)(data + i + 0x14); char * tmpBuffer = new char[totalUncompressedSize]; memset(tmpBuffer, 0, totalUncompressedSize); int eSize = *(int*)(data + i + 0x88); int oSize = *(int*)(data + i + 0x8C); char * entry = new char[eSize + 6]; entry[0x00] = 0x58; entry[0x01] = 0x85; memcpy(entry + 2, data + i + 0x90, eSize); int adler = Adler32(entry + 2, eSize); memcpy(entry + 2 + eSize, &adler, 4); unsigned int result = decompress(tmpBuffer, oSize, entry, eSize + 6); i += eSize + 0x90; if(totalFrames > 1) { int currentFrame = 2; int lastSize = oSize; // i += eSize + 0x90; for(; currentFrame <= totalFrames; i++) { if(data[i] == 0x10) { int eSize = *(int*)(data + i + 0x08); int oSize = *(int*)(data + i + 0x0C); char * entry = new char[eSize + 6]; entry[0x00] = 0x58; entry[0x01] = 0x85; memcpy(entry + 2, data + i + 0x10, eSize); int adler = Adler32(entry + 2, eSize); memcpy(entry + 2 + eSize, &adler, 4); unsigned int result2 = decompress(tmpBuffer + lastSize, oSize, entry, eSize + 6); i += eSize + 0x0F; currentFrame++; lastSize += oSize; delete[] entry; } } } char filename[255]; sprintf(filename, "dc_030000_%08x.dat", fname); fp = fopen(filename, "wb"); fwrite(tmpBuffer, totalUncompressedSize, 1, fp); fclose(fp); if(entry != NULL) delete[] entry; delete[] tmpBuffer; } } return 0; }