// -*- mode: c++; mode: auto-fill; -*- #include typedef unsigned int dword; struct PAKENTRY { char szFileName[32]; // XORed by 0xff dword dwSize; dword dwOffset; }; struct PAKHEADER { dword dwSignature; dword dwFilesAmount; }; void unmaskFileName(char* p) { char* pw = p; while(*p) { *p++ ^= 0xff; } } int usage() { printf("extbgm -- TH2X BGM/SE extractor\n" "Usage: extbgm {bgm.pak|se.pak}\n"); return 1; } int main(int ac, char** av) { if(!*++av) return usage(); FILE* fi = fopen(*av, "rb"); if(!fi) return usage(); PAKHEADER header; fread(&header, sizeof header, 1, fi); if(header.dwSignature != '\0CAL') return usage(); for(int i = 0; i < header.dwFilesAmount; i++) { PAKENTRY entry; fread(&entry, sizeof entry, 1, fi); int entrypos = ftell(fi); unmaskFileName(entry.szFileName); printf("%-32s offset: 0x%08x size: 0x%08x\n", entry.szFileName, entry.dwOffset, entry.dwSize); fseek(fi, entry.dwOffset, SEEK_SET); FILE* fo = fopen(entry.szFileName, "wb"); unsigned char buffer[1 << 16]; int nBytesToCopy = entry.dwSize, nBytesRead, nBytesToWrite; while(nBytesToCopy > 0) { nBytesRead = fread(buffer, 1, 1 << 16, fi); if(nBytesToCopy < nBytesRead) { nBytesToWrite = nBytesToCopy; nBytesToCopy = 0; } else { nBytesToWrite = nBytesRead; nBytesToCopy -= nBytesRead; } fwrite(buffer, 1, nBytesToWrite, fo); putchar('o'); } putchar('\n'); fclose(fo); fseek(fi, entrypos, SEEK_SET); } fclose(fi); }