-
Notifications
You must be signed in to change notification settings - Fork 8
Expand file tree
/
Copy pathresource_aba.cpp
More file actions
93 lines (86 loc) · 2.68 KB
/
resource_aba.cpp
File metadata and controls
93 lines (86 loc) · 2.68 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
#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;
}