diff options
author | Andrew Kurushin | 2005-08-04 10:23:49 +0000 |
---|---|---|
committer | Andrew Kurushin | 2005-08-04 10:23:49 +0000 |
commit | 41ff67ac1d4888ce41815d200cd7ed6cac0d104d (patch) | |
tree | de2071d49e7aca969cc2cb66eb6e23e0e1fb6eab | |
parent | 80d1ef4510e6098540d83491be5d53121f4b6005 (diff) | |
download | scummvm-rg350-41ff67ac1d4888ce41815d200cd7ed6cac0d104d.tar.gz scummvm-rg350-41ff67ac1d4888ce41815d200cd7ed6cac0d104d.tar.bz2 scummvm-rg350-41ff67ac1d4888ce41815d200cd7ed6cac0d104d.zip |
macBinary resource support
svn-id: r18609
-rw-r--r-- | saga/game.cpp | 52 | ||||
-rw-r--r-- | saga/music.cpp | 31 | ||||
-rw-r--r-- | saga/rscfile.cpp | 254 | ||||
-rw-r--r-- | saga/rscfile.h | 3 | ||||
-rw-r--r-- | saga/saga.h | 7 | ||||
-rw-r--r-- | saga/sndres.cpp | 17 |
6 files changed, 293 insertions, 71 deletions
diff --git a/saga/game.cpp b/saga/game.cpp index b68dfef01f..dc4d747ac0 100644 --- a/saga/game.cpp +++ b/saga/game.cpp @@ -330,10 +330,27 @@ static GameFileDescription ITEMACCD_G_GameFiles[] = { {"ITE Resources", GAME_RESOURCEFILE}, {"ITE Scripts", GAME_SCRIPTFILE}, {"ITE Sounds", GAME_SOUNDFILE}, - //{"ITE Music", GAME_MUSICFILE}, + {"ITE Music", GAME_MUSICFILE_GM}, {"ITE Voices", GAME_VOICEFILE} }; +static GameFileDescription ITEMACCD2_G_GameFiles[] = { + {"ITE Resources.bin", GAME_RESOURCEFILE | GAME_MACBINARY}, + {"ITE Scripts.bin", GAME_SCRIPTFILE | GAME_MACBINARY}, + {"ITE Sounds.bin", GAME_SOUNDFILE | GAME_MACBINARY}, + {"ITE Music.bin", GAME_MUSICFILE_GM | GAME_MACBINARY}, + {"ITE Voices.bin", GAME_VOICEFILE | GAME_MACBINARY} +}; + +static GameSoundInfo ITEMACCD_G_GameSound = { + kSoundMacPCM, + 22050, + 8, + false, + false, + false +}; + // Inherit the Earth - Mac Wyrmkeep version static GameFileDescription ITEMACCD_GameFiles[] = { {"ite.rsc", GAME_RESOURCEFILE}, @@ -700,6 +717,12 @@ static GameMD5 gameMD5[] = { { GID_ITE_MACCD_G, "8ee4d9ee27688785608d09faaa4a974c", "ITE Sounds", true }, { GID_ITE_MACCD_G, "3a1463f0c6a41381e98c2a8c55308190", "ITE Voices", true }, + { GID_ITE_MACCD2_G, "0bd506aa887bfc7965f695c6bd28237d", "ITE Resources.bin", true }, + { GID_ITE_MACCD2_G, "af0d7a2588e09ad3ecbc5b474ea238bf", "ITE Scripts.bin", true }, + { GID_ITE_MACCD2_G, "c1d20324b7cdf1650e67061b8a93251c", "ITE Music.bin", true }, + { GID_ITE_MACCD2_G, "441426c6bb2a517f65c7e49b57f7a345", "ITE Sounds.bin", true }, + { GID_ITE_MACCD2_G, "dba92ae7d57e942250fe135609708369", "ITE Voices.bin", true }, + { GID_ITE_LINCD, "8f4315a9bb10ec839253108a032c8b54", "ite.rsc", false }, { GID_ITE_LINCD, "a891405405edefc69c9d6c420c868b84", "scripts.rsc", false }, { GID_ITE_LINCD, "e2ccb61c325d6d1ead3be0e731fe29fe", "sounds.rsc", false }, @@ -856,9 +879,30 @@ static GameDescription gameDescriptions[] = { ITEMACCD_G_GameFiles, ARRAYSIZE(ITEWINDEMO_GameFonts), ITEWINDEMO_GameFonts, - &ITEMACDEMO_GameVoice, - &ITEMACDEMO_GameSound, - &ITEMACCD_GameMusic, + &ITEMACCD_G_GameSound, + &ITEMACCD_G_GameSound, + NULL, + NULL, + 0, + GF_BIG_ENDIAN_DATA | GF_MAC_RESOURCES | GF_CD_FX + }, + + // Inherit the earth - MAC CD Guild version + { + "ite", + GType_ITE, + GID_ITE_MACCD2_G, + "Inherit the Earth (MAC CD)", + &ITE_DisplayInfo, + ITE_DEFAULT_SCENE, + &ITE_Resources, + ARRAYSIZE(ITEMACCD2_G_GameFiles), + ITEMACCD2_G_GameFiles, + ARRAYSIZE(ITEWINDEMO_GameFonts), + ITEWINDEMO_GameFonts, + &ITEMACCD_G_GameSound, + &ITEMACCD_G_GameSound, + NULL, NULL, 0, GF_BIG_ENDIAN_DATA | GF_MAC_RESOURCES | GF_CD_FX diff --git a/saga/music.cpp b/saga/music.cpp index 4e8e3fd633..eb12c5383b 100644 --- a/saga/music.cpp +++ b/saga/music.cpp @@ -271,31 +271,9 @@ Music::Music(SagaEngine *vm, Audio::Mixer *mixer, MidiDriver *driver, int enable _currentVolume = 0; xmidiParser = MidiParser::createParser_XMIDI(); - smfParser = MidiParser::createParser_SMF(); + smfParser = MidiParser::createParser_SMF(); - if (_vm->getGameType() == GType_ITE) { - Common::File file; -// byte footerBuf[ARRAYSIZE(_digiTableITECD) * 8]; - - // The lookup table is stored at the end of music.rsc. I don't - // know why it has 27 elements, but the last one represents a - // very short tune. Perhaps it's a dummy? - // - // FIXME: Well, it's a hack which I don't like. Logically it should - // call LoadResource() et al, but I don't want to load those - // huge files into memory. So I use FileContext just for getting file - // name and reuse its opened file a bit. - // - // Proper approach would be to extend resource manager so it could - // return File object. - - _musicContext = _vm->_resource->getContext(GAME_MUSICFILE); - if (_musicContext != NULL) { - // The "birdchrp" is just a short, high-pitched - // whining. Use the MIDI/XMIDI version instead. - ///_digiTableITECD[6].length = 0; - } - } + _musicContext = _vm->_resource->getContext(GAME_MUSICFILE); } Music::~Music() { @@ -406,7 +384,10 @@ void Music::play(uint32 resourceId, MusicFlags flags) { // Load MIDI/XMI resource data if (_vm->getGameType() == GType_ITE) { - context = _vm->_resource->getContext(GAME_RESOURCEFILE); + context = _vm->_resource->getContext(GAME_MUSICFILE_GM); + if (context == NULL) { + context = _vm->_resource->getContext(GAME_RESOURCEFILE); + } } else { // I've listened to music from both the FM and the GM // file, and I've tentatively reached the conclusion diff --git a/saga/rscfile.cpp b/saga/rscfile.cpp index 3f933b99dd..5adb56c979 100644 --- a/saga/rscfile.cpp +++ b/saga/rscfile.cpp @@ -29,6 +29,32 @@ namespace Saga { +struct MacResMap { + int16 resAttr; + int16 typeOffset; + int16 nameOffset; + int16 numTypes; +}; + +struct MacResource { + int16 id; + int16 nameOffset; + byte attr; + int32 dataOffset; + byte name[255]; +}; + +struct MacResType { + uint32 id; + int16 items; + int16 maxItemId; + int16 offset; + MacResource *resources; +}; + + +#define ID_MIDI MKID_BE('Midi') + Resource::Resource(SagaEngine *vm): _vm(vm) { _contexts = NULL; _contextsCount = 0; @@ -38,34 +64,20 @@ Resource::~Resource() { clearContexts(); } -bool Resource::loadContext(ResourceContext *context) { +bool Resource::loadSagaContext(ResourceContext *context, uint32 contextOffset, uint32 contextSize) { size_t i; - int j; bool result; byte tableInfo[RSC_TABLEINFO_SIZE]; - uint32 resourceTableOffset; - GamePatchDescription *patchDescription; - ResourceData *resourceData; byte *tableBuffer; size_t tableSize; - uint16 subjectResourceType; - ResourceContext *subjectContext; - uint32 subjectResourceId; - uint32 patchResourceId; - ResourceData *subjectResourceData; - - if (!context->file->open(context->fileName)) { - return false; - } - - context->isBigEndian = _vm->isBigEndian(); + uint32 resourceTableOffset; + ResourceData *resourceData; - if (context->file->size() < RSC_MIN_FILESIZE) { + if (contextSize < RSC_MIN_FILESIZE) { return false; } - // Read resource table info from the rear end of file - context->file->seek((long)(-RSC_TABLEINFO_SIZE), SEEK_END); + context->file->seek(contextOffset + contextSize - RSC_TABLEINFO_SIZE); if (context->file->read(tableInfo, RSC_TABLEINFO_SIZE) != RSC_TABLEINFO_SIZE) { return false; @@ -77,7 +89,7 @@ bool Resource::loadContext(ResourceContext *context) { context->count = readS.readUint32(); // Check for sane table offset - if (resourceTableOffset != context->file->size() - RSC_TABLEINFO_SIZE - RSC_TABLEENTRY_SIZE * context->count) { + if (resourceTableOffset != contextSize - RSC_TABLEINFO_SIZE - RSC_TABLEENTRY_SIZE * context->count) { return false; } @@ -86,7 +98,7 @@ bool Resource::loadContext(ResourceContext *context) { tableBuffer = (byte *)malloc(tableSize); - context->file->seek((long)resourceTableOffset, SEEK_SET); + context->file->seek(resourceTableOffset + contextOffset, SEEK_SET); result = (context->file->read(tableBuffer, tableSize) == tableSize); if (result) { @@ -96,10 +108,10 @@ bool Resource::loadContext(ResourceContext *context) { for (i = 0; i < context->count; i++) { resourceData = &context->table[i]; - resourceData->offset = readS1.readUint32(); + resourceData->offset = contextOffset + readS1.readUint32(); resourceData->size = readS1.readUint32(); //sanity check - if ((resourceData->offset > context->file->size()) || (resourceData->size > context->file->size())) { + if ((resourceData->offset > context->file->size()) || (resourceData->size > contextSize)) { result = false; break; } @@ -107,11 +119,176 @@ bool Resource::loadContext(ResourceContext *context) { } free(tableBuffer); + return result; +} + +bool Resource::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->file->size() < 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 >= context->file->size() || macMapOffset >= context->file->size() || + macDataLength + macMapLength > context->file->size()) { + 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) && (!loadSagaContext(context, MAC_BINARY_HEADER_SIZE, macDataSize))) { + return false; + } + + return true; +} + +bool Resource::loadContext(ResourceContext *context) { + size_t i; + int j; + GamePatchDescription *patchDescription; + ResourceData *resourceData; + uint16 subjectResourceType; + ResourceContext *subjectContext; + uint32 subjectResourceId; + uint32 patchResourceId; + ResourceData *subjectResourceData; + byte *tableBuffer; + size_t tableSize; + bool isMacBinary; + + if (!context->file->open(context->fileName)) { + return false; + } + + context->isBigEndian = _vm->isBigEndian(); + + isMacBinary = (context->fileType & GAME_MACBINARY) > 0; + context->fileType &= ~GAME_MACBINARY; + + if (isMacBinary) { + if (!loadMacContext(context)) { + return false; + } + } else { + if (!loadSagaContext(context, 0, context->file->size())) { + return false; + } + } + //process internal patch files if (GAME_PATCHFILE & context->fileType) { subjectResourceType = ~GAME_PATCHFILE & context->fileType; - subjectContext = getContext(subjectResourceType); + subjectContext = getContext((GameFileTypes)subjectResourceType); if (subjectContext == NULL) { error("Resource::loadContext() Subject context not found"); } @@ -131,26 +308,25 @@ bool Resource::loadContext(ResourceContext *context) { } //process external patch files - if (result) { - for (j = 0; j < _vm->getGameDescription()->patchsCount; j++) { - patchDescription = &_vm->getGameDescription()->patchDescriptions[j]; - if ((patchDescription->fileType & context->fileType) != 0) { - if (patchDescription->resourceId < context->count) { - resourceData = &context->table[patchDescription->resourceId]; - resourceData->patchData = new PatchData(patchDescription); - if (resourceData->patchData->_patchFile->open(patchDescription->fileName)) { - resourceData->offset = 0; - resourceData->size = resourceData->patchData->_patchFile->size(); - } else { - delete resourceData->patchData; - resourceData->patchData = NULL; - } + for (j = 0; j < _vm->getGameDescription()->patchsCount; j++) { + patchDescription = &_vm->getGameDescription()->patchDescriptions[j]; + if ((patchDescription->fileType & context->fileType) != 0) { + if (patchDescription->resourceId < context->count) { + resourceData = &context->table[patchDescription->resourceId]; + resourceData->patchData = new PatchData(patchDescription); + if (resourceData->patchData->_patchFile->open(patchDescription->fileName)) { + resourceData->offset = 0; + resourceData->size = resourceData->patchData->_patchFile->size(); + } else { + delete resourceData->patchData; + resourceData->patchData = NULL; } } } } + - return result; + return true; } bool Resource::createContexts() { diff --git a/saga/rscfile.h b/saga/rscfile.h index f416ff699d..a1d385aa5d 100644 --- a/saga/rscfile.h +++ b/saga/rscfile.h @@ -31,6 +31,7 @@ namespace Saga { +#define MAC_BINARY_HEADER_SIZE 128 #define RSC_TABLEINFO_SIZE 8 #define RSC_TABLEENTRY_SIZE 8 @@ -133,6 +134,8 @@ private: int _contextsCount; bool loadContext(ResourceContext *context); + bool loadMacContext(ResourceContext *context); + bool loadSagaContext(ResourceContext *context, uint32 contextOffset, uint32 contextSize); }; diff --git a/saga/saga.h b/saga/saga.h index fc9989aaf9..1f6c3a7e14 100644 --- a/saga/saga.h +++ b/saga/saga.h @@ -253,6 +253,7 @@ enum GameIds { GID_ITE_DISK_G, GID_ITE_CD_G, GID_ITE_MACCD_G, + GID_ITE_MACCD2_G, // Wyrmkeep GID_ITE_CD, // data for Win rerelease is same as in old DOS @@ -289,14 +290,16 @@ enum GameFileTypes { GAME_MUSICFILE = 1 << 5, GAME_MUSICFILE_GM = 1 << 6, GAME_MUSICFILE_FM = 1 << 7, - GAME_PATCHFILE = 1 << 8 + GAME_PATCHFILE = 1 << 8, + GAME_MACBINARY = 1 << 9 }; enum GameSoundTypes { kSoundPCM = 0, kSoundVOX = 1, kSoundVOC = 2, - kSoundWAV = 3 + kSoundWAV = 3, + kSoundMacPCM = 4, }; enum GameFeatures { diff --git a/saga/sndres.cpp b/saga/sndres.cpp index da79280b47..f93c595d90 100644 --- a/saga/sndres.cpp +++ b/saga/sndres.cpp @@ -125,7 +125,7 @@ bool SndRes::load(ResourceContext *context, uint32 resourceId, SoundBuffer &buff buffer.isBigEndian = soundInfo->isBigEndian; if (soundResourceLength >= 8) { - if (!memcmp(&soundResource, "Creative", 8)) { + if (!memcmp(soundResource, "Creative", 8)) { resourceType = kSoundVOC; } else if (!memcmp(soundResource, "RIFF", 4) != 0) { resourceType = kSoundWAV; @@ -148,6 +148,21 @@ bool SndRes::load(ResourceContext *context, uint32 resourceId, SoundBuffer &buff } result = true; break; + case kSoundMacPCM: + buffer.frequency = soundInfo->frequency; + buffer.isSigned = soundInfo->isSigned; + buffer.sampleBits = soundInfo->sampleBits; + buffer.size = soundResourceLength - 36; + buffer.stereo = soundInfo->stereo; + if (onlyHeader) { + buffer.buffer = NULL; + } else { + buffer.buffer = (byte *)malloc(buffer.size); + memcpy(buffer.buffer, soundResource + 36, buffer.size); + } + free(soundResource); + result = true; + break; case kSoundVOX: buffer.frequency = soundInfo->frequency; buffer.isSigned = soundInfo->isSigned; |