From a2367d26f9d7f8523c313a7b82d0b719de1e6e15 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 20 Nov 2010 03:14:03 +0000 Subject: TINSEL: Preliminary functionality for reading BE data files svn-id: r54392 --- engines/tinsel/detection_tables.h | 23 +++++++++++++++++++++-- engines/tinsel/dialogs.cpp | 15 +++++++++++++++ engines/tinsel/drives.cpp | 32 +++++++++++++++++++++++++++----- engines/tinsel/drives.h | 23 +++++++++++++++++++++-- engines/tinsel/handle.cpp | 8 +++++--- engines/tinsel/scn.cpp | 9 +++++++-- engines/tinsel/sound.cpp | 8 ++++---- engines/tinsel/strres.cpp | 2 +- engines/tinsel/tinsel.cpp | 8 ++++---- engines/tinsel/tinsel.h | 9 ++++++++- 10 files changed, 113 insertions(+), 24 deletions(-) (limited to 'engines/tinsel') diff --git a/engines/tinsel/detection_tables.h b/engines/tinsel/detection_tables.h index 239e06c8dd..2a523470cc 100644 --- a/engines/tinsel/detection_tables.h +++ b/engines/tinsel/detection_tables.h @@ -77,7 +77,26 @@ static const TinselGameDescription gameDescriptions[] = { GF_CD, TINSEL_V1, }, - +#if 0 + { // Macintosh CD Demo V1 version, with *.scn files + { + "dw", + "CD Demo", + { + {"dw.scn", 0, "ae291aa4ed7f7caacbfb711b6ff2c8bd", 1286264}, + {"english.smp", 0, NULL, -1}, + }, + Common::EN_ANY, + Common::kPlatformMacintosh, + ADGF_DEMO, + GUIO_NONE + }, + GID_DW1, + 0, + GF_CD | GF_BIG_ENDIAN, + TINSEL_V1, + }, +#endif { // Multilingual Floppy V1 with *.gra files. // Note: It contains no english subtitles. { @@ -444,7 +463,7 @@ static const TinselGameDescription gameDescriptions[] = { }, GID_DW1, 0, - GF_CD | GF_SCNFILES | GF_ENHANCED_AUDIO_SUPPORT, + GF_CD | GF_SCNFILES | GF_ENHANCED_AUDIO_SUPPORT | GF_BIG_ENDIAN, TINSEL_V1, }, diff --git a/engines/tinsel/dialogs.cpp b/engines/tinsel/dialogs.cpp index 0a02924f12..73cad7a68f 100644 --- a/engines/tinsel/dialogs.cpp +++ b/engines/tinsel/dialogs.cpp @@ -5551,6 +5551,21 @@ extern void RegisterIcons(void *cptr, int num) { memmove(destP, srcP, 12); destP->attribute = 0; } + } else if (TinselV1Mac) { + // Macintosh version has BE encoded resources, so the values need to be byte swapped + MEM_NODE *node = MemoryAllocFixed(numObjects * sizeof(INV_OBJECT)); + assert(node); + invObjects = (INV_OBJECT *)MemoryDeref(node); + assert(invObjects); + INV_OBJECT *srcP = (INV_OBJECT *)cptr; + INV_OBJECT *destP = (INV_OBJECT *)invObjects; + + for (int i = 0; i < num; ++i, ++destP, ++srcP) { + destP->id = FROM_BE_32(srcP->id); + destP->hIconFilm = FROM_BE_32(srcP->hIconFilm); + destP->hScript = FROM_BE_32(srcP->hScript); + destP->attribute = FROM_BE_32(srcP->attribute); + } } else if (TinselV2) { if (invFilms == NULL) { // First time - allocate memory diff --git a/engines/tinsel/drives.cpp b/engines/tinsel/drives.cpp index 61da0345a8..58d0978426 100644 --- a/engines/tinsel/drives.cpp +++ b/engines/tinsel/drives.cpp @@ -24,6 +24,7 @@ * CD/drive handling functions */ +#include "common/config-manager.h" #include "gui/message.h" #include "tinsel/drives.h" #include "tinsel/scene.h" @@ -151,13 +152,29 @@ bool GotoCD() { bool TinselFile::_warningShown = false; -bool TinselFile::open(const Common::String &filename) { - if (Common::File::open(filename)) { - // If it's the sample file, strip off the CD number from the filename +TinselFile::TinselFile() { + _stream = NULL; +} + +TinselFile::~TinselFile() { + delete _stream; +} + +bool TinselFile::openInternal(const Common::String &filename) { + const Common::FSNode gameDataDir(ConfMan.get("path")); + const Common::FSNode fsNode = gameDataDir.getChild(filename); + Common::SeekableReadStream *stream = fsNode.createReadStream(); + if (!stream) + return false; + _stream = new Common::SeekableSubReadStreamEndian(stream, 0, stream->size(), + (_vm->getFeatures() & GF_BIG_ENDIAN) != 0, DisposeAfterUse::YES); + return true; +} +bool TinselFile::open(const Common::String &filename) { + if (openInternal(filename)) return true; - } if (!TinselV2) return false; @@ -175,7 +192,12 @@ bool TinselFile::open(const Common::String &filename) { strncpy(newFilename, fname, p - fname); strcpy(newFilename + (p - fname), p + 1); - return Common::File::open(newFilename); + return openInternal(newFilename); +} + +void TinselFile::close() { + delete _stream; + _stream = NULL; } } // End of namespace Tinsel diff --git a/engines/tinsel/drives.h b/engines/tinsel/drives.h index 81111265fa..061dae625f 100644 --- a/engines/tinsel/drives.h +++ b/engines/tinsel/drives.h @@ -27,6 +27,8 @@ #ifndef TINSEL_DRIVES_H #define TINSEL_DRIVES_H +#include "common/memstream.h" +#include "common/substream.h" #include "common/file.h" #include "tinsel/dw.h" #include "tinsel/coroutine.h" @@ -59,12 +61,29 @@ void SetNextCD(int cdNumber); bool GotoCD(); -class TinselFile: public Common::File { +class TinselFile { private: static bool _warningShown; + Common::SeekableSubReadStreamEndian *_stream; + bool openInternal(const Common::String &filename); public: - virtual bool open(const Common::String &filename); + TinselFile(); + ~TinselFile(); + bool open(const Common::String &filename); + void close(); char getCdNumber(); + + FORCEINLINE int32 pos() const { assert(_stream); return _stream->pos(); } + FORCEINLINE int32 size() const { assert(_stream); return _stream->size(); } + FORCEINLINE bool seek(int32 offset, int whence = SEEK_SET) { assert(_stream); return _stream->seek(offset, whence); } + FORCEINLINE bool eos() const { assert(_stream); return _stream->eos(); } + FORCEINLINE bool err() const { return _stream->err(); } + FORCEINLINE uint32 readUint32() { assert(_stream); return _stream->readUint32(); } + FORCEINLINE int16 readSint16() { assert(_stream); return _stream->readUint16(); } + FORCEINLINE int32 readSint32() { assert(_stream); return _stream->readUint32(); } + FORCEINLINE Common::SeekableReadStream *readStream(uint32 dataSize) { assert(_stream); return _stream->readStream(dataSize); } + FORCEINLINE uint32 read(void *dataPtr, uint32 dataSize) { assert(_stream); return _stream->read(dataPtr, dataSize); } + FORCEINLINE bool skip(uint32 offset) { return seek(offset, SEEK_CUR); } }; diff --git a/engines/tinsel/handle.cpp b/engines/tinsel/handle.cpp index 9461cf8c1c..2307d95a61 100644 --- a/engines/tinsel/handle.cpp +++ b/engines/tinsel/handle.cpp @@ -102,11 +102,13 @@ void SetupHandleTable() { int len; uint i; MEMHANDLE *pH; - Common::File f; + TinselFile f; if (f.open(TinselV1PSX? PSX_INDEX_FILENAME : INDEX_FILENAME)) { // get size of index file len = f.size(); + if (TinselV1Mac) + len -= 2; // Macintosh version has two redundant ending bytes if (len > 0) { if ((len % RECORD_SIZE) != 0) { @@ -126,13 +128,13 @@ void SetupHandleTable() { // load data for (i = 0; i < numHandles; i++) { f.read(handleTable[i].szName, 12); - handleTable[i].filesize = f.readUint32LE(); + handleTable[i].filesize = f.readUint32(); // The pointer should always be NULL. We don't // need to read that from the file. handleTable[i]._node = NULL; f.seek(4, SEEK_CUR); // For Discworld 2, read in the flags2 field - handleTable[i].flags2 = t2Flag ? f.readUint32LE() : 0; + handleTable[i].flags2 = t2Flag ? f.readUint32() : 0; } if (f.eos() || f.err()) { diff --git a/engines/tinsel/scn.cpp b/engines/tinsel/scn.cpp index 0c89819ca0..326fd9e750 100644 --- a/engines/tinsel/scn.cpp +++ b/engines/tinsel/scn.cpp @@ -46,6 +46,8 @@ byte *FindChunk(SCNHANDLE handle, uint32 chunk) { byte *bptr = LockMem(handle); uint32 *lptr = (uint32 *)bptr; uint32 add; + bool bigEndian = (_vm->getFeatures() & GF_BIG_ENDIAN) != 0; + assert(!bigEndian); // Big endian data not yet supported // Initial adjustmnet for Tinsel 1 chunk types if ((TinselVersion != TINSEL_V2) && (chunk >= CHUNK_SCENE) && @@ -60,14 +62,17 @@ byte *FindChunk(SCNHANDLE handle, uint32 chunk) { chunk -= 0x2L; while (1) { - if (READ_LE_UINT32(lptr) == chunk) + if (READ_32(lptr) == chunk) return (byte *)(lptr + 2); ++lptr; - add = READ_LE_UINT32(lptr); + add = READ_32(lptr); + if (!add) + // End of file reached return NULL; + // Move to next chunk lptr = (uint32 *)(bptr + add); } } diff --git a/engines/tinsel/sound.cpp b/engines/tinsel/sound.cpp index 0624409f92..7fab3624a4 100644 --- a/engines/tinsel/sound.cpp +++ b/engines/tinsel/sound.cpp @@ -105,7 +105,7 @@ bool SoundManager::playSample(int id, Audio::Mixer::SoundType type, Audio::Sound error(FILE_IS_CORRUPT, _vm->getSampleFile(sampleLanguage)); // read the length of the sample - uint32 sampleLen = _sampleStream.readUint32LE(); + uint32 sampleLen = _sampleStream.readUint32(); if (_sampleStream.eos() || _sampleStream.err()) error(FILE_IS_CORRUPT, _vm->getSampleFile(sampleLanguage)); @@ -264,7 +264,7 @@ bool SoundManager::playSample(int id, int sub, bool bLooped, int x, int y, int p error(FILE_IS_CORRUPT, _vm->getSampleFile(sampleLanguage)); // read the length of the sample - uint32 sampleLen = _sampleStream.readUint32LE(); + uint32 sampleLen = _sampleStream.readUint32(); if (_sampleStream.eos() || _sampleStream.err()) error(FILE_IS_CORRUPT, _vm->getSampleFile(sampleLanguage)); @@ -277,12 +277,12 @@ bool SoundManager::playSample(int id, int sub, bool bLooped, int x, int y, int p // Skipping for (int32 i = 0; i < sub; i++) { - sampleLen = _sampleStream.readUint32LE(); + sampleLen = _sampleStream.readUint32(); _sampleStream.skip(sampleLen); if (_sampleStream.eos() || _sampleStream.err()) error(FILE_IS_CORRUPT, _vm->getSampleFile(sampleLanguage)); } - sampleLen = _sampleStream.readUint32LE(); + sampleLen = _sampleStream.readUint32(); if (_sampleStream.eos() || _sampleStream.err()) error(FILE_IS_CORRUPT, _vm->getSampleFile(sampleLanguage)); } diff --git a/engines/tinsel/strres.cpp b/engines/tinsel/strres.cpp index 7ed9a773bc..aa303a5391 100644 --- a/engines/tinsel/strres.cpp +++ b/engines/tinsel/strres.cpp @@ -111,7 +111,7 @@ void ChangeLanguage(LANGUAGE newLang) { // Check whether the file is compressed or not - for compressed files the // first long is the filelength and for uncompressed files it is the chunk // identifier - textLen = f.readUint32LE(); + textLen = f.readUint32(); if (f.eos() || f.err()) error(FILE_IS_CORRUPT, _vm->getTextFile(newLang)); diff --git a/engines/tinsel/tinsel.cpp b/engines/tinsel/tinsel.cpp index aa5a9282fa..0e1001b398 100644 --- a/engines/tinsel/tinsel.cpp +++ b/engines/tinsel/tinsel.cpp @@ -722,15 +722,15 @@ void LoadBasicChunks() { // CHUNK_TOTAL_ACTORS seems to be missing in the released version, hard coding a value // TODO: Would be nice to just change 511 to MAX_SAVED_ALIVES cptr = FindChunk(MASTER_SCNHANDLE, CHUNK_TOTAL_ACTORS); - RegisterActors((cptr != NULL) ? READ_LE_UINT32(cptr) : 511); + RegisterActors((cptr != NULL) ? READ_32(cptr) : 511); // CHUNK_TOTAL_GLOBALS seems to be missing in some versions. // So if it is missing, set a reasonably high value for the number of globals. cptr = FindChunk(MASTER_SCNHANDLE, CHUNK_TOTAL_GLOBALS); - RegisterGlobals((cptr != NULL) ? READ_LE_UINT32(cptr) : 512); + RegisterGlobals((cptr != NULL) ? READ_32(cptr) : 512); cptr = FindChunk(INV_OBJ_SCNHANDLE, CHUNK_TOTAL_OBJECTS); - numObjects = (cptr != NULL) ? READ_LE_UINT32(cptr) : 0; + numObjects = (cptr != NULL) ? READ_32(cptr) : 0; cptr = FindChunk(INV_OBJ_SCNHANDLE, CHUNK_OBJECTS); @@ -763,7 +763,7 @@ void LoadBasicChunks() { // CdPlay() stuff cptr = FindChunk(MASTER_SCNHANDLE, CHUNK_CDPLAY_HANDLE); assert(cptr); - uint32 playHandle = READ_LE_UINT32(cptr); + uint32 playHandle = READ_32(cptr); assert(playHandle < 512); SetCdPlayHandle(playHandle); } diff --git a/engines/tinsel/tinsel.h b/engines/tinsel/tinsel.h index c4f4a3bc13..b4f77d18f2 100644 --- a/engines/tinsel/tinsel.h +++ b/engines/tinsel/tinsel.h @@ -81,7 +81,9 @@ enum TinselGameFeatures { // None of these defined -> 1 language, in ENGLISH.TXT GF_USE_3FLAGS = 1 << 6, // French, German, Spanish GF_USE_4FLAGS = 1 << 7, // French, German, Spanish, Italian - GF_USE_5FLAGS = 1 << 8 // All 5 flags + GF_USE_5FLAGS = 1 << 8, // All 5 flags + + GF_BIG_ENDIAN = 1 << 9 }; /** @@ -139,8 +141,13 @@ typedef bool (*KEYFPTR)(const Common::KeyState &); #define TinselV1 (TinselVersion == TINSEL_V1) #define TinselV2 (TinselVersion == TINSEL_V2) #define TinselV1PSX (TinselVersion == TINSEL_V1 && _vm->getPlatform() == Common::kPlatformPSX) +#define TinselV1Mac (TinselVersion == TINSEL_V1 && _vm->getPlatform() == Common::kPlatformMacintosh) + #define IsDemo (_vm->getFeatures() & GF_DEMO) +#define READ_16(v) ((_vm->getFeatures() & GF_BIG_ENDIAN) ? READ_BE_UINT16(v) : READ_LE_UINT16(v)) +#define READ_32(v) ((_vm->getFeatures() & GF_BIG_ENDIAN) ? READ_BE_UINT32(v) : READ_LE_UINT32(v)) + // Global reference to the TinselEngine object extern TinselEngine *_vm; -- cgit v1.2.3