aboutsummaryrefslogtreecommitdiff
path: root/engines
diff options
context:
space:
mode:
Diffstat (limited to 'engines')
-rw-r--r--engines/hugo/file.cpp591
-rw-r--r--engines/hugo/file.h68
-rw-r--r--engines/hugo/global.h2
-rw-r--r--engines/hugo/hugo.cpp11
-rw-r--r--engines/kyra/kyra_v1.h1
-rw-r--r--engines/kyra/saveload.cpp5
-rw-r--r--engines/kyra/text_lol.cpp8
-rw-r--r--engines/sci/engine/kscripts.cpp49
-rw-r--r--engines/sci/engine/script_patches.cpp30
-rw-r--r--engines/sci/engine/segment.h3
-rw-r--r--engines/sci/sound/music.cpp36
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();