diff options
Diffstat (limited to 'engines')
-rw-r--r-- | engines/hugo/file.cpp | 591 | ||||
-rw-r--r-- | engines/hugo/file.h | 68 | ||||
-rw-r--r-- | engines/hugo/global.h | 2 | ||||
-rw-r--r-- | engines/hugo/hugo.cpp | 11 | ||||
-rw-r--r-- | engines/kyra/kyra_v1.h | 1 | ||||
-rw-r--r-- | engines/kyra/saveload.cpp | 5 | ||||
-rw-r--r-- | engines/kyra/text_lol.cpp | 8 | ||||
-rw-r--r-- | engines/sci/engine/kscripts.cpp | 49 | ||||
-rw-r--r-- | engines/sci/engine/script_patches.cpp | 30 | ||||
-rw-r--r-- | engines/sci/engine/segment.h | 3 | ||||
-rw-r--r-- | engines/sci/sound/music.cpp | 36 |
11 files changed, 580 insertions, 224 deletions
diff --git a/engines/hugo/file.cpp b/engines/hugo/file.cpp index b4645c4d0b..41eb3c88e4 100644 --- a/engines/hugo/file.cpp +++ b/engines/hugo/file.cpp @@ -44,7 +44,9 @@ namespace Hugo { FileManager::FileManager(HugoEngine &vm) : _vm(vm) { +} +FileManager::~FileManager() { } byte *FileManager::convertPCC(byte *p, uint16 y, uint16 bpl, image_pt dataPtr) { @@ -235,44 +237,6 @@ void FileManager::readImage(int objNum, object_t *objPtr) { _objectsArchive.close(); } -void FileManager::readBackground(int screenIndex) { -// Read a PCX image into dib_a - seq_t seq; // Image sequence structure for Read_pcx - sceneBlock_t sceneBlock; // Read a database header entry - - debugC(1, kDebugFile, "readBackground(%d)", screenIndex); - - if (_vm.isPacked()) { - _sceneryArchive.seek((uint32) screenIndex * sizeof(sceneBlock_t), SEEK_SET); - - sceneBlock.scene_off = _sceneryArchive.readUint32LE(); - sceneBlock.scene_len = _sceneryArchive.readUint32LE(); - sceneBlock.b_off = _sceneryArchive.readUint32LE(); - sceneBlock.b_len = _sceneryArchive.readUint32LE(); - sceneBlock.o_off = _sceneryArchive.readUint32LE(); - sceneBlock.o_len = _sceneryArchive.readUint32LE(); - sceneBlock.ob_off = _sceneryArchive.readUint32LE(); - sceneBlock.ob_len = _sceneryArchive.readUint32LE(); - - _sceneryArchive.seek(sceneBlock.scene_off, SEEK_SET); - } else { - char *buf = (char *) malloc(2048 + 1); // Buffer for file access - strcat(strcat(strcpy(buf, _vm._picDir), _vm._screenNames[screenIndex]), BKGEXT); - if (!_sceneryArchive.open(buf)) { - warning("File %s not found, trying again with %s.ART", buf, _vm._screenNames[screenIndex]); - strcat(strcpy(buf, _vm._screenNames[screenIndex]), ".ART"); - if (!_sceneryArchive.open(buf)) - Utils::Error(FILE_ERR, "%s", buf); - } - } - - // Read the image into dummy seq and static dib_a - readPCX(_sceneryArchive, &seq, _vm.screen().getFrontBuffer(), true, _vm._screenNames[screenIndex]); - - if (!_vm.isPacked()) - _sceneryArchive.close(); -} - sound_pt FileManager::getSound(int16 sound, uint16 *size) { // Read sound (or music) file data. Call with SILENCE to free-up // any allocated memory. Also returns size of data @@ -333,100 +297,6 @@ bool FileManager::fileExists(char *filename) { return false; } -void FileManager::readOverlay(int screenNum, image_pt image, ovl_t overlayType) { -// Open and read in an overlay file, close file - uint32 i = 0; - int16 j, k; - int8 data; // Must be 8 bits signed - image_pt tmpImage = image; // temp ptr to overlay file - sceneBlock_t sceneBlock; // Database header entry - - debugC(1, kDebugFile, "readOverlay(%d, ...)", screenNum); - - if (_vm.isPacked()) { - _sceneryArchive.seek((uint32)screenNum * sizeof(sceneBlock_t), SEEK_SET); - - sceneBlock.scene_off = _sceneryArchive.readUint32LE(); - sceneBlock.scene_len = _sceneryArchive.readUint32LE(); - sceneBlock.b_off = _sceneryArchive.readUint32LE(); - sceneBlock.b_len = _sceneryArchive.readUint32LE(); - sceneBlock.o_off = _sceneryArchive.readUint32LE(); - sceneBlock.o_len = _sceneryArchive.readUint32LE(); - sceneBlock.ob_off = _sceneryArchive.readUint32LE(); - sceneBlock.ob_len = _sceneryArchive.readUint32LE(); - - switch (overlayType) { - case BOUNDARY: - _sceneryArchive.seek(sceneBlock.b_off, SEEK_SET); - i = sceneBlock.b_len; - break; - case OVERLAY: - _sceneryArchive.seek(sceneBlock.o_off, SEEK_SET); - i = sceneBlock.o_len; - break; - case OVLBASE: - _sceneryArchive.seek(sceneBlock.ob_off, SEEK_SET); - i = sceneBlock.ob_len; - break; - default: - Utils::Error(FILE_ERR, "%s", "Bad ovl_type"); - break; - } - if (i == 0) { - for (i = 0; i < OVL_SIZE; i++) - image[i] = 0; - return; - } - } else { - const char *ovl_ext[] = {".b", ".o", ".ob"}; - char *buf = (char *) malloc(2048 + 1); // Buffer for file access - - strcat(strcpy(buf, _vm._screenNames[screenNum]), ovl_ext[overlayType]); - - if (!fileExists(buf)) { - for (i = 0; i < OVL_SIZE; i++) - image[i] = 0; - return; - } - - if (!_sceneryArchive.open(buf)) - Utils::Error(FILE_ERR, "%s", buf); - -// if (eof(f_scenery)) { -// _lclose(f_scenery); -// return; -// } - } - - switch (_vm._gameVariant) { - case 0: // Hugo 1 DOS and WIN don't pack data - case 3: - _sceneryArchive.read(tmpImage, OVL_SIZE); - break; - default: - // Read in the overlay file using MAC Packbits. (We're not proud!) - k = 0; // byte count - do { - data = _sceneryArchive.readByte(); // Read a code byte - if ((byte)data == 0x80) // Noop - k = k; - else if (data >= 0) { // Copy next data+1 literally - for (i = 0; i <= (byte)data; i++, k++) - *tmpImage++ = _sceneryArchive.readByte(); - } else { // Repeat next byte -data+1 times - j = _sceneryArchive.readByte(); - - for (i = 0; i < (byte)(-data + 1); i++, k++) - *tmpImage++ = j; - } - } while (k < OVL_SIZE); - break; - } - - if (!_vm.isPacked()) - _sceneryArchive.close(); -} - void FileManager::saveSeq(object_t *obj) { // Save sequence number and image number in given object byte j, k; @@ -681,33 +551,6 @@ void FileManager::closePlaybackFile() { fclose(fpb); } -void FileManager::openDatabaseFiles() { -//TODO : HUGO 1 DOS uses _stringtData instead of a strings.dat -//This should be tested adequately and should be handled by an error and not by a warning. - debugC(1, kDebugFile, "openDatabaseFiles"); - - if (!_stringArchive.open(STRING_FILE)) -// Error(FILE_ERR, "%s", STRING_FILE); - warning("Hugo Error: File not found %s", STRING_FILE); - if (_vm.isPacked()) { - if (!_sceneryArchive.open(SCENERY_FILE)) - Utils::Error(FILE_ERR, "%s", SCENERY_FILE); - if (!_objectsArchive.open(OBJECTS_FILE)) - Utils::Error(FILE_ERR, "%s", OBJECTS_FILE); - } -} - -void FileManager::closeDatabaseFiles() { -// TODO: stringArchive shouldn't be closed in Hugo 1 DOS - debugC(1, kDebugFile, "closeDatabaseFiles"); - - _stringArchive.close(); - if (_vm.isPacked()) { - _sceneryArchive.close(); - _objectsArchive.close(); - } -} - char *FileManager::fetchString(int index) { //TODO : HUGO 1 DOS uses _stringtData instead of a strings.dat // Fetch string from file, decode and return ptr to string in memory @@ -901,4 +744,434 @@ void FileManager::instructions() { f.close(); } + +FileManager_v1::FileManager_v1(HugoEngine &vm) : FileManager(vm) { +} + +FileManager_v1::~FileManager_v1() { +} + +void FileManager_v1::openDatabaseFiles() { + debugC(1, kDebugFile, "openDatabaseFiles"); +} + +void FileManager_v1::closeDatabaseFiles() { + debugC(1, kDebugFile, "closeDatabaseFiles"); +} + +void FileManager_v1::readOverlay(int screenNum, image_pt image, ovl_t overlayType) { +// Open and read in an overlay file, close file + uint32 i = 0; + image_pt tmpImage = image; // temp ptr to overlay file + + debugC(1, kDebugFile, "readOverlay(%d, ...)", screenNum); + + const char *ovl_ext[] = {".b", ".o", ".ob"}; + char *buf = (char *) malloc(2048 + 1); // Buffer for file access + + strcat(strcpy(buf, _vm._screenNames[screenNum]), ovl_ext[overlayType]); + + if (!fileExists(buf)) { + for (i = 0; i < OVL_SIZE; i++) + image[i] = 0; + return; + } + + if (!_sceneryArchive1.open(buf)) + Utils::Error(FILE_ERR, "%s", buf); + + _sceneryArchive1.read(tmpImage, OVL_SIZE); + _sceneryArchive1.close(); +} + +void FileManager_v1::readBackground(int screenIndex) { +// Read a PCX image into dib_a + seq_t seq; // Image sequence structure for Read_pcx + + debugC(1, kDebugFile, "readBackground(%d)", screenIndex); + + char *buf = (char *) malloc(2048 + 1); // Buffer for file access + strcat(strcat(strcpy(buf, _vm._picDir), _vm._screenNames[screenIndex]), BKGEXT); + if (!_sceneryArchive1.open(buf)) { + warning("File %s not found, trying again with %s.ART", buf, _vm._screenNames[screenIndex]); + strcat(strcpy(buf, _vm._screenNames[screenIndex]), ".ART"); + if (!_sceneryArchive1.open(buf)) + Utils::Error(FILE_ERR, "%s", buf); + } + // Read the image into dummy seq and static dib_a + readPCX(_sceneryArchive1, &seq, _vm.screen().getFrontBuffer(), true, _vm._screenNames[screenIndex]); + + _sceneryArchive1.close(); +} + +FileManager_v2::FileManager_v2(HugoEngine &vm) : FileManager(vm) { +} + +FileManager_v2::~FileManager_v2() { +} + +void FileManager_v2::openDatabaseFiles() { + debugC(1, kDebugFile, "openDatabaseFiles"); + + if (!_stringArchive.open(STRING_FILE)) + Utils::Error(FILE_ERR, "%s", STRING_FILE); + if (!_sceneryArchive1.open("scenery.dat")) + Utils::Error(FILE_ERR, "%s", "scenery.dat"); + if (!_objectsArchive.open(OBJECTS_FILE)) + Utils::Error(FILE_ERR, "%s", OBJECTS_FILE); +} + +void FileManager_v2::closeDatabaseFiles() { + debugC(1, kDebugFile, "closeDatabaseFiles"); + + _stringArchive.close(); + _sceneryArchive1.close(); + _objectsArchive.close(); +} + +void FileManager_v2::readBackground(int screenIndex) { +// Read a PCX image into dib_a + seq_t seq; // Image sequence structure for Read_pcx + sceneBlock_t sceneBlock; // Read a database header entry + + debugC(1, kDebugFile, "readBackground(%d)", screenIndex); + + _sceneryArchive1.seek((uint32) screenIndex * sizeof(sceneBlock_t), SEEK_SET); + + sceneBlock.scene_off = _sceneryArchive1.readUint32LE(); + sceneBlock.scene_len = _sceneryArchive1.readUint32LE(); + sceneBlock.b_off = _sceneryArchive1.readUint32LE(); + sceneBlock.b_len = _sceneryArchive1.readUint32LE(); + sceneBlock.o_off = _sceneryArchive1.readUint32LE(); + sceneBlock.o_len = _sceneryArchive1.readUint32LE(); + sceneBlock.ob_off = _sceneryArchive1.readUint32LE(); + sceneBlock.ob_len = _sceneryArchive1.readUint32LE(); + + _sceneryArchive1.seek(sceneBlock.scene_off, SEEK_SET); + + // Read the image into dummy seq and static dib_a + readPCX(_sceneryArchive1, &seq, _vm.screen().getFrontBuffer(), true, _vm._screenNames[screenIndex]); +} + +void FileManager_v2::readOverlay(int screenNum, image_pt image, ovl_t overlayType) { +// Open and read in an overlay file, close file + uint32 i = 0; + int16 j, k; + int8 data; // Must be 8 bits signed + image_pt tmpImage = image; // temp ptr to overlay file + sceneBlock_t sceneBlock; // Database header entry + + debugC(1, kDebugFile, "readOverlay(%d, ...)", screenNum); + + _sceneryArchive1.seek((uint32)screenNum * sizeof(sceneBlock_t), SEEK_SET); + + sceneBlock.scene_off = _sceneryArchive1.readUint32LE(); + sceneBlock.scene_len = _sceneryArchive1.readUint32LE(); + sceneBlock.b_off = _sceneryArchive1.readUint32LE(); + sceneBlock.b_len = _sceneryArchive1.readUint32LE(); + sceneBlock.o_off = _sceneryArchive1.readUint32LE(); + sceneBlock.o_len = _sceneryArchive1.readUint32LE(); + sceneBlock.ob_off = _sceneryArchive1.readUint32LE(); + sceneBlock.ob_len = _sceneryArchive1.readUint32LE(); + + switch (overlayType) { + case BOUNDARY: + _sceneryArchive1.seek(sceneBlock.b_off, SEEK_SET); + i = sceneBlock.b_len; + break; + case OVERLAY: + _sceneryArchive1.seek(sceneBlock.o_off, SEEK_SET); + i = sceneBlock.o_len; + break; + case OVLBASE: + _sceneryArchive1.seek(sceneBlock.ob_off, SEEK_SET); + i = sceneBlock.ob_len; + break; + default: + Utils::Error(FILE_ERR, "%s", "Bad ovl_type"); + break; + } + if (i == 0) { + for (i = 0; i < OVL_SIZE; i++) + image[i] = 0; + return; + } + + // Read in the overlay file using MAC Packbits. (We're not proud!) + k = 0; // byte count + do { + data = _sceneryArchive1.readByte(); // Read a code byte + if ((byte)data == 0x80) // Noop + k = k; + else if (data >= 0) { // Copy next data+1 literally + for (i = 0; i <= (byte)data; i++, k++) + *tmpImage++ = _sceneryArchive1.readByte(); + } else { // Repeat next byte -data+1 times + j = _sceneryArchive1.readByte(); + + for (i = 0; i < (byte)(-data + 1); i++, k++) + *tmpImage++ = j; + } + } while (k < OVL_SIZE); +} + +FileManager_v3::FileManager_v3(HugoEngine &vm) : FileManager(vm) { +} + +FileManager_v3::~FileManager_v3() { +} + +void FileManager_v3::openDatabaseFiles() { + debugC(1, kDebugFile, "openDatabaseFiles"); + + if (!_stringArchive.open(STRING_FILE)) + Utils::Error(FILE_ERR, "%s", STRING_FILE); + if (!_sceneryArchive1.open("scenery.dat")) + Utils::Error(FILE_ERR, "%s", "scenery.dat"); + if (!_objectsArchive.open(OBJECTS_FILE)) + Utils::Error(FILE_ERR, "%s", OBJECTS_FILE); +} + +void FileManager_v3::closeDatabaseFiles() { + debugC(1, kDebugFile, "closeDatabaseFiles"); + + _stringArchive.close(); + _sceneryArchive1.close(); + _objectsArchive.close(); +} + +void FileManager_v3::readBackground(int screenIndex) { +// Read a PCX image into dib_a + seq_t seq; // Image sequence structure for Read_pcx + sceneBlock_t sceneBlock; // Read a database header entry + + debugC(1, kDebugFile, "readBackground(%d)", screenIndex); + + _sceneryArchive1.seek((uint32) screenIndex * sizeof(sceneBlock_t), SEEK_SET); + + sceneBlock.scene_off = _sceneryArchive1.readUint32LE(); + sceneBlock.scene_len = _sceneryArchive1.readUint32LE(); + sceneBlock.b_off = _sceneryArchive1.readUint32LE(); + sceneBlock.b_len = _sceneryArchive1.readUint32LE(); + sceneBlock.o_off = _sceneryArchive1.readUint32LE(); + sceneBlock.o_len = _sceneryArchive1.readUint32LE(); + sceneBlock.ob_off = _sceneryArchive1.readUint32LE(); + sceneBlock.ob_len = _sceneryArchive1.readUint32LE(); + + _sceneryArchive1.seek(sceneBlock.scene_off, SEEK_SET); + + // Read the image into dummy seq and static dib_a + readPCX(_sceneryArchive1, &seq, _vm.screen().getFrontBuffer(), true, _vm._screenNames[screenIndex]); +} + +void FileManager_v3::readOverlay(int screenNum, image_pt image, ovl_t overlayType) { +// Open and read in an overlay file, close file + uint32 i = 0; + image_pt tmpImage = image; // temp ptr to overlay file + sceneBlock_t sceneBlock; // Database header entry + + debugC(1, kDebugFile, "readOverlay(%d, ...)", screenNum); + + _sceneryArchive1.seek((uint32)screenNum * sizeof(sceneBlock_t), SEEK_SET); + + sceneBlock.scene_off = _sceneryArchive1.readUint32LE(); + sceneBlock.scene_len = _sceneryArchive1.readUint32LE(); + sceneBlock.b_off = _sceneryArchive1.readUint32LE(); + sceneBlock.b_len = _sceneryArchive1.readUint32LE(); + sceneBlock.o_off = _sceneryArchive1.readUint32LE(); + sceneBlock.o_len = _sceneryArchive1.readUint32LE(); + sceneBlock.ob_off = _sceneryArchive1.readUint32LE(); + sceneBlock.ob_len = _sceneryArchive1.readUint32LE(); + + switch (overlayType) { + case BOUNDARY: + _sceneryArchive1.seek(sceneBlock.b_off, SEEK_SET); + i = sceneBlock.b_len; + break; + case OVERLAY: + _sceneryArchive1.seek(sceneBlock.o_off, SEEK_SET); + i = sceneBlock.o_len; + break; + case OVLBASE: + _sceneryArchive1.seek(sceneBlock.ob_off, SEEK_SET); + i = sceneBlock.ob_len; + break; + default: + Utils::Error(FILE_ERR, "%s", "Bad ovl_type"); + break; + } + if (i == 0) { + for (i = 0; i < OVL_SIZE; i++) + image[i] = 0; + return; + } + + _sceneryArchive1.read(tmpImage, OVL_SIZE); +} + +FileManager_v4::FileManager_v4(HugoEngine &vm) : FileManager(vm) { +} + +FileManager_v4::~FileManager_v4() { +} + +void FileManager_v4::readBackground(int screenIndex) { +// Read a PCX image into dib_a + seq_t seq; // Image sequence structure for Read_pcx + sceneBlock_t sceneBlock; // Read a database header entry + Common::File sceneryArchive; + + debugC(1, kDebugFile, "readBackground(%d)", screenIndex); + + _sceneryArchive1.seek((uint32) screenIndex * sizeof(sceneBlock_t), SEEK_SET); + + sceneBlock.scene_off = _sceneryArchive1.readUint32LE(); + sceneBlock.scene_len = _sceneryArchive1.readUint32LE(); + sceneBlock.b_off = _sceneryArchive1.readUint32LE(); + sceneBlock.b_len = _sceneryArchive1.readUint32LE(); + sceneBlock.o_off = _sceneryArchive1.readUint32LE(); + sceneBlock.o_len = _sceneryArchive1.readUint32LE(); + sceneBlock.ob_off = _sceneryArchive1.readUint32LE(); + sceneBlock.ob_len = _sceneryArchive1.readUint32LE(); + + if (screenIndex < 20) { + _sceneryArchive1.seek(sceneBlock.scene_off, SEEK_SET); + + // Read the image into dummy seq and static dib_a + readPCX(_sceneryArchive1, &seq, _vm.screen().getFrontBuffer(), true, _vm._screenNames[screenIndex]); + } else { + _sceneryArchive2.seek(sceneBlock.scene_off, SEEK_SET); + + // Read the image into dummy seq and static dib_a + readPCX(_sceneryArchive2, &seq, _vm.screen().getFrontBuffer(), true, _vm._screenNames[screenIndex]); + } +} + +void FileManager_v4::openDatabaseFiles() { + debugC(1, kDebugFile, "openDatabaseFiles"); + + if (!_stringArchive.open(STRING_FILE)) + Utils::Error(FILE_ERR, "%s", STRING_FILE); + if (!_sceneryArchive1.open("scenery1.dat")) + Utils::Error(FILE_ERR, "%s", "scenery1.dat"); + if (!_sceneryArchive2.open("scenery2.dat")) + Utils::Error(FILE_ERR, "%s", "scenery2.dat"); + if (!_objectsArchive.open(OBJECTS_FILE)) + Utils::Error(FILE_ERR, "%s", OBJECTS_FILE); +} + +void FileManager_v4::closeDatabaseFiles() { + debugC(1, kDebugFile, "closeDatabaseFiles"); + + _stringArchive.close(); + _sceneryArchive1.close(); + _sceneryArchive2.close(); + _objectsArchive.close(); +} + +void FileManager_v4::readOverlay(int screenNum, image_pt image, ovl_t overlayType) { +// Open and read in an overlay file, close file + uint32 i = 0; + int16 j, k; + int8 data; // Must be 8 bits signed + image_pt tmpImage = image; // temp ptr to overlay file + sceneBlock_t sceneBlock; // Database header entry + Common::File sceneryArchive; + + debugC(1, kDebugFile, "readOverlay(%d, ...)", screenNum); + + _sceneryArchive1.seek((uint32)screenNum * sizeof(sceneBlock_t), SEEK_SET); + + sceneBlock.scene_off = _sceneryArchive1.readUint32LE(); + sceneBlock.scene_len = _sceneryArchive1.readUint32LE(); + sceneBlock.b_off = _sceneryArchive1.readUint32LE(); + sceneBlock.b_len = _sceneryArchive1.readUint32LE(); + sceneBlock.o_off = _sceneryArchive1.readUint32LE(); + sceneBlock.o_len = _sceneryArchive1.readUint32LE(); + sceneBlock.ob_off = _sceneryArchive1.readUint32LE(); + sceneBlock.ob_len = _sceneryArchive1.readUint32LE(); + + if (screenNum < 20) { + switch (overlayType) { + case BOUNDARY: + _sceneryArchive1.seek(sceneBlock.b_off, SEEK_SET); + i = sceneBlock.b_len; + break; + case OVERLAY: + _sceneryArchive1.seek(sceneBlock.o_off, SEEK_SET); + i = sceneBlock.o_len; + break; + case OVLBASE: + _sceneryArchive1.seek(sceneBlock.ob_off, SEEK_SET); + i = sceneBlock.ob_len; + break; + default: + Utils::Error(FILE_ERR, "%s", "Bad ovl_type"); + break; + } + if (i == 0) { + for (i = 0; i < OVL_SIZE; i++) + image[i] = 0; + return; + } + + // Read in the overlay file using MAC Packbits. (We're not proud!) + k = 0; // byte count + do { + data = _sceneryArchive1.readByte(); // Read a code byte + if ((byte)data == 0x80) // Noop + k = k; + else if (data >= 0) { // Copy next data+1 literally + for (i = 0; i <= (byte)data; i++, k++) + *tmpImage++ = _sceneryArchive1.readByte(); + } else { // Repeat next byte -data+1 times + j = _sceneryArchive1.readByte(); + + for (i = 0; i < (byte)(-data + 1); i++, k++) + *tmpImage++ = j; + } + } while (k < OVL_SIZE); + } else { + switch (overlayType) { + case BOUNDARY: + _sceneryArchive2.seek(sceneBlock.b_off, SEEK_SET); + i = sceneBlock.b_len; + break; + case OVERLAY: + _sceneryArchive2.seek(sceneBlock.o_off, SEEK_SET); + i = sceneBlock.o_len; + break; + case OVLBASE: + _sceneryArchive2.seek(sceneBlock.ob_off, SEEK_SET); + i = sceneBlock.ob_len; + break; + default: + Utils::Error(FILE_ERR, "%s", "Bad ovl_type"); + break; + } + if (i == 0) { + for (i = 0; i < OVL_SIZE; i++) + image[i] = 0; + return; + } + + // Read in the overlay file using MAC Packbits. (We're not proud!) + k = 0; // byte count + do { + data = _sceneryArchive2.readByte(); // Read a code byte + if ((byte)data == 0x80) // Noop + k = k; + else if (data >= 0) { // Copy next data+1 literally + for (i = 0; i <= (byte)data; i++, k++) + *tmpImage++ = _sceneryArchive2.readByte(); + } else { // Repeat next byte -data+1 times + j = _sceneryArchive2.readByte(); + + for (i = 0; i < (byte)(-data + 1); i++, k++) + *tmpImage++ = j; + } + } while (k < OVL_SIZE); + } +} } // End of namespace Hugo + diff --git a/engines/hugo/file.h b/engines/hugo/file.h index c044a7307f..71bd0bf75c 100644 --- a/engines/hugo/file.h +++ b/engines/hugo/file.h @@ -42,38 +42,41 @@ namespace Hugo { class FileManager { public: FileManager(HugoEngine &vm); + virtual ~FileManager(); bool fileExists(char *filename); - char *fetchString(int index); - sound_pt getSound(short sound, uint16 *size); void closePlaybackFile(); - void closeDatabaseFiles(); void initSavedGame(); void instructions(); - void openDatabaseFiles(); - void readBackground(int screenIndex); void readBootFile(); void readImage(int objNum, object_t *objPtr); - void readOverlay(int screenNum, image_pt image, ovl_t overlayType); void readUIFItem(short id, byte *buf); void restoreGame(short slot); void restoreSeq(object_t *obj); void saveGame(short slot, const char *descrip); void saveSeq(object_t *obj); -private: + virtual void openDatabaseFiles() = 0; + virtual void closeDatabaseFiles() = 0; + + virtual void readBackground(int screenIndex) = 0; + virtual void readOverlay(int screenNum, image_pt image, ovl_t overlayType) = 0; + +protected: HugoEngine &_vm; Common::File _stringArchive; /* Handle for string file */ - Common::File _sceneryArchive; /* Handle for scenery file */ + Common::File _sceneryArchive1; /* Handle for scenery file */ Common::File _objectsArchive; /* Handle for objects file */ - byte *convertPCC(byte *p, uint16 y, uint16 bpl, image_pt data_p); seq_t *readPCX(Common::File &f, seq_t *seqPtr, byte *imagePtr, bool firstFl, const char *name); +private: + + byte *convertPCC(byte *p, uint16 y, uint16 bpl, image_pt data_p); uif_hdr_t *getUIFHeader(uif_t id); //Strangerke : Not used? @@ -83,6 +86,51 @@ private: // char pbget(); }; -} // End of namespace Hugo +class FileManager_v1 : public FileManager { +public: + FileManager_v1(HugoEngine &vm); + ~FileManager_v1(); + void openDatabaseFiles(); + void closeDatabaseFiles(); + void readBackground(int screenIndex); + void readOverlay(int screenNum, image_pt image, ovl_t overlayType); +}; + +class FileManager_v2 : public FileManager { +public: + FileManager_v2(HugoEngine &vm); + ~FileManager_v2(); + + void openDatabaseFiles(); + void closeDatabaseFiles(); + void readBackground(int screenIndex); + void readOverlay(int screenNum, image_pt image, ovl_t overlayType); +}; + +class FileManager_v3 : public FileManager { +public: + FileManager_v3(HugoEngine &vm); + ~FileManager_v3(); + + void openDatabaseFiles(); + void closeDatabaseFiles(); + void readBackground(int screenIndex); + void readOverlay(int screenNum, image_pt image, ovl_t overlayType); +}; + +class FileManager_v4 : public FileManager { +public: + FileManager_v4(HugoEngine &vm); + ~FileManager_v4(); + + void openDatabaseFiles(); + void closeDatabaseFiles(); + void readBackground(int screenIndex); + void readOverlay(int screenNum, image_pt image, ovl_t overlayType); +private: + Common::File _sceneryArchive2; /* Handle for scenery file */ + +}; +} // End of namespace Hugo #endif //HUGO_FILE_H diff --git a/engines/hugo/global.h b/engines/hugo/global.h index 110a5957fe..1437eb3734 100644 --- a/engines/hugo/global.h +++ b/engines/hugo/global.h @@ -37,12 +37,10 @@ namespace Hugo { #define DESCRIPLEN 32 /* Length of description string */ #define MAX_SOUNDS 64 /* Max number of sounds */ #define BOOTFILE "HUGO.BSF" /* Name of boot structure file */ -#define CONFIGFILE "CONFIG.DAT" /* Name of config file */ #define LEN_MASK 0x3F /* Lower 6 bits are length */ #define PBFILE "playback.dat" /* Name scenery and objects picture databases */ -#define SCENERY_FILE "scenery.dat" #define OBJECTS_FILE "objects.dat" #define STRING_FILE "strings.dat" #define SOUND_FILE "sounds.dat" diff --git a/engines/hugo/hugo.cpp b/engines/hugo/hugo.cpp index 58f4dc444e..316c16f018 100644 --- a/engines/hugo/hugo.cpp +++ b/engines/hugo/hugo.cpp @@ -140,7 +140,6 @@ Common::Error HugoEngine::run() { s_Engine = this; initGraphics(320, 200, false); - _fileManager = new FileManager(*this); _screen = new Screen(*this); _mouseHandler = new MouseHandler(*this); _inventoryHandler = new InventoryHandler(*this); @@ -149,27 +148,33 @@ Common::Error HugoEngine::run() { _soundHandler = new SoundHandler(*this); switch (_gameVariant) { - case 0: + case 0: // H1 Win + _fileManager = new FileManager_v3(*this); _scheduler = new Scheduler_v2(*this); _introHandler = new intro_1w(*this); break; case 1: + _fileManager = new FileManager_v2(*this); _scheduler = new Scheduler_v2(*this); _introHandler = new intro_2w(*this); break; case 2: + _fileManager = new FileManager_v2(*this); _scheduler = new Scheduler_v2(*this); _introHandler = new intro_3w(*this); break; - case 3: + case 3: // H1 DOS + _fileManager = new FileManager_v1(*this); _scheduler = new Scheduler_v1(*this); _introHandler = new intro_1d(*this); break; case 4: + _fileManager = new FileManager_v2(*this); _scheduler = new Scheduler_v1(*this); _introHandler = new intro_2d(*this); break; case 5: + _fileManager = new FileManager_v4(*this); _scheduler = new Scheduler_v2(*this); _introHandler = new intro_3d(*this); break; diff --git a/engines/kyra/kyra_v1.h b/engines/kyra/kyra_v1.h index f05e113456..d077d3a3b0 100644 --- a/engines/kyra/kyra_v1.h +++ b/engines/kyra/kyra_v1.h @@ -387,6 +387,7 @@ protected: bool canSaveGameStateCurrently() { return _isSaveAllowed; } const char *getSavegameFilename(int num); + Common::String _savegameFilename; static Common::String getSavegameFilename(const Common::String &target, int num); bool saveFileLoadable(int slot); diff --git a/engines/kyra/saveload.cpp b/engines/kyra/saveload.cpp index 56e1c73d0a..b1cc954137 100644 --- a/engines/kyra/saveload.cpp +++ b/engines/kyra/saveload.cpp @@ -224,9 +224,8 @@ Common::WriteStream *KyraEngine_v1::openSaveForWriting(const char *filename, con } const char *KyraEngine_v1::getSavegameFilename(int num) { - static Common::String filename; - filename = getSavegameFilename(_targetName, num); - return filename.c_str(); + _savegameFilename = getSavegameFilename(_targetName, num); + return _savegameFilename.c_str(); } Common::String KyraEngine_v1::getSavegameFilename(const Common::String &target, int num) { diff --git a/engines/kyra/text_lol.cpp b/engines/kyra/text_lol.cpp index d5264be483..7f9531507c 100644 --- a/engines/kyra/text_lol.cpp +++ b/engines/kyra/text_lol.cpp @@ -204,10 +204,12 @@ void TextDisplayer_LoL::printDialogueText(int dim, char *str, EMCState *script, } void TextDisplayer_LoL::printMessage(uint16 type, const char *str, ...) { - static uint8 textColors256[] = { 0xfe, 0xa2, 0x84, 0x97, 0x9F }; - static uint8 textColors16[] = { 0x33, 0xaa, 0x88, 0x55, 0x99 }; - static uint8 soundEffect[] = { 0x0B, 0x00, 0x2B, 0x1B, 0x00 }; + static const uint8 textColors256[] = { 0xfe, 0xa2, 0x84, 0x97, 0x9F }; + static const uint8 textColors16[] = { 0x33, 0xaa, 0x88, 0x55, 0x99 }; + static const uint8 soundEffect[] = { 0x0B, 0x00, 0x2B, 0x1B, 0x00 }; + const uint8 *textColors = _vm->gameFlags().use16ColorMode ? textColors16 : textColors256; + if (type & 4) type ^= 4; else diff --git a/engines/sci/engine/kscripts.cpp b/engines/sci/engine/kscripts.cpp index ef99c4cc85..a975ce2988 100644 --- a/engines/sci/engine/kscripts.cpp +++ b/engines/sci/engine/kscripts.cpp @@ -143,23 +143,23 @@ reg_t kResCheck(EngineState *s, int argc, reg_t *argv) { } reg_t kClone(EngineState *s, int argc, reg_t *argv) { - reg_t parent_addr = argv[0]; - const Object *parent_obj = s->_segMan->getObject(parent_addr); - const bool parentIsClone = parent_obj->isClone(); - reg_t clone_addr; - Clone *clone_obj; // same as Object* - - if (!parent_obj) { - error("Attempt to clone non-object/class at %04x:%04x failed", PRINT_REG(parent_addr)); + reg_t parentAddr = argv[0]; + const Object *parentObj = s->_segMan->getObject(parentAddr); + reg_t cloneAddr; + Clone *cloneObj; // same as Object* + + if (!parentObj) { + error("Attempt to clone non-object/class at %04x:%04x failed", PRINT_REG(parentAddr)); return NULL_REG; } - debugC(2, kDebugLevelMemory, "Attempting to clone from %04x:%04x", PRINT_REG(parent_addr)); + debugC(2, kDebugLevelMemory, "Attempting to clone from %04x:%04x", PRINT_REG(parentAddr)); - clone_obj = s->_segMan->allocateClone(&clone_addr); + uint16 infoSelector = readSelectorValue(s->_segMan, parentAddr, SELECTOR(_info_)); + cloneObj = s->_segMan->allocateClone(&cloneAddr); - if (!clone_obj) { - error("Cloning %04x:%04x failed-- internal error", PRINT_REG(parent_addr)); + if (!cloneObj) { + error("Cloning %04x:%04x failed-- internal error", PRINT_REG(parentAddr)); return NULL_REG; } @@ -168,24 +168,25 @@ reg_t kClone(EngineState *s, int argc, reg_t *argv) { // invalidate all pointers, references and iterators to data in the clones // segment. // - // The reason why it might invalidate those is, that the segement code + // The reason why it might invalidate those is, that the segment code // (Table) uses Common::Array for internal storage. Common::Array now // might invalidate references to its contained data, when it has to // extend the internal storage size. - if (parentIsClone) - parent_obj = s->_segMan->getObject(parent_addr); + if (infoSelector & kInfoFlagClone) + parentObj = s->_segMan->getObject(parentAddr); - *clone_obj = *parent_obj; + *cloneObj = *parentObj; // Mark as clone - clone_obj->markAsClone(); // sets bit 0 of -info- selector - clone_obj->setSpeciesSelector(clone_obj->getPos()); - if (parent_obj->isClass()) - clone_obj->setSuperClassSelector(parent_obj->getPos()); - s->_segMan->getScript(parent_obj->getPos().segment)->incrementLockers(); - s->_segMan->getScript(clone_obj->getPos().segment)->incrementLockers(); - - return clone_addr; + writeSelectorValue(s->_segMan, cloneAddr, SELECTOR(_info_), infoSelector | kInfoFlagClone); + + cloneObj->setSpeciesSelector(cloneObj->getPos()); + if (parentObj->isClass()) + cloneObj->setSuperClassSelector(parentObj->getPos()); + s->_segMan->getScript(parentObj->getPos().segment)->incrementLockers(); + s->_segMan->getScript(cloneObj->getPos().segment)->incrementLockers(); + + return cloneAddr; } extern void _k_view_list_mark_free(EngineState *s, reg_t off); diff --git a/engines/sci/engine/script_patches.cpp b/engines/sci/engine/script_patches.cpp index fbd58cf20c..810e47b379 100644 --- a/engines/sci/engine/script_patches.cpp +++ b/engines/sci/engine/script_patches.cpp @@ -183,6 +183,31 @@ const SciScriptSignature ecoquest2Signatures[] = { }; // =========================================================================== +// script 0 of freddy pharkas/CD PointsSound::check waits for a signal and if +// no signal received will call kDoSound(0xD) which is a dummy in sierra sci +// and ScummVM and will use acc (which is not set by the dummy) to trigger +// sound disposal. This somewhat worked in sierra sci, because the sample +// was already playing in the sound driver. In our case we would also stop +// the sample from playing, so we patch it out +// The "score" code is already buggy and sets volume to 0 when playing +const byte freddypharkasSignatureScoreDisposal[] = { + 10, + 0x67, 0x32, // pTos 32 (selector theAudCount) + 0x78, // push1 + 0x39, 0x0d, // pushi 0d + 0x43, 0x75, 0x02, // call kDoAudio + 0x1c, // ne? + 0x31, // bnt (-> to skip disposal) + 0 +}; + +const uint16 freddypharkasPatchScoreDisposal[] = { + 0x34, 0x00, 0x00, // ldi 0000 + 0x34, 0x00, 0x00, // ldi 0000 + 0x34, 0x00, 0x00, // ldi 0000 + PATCH_END +}; + // script 215 of freddy pharkas lowerLadder::doit and highLadder::doit actually // process keyboard-presses when the ladder is on the screen in that room. // They strangely also call kGetEvent. Because the main User::doit also calls @@ -219,9 +244,10 @@ const uint16 freddypharkasPatchLadderEvent[] = { // script, description, magic DWORD, adjust const SciScriptSignature freddypharkasSignatures[] = { + { 0, "CD: score early disposal", PATCH_MAGICDWORD(0x39, 0x0d, 0x43, 0x75), -3, freddypharkasSignatureScoreDisposal, freddypharkasPatchScoreDisposal }, // this is not a typo, both lowerLadder::doit and highLadder::doit have the same event code - { 320, "lower ladder event issue", PATCH_MAGICDWORD(0x6d, 0x76, 0x38, 0xf5), -1, freddypharkasSignatureLadderEvent, freddypharkasPatchLadderEvent }, - { 320, "high ladder event issue", PATCH_MAGICDWORD(0x6d, 0x76, 0x38, 0xf5), -1, freddypharkasSignatureLadderEvent, freddypharkasPatchLadderEvent }, + { 320, "lower ladder event issue", PATCH_MAGICDWORD(0x6d, 0x76, 0x38, 0xf5), -1, freddypharkasSignatureLadderEvent, freddypharkasPatchLadderEvent }, + { 320, "high ladder event issue", PATCH_MAGICDWORD(0x6d, 0x76, 0x38, 0xf5), -1, freddypharkasSignatureLadderEvent, freddypharkasPatchLadderEvent }, SCI_SIGNATUREENTRY_TERMINATOR }; diff --git a/engines/sci/engine/segment.h b/engines/sci/engine/segment.h index 3c7addfab2..6eca708e2e 100644 --- a/engines/sci/engine/segment.h +++ b/engines/sci/engine/segment.h @@ -290,9 +290,6 @@ public: bool isClass() const { return (getInfoSelector().offset & kInfoFlagClass); } const Object *getClass(SegManager *segMan) const; - void markAsClone() { setInfoSelector(make_reg(0, getInfoSelector().offset | kInfoFlagClone)); } - bool isClone() const { return (getInfoSelector().offset & kInfoFlagClone); } - void markAsFreed() { _flags |= OBJECT_FLAG_FREED; } bool isFreed() const { return _flags & OBJECT_FLAG_FREED; } diff --git a/engines/sci/sound/music.cpp b/engines/sci/sound/music.cpp index fe1d4fdbbb..e2540e1a8f 100644 --- a/engines/sci/sound/music.cpp +++ b/engines/sci/sound/music.cpp @@ -352,20 +352,25 @@ void SciMusic::soundPlay(MusicEntry *pSnd) { } } - if (pSnd->pStreamAud && !_pMixer->isSoundHandleActive(pSnd->hCurrentAud)) { - if (pSnd->loop > 1) { - pSnd->pLoopStream = new Audio::LoopingAudioStream(pSnd->pStreamAud, - pSnd->loop, DisposeAfterUse::NO); - _pMixer->playStream(pSnd->soundType, &pSnd->hCurrentAud, - pSnd->pLoopStream, -1, pSnd->volume, 0, - DisposeAfterUse::NO); - } else { - // Rewind in case we play the same sample multiple times - // (non-looped) like in pharkas right at the start - pSnd->pStreamAud->rewind(); - _pMixer->playStream(pSnd->soundType, &pSnd->hCurrentAud, - pSnd->pStreamAud, -1, pSnd->volume, 0, - DisposeAfterUse::NO); + if (pSnd->pStreamAud) { + if (!_pMixer->isSoundHandleActive(pSnd->hCurrentAud)) { + // Sierra SCI ignores volume set when playing samples via kDoSound + // At least freddy pharkas/CD has a script bug that sets volume to 0 + // when playing the "score" sample + if (pSnd->loop > 1) { + pSnd->pLoopStream = new Audio::LoopingAudioStream(pSnd->pStreamAud, + pSnd->loop, DisposeAfterUse::NO); + _pMixer->playStream(pSnd->soundType, &pSnd->hCurrentAud, + pSnd->pLoopStream, -1, _pMixer->kMaxChannelVolume, 0, + DisposeAfterUse::NO); + } else { + // Rewind in case we play the same sample multiple times + // (non-looped) like in pharkas right at the start + pSnd->pStreamAud->rewind(); + _pMixer->playStream(pSnd->soundType, &pSnd->hCurrentAud, + pSnd->pStreamAud, -1, _pMixer->kMaxChannelVolume, 0, + DisposeAfterUse::NO); + } } } else { if (pSnd->pMidiParser) { @@ -415,7 +420,8 @@ void SciMusic::soundStop(MusicEntry *pSnd) { void SciMusic::soundSetVolume(MusicEntry *pSnd, byte volume) { assert(volume <= MUSIC_VOLUME_MAX); if (pSnd->pStreamAud) { - _pMixer->setChannelVolume(pSnd->hCurrentAud, volume * 2); // Mixer is 0-255, SCI is 0-127 + // we simply ignore volume changes for samples, because sierra sci also + // doesn't support volume for samples via kDoSound } else if (pSnd->pMidiParser) { _mutex.lock(); pSnd->pMidiParser->mainThreadBegin(); |