From 126f55fd0ec2cea7e8a397c4ba810d4c562ce3ae Mon Sep 17 00:00:00 2001 From: Gregory Montoir Date: Fri, 7 Dec 2007 20:45:51 +0000 Subject: backported some changes for OS - added parsing of VOL.CNF to get the (filename,bundle) mapping (should be more efficient than testing every bundle file) - delphineUnpack allows "inplace unpacking", use this instead of allocating temporary buffers - relation script run count should be set in _localVars[0] - added comments for some "special" script variables svn-id: r29749 --- engines/cine/cine.cpp | 6 + engines/cine/cine.h | 17 ++- engines/cine/main_loop.cpp | 4 + engines/cine/part.cpp | 350 ++++++++++++++------------------------------- engines/cine/rel.cpp | 1 + engines/cine/rel.h | 1 + engines/cine/various.cpp | 5 + 7 files changed, 140 insertions(+), 244 deletions(-) diff --git a/engines/cine/cine.cpp b/engines/cine/cine.cpp index 7a8dfac60f..60f3efa1ae 100644 --- a/engines/cine/cine.cpp +++ b/engines/cine/cine.cpp @@ -52,6 +52,7 @@ CineEngine *g_cine; CineEngine::CineEngine(OSystem *syst, const CINEGameDescription *gameDesc) : Engine(syst), _gameDescription(gameDesc) { Common::addSpecialDebugLevel(kCineDebugScript, "Script", "Script debug level"); + Common::addSpecialDebugLevel(kCineDebugPart, "Part", "Part debug level"); // Setup mixer if (!_mixer->isReady()) { @@ -117,6 +118,10 @@ void CineEngine::initialize() { animDataTable = (AnimData *)malloc(NUM_MAX_ANIMDATA * sizeof(AnimData)); + if (g_cine->getGameType() == Cine::GType_OS && g_cine->getPlatform() == Common::kPlatformPC) { + readVolCnf(); + } + loadTextData("texte.dat", textDataPtr); if (g_cine->getGameType() == Cine::GType_OS && !(g_cine->getFeatures() & GF_DEMO)) { @@ -149,6 +154,7 @@ void CineEngine::initialize() { relTable[i].obj1Param1 = 0; relTable[i].obj1Param2 = 0; relTable[i].obj2Param = 0; + relTable[i].runCount = 0; } for (i = 0; i < NUM_MAX_ANIMDATA; i++) { diff --git a/engines/cine/cine.h b/engines/cine/cine.h index b225f9490a..8d9fdb6f8e 100644 --- a/engines/cine/cine.h +++ b/engines/cine/cine.h @@ -30,6 +30,9 @@ #include "common/scummsys.h" #include "common/file.h" #include "common/util.h" +#include "common/str.h" +#include "common/hashmap.h" +#include "common/hash-str.h" #include "engines/engine.h" @@ -61,6 +64,8 @@ enum CineGameFeatures { struct CINEGameDescription; +typedef Common::HashMap StringPtrHashMap; + class CineEngine : public Engine { protected: @@ -87,10 +92,14 @@ public: Common::RandomSource _rnd; + Common::StringList _volumeResourceFiles; + StringPtrHashMap _volumeEntriesMap; + private: void initialize(void); bool makeLoad(char *saveName); void mainLoop(int bootScriptIdx); + void readVolCnf(); bool _preLoad; }; @@ -103,7 +112,10 @@ enum { VAR_MOUSE_X_MODE = 253, VAR_MOUSE_X_POS = 249, VAR_MOUSE_Y_MODE = 251, - VAR_MOUSE_Y_POS = 250 + VAR_MOUSE_Y_POS = 250, + // OS only + VAR_BYPASS_PROTECTION = 255, + VAR_LOW_MEMORY = 0 }; enum { @@ -113,7 +125,8 @@ enum { }; enum { - kCineDebugScript = 1 << 0 + kCineDebugScript = 1 << 0, + kCineDebugPart = 1 << 1 }; enum { diff --git a/engines/cine/main_loop.cpp b/engines/cine/main_loop.cpp index 1f1622253e..04334e8b98 100644 --- a/engines/cine/main_loop.cpp +++ b/engines/cine/main_loop.cpp @@ -230,6 +230,10 @@ void CineEngine::mainLoop(int bootScriptIdx) { globalVars[VAR_MOUSE_X_POS] = 0; globalVars[VAR_MOUSE_Y_POS] = 0; + if (g_cine->getGameType() == Cine::GType_OS) { + globalVars[VAR_BYPASS_PROTECTION] = 0; // set to 1 to bypass the copy protection + globalVars[VAR_LOW_MEMORY] = 0; // set to 1 to disable some animations, sounds etc. + } for (i = 0; i < 16; i++) { c_palette[i] = 0; diff --git a/engines/cine/part.cpp b/engines/cine/part.cpp index b862d72b53..18c3a8787e 100644 --- a/engines/cine/part.cpp +++ b/engines/cine/part.cpp @@ -23,6 +23,8 @@ * */ +#include "common/endian.h" + #include "cine/cine.h" #include "cine/unpack.h" #include "cine/various.h" @@ -71,187 +73,6 @@ void closePart(void) { // TODO } -static const char *bundleNamesDOSEN[] = { - "EGOUBASE", - "LABYBASE", - "PROCEGOU", - "PROCLABY", - "PROCS00", - "PROCS01", - "PROCS02", - "PROCS03", - "PROCS04", - "PROCS06", - "PROCS07", - "PROCS08", - "PROCS10", - "PROCS12", - "PROCS13", - "PROCS15", - "PROCS16", - "RSC00", - "RSC01", - "RSC02", - "RSC03", - "RSC04", - "RSC05", - "RSC06", - "RSC07", - "RSC08", - "RSC09", - "RSC10", - "RSC11", - "RSC12", - "RSC13", - "RSC14", - "RSC15", - "RSC16", - "RSC17", - "SONS1", - "SONS2", - "SONS3", - "SONS4", - "SONS5", - "SONS6", - "SONS7", - "SONS8", - "SONS9", - NULL -}; - -static const char *bundleNamesDOSUS[] = { - "EGOUBASE", - "LABYBASE", - "PROCEGOU", - "PROCLABY", - "PROCS00", - "PROCS01", - "PROCS02", - "PROCS03", - "PROCS04", - "PROCS06", - "PROCS07", - "PROCS08", - "PROCS12", - "PROCS13", - "PROCS15", - "PROCS16", - "RSC00", - "RSC02", - "RSC03", - "RSC04", - "RSC05", - "RSC06", - "RSC07", - "RSC08", - "RSC09", - "RSC10", - "RSC11", - "RSC12", - "RSC13", - "RSC14", - "RSC15", - "RSC16", - "RSC17", - "SONS31", - "SONS32", - "SONS33", - "SONS34", - NULL -}; - -static const char *bundleNamesDOSFR[] = { - "EGOUBASE", - "LABYBASE", - "PROCEGOU", - "PROCLABY", - "PROCS00", - "PROCS01", - "PROCS02", - "PROCS03", - "PROCS04", - "PROCS06", - "PROCS07", - "PROCS08", - "PROCS10", - "PROCS12", - "PROCS13", - "PROCS15", - "PROCS16", - "RSC00", - "RSC01", - "RSC02", - "RSC03", - "RSC04", - "RSC05", - "RSC06", - "RSC07", - "RSC08", - "RSC09", - "RSC10", - "RSC11", - "RSC12", - "RSC13", - "RSC14", - "RSC15", - "RSC16", - "RSC17", - "SONS31", - "SONS32", - "SONS33", - "SONS34", - NULL -}; - -static const char *bundleNamesDOSES[] = { - "EGOUBASE", - "LABYBASE", - "PROCS1", - "PROCS2", - "PROCS3", - "PROCS4", - "PROCS5", - "PROCS6", - "SD01A", - "SD01B", - "SD01C", - "SD01D", - "SD021", - "SD022", - "SD03", - "SDSONS", - "SDSONS2", - "SDSONS3", - "SINTRO2", - NULL -}; - -static const char *bundleNamesDOSInt[] = { - "EGOUBASE", - "LABYBASE", - "PROCS1", - "PROCS2", - "PROCS3", - "PROCS4", - "PROCS5", - "PROCS6", - "SD01A", - "SD01B", - "SD01C", - "SD01D", - "SD021", - "SD022", - "SD03", - "SDS1", - "SDS2", - "SDS3", - "SDS4", - "SDS5", - "SDS6", - "SINTRO2", - NULL -}; - static const char *bundleNamesAmiga[] = { "EGOUBASE", "LABYBASE", @@ -300,69 +121,120 @@ static const char *bundleNamesAtari[] = { NULL }; -int16 findFileInBundle(const char *fileName) { - uint16 i; +static void fixVolCnfFileName(char *dst, const uint8 *src) { + memcpy(dst, src, 8); src += 8; + dst[8] = 0; + char *ext = strchr(dst, ' '); + if (!ext) { + ext = &dst[8]; + } + if (*src == ' ') { + *ext = 0; + } else { + *ext++ = '.'; + memcpy(ext, src, 3); + char *end = strchr(ext, ' '); + if (!end) { + end = &ext[3]; + } + *end = 0; + } +} +void CineEngine::readVolCnf() { + Common::File f; + if (!f.open("vol.cnf")) { + error("Unable to open 'vol.cnf'"); + } + f.seek(8, SEEK_SET); + uint32 unpackedSize = f.readUint32BE(); + uint32 packedSize = f.readUint32BE(); + uint8 *buf = (uint8 *)malloc(unpackedSize); + if (!buf) { + error("Unable to allocate %d bytes", unpackedSize); + } + f.read(buf, packedSize); + if (packedSize != unpackedSize) { + bool b = delphineUnpack(buf, buf, packedSize); + if (!b) { + error("Error while unpacking 'vol.cnf' data"); + } + } + uint8 *p = buf; + int resourceFilesCount = READ_BE_UINT16(p); p += 2; + int entrySize = READ_BE_UINT16(p); p += 2; + for (int i = 0; i < resourceFilesCount; ++i) { + char volumeResourceFile[9]; + memcpy(volumeResourceFile, p, 8); + volumeResourceFile[8] = 0; + _volumeResourceFiles.push_back(volumeResourceFile); + p += entrySize; + } + + int volumeEntriesCount = 0; + for (int i = 0; i < resourceFilesCount; ++i) { + int size = READ_BE_UINT32(p); p += 4; + assert((size % 11) == 0); + volumeEntriesCount += size / 11; + p += size; + } + + p = buf + 4 + resourceFilesCount * entrySize; + for (int i = 0; i < resourceFilesCount; ++i) { + int count = READ_BE_UINT32(p) / 11; p += 4; + while (count--) { + char volumeEntryName[12]; + fixVolCnfFileName(volumeEntryName, p); + _volumeEntriesMap.setVal(volumeEntryName, _volumeResourceFiles[i].c_str()); + debugC(5, kCineDebugPart, "Added volume entry name '%s' resource file '%s'\n", volumeEntryName, _volumeResourceFiles[i].c_str()); + p += 11; + } + } + + free(buf); +} + +int16 findFileInBundle(const char *fileName) { if (g_cine->getGameType() == Cine::GType_OS) { - for (i = 0; i < numElementInPart; i++) { + // look first in currently loaded resource file + for (int i = 0; i < numElementInPart; i++) { if (!scumm_stricmp(fileName, partBuffer[i].partName)) { return i; } } - - const char **bPtr = 0; - + // not found, open the required resource file if (g_cine->getPlatform() == Common::kPlatformPC) { - switch (g_cine->getLanguage()) { - case Common::EN_GRB: - bPtr = bundleNamesDOSEN; - break; - case Common::EN_USA: - if (g_cine->getFeatures() & GF_CD) - bPtr = bundleNamesDOSUS; - else - bPtr = bundleNamesDOSInt; - break; - case Common::DE_DEU: - case Common::IT_ITA: - bPtr = bundleNamesDOSInt; - break; - case Common::ES_ESP: - if (g_cine->getFeatures() & GF_CD) - bPtr = bundleNamesDOSInt; - else - bPtr = bundleNamesDOSES; - break; - case Common::FR_FRA: - bPtr = bundleNamesDOSFR; - break; - default: - break; + StringPtrHashMap::const_iterator it = g_cine->_volumeEntriesMap.find(fileName); + if (it == g_cine->_volumeEntriesMap.end()) { + warning("Unable to find part file for filename '%s'", fileName); + return -1; } - } else if (g_cine->getPlatform() == Common::kPlatformAmiga) { - if (g_cine->getFeatures() & GF_DEMO) - bPtr = bundleNamesAmigaDemo; - else - bPtr = bundleNamesAmiga; - } else if (g_cine->getPlatform() == Common::kPlatformAtariST) { + const char *part = (*it)._value; + loadPart(part); + } else { + // special case for Amiga & Atari versions + // TODO: handle it like the original interpreter does + const char **bPtr = 0; + if (g_cine->getPlatform() == Common::kPlatformAmiga) { + bPtr = (g_cine->getFeatures() & GF_DEMO) ? bundleNamesAmigaDemo : bundleNamesAmiga; + } else if (g_cine->getPlatform() == Common::kPlatformAtariST) { bPtr = bundleNamesAtari; - } - - while (*bPtr) { - loadPart(*bPtr); - - for (i = 0; i < numElementInPart; i++) { - if (!scumm_stricmp(fileName, partBuffer[i].partName)) { - return i; + } + while (*bPtr) { + loadPart(*bPtr); + for (int i = 0; i < numElementInPart; i++) { + if (!scumm_stricmp(fileName, partBuffer[i].partName)) { + return i; + } } + bPtr++; } - bPtr++; + return -1; } - } else { - for (i = 0; i < numElementInPart; i++) { - if (!scumm_stricmp(fileName, partBuffer[i].partName)) { - return i; - } + } + for (int i = 0; i < numElementInPart; i++) { + if (!scumm_stricmp(fileName, partBuffer[i].partName)) { + return i; } } return -1; @@ -376,17 +248,11 @@ void readFromPart(int16 idx, byte *dataPtr) { } byte *readBundleFile(int16 foundFileIdx) { - byte *dataPtr; - - dataPtr = (byte *)calloc(partBuffer[foundFileIdx].unpackedSize, 1); - + assert(foundFileIdx >= 0 && foundFileIdx < numElementInPart); + byte *dataPtr = (byte *)calloc(partBuffer[foundFileIdx].unpackedSize, 1); if (partBuffer[foundFileIdx].unpackedSize != partBuffer[foundFileIdx].packedSize) { - byte *unpackBuffer; - - unpackBuffer = (byte *)malloc(partBuffer[foundFileIdx].packedSize); - readFromPart(foundFileIdx, unpackBuffer); - delphineUnpack(dataPtr, unpackBuffer, partBuffer[foundFileIdx].packedSize); - free(unpackBuffer); + readFromPart(foundFileIdx, dataPtr); + delphineUnpack(dataPtr, dataPtr, partBuffer[foundFileIdx].packedSize); } else { readFromPart(foundFileIdx, dataPtr); } diff --git a/engines/cine/rel.cpp b/engines/cine/rel.cpp index 2fed7c2ff3..15697c2cf1 100644 --- a/engines/cine/rel.cpp +++ b/engines/cine/rel.cpp @@ -84,6 +84,7 @@ void loadRel(char *pRelName) { relTable[i].obj1Param1 = READ_BE_UINT16(ptr); ptr += 2; relTable[i].obj1Param2 = READ_BE_UINT16(ptr); ptr += 2; relTable[i].obj2Param = READ_BE_UINT16(ptr); ptr += 2; + relTable[i].runCount = 0; } for (i = 0; i < numEntry; i++) { diff --git a/engines/cine/rel.h b/engines/cine/rel.h index dbdab7e8af..3e8332a55e 100644 --- a/engines/cine/rel.h +++ b/engines/cine/rel.h @@ -34,6 +34,7 @@ struct RelObjectScript { uint16 obj1Param1; uint16 obj1Param2; uint16 obj2Param; + uint16 runCount; }; #define NUM_MAX_REL 255 diff --git a/engines/cine/various.cpp b/engines/cine/various.cpp index 378437babf..bb97ba3188 100644 --- a/engines/cine/various.cpp +++ b/engines/cine/various.cpp @@ -171,6 +171,11 @@ void runObjectScript(int16 entryIdx) { pNewElement->scriptPtr = (byte *)relTable[entryIdx].data; pNewElement->scriptIdx = entryIdx; + if (g_cine->getGameType() == Cine::GType_OS) { + pNewElement->localVars[0] = relTable[entryIdx].runCount; + ++relTable[entryIdx].runCount; + } + computeScriptStack(pNewElement->scriptPtr, pNewElement->stack, relTable[entryIdx].size); } -- cgit v1.2.3