#include "resource_aba.h" #include "unpack.h" #include "util.h" ResourceAba::ResourceAba(FileSystem *fs) : _fs(fs) { _filesCount = 0; _entries = 0; _entriesCount = 0; } ResourceAba::~ResourceAba() { free(_entries); } static int compareAbaEntry(const void *a, const void *b) { return strcasecmp(((const ResourceAbaEntry *)a)->name, ((const ResourceAbaEntry *)b)->name); } void ResourceAba::readEntries(const char *aba) { assert(_filesCount < 3); if (_f[_filesCount].open(aba, "rb", _fs)) { File &f = _f[_filesCount]; const int currentCount = _entriesCount; const int entriesCount = f.readUint16BE(); _entries = (ResourceAbaEntry *)realloc(_entries, (currentCount + entriesCount) * sizeof(ResourceAbaEntry)); if (!_entries) { error("Failed to allocate %d _entries", currentCount + entriesCount); return; } _entriesCount = currentCount + entriesCount; const int entrySize = f.readUint16BE(); assert(entrySize == 30); uint32_t nextOffset = 0; for (int i = 0; i < entriesCount; ++i) { const int j = currentCount + i; f.read(_entries[j].name, sizeof(_entries[j].name)); _entries[j].offset = f.readUint32BE(); _entries[j].compressedSize = f.readUint32BE(); _entries[j].size = f.readUint32BE(); _entries[j].fileIndex = _filesCount; const uint32_t tag = f.readUint32BE(); assert(tag == TAG); debug(DBG_RES, "'%s' offset 0x%X size %d/%d", _entries[j].name, _entries[j].offset, _entries[j].compressedSize, _entries[j].size); if (i != 0) { assert(nextOffset == _entries[j].offset); } nextOffset = _entries[j].offset + _entries[j].compressedSize; } qsort(_entries, _entriesCount, sizeof(ResourceAbaEntry), compareAbaEntry); ++_filesCount; } } const ResourceAbaEntry *ResourceAba::findEntry(const char *name) const { ResourceAbaEntry tmp; strcpy(tmp.name, name); return (const ResourceAbaEntry *)bsearch(&tmp, _entries, _entriesCount, sizeof(ResourceAbaEntry), compareAbaEntry); } uint8_t *ResourceAba::loadEntry(const char *name, uint32_t *size) { uint8_t *dst = 0; const ResourceAbaEntry *e = findEntry(name); if (e) { if (size) { *size = e->size; } uint8_t *tmp = (uint8_t *)malloc(e->compressedSize); if (!tmp) { error("Failed to allocate %d bytes", e->compressedSize); return 0; } _f[e->fileIndex].seek(e->offset); _f[e->fileIndex].read(tmp, e->compressedSize); if (e->compressedSize == e->size) { dst = tmp; } else { dst = (uint8_t *)malloc(e->size); if (!dst) { error("Failed to allocate %d bytes", e->size); free(tmp); return 0; } const bool ret = bytekiller_unpack(dst, e->size, tmp, e->compressedSize); if (!ret) { error("Bad CRC for '%s'", name); } free(tmp); } } return dst; }