107 lines
3.1 KiB
C++
107 lines
3.1 KiB
C++
|
|
#include <assert.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include "fs.h"
|
|
#include "resource_mac.h"
|
|
#include "util.h"
|
|
|
|
const char *ResourceMac::FILENAME1 = "Flashback.bin";
|
|
const char *ResourceMac::FILENAME2 = "Flashback.rsrc";
|
|
|
|
ResourceMac::ResourceMac(const char *filePath, FileSystem *fs)
|
|
: _dataOffset(0), _types(0), _entries(0), _sndIndex(-1) {
|
|
memset(&_map, 0, sizeof(_map));
|
|
_f.open(filePath, "rb", fs);
|
|
}
|
|
|
|
ResourceMac::~ResourceMac() {
|
|
if (_entries) {
|
|
for (int i = 0; i < _map.typesCount; ++i) {
|
|
free(_entries[i]);
|
|
}
|
|
free(_entries);
|
|
}
|
|
free(_types);
|
|
}
|
|
|
|
void ResourceMac::load() {
|
|
const uint32_t sig = _f.readUint32BE();
|
|
if (sig == 0x00051607) { // AppleDouble
|
|
debug(DBG_INFO, "Load Macintosh data from AppleDouble");
|
|
_f.seek(24);
|
|
const int count = _f.readUint16BE();
|
|
for (int i = 0; i < count; ++i) {
|
|
const int id = _f.readUint32BE();
|
|
const int offset = _f.readUint32BE();
|
|
const int length = _f.readUint32BE();
|
|
if (id == 2) { // resource fork
|
|
loadResourceFork(offset, length);
|
|
break;
|
|
}
|
|
}
|
|
} else { // MacBinary
|
|
debug(DBG_INFO, "Load Macintosh data from MacBinary");
|
|
_f.seek(83);
|
|
uint32_t dataSize = _f.readUint32BE();
|
|
uint32_t resourceOffset = 128 + ((dataSize + 127) & ~127);
|
|
loadResourceFork(resourceOffset, dataSize);
|
|
}
|
|
}
|
|
|
|
void ResourceMac::loadResourceFork(uint32_t resourceOffset, uint32_t dataSize) {
|
|
_f.seek(resourceOffset);
|
|
_dataOffset = resourceOffset + _f.readUint32BE();
|
|
uint32_t mapOffset = resourceOffset + _f.readUint32BE();
|
|
|
|
_f.seek(mapOffset + 22);
|
|
_f.readUint16BE();
|
|
_map.typesOffset = _f.readUint16BE();
|
|
_map.namesOffset = _f.readUint16BE();
|
|
_map.typesCount = _f.readUint16BE() + 1;
|
|
|
|
_f.seek(mapOffset + _map.typesOffset + 2);
|
|
_types = (ResourceMacType *)calloc(_map.typesCount, sizeof(ResourceMacType));
|
|
for (int i = 0; i < _map.typesCount; ++i) {
|
|
_f.read(_types[i].id, 4);
|
|
_types[i].count = _f.readUint16BE() + 1;
|
|
_types[i].startOffset = _f.readUint16BE();
|
|
if (_sndIndex < 0 && memcmp(_types[i].id, "snd ", 4) == 0) {
|
|
_sndIndex = i;
|
|
}
|
|
}
|
|
_entries = (ResourceMacEntry **)calloc(_map.typesCount, sizeof(ResourceMacEntry *));
|
|
for (int i = 0; i < _map.typesCount; ++i) {
|
|
_f.seek(mapOffset + _map.typesOffset + _types[i].startOffset);
|
|
_entries[i] = (ResourceMacEntry *)calloc(_types[i].count, sizeof(ResourceMacEntry));
|
|
for (int j = 0; j < _types[i].count; ++j) {
|
|
_entries[i][j].id = _f.readUint16BE();
|
|
_entries[i][j].nameOffset = _f.readUint16BE();
|
|
_entries[i][j].dataOffset = _f.readUint32BE() & 0x00FFFFFF;
|
|
_f.readUint32BE();
|
|
}
|
|
for (int j = 0; j < _types[i].count; ++j) {
|
|
_entries[i][j].name[0] = '\0';
|
|
if (_entries[i][j].nameOffset != 0xFFFF) {
|
|
_f.seek(mapOffset + _map.namesOffset + _entries[i][j].nameOffset);
|
|
const int len = _f.readByte();
|
|
assert(len < kResourceMacEntryNameLength - 1);
|
|
_f.read(_entries[i][j].name, len);
|
|
_entries[i][j].name[len] = '\0';
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
const ResourceMacEntry *ResourceMac::findEntry(const char *name) const {
|
|
for (int type = 0; type < _map.typesCount; ++type) {
|
|
for (int i = 0; i < _types[type].count; ++i) {
|
|
if (strcmp(name, _entries[type][i].name) == 0) {
|
|
return &_entries[type][i];
|
|
}
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|