refactor resource module:

- struct ResourceContext => class ResourceContext
- replace "*alloc","free" with array templates
- simplify createContexts routines

svn-id: r46254
This commit is contained in:
Andrew Kurushin 2009-12-04 17:52:42 +00:00
parent 4fb779dbaf
commit aa147a2f5a
12 changed files with 486 additions and 556 deletions

View File

@ -352,7 +352,7 @@ void Actor::loadFrameList(int frameListResourceId, ActorFrameSequence *&framesPo
memoryError("Actor::loadFrameList");
}
MemoryReadStreamEndian readS(resourcePointer, resourceLength, _actorContext->isBigEndian);
MemoryReadStreamEndian readS(resourcePointer, resourceLength, _actorContext->isBigEndian());
for (int i = 0; i < framesCount; i++) {
debug(9, "frameType %d", i);

View File

@ -90,7 +90,7 @@ void Font::loadFont(uint32 fontResourceId) {
error("Font::loadFont() Invalid font length (%i < %i)", (int)fontResourceLength, FONT_DESCSIZE);
}
MemoryReadStreamEndian readS(fontResourcePointer, fontResourceLength, fontContext->isBigEndian);
MemoryReadStreamEndian readS(fontResourcePointer, fontResourceLength, fontContext->isBigEndian());
// Create new font structure
font = (FontData *)malloc(sizeof(*font));

View File

@ -296,12 +296,12 @@ void Music::play(uint32 resourceId, MusicFlags flags) {
// Digital music
ResourceData *resData = _digitalMusicContext->getResourceData(resourceId - 9);
Common::File *musicFile = _digitalMusicContext->getFile(resData);
int offs = (_digitalMusicContext->isCompressed) ? 9 : 0;
int offs = (_digitalMusicContext->isCompressed()) ? 9 : 0;
Common::SeekableSubReadStream *musicStream = new Common::SeekableSubReadStream(musicFile,
(uint32)resData->offset + offs, (uint32)resData->offset + resData->size - offs);
if (!_digitalMusicContext->isCompressed) {
if (!_digitalMusicContext->isCompressed()) {
byte musicFlags = Audio::Mixer::FLAG_AUTOFREE | Audio::Mixer::FLAG_STEREO |
Audio::Mixer::FLAG_16BITS | Audio::Mixer::FLAG_LITTLE_ENDIAN;
if (flags == MUSIC_LOOP)

View File

@ -39,21 +39,13 @@
namespace Saga {
Resource::Resource(SagaEngine *vm): _vm(vm) {
_contexts = NULL;
_contextsCount = 0;
}
Resource::~Resource() {
clearContexts();
}
bool Resource::loadResContext_v1(ResourceContext *context, uint32 contextOffset, uint32 contextSize) {
bool ResourceContext::loadResV1(uint32 contextOffset, uint32 contextSize) {
size_t i;
bool result;
byte tableInfo[RSC_TABLEINFO_SIZE];
byte *tableBuffer;
size_t tableSize;
uint32 count;
uint32 resourceTableOffset;
ResourceData *resourceData;
@ -61,41 +53,41 @@ bool Resource::loadResContext_v1(ResourceContext *context, uint32 contextOffset,
return false;
}
context->file->seek(contextOffset + contextSize - RSC_TABLEINFO_SIZE);
_file.seek(contextOffset + contextSize - RSC_TABLEINFO_SIZE);
if (context->file->read(tableInfo, RSC_TABLEINFO_SIZE) != RSC_TABLEINFO_SIZE) {
if (_file.read(tableInfo, RSC_TABLEINFO_SIZE) != RSC_TABLEINFO_SIZE) {
return false;
}
MemoryReadStreamEndian readS(tableInfo, RSC_TABLEINFO_SIZE, context->isBigEndian);
MemoryReadStreamEndian readS(tableInfo, RSC_TABLEINFO_SIZE, _isBigEndian);
resourceTableOffset = readS.readUint32();
context->count = readS.readUint32();
count = readS.readUint32();
// Check for sane table offset
if (resourceTableOffset != contextSize - RSC_TABLEINFO_SIZE - RSC_TABLEENTRY_SIZE * context->count) {
if (resourceTableOffset != contextSize - RSC_TABLEINFO_SIZE - RSC_TABLEENTRY_SIZE * count) {
return false;
}
// Load resource table
tableSize = RSC_TABLEENTRY_SIZE * context->count;
tableSize = RSC_TABLEENTRY_SIZE * count;
tableBuffer = (byte *)malloc(tableSize);
context->file->seek(resourceTableOffset + contextOffset, SEEK_SET);
_file.seek(resourceTableOffset + contextOffset, SEEK_SET);
result = (context->file->read(tableBuffer, tableSize) == tableSize);
result = (_file.read(tableBuffer, tableSize) == tableSize);
if (result) {
context->table = (ResourceData *)calloc(context->count, sizeof(*context->table));
_table.resize(count);
MemoryReadStreamEndian readS1(tableBuffer, tableSize, context->isBigEndian);
MemoryReadStreamEndian readS1(tableBuffer, tableSize, _isBigEndian);
for (i = 0; i < context->count; i++) {
resourceData = &context->table[i];
for (i = 0; i < count; i++) {
resourceData = &_table[i];
resourceData->offset = contextOffset + readS1.readUint32();
resourceData->size = readS1.readUint32();
//sanity check
if ((resourceData->offset > (uint)context->fileSize) || (resourceData->size > contextSize)) {
if ((resourceData->offset > (uint)_fileSize) || (resourceData->size > contextSize)) {
result = false;
break;
}
@ -106,7 +98,7 @@ bool Resource::loadResContext_v1(ResourceContext *context, uint32 contextOffset,
return result;
}
bool Resource::loadContext(ResourceContext *context) {
bool ResourceContext::load(SagaEngine *vm, Resource *resource) {
size_t i;
const GamePatchDescription *patchDescription;
ResourceData *resourceData;
@ -119,45 +111,49 @@ bool Resource::loadContext(ResourceContext *context) {
size_t tableSize;
bool isMacBinary;
if (!context->file->open(context->fileName)) {
if (_fileName == NULL) { // IHNM special case
return true;
}
if (!_file.open(_fileName)) {
return false;
}
context->fileSize = context->file->size();
context->isBigEndian = _vm->isBigEndian();
_fileSize = _file.size();
_isBigEndian = vm->isBigEndian();
if (context->fileType & GAME_SWAPENDIAN)
context->isBigEndian = !context->isBigEndian;
if (_fileType & GAME_SWAPENDIAN)
_isBigEndian = !_isBigEndian;
isMacBinary = (context->fileType & GAME_MACBINARY) > 0;
context->fileType &= ~GAME_MACBINARY;
isMacBinary = (_fileType & GAME_MACBINARY) > 0;
_fileType &= ~GAME_MACBINARY;
if (!isMacBinary) {
if (!loadResContext(context, 0, context->fileSize)) {
if (!loadRes(0, _fileSize)) {
return false;
}
} else {
if (!loadMacContext(context)) {
if (!loadMac()) {
return false;
}
}
//process internal patch files
if (context->fileType & GAME_PATCHFILE) {
subjectResourceType = ~GAME_PATCHFILE & context->fileType;
subjectContext = getContext((GameFileTypes)subjectResourceType);
if (_fileType & GAME_PATCHFILE) {
subjectResourceType = ~GAME_PATCHFILE & _fileType;
subjectContext = resource->getContext((GameFileTypes)subjectResourceType);
if (subjectContext == NULL) {
error("Resource::loadContext() Subject context not found");
error("ResourceContext::load() Subject context not found");
}
loadResource(context, context->count - 1, tableBuffer, tableSize);
resource->loadResource(this, _table.size() - 1, tableBuffer, tableSize);
MemoryReadStreamEndian readS2(tableBuffer, tableSize, context->isBigEndian);
MemoryReadStreamEndian readS2(tableBuffer, tableSize, _isBigEndian);
for (i = 0; i < tableSize / 8; i++) {
subjectResourceId = readS2.readUint32();
patchResourceId = readS2.readUint32();
subjectResourceData = subjectContext->getResourceData(subjectResourceId);
resourceData = context->getResourceData(patchResourceId);
subjectResourceData->patchData = new PatchData(context->file);
resourceData = getResourceData(patchResourceId);
subjectResourceData->patchData = new PatchData(&_file);
subjectResourceData->offset = resourceData->offset;
subjectResourceData->size = resourceData->size;
}
@ -165,10 +161,10 @@ bool Resource::loadContext(ResourceContext *context) {
}
//process external patch files
for (patchDescription = _vm->getPatchDescriptions(); patchDescription && patchDescription->fileName; ++patchDescription) {
if ((patchDescription->fileType & context->fileType) != 0) {
if (patchDescription->resourceId < context->count) {
resourceData = &context->table[patchDescription->resourceId];
for (patchDescription = vm->getPatchDescriptions(); patchDescription && patchDescription->fileName; ++patchDescription) {
if ((patchDescription->fileType & _fileType) != 0) {
if (patchDescription->resourceId < _table.size()) {
resourceData = &_table[patchDescription->resourceId];
resourceData->patchData = new PatchData(patchDescription);
if (resourceData->patchData->_patchFile->open(patchDescription->fileName)) {
resourceData->offset = 0;
@ -176,7 +172,7 @@ bool Resource::loadContext(ResourceContext *context) {
// ITE uses several patch files which are loaded and then not needed
// anymore (as they're in memory), so close them here. IHNM uses only
// 1 patch file, which is reused, so don't close it
if (_vm->getGameId() == GID_ITE)
if (vm->getGameId() == GID_ITE)
resourceData->patchData->_patchFile->close();
} else {
delete resourceData->patchData;
@ -189,221 +185,140 @@ bool Resource::loadContext(ResourceContext *context) {
// Close the file if it's part of a series of files
// This prevents having all voice files open in IHNM for no reason, as each chapter uses
// a different voice file
if (context->serial > 0)
context->file->close();
if (_serial > 0)
_file.close();
return true;
}
bool Resource::createContexts() {
int i;
Resource::Resource(SagaEngine *vm): _vm(vm) {
}
Resource::~Resource() {
clearContexts();
}
void Resource::addContext(const char *fileName, uint16 fileType, bool isCompressed, int serial) {
ResourceContext *context;
int soundFileIndex = 0;
int voicesFileIndex = 0;
bool digitalMusic = false;
context = createContext();
context->_fileName = fileName;
context->_fileType = fileType;
context->_isCompressed = isCompressed;
context->_serial = serial;
_contexts.push_back(context);
}
bool Resource::createContexts() {
bool soundFileInArray = false;
bool multipleVoices = false;
bool censoredVersion = false;
bool compressedSounds = false;
bool compressedMusic = false;
uint16 voiceFileType = GAME_VOICEFILE;
bool fileFound = false;
int maxFile = 0;
_vm->_voiceFilesExist = true;
struct SoundFileInfo {
int gameId;
char fileName[40];
bool isCompressed;
uint16 voiceFileAddType;
};
SoundFileInfo *curSoundfiles = 0;
// If the Wyrmkeep credits file is found, set the Wyrmkeep version flag to true
if (Common::File::exists("graphics/credit3n.dlt")) {
_vm->_gf_wyrmkeep = true;
}
_contextsCount = 0;
for (i = 0; _vm->getFilesDescriptions()[i].fileName; i++) {
_contextsCount++;
if (_vm->getFilesDescriptions()[i].fileType == GAME_SOUNDFILE)
for (const ADGameFileDescription *gameFileDescription = _vm->getFilesDescriptions();
gameFileDescription->fileName; gameFileDescription++) {
addContext(gameFileDescription->fileName, gameFileDescription->fileType);
if (gameFileDescription->fileType == GAME_SOUNDFILE) {
soundFileInArray = true;
}
}
//// Detect and add SFX files ////////////////////////////////////////////////
SoundFileInfo sfxFilesITE[] = {
{ "sounds.rsc", false },
{ "sounds.cmp", true },
{ "soundsd.rsc", false },
{ "soundsd.cmp", true }
};
SoundFileInfo sfxFiles[] = {
{ GID_ITE, "sounds.rsc", false },
{ GID_ITE, "sounds.cmp", true },
{ GID_ITE, "soundsd.rsc", false },
{ GID_ITE, "soundsd.cmp", true },
#ifdef ENABLE_IHNM
SoundFileInfo sfxFilesIHNM[] = {
{ "sfx.res", false },
{ "sfx.cmp", true }
};
{ GID_IHNM, "sfx.res", false },
{ GID_IHNM, "sfx.cmp", true },
#endif
#ifdef ENABLE_SAGA2
SoundFileInfo sfxFilesFTA2[] = {
{ "ftasound.hrs", false }
};
SoundFileInfo sfxFilesDino[] = {
{ "dinosnd.hrs", false },
};
{ GID_FTA2, "ftasound.hrs", false },
{ GID_DINO, "dinosnd.hrs", false },
#endif
{ -1, NULL, false }
};
_soundFileName[0] = 0;
if (!soundFileInArray) {
// If the sound file is not specified in the detector table, add it here
fileFound = false;
switch (_vm->getGameId()) {
case GID_ITE:
curSoundfiles = sfxFilesITE;
maxFile = 4;
break;
#ifdef ENABLE_IHNM
case GID_IHNM:
curSoundfiles = sfxFilesIHNM;
maxFile = 2;
break;
#endif
#ifdef ENABLE_SAGA2
case GID_DINO:
curSoundfiles = sfxFilesDino;
maxFile = 1;
break;
case GID_FTA2:
curSoundfiles = sfxFilesFTA2;
maxFile = 1;
break;
#endif
}
for (i = 0; i < maxFile; i++) {
if (Common::File::exists(curSoundfiles[i].fileName)) {
_contextsCount++;
soundFileIndex = _contextsCount - 1;
strcpy(_soundFileName, curSoundfiles[i].fileName);
compressedSounds = curSoundfiles[i].isCompressed;
fileFound = true;
break;
}
}
if (!fileFound) {
// No sound file found, don't add any file to the array
soundFileInArray = true;
if (_vm->getGameId() == GID_ITE) {
// ITE floppy versions have both voices and sounds in voices.rsc
voiceFileType = GAME_SOUNDFILE | GAME_VOICEFILE;
}
for (SoundFileInfo *curSoundFile = sfxFiles; (curSoundFile->gameId != -1); curSoundFile++) {
if (curSoundFile->gameId != _vm->getGameId()) continue;
if (!Common::File::exists(curSoundFile->fileName)) continue;
strcpy(_soundFileName, curSoundFile->fileName);
addContext(_soundFileName, GAME_SOUNDFILE, curSoundFile->isCompressed);
break;
}
}
//// Detect and add voice files /////////////////////////////////////////////
SoundFileInfo voiceFilesITE[] = {
{ "voices.rsc", false },
{ "voices.cmp", true },
{ "voicesd.rsc", false },
{ "voicesd.cmp", true },
{ "inherit the earth voices", false },
{ "inherit the earth voices.cmp", true },
{ "ite voices.bin", false }
};
SoundFileInfo voiceFiles[] = {
{ GID_ITE, "voices.rsc", false , (_soundFileName[0] == 0) ? GAME_SOUNDFILE : 0},
{ GID_ITE, "voices.cmp", true , (_soundFileName[0] == 0) ? GAME_SOUNDFILE : 0},
{ GID_ITE, "voicesd.rsc", false , (_soundFileName[0] == 0) ? GAME_SOUNDFILE : 0},
{ GID_ITE, "voicesd.cmp", true , (_soundFileName[0] == 0) ? GAME_SOUNDFILE : 0},
// The resources in the Wyrmkeep combined Windows/Mac/Linux CD version are little endian, but
// the voice file is big endian. If we got such a version with mixed files, mark this voice file
// as big endian
{ GID_ITE, "inherit the earth voices", false , _vm->isBigEndian() ? 0 : GAME_SWAPENDIAN},
{ GID_ITE, "inherit the earth voices.cmp", true , _vm->isBigEndian() ? 0 : GAME_SWAPENDIAN},
{ GID_ITE, "ite voices.bin", false , GAME_MACBINARY},
#ifdef ENABLE_IHNM
SoundFileInfo voiceFilesIHNM[] = {
{ "voicess.res", false },
{ "voicess.cmp", true },
{ "voicesd.res", false },
{ "voicesd.cmp", true },
};
{ GID_IHNM, "voicess.res", false , 0},
{ GID_IHNM, "voicess.cmp", true , 0},
{ GID_IHNM, "voicesd.res", false , 0},
{ GID_IHNM, "voicesd.cmp", true , 0},
#endif
#ifdef ENABLE_SAGA2
SoundFileInfo voiceFilesFTA2[] = {
{ "ftavoice.hrs", false },
};
{ GID_FTA2, "ftavoice.hrs", false , 0},
#endif
{ -1, NULL, false , 0}
};
// Detect and add voice files
fileFound = false;
_voicesFileName[0][0] = 0;
for (SoundFileInfo *curSoundFile = voiceFiles; (curSoundFile->gameId != -1); curSoundFile++) {
if (curSoundFile->gameId != _vm->getGameId()) continue;
if (!Common::File::exists(curSoundFile->fileName)) continue;
switch (_vm->getGameId()) {
case GID_ITE:
curSoundfiles = voiceFilesITE;
maxFile = 7;
break;
#ifdef ENABLE_IHNM
case GID_IHNM:
curSoundfiles = voiceFilesIHNM;
maxFile = 4;
break;
#endif
#ifdef ENABLE_SAGA2
/*
case GID_DINO:
// TODO
curSoundfiles = NULL;
maxFile = 0;
break;
*/
case GID_FTA2:
curSoundfiles = voiceFilesFTA2;
maxFile = 1;
break;
#endif
}
strcpy(_voicesFileName[0], curSoundFile->fileName);
addContext(_voicesFileName[0], GAME_VOICEFILE | curSoundFile->voiceFileAddType, curSoundFile->isCompressed);
for (i = 0; i < maxFile; i++) {
if (Common::File::exists(curSoundfiles[i].fileName)) {
_contextsCount++;
voicesFileIndex = _contextsCount - 1;
strcpy(_voicesFileName[0], curSoundfiles[i].fileName);
compressedSounds = curSoundfiles[i].isCompressed;
fileFound = true;
// Special cases
if (!scumm_stricmp(curSoundfiles[i].fileName, "inherit the earth voices") ||
!scumm_stricmp(curSoundfiles[i].fileName, "inherit the earth voices.cmp")) {
// The resources in the Wyrmkeep combined Windows/Mac/Linux CD version are little endian, but
// the voice file is big endian. If we got such a version with mixed files, mark this voice file
// as big endian
if (!_vm->isBigEndian())
voiceFileType = GAME_VOICEFILE | GAME_SWAPENDIAN; // This file is big endian
}
if (!scumm_stricmp(curSoundfiles[i].fileName, "ite voices.bin")) {
voiceFileType = GAME_VOICEFILE | GAME_MACBINARY;
}
if (!scumm_stricmp(curSoundfiles[i].fileName, "voicess.res") ||
!scumm_stricmp(curSoundfiles[i].fileName, "voicess.cmp")) {
// Special cases
if (!scumm_stricmp(curSoundFile->fileName, "voicess.res") ||
!scumm_stricmp(curSoundFile->fileName, "voicess.cmp")) {
// IHNM has multiple voice files
multipleVoices = true;
// Note: it is assumed that the voice files are always last in the list
if (Common::File::exists("voices4.res") || Common::File::exists("voices4.cmp")) {
_contextsCount += 6; // voices1-voices6
} else {
// The German and French versions of IHNM don't have Nimdok's chapter,
// therefore the voices file for that chapter is missing
_contextsCount += 5; // voices1-voices3, voices4-voices5
censoredVersion = true;
for (size_t i = 1; i <= 6; i++) { // voices1-voices6
sprintf(_voicesFileName[i], "voices%i.%s", i, curSoundFile->isCompressed ? "cmp" : "res");
if (i == 4) {
// The German and French versions of IHNM don't have Nimdok's chapter,
// therefore the voices file for that chapter is missing
if (!Common::File::exists(_voicesFileName[i])) {
continue;
}
}
addContext(_voicesFileName[i], GAME_VOICEFILE, curSoundFile->isCompressed, i);
}
}
break;
}
break;
}
if (!fileFound) {
if (_voicesFileName[0][0] == 0) {
if (_vm->getGameId() == GID_IHNM && _vm->isMacResources()) {
// The Macintosh version of IHNM has no voices.res, and it has all
// its voice files in subdirectories, so don't do anything here
_contexts.push_back(new VoiceResourceContext_RES());
} else {
warning("No voice file found, voices will be disabled");
_vm->_voicesEnabled = false;
@ -412,83 +327,27 @@ bool Resource::createContexts() {
}
}
//// Detect and add ITE music files /////////////////////////////////////////
SoundFileInfo musicFilesITE[] = {
{ "music.rsc", false },
{ "music.cmp", true },
{ "musicd.rsc", false },
{ "musicd.cmp", true },
//// Detect and add music files /////////////////////////////////////////
SoundFileInfo musicFiles[] = {
{ GID_ITE, "music.rsc", false },
{ GID_ITE, "music.cmp", true },
{ GID_ITE, "musicd.rsc", false },
{ GID_ITE, "musicd.cmp", true },
{ -1, NULL, false }
};
// Check for digital music in ITE
if (_vm->getGameId() == GID_ITE) {
fileFound = false;
for (i = 0; i < 4; i++) {
if (Common::File::exists(musicFilesITE[i].fileName)) {
_contextsCount++;
digitalMusic = true;
compressedMusic = musicFilesITE[i].isCompressed;
fileFound = true;
strcpy(_musicFileName, musicFilesITE[i].fileName);
break;
}
}
if (!fileFound) {
// No sound file found, don't add any file to the array
digitalMusic = false;
}
for (SoundFileInfo *curSoundFile = musicFiles; (curSoundFile->gameId != -1); curSoundFile++) {
if (curSoundFile->gameId != _vm->getGameId()) continue;
if (!Common::File::exists(curSoundFile->fileName)) continue;
strcpy(_musicFileName, curSoundFile->fileName);
addContext(_musicFileName, GAME_DIGITALMUSICFILE, curSoundFile->isCompressed);
break;
}
_contexts = (ResourceContext*)calloc(_contextsCount, sizeof(*_contexts));
for (i = 0; i < _contextsCount; i++) {
context = &_contexts[i];
context->file = new Common::File();
context->serial = 0;
// For ITE, add the digital music file and sfx file information here
if (_vm->getGameId() == GID_ITE && digitalMusic && i == _contextsCount - 1) {
context->fileName = _musicFileName;
context->fileType = GAME_DIGITALMUSICFILE;
context->isCompressed = compressedMusic;
} else if (!soundFileInArray && i == soundFileIndex) {
context->fileName = _soundFileName;
context->fileType = GAME_SOUNDFILE;
context->isCompressed = compressedSounds;
} else if (_vm->_voiceFilesExist && i == voicesFileIndex && !(_vm->getGameId() == GID_IHNM && _vm->isMacResources())) {
context->fileName = _voicesFileName[0];
// can be GAME_VOICEFILE or GAME_SOUNDFILE | GAME_VOICEFILE or GAME_VOICEFILE | GAME_SWAPENDIAN
context->fileType = voiceFileType;
context->isCompressed = compressedSounds;
} else {
if (!(_vm->_voiceFilesExist && multipleVoices && (i > voicesFileIndex))) {
context->fileName = _vm->getFilesDescriptions()[i].fileName;
context->fileType = _vm->getFilesDescriptions()[i].fileType;
context->isCompressed = compressedSounds;
} else {
int token = (censoredVersion && (i - voicesFileIndex >= 4)) ? 1 : 0; // censored versions don't have voice4
if (compressedSounds)
sprintf(_voicesFileName[i - voicesFileIndex + token], "voices%i.cmp", i - voicesFileIndex + token);
else
sprintf(_voicesFileName[i - voicesFileIndex + token], "voices%i.res", i - voicesFileIndex + token);
context->fileName = _voicesFileName[i - voicesFileIndex + token];
context->fileType = GAME_VOICEFILE;
context->isCompressed = compressedSounds;
// IHNM has several different voice files, so we need to allow
// multiple resource contexts of the same type. We tell them
// apart by assigning each of the duplicates a unique serial
// number. The default behaviour when requesting a context will
// be to look for serial number 0.
context->serial = i - voicesFileIndex + token;
}
}
if (!loadContext(context)) {
for (ResourceContextList::iterator i = _contexts.begin(); i != _contexts.end(); ++i) {
if (!(*i)->load(_vm, this)) {
return false;
}
}
@ -496,27 +355,12 @@ bool Resource::createContexts() {
}
void Resource::clearContexts() {
int i;
size_t j;
ResourceContext *context;
if (_contexts == NULL) {
return;
ResourceContextList::iterator i = _contexts.begin();
while (i != _contexts.end()) {
ResourceContext * context = *i;
i = _contexts.erase(i);
delete context;
}
for (i = 0; i < _contextsCount; i++) {
context = &_contexts[i];
delete context->file;
if (context->table != NULL) {
for (j = 0; j < context->count; j++) {
delete context->table[j].patchData;
}
}
if (_vm->isSaga2()) {
free(context->categories);
}
free(context->table);
}
free(_contexts);
_contexts = NULL;
}
void Resource::loadResource(ResourceContext *context, uint32 resourceId, byte*&resourceBuffer, size_t &resourceSize) {
@ -548,4 +392,14 @@ void Resource::loadResource(ResourceContext *context, uint32 resourceId, byte*&r
file->close();
}
ResourceContext *Resource::getContext(uint16 fileType, int serial) {
for (ResourceContextList::const_iterator i = _contexts.begin(); i != _contexts.end(); ++i) {
ResourceContext * context = *i;
if ((context->fileType() & fileType) && (context->serial() == serial)) {
return context;
}
}
return NULL;
}
} // End of namespace Saga

View File

@ -62,53 +62,111 @@ struct ResourceData {
size_t size;
PatchData *patchData;
bool isExternal() { return ((offset & (1L<<31)) != 0L); } // SAGA2
ResourceData() :
id(0), offset(0), size(0), patchData(NULL) {
}
~ResourceData() {
if (patchData) {
delete patchData;
patchData = NULL;
}
}
bool isExternal() { // SAGA2
return ((offset & (1L<<31)) != 0L);
}
};
struct ResourceContext {
const char *fileName;
uint16 fileType;
Common::File *file;
int32 fileSize;
int serial; // IHNM speech files
class ResourceDataArray : public Common::Array<ResourceData> {
};
bool isCompressed;
bool isBigEndian;
ResourceData *table;
size_t count;
ResourceData *categories; // SAGA2
class ResourceContext {
friend class Resource;
protected:
const char *_fileName;
uint16 _fileType;
bool _isCompressed;
int _serial; // IHNM speech files
Common::File *getFile(ResourceData *resourceData) const {
if (resourceData->patchData != NULL) {
if (!resourceData->patchData->_patchFile->isOpen())
resourceData->patchData->_patchFile->open(resourceData->patchData->_patchDescription->fileName);
return resourceData->patchData->_patchFile;
bool _isBigEndian;
ResourceDataArray _table;
Common::File _file;
int32 _fileSize;
bool load(SagaEngine *_vm, Resource *resource);
bool loadResV1(uint32 contextOffset, uint32 contextSize);
virtual bool loadMac() = 0;
virtual bool loadRes(uint32 contextOffset, uint32 contextSize) = 0;
public:
ResourceContext():
_fileName(NULL), _fileType(0), _isCompressed(false), _serial(0),
_isBigEndian(false),
_fileSize(0) {
}
bool isCompressed() const {
return _isCompressed;
}
uint16 fileType() const {
return _fileType;
}
int serial() const {
return _serial;
}
bool isBigEndian() const {
return _isBigEndian;
}
const char * fileName() const {
return _fileName;
}
Common::File *getFile(ResourceData *resourceData) {
Common::File *file;
const char * fn;
if (resourceData && resourceData->patchData != NULL) {
file = resourceData->patchData->_patchFile;
fn = resourceData->patchData->_patchDescription->fileName;
} else {
return file;
file = &_file;
fn = _fileName;
}
if (!file->isOpen())
file->open(fn);
return file;
}
bool validResourceId(uint32 resourceId) const {
return (resourceId < count);
return (resourceId < _table.size());
}
ResourceData *getResourceData(uint32 resourceId) const {
if (resourceId >= count) {
ResourceData *getResourceData(uint32 resourceId) {
if (resourceId >= _table.size()) {
error("ResourceContext::getResourceData() wrong resourceId %d", resourceId);
}
return &table[resourceId];
return &_table[resourceId];
}
// SAGA 2
int32 getEntryNum(uint32 id) {
for (int32 i = 0; i < (int32)count; i++) {
if (table[i].id == id) {
return i;
int32 num = 0;
for (ResourceDataArray::const_iterator i = _table.begin(); i != _table.end(); ++i) {
if (i->id == id) {
return num;
}
num++;
}
return -1;
}
};
class ResourceContextList : public Common::List<ResourceContext*> {
};
struct MetaResource {
@ -145,32 +203,29 @@ public:
virtual uint32 convertResourceId(uint32 resourceId) = 0;
virtual void loadGlobalResources(int chapter, int actorsEntrance) = 0;
ResourceContext *getContext(uint16 fileType, int serial = 0) {
for (int i = 0; i < _contextsCount; i++) {
if ((_contexts[i].fileType & fileType) && _contexts[i].serial == serial) {
return &_contexts[i];
}
}
return NULL;
}
ResourceContext *getContext(uint16 fileType, int serial = 0);
protected:
SagaEngine *_vm;
ResourceContext *_contexts;
int _contextsCount;
ResourceContextList _contexts;
char _voicesFileName[8][256];
char _musicFileName[256];
char _soundFileName[256];
bool loadContext(ResourceContext *context);
virtual bool loadMacContext(ResourceContext *context) = 0;
virtual bool loadResContext(ResourceContext *context, uint32 contextOffset, uint32 contextSize) = 0;
bool loadResContext_v1(ResourceContext *context, uint32 contextOffset, uint32 contextSize);
void addContext(const char *fileName, uint16 fileType, bool isCompressed = false, int serial = 0);
virtual ResourceContext *createContext() = 0;
public:
virtual MetaResource* getMetaResource() = 0;
};
// ITE
class ResourceContext_RSC: public ResourceContext {
protected:
virtual bool loadMac();
virtual bool loadRes(uint32 contextOffset, uint32 contextSize) {
return loadResV1(contextOffset, contextSize);
}
};
class Resource_RSC : public Resource {
public:
Resource_RSC(SagaEngine *vm) : Resource(vm) {}
@ -180,32 +235,70 @@ public:
MetaResource *dummy = 0;
return dummy;
}
private:
virtual bool loadMacContext(ResourceContext *context);
virtual bool loadResContext(ResourceContext *context, uint32 contextOffset, uint32 contextSize) {
return loadResContext_v1(context, contextOffset, contextSize);
protected:
virtual ResourceContext *createContext() {
return new ResourceContext_RSC();
}
};
#ifdef ENABLE_IHNM
// IHNM
class ResourceContext_RES: public ResourceContext {
protected:
virtual bool loadMac() {
return false;
}
virtual bool loadRes(uint32 contextOffset, uint32 contextSize) {
return loadResV1(0, contextSize);
}
};
//TODO: move load routines from sndres
class VoiceResourceContext_RES: public ResourceContext {
protected:
virtual bool loadMac() {
return false;
}
virtual bool loadRes(uint32 contextOffset, uint32 contextSize) {
return false;
}
public:
VoiceResourceContext_RES() : ResourceContext() {
_fileType = GAME_VOICEFILE;
_isBigEndian = true;
}
};
class Resource_RES : public Resource {
public:
Resource_RES(SagaEngine *vm) : Resource(vm) {}
virtual uint32 convertResourceId(uint32 resourceId) { return resourceId; }
virtual void loadGlobalResources(int chapter, int actorsEntrance);
virtual MetaResource* getMetaResource() { return &_metaResource; };
private:
virtual bool loadMacContext(ResourceContext *context) { return false; }
virtual bool loadResContext(ResourceContext *context, uint32 contextOffset, uint32 contextSize) {
return loadResContext_v1(context, 0, contextSize);
protected:
virtual ResourceContext *createContext() {
return new ResourceContext_RES();
}
private:
MetaResource _metaResource;
};
#endif
#ifdef ENABLE_SAGA2
// DINO, FTA2
class ResourceContext_HRS: public ResourceContext {
protected:
ResourceDataArray _categories;
virtual bool loadMac() {
return false;
}
virtual bool loadRes(uint32 contextOffset, uint32 contextSize) {
return loadResV2(contextSize);
}
bool loadResV2(uint32 contextSize);
};
class Resource_HRS : public Resource {
public:
Resource_HRS(SagaEngine *vm) : Resource(vm) {}
@ -215,12 +308,10 @@ public:
MetaResource *dummy = 0;
return dummy;
}
private:
virtual bool loadMacContext(ResourceContext *context) { return false; }
virtual bool loadResContext(ResourceContext *context, uint32 contextOffset, uint32 contextSize) {
return loadResContext_v2(context, contextSize);
protected:
virtual ResourceContext *createContext() {
return new ResourceContext_HRS();
}
bool loadResContext_v2(ResourceContext *context, uint32 contextSize);
};
#endif

View File

@ -42,64 +42,54 @@
namespace Saga {
void readElement(Common::File *file, Saga::ResourceData *element) {
element->id = file->readUint32BE();
element->offset = file->readUint32LE();
element->size = file->readUint32LE();
debug(3, "Entry: id %u, offset %u, size %u", element->id, (uint)element->offset, (uint)element->size);
void readElement(Common::File &file, Saga::ResourceData &element) {
element.id = file.readUint32BE();
element.offset = file.readUint32LE();
element.size = file.readUint32LE();
debug(3, "Entry: id %u, offset %u, size %u", element.id, (uint)element.offset, (uint)element.size);
}
bool Resource_HRS::loadResContext_v2(ResourceContext *context, uint32 contextSize) {
ResourceData *origin = new ResourceData();
bool ResourceContext_HRS::loadResV2(uint32 contextSize) {
ResourceData origin;
uint32 firstEntryOffset;
uint32 tableSize;
int i, count;
const uint32 resourceSize = 4 + 4 + 4; // id, size, offset
debug(3, "Context %s =====", context->fileName);
context->file->seek(0, SEEK_SET);
debug(3, "Context %s =====", _fileName);
_file.seek(0, SEEK_SET);
readElement(context->file, origin);
readElement(_file, origin);
// Check if the file is valid
if (origin->id != MKID_BE('HRES')) { // header
delete origin;
if (origin.id != MKID_BE('HRES')) { // header
return false;
}
// Read offset of first entry
context->file->seek(origin->offset - sizeof(uint32), SEEK_SET);
firstEntryOffset = context->file->readUint32LE();
_file.seek(origin.offset - sizeof(uint32), SEEK_SET);
firstEntryOffset = _file.readUint32LE();
// Allocate buffers for table, categories and data
context->categories = (ResourceData *) calloc(origin->size / resourceSize, sizeof(*context->categories));
tableSize = origin->offset - firstEntryOffset - sizeof(uint32);
context->table = (ResourceData *) calloc(tableSize / resourceSize, sizeof(*context->table));
if (context->categories == NULL || context->table == NULL) {
delete origin;
return false;
}
_categories.resize(origin.size / resourceSize);
tableSize = origin.offset - firstEntryOffset - sizeof(uint32);
_table.resize(tableSize / resourceSize);
// Read categories
count = origin->size / resourceSize;
count = origin.size / resourceSize;
debug(3, "Categories: %d =====", count);
for (i = 0; i < count; i++) {
readElement(context->file, &context->categories[i]);
readElement(_file, _categories[i]);
}
context->file->seek(firstEntryOffset, SEEK_SET);
_file.seek(firstEntryOffset, SEEK_SET);
// Read table entries
count = tableSize / resourceSize;
debug(3, "Entries: %d =====", count);
for (i = 0; i < count; i++) {
readElement(context->file, &context->table[i]);
readElement(_file, _table[i]);
}
context->count = tableSize / resourceSize;
delete origin;
return true;
}

View File

@ -52,6 +52,12 @@ struct MacResource {
byte attr;
int32 dataOffset;
byte name[255];
MacResource() : id(0), nameOffset(0), attr(0), dataOffset(0) {
name[0] = 0;
}
};
class MacResourceArray : public Common::Array<MacResource> {
};
struct MacResType {
@ -59,11 +65,135 @@ struct MacResType {
int16 items;
int16 maxItemId;
int16 offset;
MacResource *resources;
MacResourceArray resources;
MacResType() : id(0), items(0), maxItemId(0), offset(0) {
}
};
class MacResTypeArray : public Common::Array<MacResType> {
};
#define ID_MIDI MKID_BE('Midi')
bool ResourceContext_RSC::loadMac() {
int32 macDataSize, macDataSizePad;
int32 macResSize, macResSizePad;
int32 macResOffset;
uint32 macMapLength;
uint32 macDataLength;
uint32 macMapOffset;
uint32 macDataOffset;
MacResMap macResMap;
MacResTypeArray macResTypes;
byte macNameLen;
bool notSagaContext = false;
if (_fileSize < RSC_MIN_FILESIZE + MAC_BINARY_HEADER_SIZE) {
return false;
}
if (_file.readByte() != 0) {
return false;
}
_file.readByte(); //MAX Name Len
_file.seek(74);
if (_file.readByte() != 0) {
return false;
}
_file.seek(82);
if (_file.readByte() != 0) {
return false;
}
macDataSize = _file.readSint32BE();
macResSize = _file.readSint32BE();
macDataSizePad = (((macDataSize + 127) >> 7) << 7);
macResSizePad = (((macResSize + 127) >> 7) << 7);
macResOffset = MAC_BINARY_HEADER_SIZE + macDataSizePad;
_file.seek(macResOffset);
macDataOffset = _file.readUint32BE() + macResOffset;
macMapOffset = _file.readUint32BE() + macResOffset;
macDataLength = _file.readUint32BE();
macMapLength = _file.readUint32BE();
if (macDataOffset >= (uint)_fileSize || macMapOffset >= (uint)_fileSize ||
macDataLength + macMapLength > (uint)_fileSize) {
return false;
}
_file.seek(macMapOffset + 22);
macResMap.resAttr = _file.readUint16BE();
macResMap.typeOffset = _file.readUint16BE();
macResMap.nameOffset = _file.readUint16BE();
macResMap.numTypes = _file.readUint16BE();
macResMap.numTypes++;
_file.seek(macMapOffset + macResMap.typeOffset + 2);
macResTypes.resize(macResMap.numTypes);
for (MacResTypeArray::iterator k = macResTypes.begin(); k != macResTypes.end(); ++k) {
k->id = _file.readUint32BE();
k->items = _file.readUint16BE();
k->offset = _file.readUint16BE();
k->items++;
k->resources.resize(k->items);
}
for (MacResTypeArray::iterator k = macResTypes.begin(); k != macResTypes.end(); ++k) {
_file.seek(k->offset + macMapOffset + macResMap.typeOffset);
for (MacResourceArray::iterator j = k->resources.begin(); j != k->resources.end(); ++j) {
j->id = _file.readUint16BE();
j->nameOffset = _file.readUint16BE();
j->dataOffset = _file.readUint32BE();
macResSize = _file.readUint32BE();
j->attr = j->dataOffset >> 24;
j->dataOffset &= 0xFFFFFF;
if (j->id > k->maxItemId) {
k->maxItemId = j->id;
}
}
for (MacResourceArray::iterator j = k->resources.begin(); j != k->resources.end(); ++j) {
if (j->nameOffset != -1) {
_file.seek(j->nameOffset + macMapOffset + macResMap.nameOffset);
macNameLen = _file.readByte();
_file.read(j->name, macNameLen);
}
}
}
//
for (MacResTypeArray::iterator k = macResTypes.begin(); k != macResTypes.end(); ++k) {
//getting offsets & sizes of midi
if (((_fileType & GAME_MUSICFILE_GM) > 0) && (k->id == ID_MIDI)) {
_table.resize(k->maxItemId + 1);
for (MacResourceArray::iterator j = k->resources.begin(); j != k->resources.end(); ++j) {
_file.seek(macDataOffset + j->dataOffset);
_table[j->id].size = _file.readUint32BE();
_table[j->id].offset = _file.pos();
}
notSagaContext = true;
break;
}
}
if ((!notSagaContext) && (!loadRes(MAC_BINARY_HEADER_SIZE, macDataSize))) {
return false;
}
return true;
}
uint32 Resource_RSC::convertResourceId(uint32 resourceId) {
if (_vm->isMacResources()) {
@ -79,134 +209,4 @@ uint32 Resource_RSC::convertResourceId(uint32 resourceId) {
return resourceId;
}
bool Resource_RSC::loadMacContext(ResourceContext *context) {
int32 macDataSize, macDataSizePad;
int32 macResSize, macResSizePad;
int32 macResOffset;
uint32 macMapLength;
uint32 macDataLength;
uint32 macMapOffset;
uint32 macDataOffset;
MacResMap macResMap;
MacResType *macResTypes;
MacResType *macResType;
MacResource *macResource;
int i, j;
byte macNameLen;
bool notSagaContext = false;
if (context->fileSize < RSC_MIN_FILESIZE + MAC_BINARY_HEADER_SIZE) {
return false;
}
if (context->file->readByte() != 0) {
return false;
}
context->file->readByte(); //MAX Name Len
context->file->seek(74);
if (context->file->readByte() != 0) {
return false;
}
context->file->seek(82);
if (context->file->readByte() != 0) {
return false;
}
macDataSize = context->file->readSint32BE();
macResSize = context->file->readSint32BE();
macDataSizePad = (((macDataSize + 127) >> 7) << 7);
macResSizePad = (((macResSize + 127) >> 7) << 7);
macResOffset = MAC_BINARY_HEADER_SIZE + macDataSizePad;
context->file->seek(macResOffset);
macDataOffset = context->file->readUint32BE() + macResOffset;
macMapOffset = context->file->readUint32BE() + macResOffset;
macDataLength = context->file->readUint32BE();
macMapLength = context->file->readUint32BE();
if (macDataOffset >= (uint)context->fileSize || macMapOffset >= (uint)context->fileSize ||
macDataLength + macMapLength > (uint)context->fileSize) {
return false;
}
context->file->seek(macMapOffset + 22);
macResMap.resAttr = context->file->readUint16BE();
macResMap.typeOffset = context->file->readUint16BE();
macResMap.nameOffset = context->file->readUint16BE();
macResMap.numTypes = context->file->readUint16BE();
macResMap.numTypes++;
context->file->seek(macMapOffset + macResMap.typeOffset + 2);
macResTypes = (MacResType *)calloc(macResMap.numTypes, sizeof(*macResTypes));
for (i = macResMap.numTypes, macResType = macResTypes; i > 0; i--, macResType++) {
macResType->id = context->file->readUint32BE();
macResType->items = context->file->readUint16BE();
macResType->offset = context->file->readUint16BE();
macResType->items++;
macResType->resources = (MacResource*)calloc(macResType->items, sizeof(*macResType->resources));
}
for (i = macResMap.numTypes, macResType = macResTypes; i > 0; i--, macResType++) {
context->file->seek(macResType->offset + macMapOffset + macResMap.typeOffset);
for (j = macResType->items, macResource = macResType->resources; j > 0; j--, macResource++) {
macResource->id = context->file->readUint16BE();
macResource->nameOffset = context->file->readUint16BE();
macResource->dataOffset = context->file->readUint32BE();
macResSize = context->file->readUint32BE();
macResource->attr = macResource->dataOffset >> 24;
macResource->dataOffset &= 0xFFFFFF;
if (macResource->id > macResType->maxItemId) {
macResType->maxItemId = macResource->id;
}
}
for (j = macResType->items, macResource = macResType->resources; j > 0; j--, macResource++) {
if (macResource->nameOffset != -1) {
context->file->seek(macResource->nameOffset + macMapOffset + macResMap.nameOffset);
macNameLen = context->file->readByte();
context->file->read(macResource->name, macNameLen);
}
}
}
//
for (i = macResMap.numTypes, macResType = macResTypes; i > 0; i--, macResType++) {
//getting offsets & sizes of midi
if (((context->fileType & GAME_MUSICFILE_GM) > 0) && (macResType->id == ID_MIDI)) {
context->count = macResType->maxItemId + 1;
context->table = (ResourceData *)calloc(context->count, sizeof(*context->table));
for (j = macResType->items, macResource = macResType->resources; j > 0; j--, macResource++) {
context->file->seek(macDataOffset + macResource->dataOffset);
context->table[macResource->id].size = context->file->readUint32BE();
context->table[macResource->id].offset = context->file->pos();
}
notSagaContext = true;
break;
}
}
//free
for (i = 0; i < macResMap.numTypes; i++) {
free(macResTypes[i].resources);
}
free(macResTypes);
if ((!notSagaContext) && (!loadResContext(context, MAC_BINARY_HEADER_SIZE, macDataSize))) {
return false;
}
return true;
}
} // End of namespace Saga

View File

@ -79,7 +79,7 @@ class PalAnim;
class Puzzle;
class Resource;
struct ResourceContext;
class ResourceContext;
struct StringList;
using Common::MemoryReadStream;

View File

@ -168,7 +168,7 @@ Scene::Scene(SagaEngine *vm) : _vm(vm) {
memoryError("Scene::Scene()");
}
MemoryReadStreamEndian readS(sceneLUTPointer, sceneLUTLength, _sceneContext->isBigEndian);
MemoryReadStreamEndian readS(sceneLUTPointer, sceneLUTLength, _sceneContext->isBigEndian());
for (i = 0; i < _sceneCount; i++) {
_sceneLUT[i] = readS.readUint16();
@ -929,7 +929,7 @@ void Scene::loadSceneDescriptor(uint32 resourceId) {
_vm->_resource->loadResource(_sceneContext, resourceId, sceneDescriptorData, sceneDescriptorDataLength);
if (sceneDescriptorDataLength == 16) {
MemoryReadStreamEndian readS(sceneDescriptorData, sceneDescriptorDataLength, _sceneContext->isBigEndian);
MemoryReadStreamEndian readS(sceneDescriptorData, sceneDescriptorDataLength, _sceneContext->isBigEndian());
_sceneDescription.flags = readS.readSint16();
_sceneDescription.resourceListResourceId = readS.readSint16();
@ -960,7 +960,7 @@ void Scene::loadSceneResourceList(uint32 resourceId) {
_vm->_resource->loadResource(_sceneContext, resourceId, resourceListData, resourceListDataLength);
if ((resourceListDataLength % SAGA_RESLIST_ENTRY_LEN) == 0) {
MemoryReadStreamEndian readS(resourceListData, resourceListDataLength, _sceneContext->isBigEndian);
MemoryReadStreamEndian readS(resourceListData, resourceListDataLength, _sceneContext->isBigEndian());
// Allocate memory for scene resource list
_resourceListCount = resourceListDataLength / SAGA_RESLIST_ENTRY_LEN;
@ -1302,7 +1302,7 @@ void Scene::loadSceneEntryList(const byte* resourcePointer, size_t resourceLengt
_entryList.entryListCount = resourceLength / 8;
MemoryReadStreamEndian readS(resourcePointer, resourceLength, _sceneContext->isBigEndian);
MemoryReadStreamEndian readS(resourcePointer, resourceLength, _sceneContext->isBigEndian());
if (_entryList.entryList)

View File

@ -109,7 +109,7 @@ SAGA1Script::SAGA1Script(SagaEngine *vm) : Script(vm) {
}
// Convert LUT resource to logical LUT
MemoryReadStreamEndian scriptS(resourcePointer, resourceLength, resourceContext->isBigEndian);
MemoryReadStreamEndian scriptS(resourcePointer, resourceLength, resourceContext->isBigEndian());
for (i = 0; i < _modulesCount; i++) {
memset(&_modules[i], 0, sizeof(ModuleData));
@ -1127,7 +1127,7 @@ void Script::loadModuleBase(ModuleData &module, const byte *resourcePointer, siz
memcpy(module.moduleBase, resourcePointer, resourceLength);
MemoryReadStreamEndian scriptS(module.moduleBase, module.moduleBaseSize, _scriptContext->isBigEndian);
MemoryReadStreamEndian scriptS(module.moduleBase, module.moduleBaseSize, _scriptContext->isBigEndian());
module.entryPointsCount = scriptS.readUint16();
scriptS.readUint16(); //skip
@ -1177,7 +1177,7 @@ void Script::loadVoiceLUT(VoiceLUT &voiceLUT, const byte *resourcePointer, size_
error("Script::loadVoiceLUT() not enough memory");
}
MemoryReadStreamEndian scriptS(resourcePointer, resourceLength, _scriptContext->isBigEndian);
MemoryReadStreamEndian scriptS(resourcePointer, resourceLength, _scriptContext->isBigEndian());
for (i = 0; i < voiceLUT.voicesCount; i++) {
voiceLUT.voices[i] = scriptS.readUint16();

View File

@ -48,15 +48,14 @@ namespace Saga {
#define RID_IHNM_SFX_LUT 265
#define RID_IHNMDEMO_SFX_LUT 222
SndRes::SndRes(SagaEngine *vm) : _vm(vm) {
SndRes::SndRes(SagaEngine *vm) : _vm(vm), _sfxContext(NULL), _voiceContext(NULL), _voiceSerial(-1) {
// Load sound module resource file contexts
_sfxContext = _vm->_resource->getContext(GAME_SOUNDFILE);
if (_sfxContext == NULL) {
error("SndRes::SndRes resource context not found");
}
_voiceSerial = -1;
setVoiceBank(0);
if (_vm->getGameId() == GID_ITE) {
@ -117,6 +116,7 @@ SndRes::~SndRes() {
}
void SndRes::setVoiceBank(int serial) {
Common::File *file;
if (_voiceSerial == serial)
return;
@ -126,12 +126,7 @@ void SndRes::setVoiceBank(int serial) {
if (_vm->getGameId() == GID_IHNM && _vm->isMacResources()) {
_voiceSerial = serial;
// Set a dummy voice context
_voiceContext = new ResourceContext();
_voiceContext->fileType = GAME_VOICEFILE;
_voiceContext->count = 0;
_voiceContext->serial = 0;
_voiceContext->isBigEndian = true;
_voiceContext->isCompressed = false;
_voiceContext = new VoiceResourceContext_RES();
return;
}
#endif
@ -141,16 +136,16 @@ void SndRes::setVoiceBank(int serial) {
return;
// Close previous voice bank file
if (_voiceSerial >= 0 && _voiceContext->file->isOpen())
_voiceContext->file->close();
if (_voiceContext != NULL) {
file = _voiceContext->getFile(NULL);
if (file->isOpen()) {
file->close();
}
}
_voiceSerial = serial;
_voiceContext = _vm->_resource->getContext(GAME_VOICEFILE, _voiceSerial);
// Open new voice bank file
if (!_voiceContext->file->isOpen())
_voiceContext->file->open(_voiceContext->fileName);
}
void SndRes::playSound(uint32 resourceId, int volume, bool loop) {
@ -199,11 +194,12 @@ bool SndRes::load(ResourceContext *context, uint32 resourceId, SoundBuffer &buff
}
#ifdef ENABLE_IHNM
//TODO: move to resource_res so we can use normal "getResourceData" and "getFile" methods
if (_vm->getGameId() == GID_IHNM && _vm->isMacResources()) {
char soundFileName[40];
int dirIndex = resourceId / 64;
if ((context->fileType & GAME_VOICEFILE) != 0) {
if ((context->fileType() & GAME_VOICEFILE) != 0) {
if (_voiceSerial == 0) {
sprintf(soundFileName, "Voices/VoicesS/Voices%d/VoicesS%03x", dirIndex, resourceId);
} else {
@ -217,7 +213,6 @@ bool SndRes::load(ResourceContext *context, uint32 resourceId, SoundBuffer &buff
file->open(soundFileName);
soundResourceLength = file->size();
context->isBigEndian = true;
} else
#endif
{
@ -249,14 +244,14 @@ bool SndRes::load(ResourceContext *context, uint32 resourceId, SoundBuffer &buff
bool uncompressedSound = false;
// If patch data exists for sound resource 4 (used in ITE intro), don't treat this sound as compressed
// Patch data for this resource is in file p2_a.iaf or p2_a.voc
if (_vm->getGameId() == GID_ITE && resourceId == 4 && context->table[resourceId].patchData != NULL)
if (_vm->getGameId() == GID_ITE && resourceId == 4 && context->getResourceData(resourceId)->patchData != NULL)
uncompressedSound = true;
// FIXME: Currently, the SFX.RES file in IHNM cannot be compressed
if (_vm->getGameId() == GID_IHNM && (context->fileType & GAME_SOUNDFILE))
if (_vm->getGameId() == GID_IHNM && (context->fileType() & GAME_SOUNDFILE))
uncompressedSound = true;
if (context->isCompressed && !uncompressedSound) {
if (context->isCompressed() && !uncompressedSound) {
if (header[0] == char(0)) {
resourceType = kSoundMP3;
} else if (header[0] == char(1)) {
@ -269,7 +264,7 @@ bool SndRes::load(ResourceContext *context, uint32 resourceId, SoundBuffer &buff
}
// Default sound type is 16-bit signed PCM, used in ITE by PCM and VOX files
buffer.isCompressed = context->isCompressed;
buffer.isCompressed = context->isCompressed();
buffer.soundType = resourceType;
buffer.originalSize = 0;
// Set default flags and frequency for PCM, VOC and VOX files, which got no header
@ -281,20 +276,20 @@ bool SndRes::load(ResourceContext *context, uint32 resourceId, SoundBuffer &buff
buffer.flags &= ~Audio::Mixer::FLAG_16BITS;
} else {
// Voice files in newer ITE demo versions are OKI ADPCM (VOX) encoded
if (!scumm_stricmp(context->fileName, "voicesd.rsc"))
if (!scumm_stricmp(context->fileName(), "voicesd.rsc"))
resourceType = kSoundVOX;
}
}
buffer.buffer = NULL;
// Check for LE sounds
if (!context->isBigEndian)
if (!context->isBigEndian())
buffer.flags |= Audio::Mixer::FLAG_LITTLE_ENDIAN;
if ((context->fileType & GAME_VOICEFILE) && (_vm->getFeatures() & GF_LE_VOICES))
if ((context->fileType() & GAME_VOICEFILE) && (_vm->getFeatures() & GF_LE_VOICES))
buffer.flags |= Audio::Mixer::FLAG_LITTLE_ENDIAN;
// Older Mac versions of ITE were Macbinary packed
int soundOffset = (context->fileType & GAME_MACBINARY) ? 36 : 0;
int soundOffset = (context->fileType() & GAME_MACBINARY) ? 36 : 0;
switch (resourceType) {
case kSoundPCM:
@ -404,7 +399,7 @@ int SndRes::getVoiceLength(uint32 resourceId) {
return -1;
}
if (!_voiceContext->isCompressed || buffer.originalSize == 0)
if (!_voiceContext->isCompressed() || buffer.originalSize == 0)
msDouble = (double)buffer.size;
else
msDouble = (double)buffer.originalSize;

View File

@ -106,7 +106,7 @@ void Sprite::loadList(int resourceId, SpriteList &spriteList) {
return;
}
MemoryReadStreamEndian readS(spriteListData, spriteListLength, _spriteContext->isBigEndian);
MemoryReadStreamEndian readS(spriteListData, spriteListLength, _spriteContext->isBigEndian());
spriteCount = readS.readUint16();
@ -142,7 +142,7 @@ void Sprite::loadList(int resourceId, SpriteList &spriteList) {
spritePointer += offset;
if (bigHeader) {
MemoryReadStreamEndian readS2(spritePointer, 8, _spriteContext->isBigEndian);
MemoryReadStreamEndian readS2(spritePointer, 8, _spriteContext->isBigEndian());
spriteInfo->xAlign = readS2.readSint16();
spriteInfo->yAlign = readS2.readSint16();