aboutsummaryrefslogtreecommitdiff
path: root/engines/mohawk
diff options
context:
space:
mode:
Diffstat (limited to 'engines/mohawk')
-rw-r--r--engines/mohawk/console.cpp43
-rw-r--r--engines/mohawk/console.h1
-rw-r--r--engines/mohawk/detection.cpp847
-rw-r--r--engines/mohawk/detection_tables.h1030
-rw-r--r--engines/mohawk/dialogs.cpp17
-rw-r--r--engines/mohawk/graphics.cpp53
-rw-r--r--engines/mohawk/graphics.h12
-rw-r--r--engines/mohawk/jpeg.cpp87
-rw-r--r--engines/mohawk/jpeg.h59
-rw-r--r--engines/mohawk/module.mk10
-rw-r--r--engines/mohawk/mohawk.cpp2
-rw-r--r--engines/mohawk/myst.cpp2
-rw-r--r--engines/mohawk/myst_pict.cpp272
-rw-r--r--engines/mohawk/myst_pict.h57
-rw-r--r--engines/mohawk/myst_scripts.cpp2
-rw-r--r--engines/mohawk/resource.cpp2
-rw-r--r--engines/mohawk/riven.cpp119
-rw-r--r--engines/mohawk/riven.h20
-rw-r--r--engines/mohawk/riven_external.cpp258
-rw-r--r--engines/mohawk/riven_external.h3
-rw-r--r--engines/mohawk/riven_saveload.cpp67
-rw-r--r--engines/mohawk/riven_saveload.h3
-rw-r--r--engines/mohawk/riven_scripts.cpp86
-rw-r--r--engines/mohawk/riven_scripts.h33
-rw-r--r--engines/mohawk/riven_vars.cpp2
-rw-r--r--engines/mohawk/sound.cpp15
-rw-r--r--engines/mohawk/video.cpp415
-rw-r--r--engines/mohawk/video.h114
28 files changed, 2085 insertions, 1546 deletions
diff --git a/engines/mohawk/console.cpp b/engines/mohawk/console.cpp
index 389665db39..5dcfff4f90 100644
--- a/engines/mohawk/console.cpp
+++ b/engines/mohawk/console.cpp
@@ -28,9 +28,10 @@
#include "mohawk/myst_scripts.h"
#include "mohawk/graphics.h"
#include "mohawk/riven.h"
+#include "mohawk/riven_external.h"
#include "mohawk/livingbooks.h"
#include "mohawk/sound.h"
-#include "mohawk/video/video.h"
+#include "mohawk/video.h"
namespace Mohawk {
@@ -307,6 +308,7 @@ RivenConsole::RivenConsole(MohawkEngine_Riven *vm) : GUI::Debugger(), _vm(vm) {
DCmd_Register("dumpScript", WRAP_METHOD(RivenConsole, Cmd_DumpScript));
DCmd_Register("listZipCards", WRAP_METHOD(RivenConsole, Cmd_ListZipCards));
DCmd_Register("getRMAP", WRAP_METHOD(RivenConsole, Cmd_GetRMAP));
+ DCmd_Register("combos", WRAP_METHOD(RivenConsole, Cmd_Combos));
}
RivenConsole::~RivenConsole() {
@@ -556,9 +558,11 @@ bool RivenConsole::Cmd_DumpScript(int argc, const char **argv) {
printf ("==================================\n\n");
Common::SeekableReadStream *cardStream = _vm->getRawData(MKID_BE('CARD'), (uint16)atoi(argv[3]));
cardStream->seek(4);
- RivenScriptList scriptList = RivenScript::readScripts(_vm, cardStream);
- for (uint32 i = 0; i < scriptList.size(); i++)
+ RivenScriptList scriptList = _vm->_scriptMan->readScripts(cardStream, false);
+ for (uint32 i = 0; i < scriptList.size(); i++) {
scriptList[i]->dumpScript(varNames, xNames, 0);
+ delete scriptList[i];
+ }
delete cardStream;
} else if (!scumm_stricmp(argv[2], "HSPT")) {
printf ("\n\nDumping scripts for %s\'s card %d hotspots!\n", argv[1], (uint16)atoi(argv[3]));
@@ -571,9 +575,11 @@ bool RivenConsole::Cmd_DumpScript(int argc, const char **argv) {
for (uint16 i = 0; i < hotspotCount; i++) {
printf ("Hotspot %d:\n", i);
hsptStream->seek(22, SEEK_CUR); // Skip non-script related stuff
- RivenScriptList scriptList = RivenScript::readScripts(_vm, hsptStream);
- for (uint32 j = 0; j < scriptList.size(); j++)
+ RivenScriptList scriptList = _vm->_scriptMan->readScripts(hsptStream, false);
+ for (uint32 j = 0; j < scriptList.size(); j++) {
scriptList[j]->dumpScript(varNames, xNames, 1);
+ delete scriptList[j];
+ }
}
delete hsptStream;
@@ -608,6 +614,33 @@ bool RivenConsole::Cmd_GetRMAP(int argc, const char **argv) {
return true;
}
+bool RivenConsole::Cmd_Combos(int argc, const char **argv) {
+ // In the vain of SCUMM's 'drafts' command, this command will list
+ // out all combinations needed in Riven, decoded from the variables.
+ // You'll need to look up the Rebel Tunnel puzzle on your own; the
+ // solution is constant.
+
+ uint32 teleCombo = *_vm->matchVarToString("tcorrectorder");
+ uint32 prisonCombo = *_vm->matchVarToString("pcorrectorder");
+ uint32 domeCombo = *_vm->matchVarToString("adomecombo");
+
+ DebugPrintf("Telescope Combo:\n ");
+ for (int i = 0; i < 5; i++)
+ DebugPrintf("%d ", _vm->_externalScriptHandler->getComboDigit(teleCombo, i));
+
+ DebugPrintf("\nPrison Combo:\n ");
+ for (int i = 0; i < 5; i++)
+ DebugPrintf("%d ", _vm->_externalScriptHandler->getComboDigit(prisonCombo, i));
+
+ DebugPrintf("\nDome Combo:\n ");
+ for (int i = 1; i <= 25; i++)
+ if (domeCombo & (1 << (25 - i)))
+ DebugPrintf("%d ", i);
+
+ DebugPrintf("\n");
+ return true;
+}
+
LivingBooksConsole::LivingBooksConsole(MohawkEngine_LivingBooks *vm) : GUI::Debugger(), _vm(vm) {
DCmd_Register("playSound", WRAP_METHOD(LivingBooksConsole, Cmd_PlaySound));
DCmd_Register("stopSound", WRAP_METHOD(LivingBooksConsole, Cmd_StopSound));
diff --git a/engines/mohawk/console.h b/engines/mohawk/console.h
index 9a30d46225..1806c61027 100644
--- a/engines/mohawk/console.h
+++ b/engines/mohawk/console.h
@@ -88,6 +88,7 @@ private:
bool Cmd_DumpScript(int argc, const char **argv);
bool Cmd_ListZipCards(int argc, const char **argv);
bool Cmd_GetRMAP(int argc, const char **argv);
+ bool Cmd_Combos(int argc, const char **argv);
};
class LivingBooksConsole : public GUI::Debugger {
diff --git a/engines/mohawk/detection.cpp b/engines/mohawk/detection.cpp
index a7b1fe7fae..f04338239f 100644
--- a/engines/mohawk/detection.cpp
+++ b/engines/mohawk/detection.cpp
@@ -117,846 +117,21 @@ static const PlainGameDescriptor mohawkGames[] = {
{"ruff", "Ruff's Bone"},
{"newkid", "The New Kid on the Block"},
{"arthurrace", "Arthur's Reading Race"},
+ {"arthurbday", "Arthur's Birthday"},
+ {"lilmonster", "Little Monster at School"},
#endif
{0, 0}
};
+#include "mohawk/detection_tables.h"
-namespace Mohawk {
-
-static const MohawkGameDescription gameDescriptions[] = {
- // Myst
- // English Windows 3.11
- // From clone2727
- {
- {
- "myst",
- "",
- AD_ENTRY1("MYST.DAT", "ae3258c9c90128d274aa6a790b3ad181"),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_NO_FLAGS,
- Common::GUIO_NONE
- },
- GType_MYST,
- 0,
- 0,
- },
-
- // Myst Demo
- // English Windows 3.11
- // From CD-ROM Today July, 1994
- {
- {
- "myst",
- "Demo",
- AD_ENTRY1("DEMO.DAT", "c39303dd53fb5c4e7f3c23231c606cd0"),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_DEMO,
- Common::GUIO_NONE
- },
- GType_MYST,
- GF_DEMO,
- 0,
- },
-
- // Myst
- // German Windows 3.11
- // From clone2727
- {
- {
- "myst",
- "",
- AD_ENTRY1("MYST.DAT", "4beb3366ed3f3b9bfb6e81a14a43bdcc"),
- Common::DE_DEU,
- Common::kPlatformWindows,
- ADGF_NO_FLAGS,
- Common::GUIO_NONE
- },
- GType_MYST,
- 0,
- 0,
- },
-
- // Myst
- // German Windows 3.11
- // From LordHoto
- {
- {
- "myst",
- "",
- AD_ENTRY1("MYST.DAT", "e0937cca1ab125e48e30dc3cd5046ddf"),
- Common::DE_DEU,
- Common::kPlatformWindows,
- ADGF_NO_FLAGS,
- Common::GUIO_NONE
- },
- GType_MYST,
- 0,
- 0,
- },
-
- // Myst
- // Spanish Windows ?
- // From jvprat
- {
- {
- "myst",
- "",
- AD_ENTRY1("MYST.DAT", "f7e7d7ca69934f1351b5acd4fe4d44c2"),
- Common::ES_ESP,
- Common::kPlatformWindows,
- ADGF_NO_FLAGS,
- Common::GUIO_NONE
- },
- GType_MYST,
- 0,
- 0,
- },
-
- // Myst
- // Japanese Windows 3.11
- // From clone2727
- {
- {
- "myst",
- "",
- AD_ENTRY1("MYST.DAT", "032c88e3b7e8db4ca475e7b7db9a66bb"),
- Common::JA_JPN,
- Common::kPlatformWindows,
- ADGF_NO_FLAGS,
- Common::GUIO_NONE
- },
- GType_MYST,
- 0,
- 0,
- },
-
- // Myst
- // French Windows 3.11
- // From Strangerke
- {
- {
- "myst",
- "",
- AD_ENTRY1("MYST.DAT", "d631d42567a941c67c78f2e491f4ea58"),
- Common::FR_FRA,
- Common::kPlatformWindows,
- ADGF_NO_FLAGS,
- Common::GUIO_NONE
- },
- GType_MYST,
- 0,
- 0,
- },
-
- // Making of Myst
- // English Windows 3.11
- // From clone2727
- {
- {
- "MakingOfMyst",
- "",
- AD_ENTRY1("MAKING.DAT", "f6387e8f0f7b8a3e42c95294315d6a0e"),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_NO_FLAGS,
- Common::GUIO_NONE
- },
- GType_MAKINGOF,
- 0,
- 0,
- },
-
- // Making of Myst
- // Japanese Windows 3.11
- // From clone2727
- {
- {
- "MakingOfMyst",
- "",
- AD_ENTRY1("MAKING.DAT", "03ff62607e64419ab2b6ebf7b7bcdf63"),
- Common::JA_JPN,
- Common::kPlatformWindows,
- ADGF_NO_FLAGS,
- Common::GUIO_NONE
- },
- GType_MAKINGOF,
- 0,
- 0,
- },
-
- // Myst Masterpiece Edition
- // English Windows
- // From clone2727
- {
- {
- "myst",
- "Masterpiece Edition",
- AD_ENTRY1("MYST.DAT", "c4cae9f143b5947262e6cb2397e1617e"),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_NO_FLAGS,
- Common::GUIO_NONE
- },
- GType_MYST,
- GF_ME,
- 0,
- },
-
- // Myst Masterpiece Edition
- // English Windows
- // From clone2727
- {
- {
- "myst",
- "Masterpiece Edition",
- AD_ENTRY1("MYST.DAT", "c4cae9f143b5947262e6cb2397e1617e"),
- Common::EN_ANY,
- Common::kPlatformMacintosh,
- ADGF_NO_FLAGS,
- Common::GUIO_NONE
- },
- GType_MYST,
- GF_ME,
- 0,
- },
-
- // Myst Masterpiece Edition
- // German Windows
- // From DrMcCoy (Included in "Myst: Die Trilogie")
- {
- {
- "myst",
- "Masterpiece Edition",
- AD_ENTRY1("MYST.DAT", "f88e0ace66dbca78eebdaaa1d3314ceb"),
- Common::DE_DEU,
- Common::kPlatformWindows,
- ADGF_NO_FLAGS,
- Common::GUIO_NONE
- },
- GType_MYST,
- GF_ME,
- 0,
- },
-
- // Riven: The Sequel to Myst
- // Version 1.0 (5CD)
- // From clone2727
- {
- {
- "riven",
- "",
- AD_ENTRY1("a_Data.MHK", "71145fdecbd68a0cfc292c2fbddf8e08"),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_NO_FLAGS,
- Common::GUIO_NONE
- },
- GType_RIVEN,
- 0,
- 0,
- },
-
- // Riven: The Sequel to Myst
- // Version 1.03 (5CD)
- // From ST
- {
- {
- "riven",
- "",
- AD_ENTRY1("a_Data.MHK", "d8ccae34a0e3c709135a73f449b783be"),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_NO_FLAGS,
- Common::GUIO_NONE
- },
- GType_RIVEN,
- 0,
- 0,
- },
-
- // Riven: The Sequel to Myst
- // Version 1.? (5CD)
- // From jvprat
- {
- {
- "riven",
- "",
- AD_ENTRY1("a_Data.MHK", "249e8c995d191b03ee94c892c0eac775"),
- Common::ES_ESP,
- Common::kPlatformWindows,
- ADGF_NO_FLAGS,
- Common::GUIO_NONE
- },
- GType_RIVEN,
- 0,
- 0,
- },
-
- // Riven: The Sequel to Myst
- // Version 1.? (DVD, From "Myst 10th Anniversary Edition")
- // From Clone2727
- {
- {
- "riven",
- "DVD",
- AD_ENTRY1("a_Data.MHK", "08fcaa5d5a2a01d7a5a6960f497212fe"),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_NO_FLAGS,
- Common::GUIO_NONE
- },
- GType_RIVEN,
- GF_DVD,
- 0,
- },
-
- // Riven: The Sequel to Myst
- // Version 1.0 (DVD, From "Myst: Die Trilogie")
- // From DrMcCoy
- {
- {
- "riven",
- "",
- AD_ENTRY1("a_Data.MHK", "a5fe1c91a6033eb6ee54b287578b74b9"),
- Common::DE_DEU,
- Common::kPlatformWindows,
- ADGF_NO_FLAGS,
- Common::GUIO_NONE
- },
- GType_RIVEN,
- GF_DVD,
- 0,
- },
-
- // Riven: The Sequel to Myst
- // Version ? (Demo, From "Prince of Persia Collector's Edition")
- // From Clone2727
- {
- {
- "riven",
- "Demo",
- AD_ENTRY1("a_Data.MHK", "bae6b03bd8d6eb350d35fd13f0e3139f"),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_DEMO,
- Common::GUIO_NONE
- },
- GType_RIVEN,
- GF_DEMO,
- 0,
- },
-
-#ifdef DETECT_BRODERBUND_TITLES
- {
- {
- "zoombini",
- "",
- AD_ENTRY1("ZOOMBINI.MHK", "98b758fec55104c096cfd129048be9a6"),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_NO_FLAGS,
- Common::GUIO_NONE
- },
- GType_ZOOMBINI,
- GF_HASMIDI,
- 0
- },
-
- {
- {
- "csworld",
- "v3.0",
- AD_ENTRY1("C2K.MHK", "605fe88380848031bbd0ff84ade6fe40"),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_NO_FLAGS,
- Common::GUIO_NONE
- },
- GType_CSWORLD,
- 0,
- 0
- },
-
- {
- {
- "csworld",
- "v3.5",
- AD_ENTRY1("C2K.MHK", "d4857aeb0f5e2e0c4ac556aa74f38c23"),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_NO_FLAGS,
- Common::GUIO_NONE
- },
- GType_CSWORLD,
- 0,
- 0
- },
-
- {
- {
- "csamtrak",
- "",
- AD_ENTRY1("AMTRAK.MHK", "2f95301f0bb950d555bb7b0e3b1b7eb1"),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_NO_FLAGS,
- Common::GUIO_NONE
- },
- GType_CSAMTRAK,
- 0,
- 0
- },
-
- {
- {
- "maggiess",
- "",
- AD_ENTRY1("MAGGIESS.MHK", "08f75fc8c0390e68fdada5ddb35d0355"),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_NO_FLAGS,
- Common::GUIO_NONE
- },
- GType_MAGGIESS,
- 0,
- 0
- },
-
- {
- {
- "jamesmath",
- "",
- AD_ENTRY1("BRODER.MHK", "007299da8b2c6e8ec1cde9598c243024"),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_NO_FLAGS,
- Common::GUIO_NONE
- },
- GType_JAMESMATH,
- GF_HASMIDI,
- 0
- },
-
- // This is in the NEWDATA folder, so I assume it's a newer version ;)
- {
- {
- "jamesmath",
- "",
- AD_ENTRY1("BRODER.MHK", "53c000938a50dca92860fd9b546dd276"),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_NO_FLAGS,
- Common::GUIO_NONE
- },
- GType_JAMESMATH,
- GF_HASMIDI,
- 1
- },
-
- {
- {
- "treehouse",
- "",
- AD_ENTRY1("MAINROOM.MHK", "12f51894d7f838af639ea9bf1bc8f45b"),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_NO_FLAGS,
- Common::GUIO_NONE
- },
- GType_TREEHOUSE,
- GF_HASMIDI,
- 0
- },
-
- {
- {
- "greeneggs",
- "",
- AD_ENTRY1("GREEN.LB", "5df8438138186f89e71299d7b4f88d06"),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_NO_FLAGS,
- Common::GUIO_NONE
- },
- GType_LIVINGBOOKSV3,
- 0,
- 0
- },
-
- // 32-bit version of the previous entry
- {
- {
- "greeneggs",
- "",
- AD_ENTRY1("GREEN32.LB", "5df8438138186f89e71299d7b4f88d06"),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_NO_FLAGS,
- Common::GUIO_NONE
- },
- GType_LIVINGBOOKSV3,
- 0,
- 0
- },
-
- {
- {
- "1stdegree",
- "",
- AD_ENTRY1("AL236_1.MHK", "3ba145492a7b8b4dee0ef4222c5639c3"),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_NO_FLAGS,
- Common::GUIO_NONE
- },
- GType_1STDEGREE,
- GF_HASMIDI,
- 0
- },
-
- // In The 1st Degree
- // French Windows
- // From Strangerke
- {
- {
- "1stdegree",
- "",
- AD_ENTRY1("AL236_1.MHK", "0e0c70b1b702b6ddca61a1192ada1282"),
- Common::FR_FRA,
- Common::kPlatformWindows,
- ADGF_NO_FLAGS,
- Common::GUIO_NONE
- },
- GType_1STDEGREE,
- GF_HASMIDI,
- 0
- },
-
- {
- {
- "csusa",
- "",
- AD_ENTRY1("USAC2K.MHK", "b8c9d3a2586f62bce3a48b50d7a700e9"),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_NO_FLAGS,
- Common::GUIO_NONE
- },
- GType_CSUSA,
- 0,
- 0
- },
-
- {
- {
- "tortoise",
- "Demo v1.0",
- AD_ENTRY1("TORTOISE.512", "75d9a2f8339e423604a0c6e8177600a6"),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_DEMO,
- Common::GUIO_NONE
- },
- GType_LIVINGBOOKSV1,
- GF_DEMO,
- 0
- },
-
- {
- {
- "tortoise",
- "Demo v1.1",
- AD_ENTRY1("TORTOISE.512", "a38c99360e2bea3bfdec418469aef022"),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_DEMO,
- Common::GUIO_NONE
- },
- GType_LIVINGBOOKSV1,
- GF_DEMO,
- 0
- },
-
- {
- {
- "arthur",
- "",
- AD_ENTRY1("PAGES.512", "1550a361454ec452fe7d2328aac2003c"),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_NO_FLAGS,
- Common::GUIO_NONE
- },
- GType_LIVINGBOOKSV1,
- 0,
- 0
- },
-
- {
- {
- "arthur",
- "Demo",
- AD_ENTRY1("PAGES.512", "a4d68cef197af1416921ca5b2e0c1e31"),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_DEMO,
- Common::GUIO_NONE
- },
- GType_LIVINGBOOKSV1,
- GF_DEMO,
- 0
- },
-
- {
- {
- "arthur",
- "Demo",
- AD_ENTRY1("Bookoutline", "7e2691611ff4c7b89c05221736628059"),
- Common::EN_ANY,
- Common::kPlatformMacintosh,
- ADGF_DEMO,
- Common::GUIO_NONE
- },
- GType_LIVINGBOOKSV1,
- GF_DEMO,
- 0
- },
-
- {
- {
- "grandma",
- "Demo v1.0",
- AD_ENTRY1("PAGES.512", "95d9f4b035bf5d15c57a9189f231b0f8"),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_DEMO,
- Common::GUIO_NONE
- },
- GType_LIVINGBOOKSV1,
- GF_DEMO,
- 0
- },
-
- {
- {
- "grandma",
- "Demo v1.1",
- AD_ENTRY1("GRANDMA.512", "72a4d5fb1b3f06b5f75425635d42ce2e"),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_DEMO,
- Common::GUIO_NONE
- },
- GType_LIVINGBOOKSV1,
- GF_DEMO,
- 0
- },
-
- {
- {
- "grandma",
- "Demo",
- AD_ENTRY1("Bookoutline", "553c93891b9631d1e1d269599e1efa6c"),
- Common::EN_ANY,
- Common::kPlatformMacintosh,
- ADGF_DEMO,
- Common::GUIO_NONE
- },
- GType_LIVINGBOOKSV1,
- GF_DEMO,
- 0
- },
-
- {
- {
- "ruff",
- "Demo",
- AD_ENTRY1("RUFF.512", "2ba1aa65177c816e156db648c398d362"),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_DEMO,
- Common::GUIO_NONE
- },
- GType_LIVINGBOOKSV1,
- GF_DEMO,
- 0
- },
-
- {
- {
- "ruff",
- "Demo",
- AD_ENTRY1("Ruff's Bone Demo", "22553ac2ceb2a166bdf1def6ad348532"),
- Common::EN_ANY,
- Common::kPlatformMacintosh,
- ADGF_DEMO,
- Common::GUIO_NONE
- },
- GType_LIVINGBOOKSV1,
- GF_DEMO,
- 0
- },
-
- {
- {
- "newkid",
- "Demo v1.0",
- AD_ENTRY1("NEWKID.512", "2b9d94763a50d514c04a3af488934f73"),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_DEMO,
- Common::GUIO_NONE
- },
- GType_LIVINGBOOKSV1,
- GF_DEMO,
- 0
- },
-
- {
- {
- "newkid",
- "Demo v1.1",
- AD_ENTRY1("NEWKID.512", "41e975b7390c626f8d1058a34f9d9b2e"),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_DEMO,
- Common::GUIO_NONE
- },
- GType_LIVINGBOOKSV1,
- GF_DEMO,
- 0
- },
-
- {
- {
- "arthurrace",
- "",
- AD_ENTRY1("RACE.LB", "1645f36bcb36e440d928e920aa48c373"),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_NO_FLAGS,
- Common::GUIO_NONE
- },
- GType_LIVINGBOOKSV3,
- 0,
- 0
- },
-
- // 32-bit version of the previous entry
- {
- {
- "arthurrace",
- "",
- AD_ENTRY1("RACE32.LB", "292a05bc48c1dd9583821a4181a02ef2"),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_NO_FLAGS,
- Common::GUIO_NONE
- },
- GType_LIVINGBOOKSV3,
- 0,
- 0
- },
-#endif
-
- { AD_TABLE_END_MARKER, 0, 0, 0 }
+static const char *directoryGlobs[] = {
+ "all",
+ "assets1",
+ "data",
+ 0
};
-//////////////////////////////
-//Fallback detection
-//////////////////////////////
-
-static const MohawkGameDescription fallbackDescs[] = {
- {
- {
- "myst",
- "unknown",
- AD_ENTRY1(0, 0),
- Common::UNK_LANG,
- Common::kPlatformWindows,
- ADGF_NO_FLAGS,
- Common::GUIO_NONE
- },
- GType_MYST,
- 0,
- 0
- },
-
- {
- {
- "MakingOfMyst",
- "unknown",
- AD_ENTRY1(0, 0),
- Common::UNK_LANG,
- Common::kPlatformWindows,
- ADGF_NO_FLAGS,
- Common::GUIO_NONE
- },
- GType_MAKINGOF,
- 0,
- 0
- },
-
- {
- {
- "myst",
- "unknown (Masterpiece Edition)",
- AD_ENTRY1(0, 0),
- Common::UNK_LANG,
- Common::kPlatformWindows,
- ADGF_NO_FLAGS,
- Common::GUIO_NONE
- },
- GType_MYST,
- GF_ME,
- 0
- },
-
- {
- {
- "riven",
- "unknown",
- AD_ENTRY1(0, 0),
- Common::UNK_LANG,
- Common::kPlatformWindows,
- ADGF_NO_FLAGS,
- Common::GUIO_NONE
- },
- GType_RIVEN,
- 0,
- 0
- },
-
- {
- {
- "riven",
- "unknown (DVD)",
- AD_ENTRY1(0, 0),
- Common::UNK_LANG,
- Common::kPlatformWindows,
- ADGF_NO_FLAGS,
- Common::GUIO_NONE
- },
- GType_RIVEN,
- GF_DVD,
- 0
- }
-};
-
-static const ADFileBasedFallback fileBased[] = {
- { &fallbackDescs[0], { "MYST.DAT", 0 } },
- { &fallbackDescs[1], { "MAKING.DAT", 0 } },
- { &fallbackDescs[2], { "MYST.DAT", "Help.dat", 0 } }, // Help system doesn't exist in original
- { &fallbackDescs[3], { "a_Data.MHK", 0 } },
- { &fallbackDescs[4], { "a_Data.MHK", "t_Data1.MHK" , 0 } },
- { 0, { 0 } }
-};
-
-} // End of namespace Mohawk
-
static const ADParams detectionParams = {
// Pointer to ADGameDescription or its superset structure
(const byte *)Mohawk::gameDescriptions,
@@ -975,7 +150,11 @@ static const ADParams detectionParams = {
// Flags
0,
// Additional GUI options (for every game)
- Common::GUIO_NONE
+ Common::GUIO_NONE,
+ // Maximum directory depth
+ 2,
+ // List of directory globs
+ directoryGlobs
};
class MohawkMetaEngine : public AdvancedMetaEngine {
diff --git a/engines/mohawk/detection_tables.h b/engines/mohawk/detection_tables.h
new file mode 100644
index 0000000000..7470dbf1dd
--- /dev/null
+++ b/engines/mohawk/detection_tables.h
@@ -0,0 +1,1030 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+namespace Mohawk {
+
+static const MohawkGameDescription gameDescriptions[] = {
+ // Myst
+ // English Windows 3.11
+ // From clone2727
+ {
+ {
+ "myst",
+ "",
+ AD_ENTRY1("MYST.DAT", "ae3258c9c90128d274aa6a790b3ad181"),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NONE
+ },
+ GType_MYST,
+ 0,
+ 0,
+ },
+
+ // Myst Demo
+ // English Windows 3.11
+ // From CD-ROM Today July, 1994
+ {
+ {
+ "myst",
+ "Demo",
+ AD_ENTRY1("DEMO.DAT", "c39303dd53fb5c4e7f3c23231c606cd0"),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_DEMO,
+ Common::GUIO_NONE
+ },
+ GType_MYST,
+ GF_DEMO,
+ 0,
+ },
+
+ // Myst
+ // German Windows 3.11
+ // From clone2727
+ {
+ {
+ "myst",
+ "",
+ AD_ENTRY1("MYST.DAT", "4beb3366ed3f3b9bfb6e81a14a43bdcc"),
+ Common::DE_DEU,
+ Common::kPlatformWindows,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NONE
+ },
+ GType_MYST,
+ 0,
+ 0,
+ },
+
+ // Myst
+ // German Windows 3.11
+ // From LordHoto
+ {
+ {
+ "myst",
+ "",
+ AD_ENTRY1("MYST.DAT", "e0937cca1ab125e48e30dc3cd5046ddf"),
+ Common::DE_DEU,
+ Common::kPlatformWindows,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NONE
+ },
+ GType_MYST,
+ 0,
+ 0,
+ },
+
+ // Myst
+ // Spanish Windows ?
+ // From jvprat
+ {
+ {
+ "myst",
+ "",
+ AD_ENTRY1("MYST.DAT", "f7e7d7ca69934f1351b5acd4fe4d44c2"),
+ Common::ES_ESP,
+ Common::kPlatformWindows,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NONE
+ },
+ GType_MYST,
+ 0,
+ 0,
+ },
+
+ // Myst
+ // Japanese Windows 3.11
+ // From clone2727
+ {
+ {
+ "myst",
+ "",
+ AD_ENTRY1("MYST.DAT", "032c88e3b7e8db4ca475e7b7db9a66bb"),
+ Common::JA_JPN,
+ Common::kPlatformWindows,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NONE
+ },
+ GType_MYST,
+ 0,
+ 0,
+ },
+
+ // Myst
+ // French Windows 3.11
+ // From Strangerke
+ {
+ {
+ "myst",
+ "",
+ AD_ENTRY1("MYST.DAT", "d631d42567a941c67c78f2e491f4ea58"),
+ Common::FR_FRA,
+ Common::kPlatformWindows,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NONE
+ },
+ GType_MYST,
+ 0,
+ 0,
+ },
+
+ // Making of Myst
+ // English Windows 3.11
+ // From clone2727
+ {
+ {
+ "MakingOfMyst",
+ "",
+ AD_ENTRY1("MAKING.DAT", "f6387e8f0f7b8a3e42c95294315d6a0e"),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NONE
+ },
+ GType_MAKINGOF,
+ 0,
+ 0,
+ },
+
+ // Making of Myst
+ // Japanese Windows 3.11
+ // From clone2727
+ {
+ {
+ "MakingOfMyst",
+ "",
+ AD_ENTRY1("MAKING.DAT", "03ff62607e64419ab2b6ebf7b7bcdf63"),
+ Common::JA_JPN,
+ Common::kPlatformWindows,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NONE
+ },
+ GType_MAKINGOF,
+ 0,
+ 0,
+ },
+
+ // Myst Masterpiece Edition
+ // English Windows
+ // From clone2727
+ {
+ {
+ "myst",
+ "Masterpiece Edition",
+ AD_ENTRY1("MYST.DAT", "c4cae9f143b5947262e6cb2397e1617e"),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NONE
+ },
+ GType_MYST,
+ GF_ME,
+ 0,
+ },
+
+ // Myst Masterpiece Edition
+ // English Windows
+ // From clone2727
+ {
+ {
+ "myst",
+ "Masterpiece Edition",
+ AD_ENTRY1("MYST.DAT", "c4cae9f143b5947262e6cb2397e1617e"),
+ Common::EN_ANY,
+ Common::kPlatformMacintosh,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NONE
+ },
+ GType_MYST,
+ GF_ME,
+ 0,
+ },
+
+ // Myst Masterpiece Edition
+ // German Windows
+ // From DrMcCoy (Included in "Myst: Die Trilogie")
+ {
+ {
+ "myst",
+ "Masterpiece Edition",
+ AD_ENTRY1("MYST.DAT", "f88e0ace66dbca78eebdaaa1d3314ceb"),
+ Common::DE_DEU,
+ Common::kPlatformWindows,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NONE
+ },
+ GType_MYST,
+ GF_ME,
+ 0,
+ },
+
+ // Myst Masterpiece Edition
+ // French Windows
+ // From gamin (Included in "Myst: La Trilogie")
+ {
+ {
+ "myst",
+ "Masterpiece Edition",
+ AD_ENTRY1("MYST.DAT", "aea81633b2d2ae498f09072fb87263b6"),
+ Common::FR_FRA,
+ Common::kPlatformWindows,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NONE
+ },
+ GType_MYST,
+ GF_ME,
+ 0,
+ },
+
+ // Riven: The Sequel to Myst
+ // Version 1.0 (5CD)
+ // From clone2727
+ {
+ {
+ "riven",
+ "",
+ AD_ENTRY1("a_Data.MHK", "71145fdecbd68a0cfc292c2fbddf8e08"),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NONE
+ },
+ GType_RIVEN,
+ 0,
+ 0,
+ },
+
+ // Riven: The Sequel to Myst
+ // Version 1.03 (5CD)
+ // From ST
+ {
+ {
+ "riven",
+ "",
+ AD_ENTRY1("a_Data.MHK", "d8ccae34a0e3c709135a73f449b783be"),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NONE
+ },
+ GType_RIVEN,
+ 0,
+ 0,
+ },
+
+ // Riven: The Sequel to Myst
+ // Version 1.? (5CD)
+ // From jvprat
+ {
+ {
+ "riven",
+ "",
+ AD_ENTRY1("a_Data.MHK", "249e8c995d191b03ee94c892c0eac775"),
+ Common::ES_ESP,
+ Common::kPlatformWindows,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NONE
+ },
+ GType_RIVEN,
+ 0,
+ 0,
+ },
+
+ // Riven: The Sequel to Myst
+ // Version 1.? (DVD, From "Myst 10th Anniversary Edition")
+ // From Clone2727
+ {
+ {
+ "riven",
+ "DVD",
+ AD_ENTRY1("a_Data.MHK", "08fcaa5d5a2a01d7a5a6960f497212fe"),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NONE
+ },
+ GType_RIVEN,
+ GF_DVD,
+ 0,
+ },
+
+ // Riven: The Sequel to Myst
+ // Version 1.0 (DVD, From "Myst: Die Trilogie")
+ // From DrMcCoy
+ {
+ {
+ "riven",
+ "",
+ AD_ENTRY1("a_Data.MHK", "a5fe1c91a6033eb6ee54b287578b74b9"),
+ Common::DE_DEU,
+ Common::kPlatformWindows,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NONE
+ },
+ GType_RIVEN,
+ GF_DVD,
+ 0,
+ },
+
+ // Riven: The Sequel to Myst
+ // Version ? (DVD, From "Myst: La Trilogie")
+ // From gamin
+ {
+ {
+ "riven",
+ "",
+ AD_ENTRY1("a_Data.MHK", "aff2a384aaa9a0e0ec51010f708c5c04"),
+ Common::FR_FRA,
+ Common::kPlatformWindows,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NONE
+ },
+ GType_RIVEN,
+ GF_DVD,
+ 0,
+ },
+
+ // Riven: The Sequel to Myst
+ // Version ? (Demo, From "Prince of Persia Collector's Edition")
+ // From Clone2727
+ {
+ {
+ "riven",
+ "Demo",
+ AD_ENTRY1("a_Data.MHK", "bae6b03bd8d6eb350d35fd13f0e3139f"),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_DEMO,
+ Common::GUIO_NONE
+ },
+ GType_RIVEN,
+ GF_DEMO,
+ 0,
+ },
+
+#ifdef DETECT_BRODERBUND_TITLES
+ {
+ {
+ "zoombini",
+ "",
+ AD_ENTRY1("ZOOMBINI.MHK", "98b758fec55104c096cfd129048be9a6"),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NONE
+ },
+ GType_ZOOMBINI,
+ GF_HASMIDI,
+ 0
+ },
+
+ {
+ {
+ "csworld",
+ "v3.0",
+ AD_ENTRY1("C2K.MHK", "605fe88380848031bbd0ff84ade6fe40"),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NONE
+ },
+ GType_CSWORLD,
+ 0,
+ 0
+ },
+
+ {
+ {
+ "csworld",
+ "v3.5",
+ AD_ENTRY1("C2K.MHK", "d4857aeb0f5e2e0c4ac556aa74f38c23"),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NONE
+ },
+ GType_CSWORLD,
+ 0,
+ 0
+ },
+
+ {
+ {
+ "csamtrak",
+ "",
+ AD_ENTRY1("AMTRAK.MHK", "2f95301f0bb950d555bb7b0e3b1b7eb1"),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NONE
+ },
+ GType_CSAMTRAK,
+ 0,
+ 0
+ },
+
+ {
+ {
+ "maggiess",
+ "",
+ AD_ENTRY1("MAGGIESS.MHK", "08f75fc8c0390e68fdada5ddb35d0355"),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NONE
+ },
+ GType_MAGGIESS,
+ 0,
+ 0
+ },
+
+ {
+ {
+ "jamesmath",
+ "",
+ AD_ENTRY1("BRODER.MHK", "007299da8b2c6e8ec1cde9598c243024"),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NONE
+ },
+ GType_JAMESMATH,
+ GF_HASMIDI,
+ 0
+ },
+
+ // This is in the NEWDATA folder, so I assume it's a newer version ;)
+ {
+ {
+ "jamesmath",
+ "",
+ AD_ENTRY1("BRODER.MHK", "53c000938a50dca92860fd9b546dd276"),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NONE
+ },
+ GType_JAMESMATH,
+ GF_HASMIDI,
+ 1
+ },
+
+ {
+ {
+ "treehouse",
+ "",
+ AD_ENTRY1("MAINROOM.MHK", "12f51894d7f838af639ea9bf1bc8f45b"),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NONE
+ },
+ GType_TREEHOUSE,
+ GF_HASMIDI,
+ 0
+ },
+
+ {
+ {
+ "greeneggs",
+ "",
+ AD_ENTRY1("GREEN.LB", "5df8438138186f89e71299d7b4f88d06"),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NONE
+ },
+ GType_LIVINGBOOKSV3,
+ 0,
+ 0
+ },
+
+ // 32-bit version of the previous entry
+ {
+ {
+ "greeneggs",
+ "",
+ AD_ENTRY1("GREEN32.LB", "5df8438138186f89e71299d7b4f88d06"),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NONE
+ },
+ GType_LIVINGBOOKSV3,
+ 0,
+ 0
+ },
+
+ {
+ {
+ "1stdegree",
+ "",
+ AD_ENTRY1("AL236_1.MHK", "3ba145492a7b8b4dee0ef4222c5639c3"),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NONE
+ },
+ GType_1STDEGREE,
+ GF_HASMIDI,
+ 0
+ },
+
+ // In The 1st Degree
+ // French Windows
+ // From Strangerke
+ {
+ {
+ "1stdegree",
+ "",
+ AD_ENTRY1("AL236_1.MHK", "0e0c70b1b702b6ddca61a1192ada1282"),
+ Common::FR_FRA,
+ Common::kPlatformWindows,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NONE
+ },
+ GType_1STDEGREE,
+ GF_HASMIDI,
+ 0
+ },
+
+ {
+ {
+ "csusa",
+ "",
+ AD_ENTRY1("USAC2K.MHK", "b8c9d3a2586f62bce3a48b50d7a700e9"),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NONE
+ },
+ GType_CSUSA,
+ 0,
+ 0
+ },
+
+ {
+ {
+ "tortoise",
+ "Demo v1.0",
+ AD_ENTRY1("TORTOISE.512", "75d9a2f8339e423604a0c6e8177600a6"),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_DEMO,
+ Common::GUIO_NONE
+ },
+ GType_LIVINGBOOKSV1,
+ GF_DEMO,
+ 0
+ },
+
+ {
+ {
+ "tortoise",
+ "Demo v1.1",
+ AD_ENTRY1("TORTOISE.512", "a38c99360e2bea3bfdec418469aef022"),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_DEMO,
+ Common::GUIO_NONE
+ },
+ GType_LIVINGBOOKSV1,
+ GF_DEMO,
+ 0
+ },
+
+ {
+ {
+ "tortoise",
+ "Demo",
+ AD_ENTRY1("The Tortoise and the Hare Demo", "35d571806838667743c7c15a133e9335"),
+ Common::EN_ANY,
+ Common::kPlatformMacintosh,
+ ADGF_DEMO,
+ Common::GUIO_NONE
+ },
+ GType_LIVINGBOOKSV1,
+ GF_DEMO,
+ 0
+ },
+
+ {
+ {
+ "arthur",
+ "",
+ AD_ENTRY1("PAGES.512", "1550a361454ec452fe7d2328aac2003c"),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NONE
+ },
+ GType_LIVINGBOOKSV1,
+ 0,
+ 0
+ },
+
+ {
+ {
+ "arthur",
+ "Demo",
+ AD_ENTRY1("PAGES.512", "a4d68cef197af1416921ca5b2e0c1e31"),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_DEMO,
+ Common::GUIO_NONE
+ },
+ GType_LIVINGBOOKSV1,
+ GF_DEMO,
+ 0
+ },
+
+ {
+ {
+ "arthur",
+ "Demo v1.1",
+ AD_ENTRY1("ARTHUR.512", "f19e824e0a2f2745ed698e6aaf44f838"),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_DEMO,
+ Common::GUIO_NONE
+ },
+ GType_LIVINGBOOKSV1,
+ GF_DEMO,
+ 0
+ },
+
+ {
+ {
+ "arthur",
+ "Demo",
+ AD_ENTRY1("Bookoutline", "7e2691611ff4c7b89c05221736628059"),
+ Common::EN_ANY,
+ Common::kPlatformMacintosh,
+ ADGF_DEMO,
+ Common::GUIO_NONE
+ },
+ GType_LIVINGBOOKSV1,
+ GF_DEMO,
+ 0
+ },
+
+ {
+ {
+ "arthur",
+ "Demo",
+ AD_ENTRY1("Arthur's Teacher Trouble Demo", "dcbd8af6bf25854df8ad36fd13665d08"),
+ Common::EN_ANY,
+ Common::kPlatformMacintosh,
+ ADGF_DEMO,
+ Common::GUIO_NONE
+ },
+ GType_LIVINGBOOKSV1,
+ GF_DEMO,
+ 0
+ },
+
+ {
+ {
+ "grandma",
+ "Demo v1.0",
+ AD_ENTRY1("PAGES.512", "95d9f4b035bf5d15c57a9189f231b0f8"),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_DEMO,
+ Common::GUIO_NONE
+ },
+ GType_LIVINGBOOKSV1,
+ GF_DEMO,
+ 0
+ },
+
+ {
+ {
+ "grandma",
+ "Demo v1.1",
+ AD_ENTRY1("GRANDMA.512", "72a4d5fb1b3f06b5f75425635d42ce2e"),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_DEMO,
+ Common::GUIO_NONE
+ },
+ GType_LIVINGBOOKSV1,
+ GF_DEMO,
+ 0
+ },
+
+ {
+ {
+ "grandma",
+ "Demo",
+ AD_ENTRY1("Bookoutline", "553c93891b9631d1e1d269599e1efa6c"),
+ Common::EN_ANY,
+ Common::kPlatformMacintosh,
+ ADGF_DEMO,
+ Common::GUIO_NONE
+ },
+ GType_LIVINGBOOKSV1,
+ GF_DEMO,
+ 0
+ },
+
+ {
+ {
+ "grandma",
+ "Demo",
+ AD_ENTRY1("Just Grandma and Me Demo", "552d8729fa77a4a83c88283c7d79bd31"),
+ Common::EN_ANY,
+ Common::kPlatformMacintosh,
+ ADGF_DEMO,
+ Common::GUIO_NONE
+ },
+ GType_LIVINGBOOKSV1,
+ GF_DEMO,
+ 0
+ },
+
+ {
+ {
+ "ruff",
+ "Demo",
+ AD_ENTRY1("RUFF.512", "2ba1aa65177c816e156db648c398d362"),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_DEMO,
+ Common::GUIO_NONE
+ },
+ GType_LIVINGBOOKSV1,
+ GF_DEMO,
+ 0
+ },
+
+ {
+ {
+ "ruff",
+ "Demo",
+ AD_ENTRY1("Ruff's Bone Demo", "22553ac2ceb2a166bdf1def6ad348532"),
+ Common::EN_ANY,
+ Common::kPlatformMacintosh,
+ ADGF_DEMO,
+ Common::GUIO_NONE
+ },
+ GType_LIVINGBOOKSV1,
+ GF_DEMO,
+ 0
+ },
+
+ {
+ {
+ "newkid",
+ "Demo v1.0",
+ AD_ENTRY1("NEWKID.512", "2b9d94763a50d514c04a3af488934f73"),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_DEMO,
+ Common::GUIO_NONE
+ },
+ GType_LIVINGBOOKSV1,
+ GF_DEMO,
+ 0
+ },
+
+ {
+ {
+ "newkid",
+ "Demo v1.1",
+ AD_ENTRY1("NEWKID.512", "41e975b7390c626f8d1058a34f9d9b2e"),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_DEMO,
+ Common::GUIO_NONE
+ },
+ GType_LIVINGBOOKSV1,
+ GF_DEMO,
+ 0
+ },
+
+ {
+ {
+ "newkid",
+ "Demo",
+ AD_ENTRY1("The New Kid on the Block Demo", "7d33237e0ea452a97f2a3acdfb9e1286"),
+ Common::EN_ANY,
+ Common::kPlatformMacintosh,
+ ADGF_DEMO,
+ Common::GUIO_NONE
+ },
+ GType_LIVINGBOOKSV1,
+ GF_DEMO,
+ 0
+ },
+
+ {
+ {
+ "arthurrace",
+ "",
+ AD_ENTRY1("RACE.LB", "1645f36bcb36e440d928e920aa48c373"),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NONE
+ },
+ GType_LIVINGBOOKSV3,
+ 0,
+ 0
+ },
+
+ // 32-bit version of the previous entry
+ {
+ {
+ "arthurrace",
+ "",
+ AD_ENTRY1("RACE32.LB", "292a05bc48c1dd9583821a4181a02ef2"),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NONE
+ },
+ GType_LIVINGBOOKSV3,
+ 0,
+ 0
+ },
+
+ {
+ {
+ "arthurbday",
+ "Demo",
+ AD_ENTRY1("BIRTHDAY.512", "fb73e387cfec65c5c930db068a8f468a"),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_DEMO,
+ Common::GUIO_NONE
+ },
+ GType_LIVINGBOOKSV1,
+ GF_DEMO,
+ 0
+ },
+
+ {
+ {
+ "arthurbday",
+ "Demo",
+ AD_ENTRY1("Arthur's Birthday Demo", "0d974ec635eea615475368e865f1b1c8"),
+ Common::EN_ANY,
+ Common::kPlatformMacintosh,
+ ADGF_DEMO,
+ Common::GUIO_NONE
+ },
+ GType_LIVINGBOOKSV1,
+ GF_DEMO,
+ 0
+ },
+
+ {
+ {
+ "lilmonster",
+ "",
+ AD_ENTRY1("MONSTER.512", "e7b24bf8f59106b5c4df51b39eb8c0ef"),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NONE
+ },
+ GType_LIVINGBOOKSV1,
+ 0,
+ 0
+ },
+
+ {
+ {
+ "lilmonster",
+ "",
+ AD_ENTRY1("BookOutline", "970409f9d967d63c05e63113f8e78fe2"),
+ Common::EN_ANY,
+ Common::kPlatformMacintosh,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NONE
+ },
+ GType_LIVINGBOOKSV1,
+ 0,
+ 0
+ },
+#endif
+
+ { AD_TABLE_END_MARKER, 0, 0, 0 }
+};
+
+//////////////////////////////
+//Fallback detection
+//////////////////////////////
+
+static const MohawkGameDescription fallbackDescs[] = {
+ {
+ {
+ "myst",
+ "unknown",
+ AD_ENTRY1(0, 0),
+ Common::UNK_LANG,
+ Common::kPlatformWindows,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NONE
+ },
+ GType_MYST,
+ 0,
+ 0
+ },
+
+ {
+ {
+ "MakingOfMyst",
+ "unknown",
+ AD_ENTRY1(0, 0),
+ Common::UNK_LANG,
+ Common::kPlatformWindows,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NONE
+ },
+ GType_MAKINGOF,
+ 0,
+ 0
+ },
+
+ {
+ {
+ "myst",
+ "unknown (Masterpiece Edition)",
+ AD_ENTRY1(0, 0),
+ Common::UNK_LANG,
+ Common::kPlatformWindows,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NONE
+ },
+ GType_MYST,
+ GF_ME,
+ 0
+ },
+
+ {
+ {
+ "riven",
+ "unknown",
+ AD_ENTRY1(0, 0),
+ Common::UNK_LANG,
+ Common::kPlatformWindows,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NONE
+ },
+ GType_RIVEN,
+ 0,
+ 0
+ },
+
+ {
+ {
+ "riven",
+ "unknown (DVD)",
+ AD_ENTRY1(0, 0),
+ Common::UNK_LANG,
+ Common::kPlatformWindows,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NONE
+ },
+ GType_RIVEN,
+ GF_DVD,
+ 0
+ }
+};
+
+static const ADFileBasedFallback fileBased[] = {
+ { &fallbackDescs[0], { "MYST.DAT", 0 } },
+ { &fallbackDescs[1], { "MAKING.DAT", 0 } },
+ { &fallbackDescs[2], { "MYST.DAT", "Help.dat", 0 } }, // Help system doesn't exist in original
+ { &fallbackDescs[3], { "a_Data.MHK", 0 } },
+ { &fallbackDescs[4], { "a_Data.MHK", "t_Data1.MHK" , 0 } },
+ { 0, { 0 } }
+};
+
+} // End of Namespace Mohawk
diff --git a/engines/mohawk/dialogs.cpp b/engines/mohawk/dialogs.cpp
index c5327dbeea..c09763cbb3 100644
--- a/engines/mohawk/dialogs.cpp
+++ b/engines/mohawk/dialogs.cpp
@@ -30,6 +30,7 @@
#include "gui/GuiManager.h"
#include "common/savefile.h"
+#include "common/translation.h"
namespace Mohawk {
@@ -77,11 +78,11 @@ enum {
};
MystOptionsDialog::MystOptionsDialog(MohawkEngine_Myst* vm) : GUI::OptionsDialog("", 120, 120, 360, 200), _vm(vm) {
- _zipModeCheckbox = new GUI::CheckboxWidget(this, 15, 10, 300, 15, "Zip Mode Activated", kZipCmd, 'Z');
- _transitionsCheckbox = new GUI::CheckboxWidget(this, 15, 30, 300, 15, "Transitions Enabled", kTransCmd, 'T');
+ _zipModeCheckbox = new GUI::CheckboxWidget(this, 15, 10, 300, 15, _("~Z~ip Mode Activated"), 0, kZipCmd);
+ _transitionsCheckbox = new GUI::CheckboxWidget(this, 15, 30, 300, 15, _("~T~ransitions Enabled"), 0, kTransCmd);
- new GUI::ButtonWidget(this, 95, 160, 120, 25, "OK", GUI::kOKCmd, 'O');
- new GUI::ButtonWidget(this, 225, 160, 120, 25, "Cancel", GUI::kCloseCmd, 'C');
+ new GUI::ButtonWidget(this, 95, 160, 120, 25, _("~O~K"), 0, GUI::kOKCmd);
+ new GUI::ButtonWidget(this, 225, 160, 120, 25, _("~C~ancel"), 0, GUI::kCloseCmd);
}
MystOptionsDialog::~MystOptionsDialog() {
@@ -111,11 +112,11 @@ void MystOptionsDialog::handleCommand(GUI::CommandSender *sender, uint32 cmd, ui
}
RivenOptionsDialog::RivenOptionsDialog(MohawkEngine_Riven* vm) : GUI::OptionsDialog("", 120, 120, 360, 200), _vm(vm) {
- _zipModeCheckbox = new GUI::CheckboxWidget(this, 15, 10, 300, 15, "Zip Mode Activated", kZipCmd, 'Z');
- _waterEffectCheckbox = new GUI::CheckboxWidget(this, 15, 30, 300, 15, "Water Effect Enabled", kWaterCmd, 'W');
+ _zipModeCheckbox = new GUI::CheckboxWidget(this, 15, 10, 300, 15, _("~Z~ip Mode Activated"), 0, kZipCmd);
+ _waterEffectCheckbox = new GUI::CheckboxWidget(this, 15, 30, 300, 15, _("~W~ater Effect Enabled"), 0, kWaterCmd);
- new GUI::ButtonWidget(this, 95, 160, 120, 25, "OK", GUI::kOKCmd, 'O');
- new GUI::ButtonWidget(this, 225, 160, 120, 25, "Cancel", GUI::kCloseCmd, 'C');
+ new GUI::ButtonWidget(this, 95, 160, 120, 25, _("~O~K"), 0, GUI::kOKCmd);
+ new GUI::ButtonWidget(this, 225, 160, 120, 25, _("~C~ancel"), 0, GUI::kCloseCmd);
}
RivenOptionsDialog::~RivenOptionsDialog() {
diff --git a/engines/mohawk/graphics.cpp b/engines/mohawk/graphics.cpp
index 35691c36aa..1974aec9c2 100644
--- a/engines/mohawk/graphics.cpp
+++ b/engines/mohawk/graphics.cpp
@@ -78,9 +78,8 @@ MystGraphics::MystGraphics(MohawkEngine_Myst* vm) : _vm(vm) {
error("Myst requires greater than 256 colors to run");
if (_vm->getFeatures() & GF_ME) {
- // We want to delete our own JPEG surfaces, so don't free after use.
- _jpegDecoder = new JPEGDecoder(false);
- _pictDecoder = new MystPICT(_jpegDecoder);
+ _jpegDecoder = new Graphics::JPEGDecoder();
+ _pictDecoder = new Graphics::PictDecoder(_pixelFormat);
} else {
_jpegDecoder = NULL;
_pictDecoder = NULL;
@@ -152,9 +151,10 @@ void MystGraphics::copyImageSectionToScreen(uint16 image, Common::Rect src, Comm
if (_vm->getFeatures() & GF_ME && _vm->getPlatform() == Common::kPlatformMacintosh && _pictureFile.picFile.isOpen()) {
for (uint32 i = 0; i < _pictureFile.pictureCount; i++)
if (_pictureFile.entries[i].id == image) {
- if (_pictureFile.entries[i].type == 0)
- surface = _jpegDecoder->decodeImage(new Common::SeekableSubReadStream(&_pictureFile.picFile, _pictureFile.entries[i].offset, _pictureFile.entries[i].offset + _pictureFile.entries[i].size));
- else if (_pictureFile.entries[i].type == 1)
+ if (_pictureFile.entries[i].type == 0) {
+ Graphics::Surface *jpegSurface = _jpegDecoder->decodeImage(new Common::SeekableSubReadStream(&_pictureFile.picFile, _pictureFile.entries[i].offset, _pictureFile.entries[i].offset + _pictureFile.entries[i].size));
+ surface->copyFrom(*jpegSurface);
+ } else if (_pictureFile.entries[i].type == 1)
surface = _pictDecoder->decodeImage(new Common::SeekableSubReadStream(&_pictureFile.picFile, _pictureFile.entries[i].offset, _pictureFile.entries[i].offset + _pictureFile.entries[i].size));
else
error ("Unknown Picture File type %d", _pictureFile.entries[i].type);
@@ -466,27 +466,22 @@ void RivenGraphics::runScheduledTransition() {
// transitions were found by hacking scripts.
switch (_scheduledTransition) {
+ case 0: // Swipe Left
+ case 1: // Swipe Right
+ case 2: // Swipe Up
+ case 3: // Swipe Down
case 12: // Pan Left
- warning ("STUB: Pan left");
- break;
case 13: // Pan Right
- warning ("STUB: Pan right");
- break;
case 14: // Pan Up
- warning ("STUB: Pan up");
- break;
case 15: // Pan Down
- warning ("STUB: Pan down");
- break;
case 16: // Dissolve
case 17: // Dissolve (tspit CARD 155)
- warning ("STUB: Dissolve");
break;
default:
- if (_scheduledTransition < 12)
- error ("Found unused transition %d", _scheduledTransition);
+ if (_scheduledTransition >= 4 && _scheduledTransition <= 11)
+ error("Found unused transition %d", _scheduledTransition);
else
- error ("Found unknown transition %d", _scheduledTransition);
+ error("Found unknown transition %d", _scheduledTransition);
}
// For now, just copy the image to screen without doing any transition.
@@ -607,19 +602,23 @@ void RivenGraphics::showInventory() {
if (_vm->getFeatures() & GF_DEMO || _vm->getCurStack() == aspit)
return;
- // There are three books and three vars. However, there's only
- // a possible two combinations. Either you have only Atrus'
- // journal or you have all three books.
- // bool hasAtrusBook = *_vm->matchVarToString("aatrusbook") != 0;
+ // There are three books and three vars. We have three different
+ // combinations. At the start you have just Atrus' journal. Later,
+ // you get Catherine's journal and the trap book. Near the end,
+ // you lose the trap book and have just the two journals.
+
bool hasCathBook = *_vm->matchVarToString("acathbook") != 0;
- // bool hasTrapBook = *_vm->matchVarToString("atrapbook") != 0;
+ bool hasTrapBook = *_vm->matchVarToString("atrapbook") != 0;
if (!hasCathBook) {
- drawInventoryImage(101, g_atrusJournalRectSolo);
+ drawInventoryImage(101, g_atrusJournalRect1);
+ } else if (!hasTrapBook) {
+ drawInventoryImage(101, g_atrusJournalRect2);
+ drawInventoryImage(102, g_cathJournalRect2);
} else {
- drawInventoryImage(101, g_atrusJournalRect);
- drawInventoryImage(102, g_cathJournalRect);
- drawInventoryImage(100, g_trapBookRect);
+ drawInventoryImage(101, g_atrusJournalRect3);
+ drawInventoryImage(102, g_cathJournalRect3);
+ drawInventoryImage(100, g_trapBookRect3);
}
_vm->_system->updateScreen();
diff --git a/engines/mohawk/graphics.h b/engines/mohawk/graphics.h
index 8d28e1ff4b..dd1764e6d6 100644
--- a/engines/mohawk/graphics.h
+++ b/engines/mohawk/graphics.h
@@ -27,11 +27,11 @@
#define MOHAWK_GRAPHICS_H
#include "mohawk/bitmap.h"
-#include "mohawk/jpeg.h"
#include "mohawk/livingbooks.h"
-#include "mohawk/myst_pict.h"
#include "common/file.h"
+#include "graphics/pict.h"
+#include "graphics/video/codecs/mjpeg.h"
namespace Mohawk {
@@ -96,16 +96,16 @@ public:
void loadExternalPictureFile(uint16 stack);
void copyImageSectionToScreen(uint16 image, Common::Rect src, Common::Rect dest);
void copyImageToScreen(uint16 image, Common::Rect dest);
- void showCursor(void);
- void hideCursor(void);
+ void showCursor();
+ void hideCursor();
void changeCursor(uint16);
void drawRect(Common::Rect rect, bool active);
private:
MohawkEngine_Myst *_vm;
MystBitmap *_bmpDecoder;
- MystPICT *_pictDecoder;
- JPEGDecoder *_jpegDecoder;
+ Graphics::PictDecoder *_pictDecoder;
+ Graphics::JPEGDecoder *_jpegDecoder;
Graphics::PixelFormat _pixelFormat;
struct PictureFile {
diff --git a/engines/mohawk/jpeg.cpp b/engines/mohawk/jpeg.cpp
deleted file mode 100644
index 07ec54dfea..0000000000
--- a/engines/mohawk/jpeg.cpp
+++ /dev/null
@@ -1,87 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * $URL$
- * $Id$
- *
- */
-
-#include "common/system.h"
-#include "graphics/conversion.h" // For YUV2RGB
-
-#include "mohawk/jpeg.h"
-
-namespace Mohawk {
-
-JPEGDecoder::JPEGDecoder(bool freeSurfaceAfterUse) : Graphics::Codec(), _freeSurfaceAfterUse(freeSurfaceAfterUse) {
- _jpeg = new Graphics::JPEG();
- _pixelFormat = g_system->getScreenFormat();
- _surface = NULL;
-}
-
-JPEGDecoder::~JPEGDecoder() {
- delete _jpeg;
-
- if (_surface) {
- _surface->free();
- delete _surface;
- }
-}
-
-Graphics::Surface *JPEGDecoder::decodeImage(Common::SeekableReadStream* stream) {
- _jpeg->read(stream);
- Graphics::Surface *ySurface = _jpeg->getComponent(1);
- Graphics::Surface *uSurface = _jpeg->getComponent(2);
- Graphics::Surface *vSurface = _jpeg->getComponent(3);
-
- Graphics::Surface *destSurface = NULL;
-
- // If we should free the surface after use, use the internal _surface storage
- // (this should be used when using as a Codec, as the Codecs should free their
- // surfaces when deleting the Codec object). Otherwise, create a new Surface
- // as the destination.
- if (_freeSurfaceAfterUse) {
- if (!_surface) {
- _surface = new Graphics::Surface();
- _surface->create(ySurface->w, ySurface->h, _pixelFormat.bytesPerPixel);
- }
- destSurface = _surface;
- } else {
- destSurface = new Graphics::Surface();
- destSurface->create(ySurface->w, ySurface->h, _pixelFormat.bytesPerPixel);
- }
-
- assert(destSurface);
-
- for (uint16 i = 0; i < destSurface->h; i++) {
- for (uint16 j = 0; j < destSurface->w; j++) {
- byte r = 0, g = 0, b = 0;
- Graphics::YUV2RGB(*((byte *)ySurface->getBasePtr(j, i)), *((byte *)uSurface->getBasePtr(j, i)), *((byte *)vSurface->getBasePtr(j, i)), r, g, b);
- if (_pixelFormat.bytesPerPixel == 2)
- *((uint16 *)destSurface->getBasePtr(j, i)) = _pixelFormat.RGBToColor(r, g, b);
- else
- *((uint32 *)destSurface->getBasePtr(j, i)) = _pixelFormat.RGBToColor(r, g, b);
- }
- }
-
- return destSurface;
-}
-
-} // End of namespace Mohawk
diff --git a/engines/mohawk/jpeg.h b/engines/mohawk/jpeg.h
deleted file mode 100644
index ec87b1e7af..0000000000
--- a/engines/mohawk/jpeg.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * $URL$
- * $Id$
- *
- */
-
-#ifndef MOHAWK_JPEG_H
-#define MOHAWK_JPEG_H
-
-#include "common/scummsys.h"
-#include "common/stream.h"
-
-#include "graphics/video/codecs/codec.h"
-#include "graphics/jpeg.h"
-#include "graphics/pixelformat.h"
-
-namespace Mohawk {
-
-// Mohawk's JPEG Decoder
-// Basically a wrapper around JPEG which converts to RGB and also functions
-// as a Codec.
-
-class JPEGDecoder : public Graphics::Codec {
-public:
- JPEGDecoder(bool freeSurfaceAfterUse);
- ~JPEGDecoder();
-
- Graphics::Surface *decodeImage(Common::SeekableReadStream *stream);
- Graphics::PixelFormat getPixelFormat() const { return _pixelFormat; }
-
-private:
- Graphics::PixelFormat _pixelFormat;
- Graphics::JPEG *_jpeg;
- Graphics::Surface *_surface;
- bool _freeSurfaceAfterUse;
-};
-
-} // End of namespace Mohawk
-
-#endif
diff --git a/engines/mohawk/module.mk b/engines/mohawk/module.mk
index b224a8b143..bb79d4abac 100644
--- a/engines/mohawk/module.mk
+++ b/engines/mohawk/module.mk
@@ -6,11 +6,9 @@ MODULE_OBJS = \
detection.o \
dialogs.o \
graphics.o \
- jpeg.o \
livingbooks.o \
mohawk.o \
myst.o \
- myst_pict.o \
myst_vars.o \
myst_saveload.o \
myst_scripts.o \
@@ -22,13 +20,7 @@ MODULE_OBJS = \
riven_scripts.o \
riven_vars.o \
sound.o \
- video/cinepak.o \
- video/qdm2.o \
- video/qtrle.o \
- video/qt_player.o \
- video/rpza.o \
- video/smc.o \
- video/video.o
+ video.o
# This module can be built as a plugin
diff --git a/engines/mohawk/mohawk.cpp b/engines/mohawk/mohawk.cpp
index 5bde6bbeec..6b4d8bb2d2 100644
--- a/engines/mohawk/mohawk.cpp
+++ b/engines/mohawk/mohawk.cpp
@@ -35,7 +35,7 @@
#include "mohawk/mohawk.h"
#include "mohawk/dialogs.h"
#include "mohawk/sound.h"
-#include "mohawk/video/video.h"
+#include "mohawk/video.h"
#include "sound/mixer.h"
diff --git a/engines/mohawk/myst.cpp b/engines/mohawk/myst.cpp
index d1ef3b2137..9ff301c129 100644
--- a/engines/mohawk/myst.cpp
+++ b/engines/mohawk/myst.cpp
@@ -33,7 +33,7 @@
#include "mohawk/dialogs.h"
#include "mohawk/resource.h"
#include "mohawk/resource_cache.h"
-#include "mohawk/video/video.h"
+#include "mohawk/video.h"
namespace Mohawk {
diff --git a/engines/mohawk/myst_pict.cpp b/engines/mohawk/myst_pict.cpp
deleted file mode 100644
index 794ec9b87f..0000000000
--- a/engines/mohawk/myst_pict.cpp
+++ /dev/null
@@ -1,272 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * $URL$
- * $Id$
- *
- */
-
-#include "common/system.h"
-
-#include "mohawk/myst_pict.h"
-
-namespace Mohawk {
-
-// The PICT code is based off of the QuickDraw specs:
-// http://developer.apple.com/documentation/mac/QuickDraw/QuickDraw-461.html
-
-MystPICT::MystPICT(JPEGDecoder *jpegDecoder) {
- _jpegDecoder = jpegDecoder;
- _pixelFormat = g_system->getScreenFormat();
-}
-
-Graphics::Surface *MystPICT::decodeImage(Common::SeekableReadStream *stream) {
- // Skip initial 512 bytes (all 0's)
- stream->seek(512, SEEK_CUR);
-
- // Read in the first part of the header
- /* uint16 fileSize = */ stream->readUint16BE();
-
- _imageRect.top = stream->readUint16BE();
- _imageRect.left = stream->readUint16BE();
- _imageRect.bottom = stream->readUint16BE();
- _imageRect.right = stream->readUint16BE();
- _imageRect.debugPrint(0, "PICT Rect:");
-
- Graphics::Surface *image = new Graphics::Surface();
- image->create(_imageRect.width(), _imageRect.height(), _pixelFormat.bytesPerPixel);
-
- // NOTE: This is only a subset of the full PICT format.
- // - Only V2 Images Supported
- // - JPEG Chunks are Supported
- // - DirectBitsRect Chunks are Supported
- for (uint32 opNum = 0; !stream->eos() && !stream->err() && stream->pos() < stream->size(); opNum++) {
- uint16 opcode = stream->readUint16BE();
- debug(2, "Found PICT opcode %04x", opcode);
-
- if (opNum == 0 && opcode != 0x0011)
- error ("Cannot find PICT version opcode");
- else if (opNum == 1 && opcode != 0x0C00)
- error ("Cannot find PICT header opcode");
-
- if (opcode == 0x0000) { // Nop
- stream->readUint16BE(); // Unknown
- } else if (opcode == 0x0001) { // Clip
- // Ignore
- uint16 clipSize = stream->readUint16BE();
- stream->seek(clipSize - 2, SEEK_CUR);
- } else if (opcode == 0x0007) { // PnSize
- // Ignore
- stream->readUint16BE();
- stream->readUint16BE();
- } else if (opcode == 0x0011) { // VersionOp
- uint16 version = stream->readUint16BE();
- if (version != 0x02FF)
- error ("Unknown PICT version");
- } else if (opcode == 0x001E) { // DefHilite
- // Ignore, Contains no Data
- } else if (opcode == 0x009A) { // DirectBitsRect
- decodeDirectBitsRect(stream, image);
- } else if (opcode == 0x00A1) { // LongComment
- stream->readUint16BE();
- uint16 dataSize = stream->readUint16BE();
- stream->seek(dataSize, SEEK_CUR);
- } else if (opcode == 0x00FF) { // OpEndPic
- stream->readUint16BE();
- break;
- } else if (opcode == 0x0C00) { // HeaderOp
- /* uint16 version = */ stream->readUint16BE();
- stream->readUint16BE(); // Reserved
- /* uint32 hRes = */ stream->readUint32BE();
- /* uint32 vRes = */ stream->readUint32BE();
- Common::Rect origResRect;
- origResRect.top = stream->readUint16BE();
- origResRect.left = stream->readUint16BE();
- origResRect.bottom = stream->readUint16BE();
- origResRect.right = stream->readUint16BE();
- stream->readUint32BE(); // Reserved
- } else if (opcode == 0x8200) { // CompressedQuickTime
- decodeCompressedQuickTime(stream, image);
- break;
- } else {
- error ("Unknown PICT opcode %04x", opcode);
- }
- }
-
- return image;
-}
-
-struct DirectBitsRectData {
- // PixMap
- struct {
- uint32 baseAddr;
- uint16 rowBytes;
- Common::Rect bounds;
- uint16 pmVersion;
- uint16 packType;
- uint32 packSize;
- uint32 hRes;
- uint32 vRes;
- uint16 pixelType;
- uint16 pixelSize;
- uint16 cmpCount;
- uint16 cmpSize;
- uint32 planeBytes;
- uint32 pmTable;
- uint32 pmReserved;
- } pixMap;
- Common::Rect srcRect;
- Common::Rect dstRect;
- uint16 mode;
-};
-
-void MystPICT::decodeDirectBitsRect(Common::SeekableReadStream *stream, Graphics::Surface *image) {
- static const Graphics::PixelFormat directBitsFormat16 = Graphics::PixelFormat(2, 5, 5, 5, 0, 10, 5, 0, 0);
-
- DirectBitsRectData directBitsData;
- directBitsData.pixMap.baseAddr = stream->readUint32BE();
- directBitsData.pixMap.rowBytes = stream->readUint16BE() & 0x3fff;
- directBitsData.pixMap.bounds.top = stream->readUint16BE();
- directBitsData.pixMap.bounds.left = stream->readUint16BE();
- directBitsData.pixMap.bounds.bottom = stream->readUint16BE();
- directBitsData.pixMap.bounds.right = stream->readUint16BE();
- directBitsData.pixMap.pmVersion = stream->readUint16BE();
- directBitsData.pixMap.packType = stream->readUint16BE();
- directBitsData.pixMap.packSize = stream->readUint32BE();
- directBitsData.pixMap.hRes = stream->readUint32BE();
- directBitsData.pixMap.vRes = stream->readUint32BE();
- directBitsData.pixMap.pixelType = stream->readUint16BE();
- directBitsData.pixMap.pixelSize = stream->readUint16BE();
- directBitsData.pixMap.cmpCount = stream->readUint16BE();
- directBitsData.pixMap.cmpSize = stream->readUint16BE();
- directBitsData.pixMap.planeBytes = stream->readUint32BE();
- directBitsData.pixMap.pmTable = stream->readUint32BE();
- directBitsData.pixMap.pmReserved = stream->readUint32BE();
- directBitsData.srcRect.top = stream->readUint16BE();
- directBitsData.srcRect.left = stream->readUint16BE();
- directBitsData.srcRect.bottom = stream->readUint16BE();
- directBitsData.srcRect.right = stream->readUint16BE();
- directBitsData.dstRect.top = stream->readUint16BE();
- directBitsData.dstRect.left = stream->readUint16BE();
- directBitsData.dstRect.bottom = stream->readUint16BE();
- directBitsData.dstRect.right = stream->readUint16BE();
- directBitsData.mode = stream->readUint16BE();
-
- if (directBitsData.pixMap.pixelSize != 16 && directBitsData.pixMap.pixelSize != 32)
- error("Unhandled directBitsRect bitsPerPixel %d", directBitsData.pixMap.pixelSize);
-
- byte bytesPerPixel = (directBitsData.pixMap.pixelSize == 16) ? 2 : 3;
- byte *buffer = new byte[image->w * image->h * bytesPerPixel];
-
- // Read in amount of data per row
- for (uint16 i = 0; i < directBitsData.pixMap.bounds.height(); i++) {
- if (directBitsData.pixMap.packType == 1 || directBitsData.pixMap.rowBytes < 8) { // Unpacked, Pad-Byte
- error("Pack Type = %d, Row Bytes = %d", directBitsData.pixMap.packType, directBitsData.pixMap.rowBytes);
- // TODO
- } else if (directBitsData.pixMap.packType == 2) { // Unpacked, No Pad-Byte
- error("Pack Type = 2");
- // TODO
- } else if (directBitsData.pixMap.packType > 2) { // Packed
- uint16 byteCount = (directBitsData.pixMap.rowBytes > 250) ? stream->readUint16BE() : stream->readByte();
- decodeDirectBitsLine(buffer + i * image->w * bytesPerPixel, directBitsData.pixMap.rowBytes, stream->readStream(byteCount), bytesPerPixel);
- }
- }
-
- if (bytesPerPixel == 2) {
- // Convert from 16-bit to whatever surface we need
- for (uint16 y = 0; y < image->h; y++) {
- for (uint16 x = 0; x < image->w; x++) {
- byte r = 0, g = 0, b = 0;
- uint32 color = READ_BE_UINT16(buffer + (y * image->w + x) * bytesPerPixel);
- directBitsFormat16.colorToRGB(color, r, g, b);
- *((uint16 *)image->getBasePtr(x, y)) = _pixelFormat.RGBToColor(r, g, b);
- }
- }
- } else {
- // Convert from 24-bit (planar!) to whatever surface we need
- for (uint16 y = 0; y < image->h; y++) {
- for (uint16 x = 0; x < image->w; x++) {
- byte r = *(buffer + y * image->w * 3 + x);
- byte g = *(buffer + y * image->w * 3 + image->w + x);
- byte b = *(buffer + y * image->w * 3 + image->w * 2 + x);
- *((uint16 *)image->getBasePtr(x, y)) = _pixelFormat.RGBToColor(r, g, b);
- }
- }
- }
-
- delete[] buffer;
-}
-
-void MystPICT::decodeDirectBitsLine(byte *out, uint32 length, Common::SeekableReadStream *data, byte bytesPerPixel) {
- uint32 dataDecoded = 0;
- byte bytesPerDecode = (bytesPerPixel == 2) ? 2 : 1;
-
- while (data->pos() < data->size() && dataDecoded < length) {
- byte op = data->readByte();
-
- if (op & 0x80) {
- uint32 runSize = (op ^ 255) + 2;
- uint16 value = (bytesPerDecode == 2) ? data->readUint16BE() : data->readByte();
-
- for (uint32 i = 0; i < runSize; i++) {
- if (bytesPerDecode == 2) {
- WRITE_BE_UINT16(out, value);
- out += 2;
- } else
- *out++ = value;
- }
- dataDecoded += runSize * bytesPerDecode;
- } else {
- uint32 runSize = (op + 1) * bytesPerDecode;
- for (uint32 i = 0; i < runSize; i++)
- *out++ = data->readByte();
- dataDecoded += runSize;
- }
- }
-
- // HACK: rowBytes is in 32-bit, but the data is 24-bit...
- if (bytesPerPixel == 3)
- dataDecoded += length / 4;
-
- if (length != dataDecoded)
- warning("Mismatched DirectBits read (%d/%d)", dataDecoded, length);
-
- delete data;
-}
-
-// Compressed QuickTime details can be found here:
-// http://developer.apple.com/documentation/QuickTime/Rm/CompressDecompress/ImageComprMgr/B-Chapter/2TheImageCompression.html
-// http://developer.apple.com/documentation/QuickTime/Rm/CompressDecompress/ImageComprMgr/F-Chapter/6WorkingwiththeImage.html
-// I'm just ignoring that because Myst ME uses none of that extra stuff. The offset is always the same.
-
-void MystPICT::decodeCompressedQuickTime(Common::SeekableReadStream *stream, Graphics::Surface *image) {
- uint32 dataSize = stream->readUint32BE();
- uint32 startPos = stream->pos();
-
- Graphics::Surface *jpegImage = _jpegDecoder->decodeImage(new Common::SeekableSubReadStream(stream, stream->pos() + 156, stream->pos() + dataSize));
- stream->seek(startPos + dataSize);
-
- image->copyFrom(*jpegImage);
-
- jpegImage->free();
- delete jpegImage;
-}
-
-} // End of namespace Mohawk
diff --git a/engines/mohawk/myst_pict.h b/engines/mohawk/myst_pict.h
deleted file mode 100644
index 0684e3352a..0000000000
--- a/engines/mohawk/myst_pict.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * $URL$
- * $Id$
- *
- */
-
-#ifndef MYST_PICT_H
-#define MYST_PICT_H
-
-#include "common/rect.h"
-#include "common/scummsys.h"
-#include "common/stream.h"
-#include "graphics/pixelformat.h"
-#include "graphics/surface.h"
-
-#include "mohawk/jpeg.h"
-
-namespace Mohawk {
-
-class MystPICT {
-public:
- MystPICT(JPEGDecoder *jpegDecoder);
- ~MystPICT() {}
- Graphics::Surface *decodeImage(Common::SeekableReadStream *stream);
-
-private:
- JPEGDecoder *_jpegDecoder;
- Common::Rect _imageRect;
- Graphics::PixelFormat _pixelFormat;
-
- void decodeDirectBitsRect(Common::SeekableReadStream *stream, Graphics::Surface *image);
- void decodeDirectBitsLine(byte *out, uint32 length, Common::SeekableReadStream *data, byte bytesPerPixel);
- void decodeCompressedQuickTime(Common::SeekableReadStream *stream, Graphics::Surface *image);
-};
-
-} // End of namespace Mohawk
-
-#endif
diff --git a/engines/mohawk/myst_scripts.cpp b/engines/mohawk/myst_scripts.cpp
index a453bb0985..2f6d178da8 100644
--- a/engines/mohawk/myst_scripts.cpp
+++ b/engines/mohawk/myst_scripts.cpp
@@ -27,7 +27,7 @@
#include "mohawk/graphics.h"
#include "mohawk/myst_scripts.h"
#include "mohawk/sound.h"
-#include "mohawk/video/video.h"
+#include "mohawk/video.h"
#include "gui/message.h"
diff --git a/engines/mohawk/resource.cpp b/engines/mohawk/resource.cpp
index 62a857b90b..74efd6770f 100644
--- a/engines/mohawk/resource.cpp
+++ b/engines/mohawk/resource.cpp
@@ -103,7 +103,7 @@ void MohawkArchive::open(Common::SeekableReadStream *stream) {
else
debug (3, "Type[%02d]: Tag = \'%s\' ResTable Offset = %04x NameTable Offset = %04x", i, tag2str(_types[i].tag), _types[i].resource_table_offset, _types[i].name_table_offset);
- //Resource Table
+ // Resource Table
_mhk->seek(_rsrc.abs_offset + _types[i].resource_table_offset);
_types[i].resTable.resources = _mhk->readUint16BE();
diff --git a/engines/mohawk/riven.cpp b/engines/mohawk/riven.cpp
index 0412144034..07b08dc220 100644
--- a/engines/mohawk/riven.cpp
+++ b/engines/mohawk/riven.cpp
@@ -29,39 +29,50 @@
#include "common/keyboard.h"
#include "mohawk/graphics.h"
+#include "mohawk/resource.h"
#include "mohawk/riven.h"
#include "mohawk/riven_external.h"
#include "mohawk/riven_saveload.h"
#include "mohawk/dialogs.h"
-#include "mohawk/video/video.h"
+#include "mohawk/video.h"
namespace Mohawk {
-Common::Rect *g_atrusJournalRectSolo;
-Common::Rect *g_atrusJournalRect;
-Common::Rect *g_cathJournalRect;
-Common::Rect *g_trapBookRect;
+Common::Rect *g_atrusJournalRect1;
+Common::Rect *g_atrusJournalRect2;
+Common::Rect *g_cathJournalRect2;
+Common::Rect *g_atrusJournalRect3;
+Common::Rect *g_cathJournalRect3;
+Common::Rect *g_trapBookRect3;
MohawkEngine_Riven::MohawkEngine_Riven(OSystem *syst, const MohawkGameDescription *gamedesc) : MohawkEngine(syst, gamedesc) {
_showHotspots = false;
_cardData.hasData = false;
_gameOver = false;
_activatedSLST = false;
+ _ignoreNextMouseUp = false;
_extrasFile = NULL;
+ _curStack = aspit;
+ _hotspots = NULL;
- // Attempt to let game run from the CDs
- // NOTE: assets2 contains higher quality audio than assets1
- const Common::FSNode gameDataDir(ConfMan.get("path"));
+ // NOTE: We can never really support CD swapping. All of the music files
+ // (*_Sounds.mhk) are stored on disc 1. They are copied to the hard drive
+ // during install and used from there. The same goes for the extras.mhk
+ // file. The following directories allow Riven to be played directly
+ // from the DVD.
+ const Common::FSNode gameDataDir(ConfMan.get("path"));
SearchMan.addSubDirectoryMatching(gameDataDir, "all");
SearchMan.addSubDirectoryMatching(gameDataDir, "data");
SearchMan.addSubDirectoryMatching(gameDataDir, "exe");
- SearchMan.addSubDirectoryMatching(gameDataDir, "assets2");
-
- g_atrusJournalRectSolo = new Common::Rect(295, 402, 313, 426);
- g_atrusJournalRect = new Common::Rect(222, 402, 240, 426);
- g_cathJournalRect = new Common::Rect(291, 408, 311, 419);
- g_trapBookRect = new Common::Rect(363, 396, 386, 432);
+ SearchMan.addSubDirectoryMatching(gameDataDir, "assets1");
+
+ g_atrusJournalRect1 = new Common::Rect(295, 402, 313, 426);
+ g_atrusJournalRect2 = new Common::Rect(259, 402, 278, 426);
+ g_cathJournalRect2 = new Common::Rect(328, 408, 348, 419);
+ g_atrusJournalRect3 = new Common::Rect(222, 402, 240, 426);
+ g_cathJournalRect3 = new Common::Rect(291, 408, 311, 419);
+ g_trapBookRect3 = new Common::Rect(363, 396, 386, 432);
}
MohawkEngine_Riven::~MohawkEngine_Riven() {
@@ -70,15 +81,17 @@ MohawkEngine_Riven::~MohawkEngine_Riven() {
delete _externalScriptHandler;
delete _extrasFile;
delete _saveLoad;
+ delete _scriptMan;
delete[] _vars;
- delete _loadDialog;
delete _optionsDialog;
delete _rnd;
- delete g_atrusJournalRectSolo;
- delete g_atrusJournalRect;
- delete g_cathJournalRect;
- delete g_trapBookRect;
- _cardData.scripts.clear();
+ delete[] _hotspots;
+ delete g_atrusJournalRect1;
+ delete g_atrusJournalRect2;
+ delete g_cathJournalRect2;
+ delete g_atrusJournalRect3;
+ delete g_cathJournalRect3;
+ delete g_trapBookRect3;
}
GUI::Debugger *MohawkEngine_Riven::getDebugger() {
@@ -93,9 +106,8 @@ Common::Error MohawkEngine_Riven::run() {
_console = new RivenConsole(this);
_saveLoad = new RivenSaveLoad(this, _saveFileMan);
_externalScriptHandler = new RivenExternal(this);
- _loadDialog = new GUI::SaveLoadChooser("Load Game:", "Load");
- _loadDialog->setSaveMode(false);
_optionsDialog = new RivenOptionsDialog(this);
+ _scriptMan = new RivenScriptManager(this);
_rnd = new Common::RandomSource();
g_eventRec.registerRandomSource(*_rnd, "riven");
@@ -147,10 +159,15 @@ Common::Error MohawkEngine_Riven::run() {
runHotspotScript(_curHotspot, kMouseDownScript);
break;
case Common::EVENT_LBUTTONUP:
- if (_curHotspot >= 0)
- runHotspotScript(_curHotspot, kMouseUpScript);
- else
- checkInventoryClick();
+ // See RivenScript::switchCard() for more information on why we sometimes
+ // disable the next up event.
+ if (!_ignoreNextMouseUp) {
+ if (_curHotspot >= 0)
+ runHotspotScript(_curHotspot, kMouseUpScript);
+ else
+ checkInventoryClick();
+ }
+ _ignoreNextMouseUp = false;
break;
case Common::EVENT_KEYDOWN:
switch (event.kbd.keycode) {
@@ -233,6 +250,7 @@ void MohawkEngine_Riven::changeToStack(uint16 n) {
// Stop any videos playing
_video->stopVideos();
+ _video->clearMLST();
// Clear the old stack files out
for (uint32 i = 0; i < _mhk.size(); i++)
@@ -310,7 +328,6 @@ void MohawkEngine_Riven::refreshCard() {
_gfx->clearWaterEffects();
_gfx->_activatedPLSTs.clear();
_video->stopVideos();
- _video->_mlstRecords.clear();
_gfx->drawPLST(1);
_activatedSLST = false;
@@ -333,13 +350,13 @@ void MohawkEngine_Riven::refreshCard() {
}
void MohawkEngine_Riven::loadCard(uint16 id) {
- // NOTE: Do not clear the card scripts because it may delete a currently running script!
+ // NOTE: The card scripts are cleared by the RivenScriptManager automatically.
Common::SeekableReadStream* inStream = getRawData(ID_CARD, id);
_cardData.name = inStream->readSint16BE();
_cardData.zipModePlace = inStream->readUint16BE();
- _cardData.scripts = RivenScript::readScripts(this, inStream);
+ _cardData.scripts = _scriptMan->readScripts(inStream);
_cardData.hasData = true;
delete inStream;
@@ -357,7 +374,10 @@ void MohawkEngine_Riven::loadCard(uint16 id) {
}
void MohawkEngine_Riven::loadHotspots(uint16 id) {
- // NOTE: Do not clear the hotspots because it may delete a currently running script!
+ // Clear old hotspots
+ delete[] _hotspots;
+
+ // NOTE: The hotspot scripts are cleared by the RivenScriptManager automatically.
Common::SeekableReadStream* inStream = getRawData(ID_HSPT, id);
@@ -399,7 +419,7 @@ void MohawkEngine_Riven::loadHotspots(uint16 id) {
_hotspots[i].zipModeHotspot = inStream->readUint16BE();
// Read in the scripts now
- _hotspots[i].scripts = RivenScript::readScripts(this, inStream);
+ _hotspots[i].scripts = _scriptMan->readScripts(inStream);
}
delete inStream;
@@ -474,26 +494,37 @@ void MohawkEngine_Riven::checkInventoryClick() {
*matchVarToString("returncardid") = _curCard;
// See RivenGraphics::showInventory() for an explanation
- // of why only this variable is used.
+ // of the variables' meanings.
bool hasCathBook = *matchVarToString("acathbook") != 0;
+ bool hasTrapBook = *matchVarToString("atrapbook") != 0;
// Go to the book if a hotspot contains the mouse
if (!hasCathBook) {
- if (g_atrusJournalRectSolo->contains(_mousePos)) {
+ if (g_atrusJournalRect1->contains(_mousePos)) {
+ _gfx->hideInventory();
+ changeToStack(aspit);
+ changeToCard(5);
+ }
+ } else if (!hasTrapBook) {
+ if (g_atrusJournalRect2->contains(_mousePos)) {
_gfx->hideInventory();
changeToStack(aspit);
changeToCard(5);
+ } else if (g_cathJournalRect2->contains(_mousePos)) {
+ _gfx->hideInventory();
+ changeToStack(aspit);
+ changeToCard(6);
}
} else {
- if (g_atrusJournalRect->contains(_mousePos)) {
+ if (g_atrusJournalRect3->contains(_mousePos)) {
_gfx->hideInventory();
changeToStack(aspit);
changeToCard(5);
- } else if (g_cathJournalRect->contains(_mousePos)) {
+ } else if (g_cathJournalRect3->contains(_mousePos)) {
_gfx->hideInventory();
changeToStack(aspit);
changeToCard(6);
- } else if (g_trapBookRect->contains(_mousePos)) {
+ } else if (g_trapBookRect3->contains(_mousePos)) {
_gfx->hideInventory();
changeToStack(aspit);
changeToCard(7);
@@ -577,7 +608,19 @@ void MohawkEngine_Riven::runHotspotScript(uint16 hotspot, uint16 scriptType) {
}
void MohawkEngine_Riven::runLoadDialog() {
- runDialog(*_loadDialog);
+ GUI::SaveLoadChooser slc("Load Game:", "Load");
+ slc.setSaveMode(false);
+
+ Common::String gameId = ConfMan.get("gameid");
+
+ const EnginePlugin *plugin = 0;
+ EngineMan.findGame(gameId, &plugin);
+
+ int slot = slc.runModal(plugin, ConfMan.getActiveDomainName());
+ if (slot >= 0)
+ loadGameState(slot);
+
+ slc.close();
}
Common::Error MohawkEngine_Riven::loadGameState(int slot) {
@@ -612,4 +655,4 @@ bool ZipMode::operator== (const ZipMode &z) const {
return z.name == name && z.id == id;
}
-}
+} // End of namespace Mohawk
diff --git a/engines/mohawk/riven.h b/engines/mohawk/riven.h
index f014b76fb8..631285455e 100644
--- a/engines/mohawk/riven.h
+++ b/engines/mohawk/riven.h
@@ -68,10 +68,12 @@ enum {
// Rects for the inventory object positions (initialized in
// MohawkEngine_Riven's constructor).
-extern Common::Rect *g_atrusJournalRectSolo;
-extern Common::Rect *g_atrusJournalRect;
-extern Common::Rect *g_cathJournalRect;
-extern Common::Rect *g_trapBookRect;
+extern Common::Rect *g_atrusJournalRect1;
+extern Common::Rect *g_atrusJournalRect2;
+extern Common::Rect *g_cathJournalRect2;
+extern Common::Rect *g_atrusJournalRect3;
+extern Common::Rect *g_cathJournalRect3;
+extern Common::Rect *g_trapBookRect3;
struct RivenHotspot {
uint16 blstID;
@@ -111,9 +113,9 @@ public:
RivenGraphics *_gfx;
RivenExternal *_externalScriptHandler;
Common::RandomSource *_rnd;
+ RivenScriptManager *_scriptMan;
Card _cardData;
- bool _gameOver;
GUI::Debugger *getDebugger();
@@ -127,7 +129,6 @@ private:
MohawkArchive *_extrasFile; // We need a separate handle for the extra data
RivenConsole *_console;
RivenSaveLoad *_saveLoad;
- GUI::SaveLoadChooser *_loadDialog;
RivenOptionsDialog *_optionsDialog;
// Stack/Card-related functions and variables
@@ -147,6 +148,10 @@ private:
uint32 *_vars;
uint32 _varCount;
+ // Miscellaneous
+ bool _gameOver;
+ bool _ignoreNextMouseUp;
+
public:
Common::SeekableReadStream *getExtrasResource(uint32 tag, uint16 id);
bool _activatedSLST;
@@ -180,6 +185,9 @@ public:
uint32 *getLocalVar(uint32 index);
uint32 *matchVarToString(Common::String varName);
uint32 *matchVarToString(const char *varName);
+
+ void setGameOver() { _gameOver = true; }
+ void ignoreNextMouseUp() { _ignoreNextMouseUp = true; }
};
} // End of namespace Mohawk
diff --git a/engines/mohawk/riven_external.cpp b/engines/mohawk/riven_external.cpp
index 99afacc5ce..67d621a54c 100644
--- a/engines/mohawk/riven_external.cpp
+++ b/engines/mohawk/riven_external.cpp
@@ -27,7 +27,7 @@
#include "mohawk/riven.h"
#include "mohawk/riven_external.h"
#include "mohawk/sound.h"
-#include "mohawk/video/video.h"
+#include "mohawk/video.h"
#include "gui/message.h"
#include "common/events.h"
@@ -210,7 +210,28 @@ void RivenExternal::runEndGame(uint16 video) {
_vm->_video->playMovieBlocking(video);
// TODO: Play until the last frame and then run the credits
- _vm->_gameOver = true;
+ _vm->setGameOver();
+}
+
+void RivenExternal::runDomeButtonMovie() {
+ // This command just plays the video of the button moving down and up.
+ _vm->_video->playMovieBlocking(2);
+}
+
+void RivenExternal::runDomeCheck() {
+ // Check if we clicked while the golden frame was showing
+
+ VideoHandle video = _vm->_video->findVideoHandle(1);
+ assert(video != NULL_VID_HANDLE);
+
+ int32 curFrame = _vm->_video->getCurFrame(video);
+ int32 frameCount = _vm->_video->getFrameCount(video);
+
+ // The final frame of the video is the 'golden' frame (double meaning: the
+ // frame that is the magic one is the one with the golden symbol) but we
+ // give a 3 frame leeway in either direction.
+ if (frameCount - curFrame < 3 || curFrame < 3)
+ *_vm->matchVarToString("domecheck") = 1;
}
// ------------------------------------------------------------------------------------
@@ -218,11 +239,13 @@ void RivenExternal::runEndGame(uint16 video) {
// ------------------------------------------------------------------------------------
void RivenExternal::xastartupbtnhide(uint16 argc, uint16 *argv) {
- // The original game hides the start/setup buttons depending on an ini entry. It's safe to ignore this command.
+ // The original game hides the start/setup buttons depending on an ini entry.
+ // It's safe to ignore this command.
}
void RivenExternal::xasetupcomplete(uint16 argc, uint16 *argv) {
- // The original game sets an ini entry to disable the setup button and use the start button only. It's safe to ignore this part of the command.
+ // The original game sets an ini entry to disable the setup button and use the
+ // start button only. It's safe to ignore this part of the command.
_vm->_sound->stopSound();
_vm->changeToCard(1);
}
@@ -261,9 +284,14 @@ void RivenExternal::xaatrusbookprevpage(uint16 argc, uint16 *argv) {
return;
(*page)--;
- // TODO: Play the page turning sound
+ // Play the page turning sound
+ if (_vm->getFeatures() & GF_DEMO)
+ _vm->_sound->playSound(4, false);
+ else
+ _vm->_sound->playSound(3, false);
// Now update the screen :)
+ _vm->_gfx->scheduleTransition(1);
_vm->_gfx->updateScreen();
}
@@ -276,9 +304,14 @@ void RivenExternal::xaatrusbooknextpage(uint16 argc, uint16 *argv) {
return;
(*page)++;
- // TODO: Play the page turning sound
+ // Play the page turning sound
+ if (_vm->getFeatures() & GF_DEMO)
+ _vm->_sound->playSound(5, false);
+ else
+ _vm->_sound->playSound(4, false);
// Now update the screen :)
+ _vm->_gfx->scheduleTransition(0);
_vm->_gfx->updateScreen();
}
@@ -326,9 +359,11 @@ void RivenExternal::xacathbookprevpage(uint16 argc, uint16 *argv) {
return;
(*page)--;
- // TODO: Play the page turning sound
+ // Play the page turning sound
+ _vm->_sound->playSound(5, false);
// Now update the screen :)
+ _vm->_gfx->scheduleTransition(3);
_vm->_gfx->updateScreen();
}
@@ -341,9 +376,11 @@ void RivenExternal::xacathbooknextpage(uint16 argc, uint16 *argv) {
return;
(*page)++;
- // TODO: Play the page turning sound
+ // Play the page turning sound
+ _vm->_sound->playSound(6, false);
// Now update the screen :)
+ _vm->_gfx->scheduleTransition(2);
_vm->_gfx->updateScreen();
}
@@ -357,12 +394,20 @@ void RivenExternal::xtrapbookback(uint16 argc, uint16 *argv) {
void RivenExternal::xatrapbookclose(uint16 argc, uint16 *argv) {
// Close the trap book
*_vm->matchVarToString("atrap") = 0;
+
+ // Play the page turning sound
+ _vm->_sound->playSound(8, false);
+
_vm->refreshCard();
}
void RivenExternal::xatrapbookopen(uint16 argc, uint16 *argv) {
// Open the trap book
*_vm->matchVarToString("atrap") = 1;
+
+ // Play the page turning sound
+ _vm->_sound->playSound(9, false);
+
_vm->refreshCard();
}
@@ -414,7 +459,11 @@ void RivenExternal::xblabbookprevpage(uint16 argc, uint16 *argv) {
return;
(*page)--;
+ // Play the page turning sound
+ _vm->_sound->playSound(22, false);
+
// Now update the screen :)
+ _vm->_gfx->scheduleTransition(1);
_vm->_gfx->updateScreen();
}
@@ -427,7 +476,11 @@ void RivenExternal::xblabbooknextpage(uint16 argc, uint16 *argv) {
return;
(*page)++;
+ // Play the page turning sound
+ _vm->_sound->playSound(23, false);
+
// Now update the screen :)
+ _vm->_gfx->scheduleTransition(0);
_vm->_gfx->updateScreen();
}
@@ -514,13 +567,14 @@ void RivenExternal::xbupdateboiler(uint16 argc, uint16 *argv) {
if (heat) {
if (platform == 0) {
_vm->_video->activateMLST(7, _vm->getCurCard());
- // TODO: Play video (non-blocking)
+ _vm->_video->playMovie(7);
} else {
_vm->_video->activateMLST(8, _vm->getCurCard());
- // TODO: Play video (non-blocking)
+ _vm->_video->playMovie(8);
}
} else {
- // TODO: Stop MLST's 7 and 8
+ _vm->_video->stopMovie(7);
+ _vm->_video->stopMovie(8);
}
_vm->refreshCard();
@@ -627,26 +681,28 @@ void RivenExternal::xbisland190_slidermw(uint16 argc, uint16 *argv) {
}
void RivenExternal::xbscpbtn(uint16 argc, uint16 *argv) {
- // TODO: Dome related
+ runDomeButtonMovie();
}
void RivenExternal::xbisland_domecheck(uint16 argc, uint16 *argv) {
- // TODO: Dome related
+ runDomeCheck();
}
void RivenExternal::xvalvecontrol(uint16 argc, uint16 *argv) {
// Get the variable for the valve
uint32 *valve = _vm->matchVarToString("bvalve");
- Common::Event event;
int changeX = 0;
int changeY = 0;
+ bool done = false;
// Set the cursor to the closed position
_vm->_gfx->changeCursor(2004);
_vm->_system->updateScreen();
- for (;;) {
+ while (!done) {
+ Common::Event event;
+
while (_vm->_system->getEventManager()->pollEvent(event)) {
switch (event.type) {
case Common::EVENT_MOUSEMOVE:
@@ -658,30 +714,53 @@ void RivenExternal::xvalvecontrol(uint16 argc, uint16 *argv) {
// FIXME: These values for changes in x/y could be tweaked.
if (*valve == 0 && changeY <= -10) {
*valve = 1;
- // TODO: Play movie
+ _vm->_gfx->changeCursor(kRivenHideCursor);
+ _vm->_video->playMovieBlocking(2);
_vm->refreshCard();
} else if (*valve == 1) {
if (changeX >= 0 && changeY >= 10) {
*valve = 0;
- // TODO: Play movie
+ _vm->_gfx->changeCursor(kRivenHideCursor);
+ _vm->_video->playMovieBlocking(3);
_vm->refreshCard();
} else if (changeX <= -10 && changeY <= 10) {
*valve = 2;
- // TODO: Play movie
+ _vm->_gfx->changeCursor(kRivenHideCursor);
+ _vm->_video->playMovieBlocking(1);
_vm->refreshCard();
}
} else if (*valve == 2 && changeX >= 10) {
*valve = 1;
- // TODO: Play movie
+ _vm->_gfx->changeCursor(kRivenHideCursor);
+ _vm->_video->playMovieBlocking(4);
_vm->refreshCard();
}
- return;
+ done = true;
default:
break;
}
}
_vm->_system->delayMillis(10);
}
+
+ // If we changed state and the new state is that the valve is flowing to
+ // the boiler, we need to update the boiler state.
+ if (*valve == 1) {
+ if (*_vm->matchVarToString("bidvlv") == 1) { // Check which way the water is going at the boiler
+ if (*_vm->matchVarToString("bblrarm") == 1) {
+ // If the pipe is open, make sure the water is drained out
+ *_vm->matchVarToString("bheat") = 0;
+ *_vm->matchVarToString("bblrwtr") = 0;
+ } else {
+ // If the pipe is closed, fill the boiler again
+ *_vm->matchVarToString("bheat") = *_vm->matchVarToString("bblrvalve");
+ *_vm->matchVarToString("bblrwtr") = 1;
+ }
+ } else {
+ // Have the grating inside the boiler match the switch outside
+ *_vm->matchVarToString("bblrgrt") = (*_vm->matchVarToString("bblrsw") == 1) ? 0 : 1;
+ }
+ }
}
void RivenExternal::xbchipper(uint16 argc, uint16 *argv) {
@@ -723,11 +802,11 @@ void RivenExternal::xgisland25_slidermw(uint16 argc, uint16 *argv) {
}
void RivenExternal::xgscpbtn(uint16 argc, uint16 *argv) {
- // TODO: Dome related
+ runDomeButtonMovie();
}
void RivenExternal::xgisland1490_domecheck(uint16 argc, uint16 *argv) {
- // TODO: Dome related
+ runDomeCheck();
}
void RivenExternal::xgplateau3160_dopools(uint16 argc, uint16 *argv) {
@@ -936,33 +1015,60 @@ void RivenExternal::xjtunnel106_pictfix(uint16 argc, uint16 *argv) {
}
void RivenExternal::xvga1300_carriage(uint16 argc, uint16 *argv) {
- // TODO: This function is supposed to do a lot more, something like this (pseudocode):
-
- // Show level pull movie
- // Set transition up
- // Change to up card
- // Show movie of carriage coming down
- // Set transition down
- // Change back to card 276
- // Show movie of carriage coming down
- // if jgallows == 0
- // Set up timer
- // Enter new input loop
- // if you click within the time
- // move forward
- // set transition right
- // change to card right
- // show movie of ascending
- // change to card 263
- // else
- // show movie of carriage ascending only
- // else
- // show movie of carriage ascending only
-
-
- // For now, if the gallows base is closed, assume ascension and move to that card.
- if (*_vm->matchVarToString("jgallows") == 0)
- _vm->changeToCard(_vm->matchRMAPToCard(0x17167));
+ // Run the gallows's carriage
+
+ _vm->_gfx->changeCursor(kRivenHideCursor); // Hide the cursor
+ _vm->_video->playMovieBlocking(1); // Play handle movie
+ _vm->_gfx->scheduleTransition(15); // Set pan down transition
+ _vm->changeToCard(_vm->matchRMAPToCard(0x18e77)); // Change to card facing up
+ _vm->_gfx->changeCursor(kRivenHideCursor); // Hide the cursor (again)
+ _vm->_video->playMovieBlocking(4); // Play carriage beginning to drop
+ _vm->_gfx->scheduleTransition(14); // Set pan up transition
+ _vm->changeToCard(_vm->matchRMAPToCard(0x183a9)); // Change to card looking straight again
+ _vm->_video->playMovieBlocking(2);
+
+ uint32 *gallows = _vm->matchVarToString("jgallows");
+ if (*gallows == 1) {
+ // If the gallows is open, play the up movie and return
+ _vm->_video->playMovieBlocking(3);
+ return;
+ }
+
+ // Give the player 5 seconds to click (anywhere)
+ uint32 startTime = _vm->_system->getMillis();
+ bool gotClick = false;
+ while (_vm->_system->getMillis() - startTime <= 5000 && !gotClick) {
+ Common::Event event;
+ while (_vm->_system->getEventManager()->pollEvent(event)) {
+ switch (event.type) {
+ case Common::EVENT_MOUSEMOVE:
+ _vm->_system->updateScreen();
+ break;
+ case Common::EVENT_LBUTTONUP:
+ gotClick = true;
+ break;
+ default:
+ break;
+ }
+ }
+
+ _vm->_system->delayMillis(10);
+ }
+
+ _vm->_gfx->changeCursor(kRivenHideCursor); // Hide the cursor
+
+ if (gotClick) {
+ _vm->_gfx->scheduleTransition(16); // Schedule dissolve transition
+ _vm->changeToCard(_vm->matchRMAPToCard(0x18d4d)); // Move forward
+ _vm->_gfx->changeCursor(kRivenHideCursor); // Hide the cursor
+ _vm->_system->delayMillis(500); // Delay a half second before changing again
+ _vm->_gfx->scheduleTransition(12); // Schedule pan left transition
+ _vm->changeToCard(_vm->matchRMAPToCard(0x18ab5)); // Turn right
+ _vm->_gfx->changeCursor(kRivenHideCursor); // Hide the cursor
+ _vm->_video->playMovieBlocking(1); // Play carriage ride movie
+ _vm->changeToCard(_vm->matchRMAPToCard(0x17167)); // We have arrived at the top
+ } else
+ _vm->_video->playMovieBlocking(3); // Too slow!
}
void RivenExternal::xjdome25_resetsliders(uint16 argc, uint16 *argv) {
@@ -978,11 +1084,11 @@ void RivenExternal::xjdome25_slidermw(uint16 argc, uint16 *argv) {
}
void RivenExternal::xjscpbtn(uint16 argc, uint16 *argv) {
- // TODO: Dome related
+ runDomeButtonMovie();
}
void RivenExternal::xjisland3500_domecheck(uint16 argc, uint16 *argv) {
- // TODO: Dome related
+ runDomeCheck();
}
int RivenExternal::jspitElevatorLoop() {
@@ -1019,8 +1125,10 @@ int RivenExternal::jspitElevatorLoop() {
void RivenExternal::xhandlecontrolup(uint16 argc, uint16 *argv) {
int changeLevel = jspitElevatorLoop();
+ // If we've moved the handle down, go down a floor
if (changeLevel == -1) {
- // TODO: Run movie
+ _vm->_video->playMovieBlocking(1);
+ _vm->_video->playMovieBlocking(2);
_vm->changeToCard(_vm->matchRMAPToCard(0x1e374));
}
}
@@ -1028,8 +1136,10 @@ void RivenExternal::xhandlecontrolup(uint16 argc, uint16 *argv) {
void RivenExternal::xhandlecontroldown(uint16 argc, uint16 *argv) {
int changeLevel = jspitElevatorLoop();
+ // If we've moved the handle up, go up a floor
if (changeLevel == 1) {
- // TODO: Run movie
+ _vm->_video->playMovieBlocking(1);
+ _vm->_video->playMovieBlocking(2);
_vm->changeToCard(_vm->matchRMAPToCard(0x1e374));
}
}
@@ -1037,11 +1147,29 @@ void RivenExternal::xhandlecontroldown(uint16 argc, uint16 *argv) {
void RivenExternal::xhandlecontrolmid(uint16 argc, uint16 *argv) {
int changeLevel = jspitElevatorLoop();
+ if (changeLevel == 0)
+ return;
+
+ // Play the handle moving video
+ if (changeLevel == 1)
+ _vm->_video->playMovieBlocking(7);
+ else
+ _vm->_video->playMovieBlocking(6);
+
+ // If the whark's mouth is open, close it
+ uint32 *mouthVar = _vm->matchVarToString("jwmouth");
+ if (*mouthVar == 1) {
+ _vm->_video->playMovieBlocking(3);
+ _vm->_video->playMovieBlocking(8);
+ *mouthVar = 0;
+ }
+
+ // Play the elevator video and then change the card
if (changeLevel == 1) {
- // TODO: Run movie
+ _vm->_video->playMovieBlocking(5);
_vm->changeToCard(_vm->matchRMAPToCard(0x1e597));
- } else if (changeLevel == -1) {
- // TODO: Run movie
+ } else {
+ _vm->_video->playMovieBlocking(4);
_vm->changeToCard(_vm->matchRMAPToCard(0x1e29c));
}
}
@@ -1172,9 +1300,11 @@ void RivenExternal::xogehnbookprevpage(uint16 argc, uint16 *argv) {
return;
(*page)--;
- // TODO: Play the page turning sound
+ // Play the page turning sound
+ _vm->_sound->playSound(12, false);
// Now update the screen :)
+ _vm->_gfx->scheduleTransition(1);
_vm->_gfx->updateScreen();
}
@@ -1187,13 +1317,15 @@ void RivenExternal::xogehnbooknextpage(uint16 argc, uint16 *argv) {
return;
(*page)++;
- // TODO: Play the page turning sound
+ // Play the page turning sound
+ _vm->_sound->playSound(13, false);
// Now update the screen :)
+ _vm->_gfx->scheduleTransition(0);
_vm->_gfx->updateScreen();
}
-static uint16 getComboDigit(uint32 correctCombo, uint32 digit) {
+uint16 RivenExternal::getComboDigit(uint32 correctCombo, uint32 digit) {
static const uint32 powers[] = { 100000, 10000, 1000, 100, 10, 1 };
return (correctCombo % powers[digit]) / powers[digit + 1];
}
@@ -1258,11 +1390,11 @@ void RivenExternal::xpisland990_elevcombo(uint16 argc, uint16 *argv) {
}
void RivenExternal::xpscpbtn(uint16 argc, uint16 *argv) {
- // TODO: Dome related
+ runDomeButtonMovie();
}
void RivenExternal::xpisland290_domecheck(uint16 argc, uint16 *argv) {
- // TODO: Dome related
+ runDomeCheck();
}
void RivenExternal::xpisland25_opencard(uint16 argc, uint16 *argv) {
@@ -1457,11 +1589,11 @@ void RivenExternal::xtakeit(uint16 argc, uint16 *argv) {
}
void RivenExternal::xtscpbtn(uint16 argc, uint16 *argv) {
- // TODO: Dome related
+ runDomeButtonMovie();
}
void RivenExternal::xtisland4990_domecheck(uint16 argc, uint16 *argv) {
- // TODO: Dome related
+ runDomeCheck();
}
void RivenExternal::xtisland5056_opencard(uint16 argc, uint16 *argv) {
diff --git a/engines/mohawk/riven_external.h b/engines/mohawk/riven_external.h
index 8270a00854..bdf3fa01bc 100644
--- a/engines/mohawk/riven_external.h
+++ b/engines/mohawk/riven_external.h
@@ -38,6 +38,7 @@ public:
~RivenExternal();
void runCommand(uint16 argc, uint16 *argv);
+ uint16 getComboDigit(uint32 correctCombo, uint32 digit);
private:
MohawkEngine_Riven *_vm;
@@ -57,6 +58,8 @@ private:
int jspitElevatorLoop();
void runDemoBoundaryDialog();
void runEndGame(uint16 video);
+ void runDomeCheck();
+ void runDomeButtonMovie();
// -----------------------------------------------------
// aspit (Main Menu, Books, Setup) external commands
diff --git a/engines/mohawk/riven_saveload.cpp b/engines/mohawk/riven_saveload.cpp
index 3c989838da..d73b4ec0dc 100644
--- a/engines/mohawk/riven_saveload.cpp
+++ b/engines/mohawk/riven_saveload.cpp
@@ -23,6 +23,7 @@
*
*/
+#include "mohawk/resource.h"
#include "mohawk/riven.h"
#include "mohawk/riven_saveload.h"
@@ -31,11 +32,9 @@
namespace Mohawk {
RivenSaveLoad::RivenSaveLoad(MohawkEngine_Riven *vm, Common::SaveFileManager *saveFileMan) : _vm(vm), _saveFileMan(saveFileMan) {
- _loadFile = new MohawkArchive();
}
RivenSaveLoad::~RivenSaveLoad() {
- delete _loadFile;
}
Common::StringArray RivenSaveLoad::generateSaveGameList() {
@@ -63,7 +62,8 @@ static uint16 mapOldStackIDToNew(uint16 oldID) {
case 8:
return aspit;
}
- error ("Unknown old stack ID %d", oldID);
+
+ error("Unknown old stack ID %d", oldID);
return 0;
}
@@ -86,7 +86,8 @@ static uint16 mapNewStackIDToOld(uint16 newID) {
case tspit:
return 4;
}
- error ("Unknown new stack ID %d", newID);
+
+ error("Unknown new stack ID %d", newID);
return 0;
}
@@ -94,26 +95,28 @@ bool RivenSaveLoad::loadGame(Common::String filename) {
if (_vm->getFeatures() & GF_DEMO) // Don't load games in the demo
return false;
- Common::InSaveFile *loadFile;
- if (!(loadFile = _saveFileMan->openForLoading(filename.c_str())))
+ Common::InSaveFile *loadFile = _saveFileMan->openForLoading(filename);
+ if (!loadFile)
return false;
- debug (0, "Loading game from \'%s\'", filename.c_str());
- _loadFile->open(loadFile);
+ debug(0, "Loading game from \'%s\'", filename.c_str());
+
+ MohawkArchive *mhk = new MohawkArchive();
+ mhk->open(loadFile);
// First, let's make sure we're using a saved game file from this version of Riven by checking the VERS resource
- Common::SeekableReadStream *vers = _loadFile->getRawData(ID_VERS, 1);
+ Common::SeekableReadStream *vers = mhk->getRawData(ID_VERS, 1);
uint32 saveGameVersion = vers->readUint32BE();
delete vers;
if ((saveGameVersion == kCDSaveGameVersion && (_vm->getFeatures() & GF_DVD))
|| (saveGameVersion == kDVDSaveGameVersion && !(_vm->getFeatures() & GF_DVD))) {
- warning ("Incompatible saved game versions. No support for this yet.");
- delete _loadFile;
+ warning("Incompatible saved game versions. No support for this yet.");
+ delete mhk;
return false;
}
// Now, we'll read in the variable values.
- Common::SeekableReadStream *vars = _loadFile->getRawData(ID_VARS, 1);
+ Common::SeekableReadStream *vars = mhk->getRawData(ID_VARS, 1);
Common::Array<uint32> rawVariables;
while (!vars->eos()) {
@@ -126,7 +129,7 @@ bool RivenSaveLoad::loadGame(Common::String filename) {
// Next, we set the variables based on the name found by the index in the VARS resource.
// TODO: Merge with code in mohawk.cpp for loading names?
- Common::SeekableReadStream *names = _loadFile->getRawData(ID_NAME, 1);
+ Common::SeekableReadStream *names = mhk->getRawData(ID_NAME, 1);
uint16 namesCount = names->readUint16BE();
uint16 *stringOffsets = new uint16[namesCount];
@@ -151,9 +154,10 @@ bool RivenSaveLoad::loadGame(Common::String filename) {
c = (char)names->readByte();
}
- // WORKAROUND: Some versions have two extra variables. However, the saves are
- // still compatible with other saves of the same version. Are these used in the
- // original interpreter anywhere? (They come from DVD v1.1)
+ // TODO: Some versions have two extra variables. However, the saves are
+ // still compatible with other saves of the same version (they come from DVD v1.1).
+ // There are used in the whark number puzzle. I thought jleftpos and jrightpos were
+ // for this purpose.
if (name == "dropLeftStart" || name == "dropRightStart")
continue;
@@ -161,11 +165,11 @@ bool RivenSaveLoad::loadGame(Common::String filename) {
*var = rawVariables[i];
- if (!scumm_stricmp(name.c_str(), "CurrentStackID"))
+ if (name.equalsIgnoreCase("CurrentStackID"))
stackID = mapOldStackIDToNew(rawVariables[i]);
- else if (!scumm_stricmp(name.c_str(), "CurrentCardID"))
+ else if (name.equalsIgnoreCase("CurrentCardID"))
cardID = rawVariables[i];
- else if (!scumm_stricmp(name.c_str(), "ReturnStackID"))
+ else if (name.equalsIgnoreCase("ReturnStackID"))
*var = mapOldStackIDToNew(rawVariables[i]);
}
@@ -179,7 +183,7 @@ bool RivenSaveLoad::loadGame(Common::String filename) {
_vm->_zipModeData.clear();
// Finally, we load in zip mode data.
- Common::SeekableReadStream *zips = _loadFile->getRawData(ID_ZIPS, 1);
+ Common::SeekableReadStream *zips = mhk->getRawData(ID_ZIPS, 1);
uint16 zipsRecordCount = zips->readUint16BE();
for (uint16 i = 0; i < zipsRecordCount; i++) {
ZipMode zip;
@@ -189,10 +193,10 @@ bool RivenSaveLoad::loadGame(Common::String filename) {
zip.id = zips->readUint16BE();
_vm->_zipModeData.push_back(zip);
}
+
delete zips;
+ delete mhk;
- delete _loadFile;
- _loadFile = NULL;
return true;
}
@@ -211,7 +215,14 @@ Common::MemoryWriteStreamDynamic *RivenSaveLoad::genVARSSection() {
for (uint32 i = 0; i < _vm->getVarCount(); i++) {
stream->writeUint32BE(0); // Unknown
stream->writeUint32BE(0); // Unknown
- stream->writeUint32BE(_vm->getGlobalVar(i));
+
+ // Remap returnstackid here because we don't actually want to change
+ // our internal returnstackid.
+ uint32 variable = _vm->getGlobalVar(i);
+ if (_vm->getGlobalVarName(i) == "returnstackid")
+ variable = mapNewStackIDToOld(variable);
+
+ stream->writeUint32BE(variable);
}
return stream;
@@ -257,17 +268,17 @@ bool RivenSaveLoad::saveGame(Common::String filename) {
// Note, this code is still WIP. It works quite well for now.
// Make sure we have the right extension
- if (!filename.hasSuffix(".rvn") && !filename.hasSuffix(".RVN"))
+ if (!filename.matchString("*.rvn", true))
filename += ".rvn";
// Convert class variables to variable numbers
*_vm->matchVarToString("currentstackid") = mapNewStackIDToOld(_vm->getCurStack());
*_vm->matchVarToString("currentcardid") = _vm->getCurCard();
- *_vm->matchVarToString("returnstackid") = mapNewStackIDToOld(*_vm->matchVarToString("returnstackid"));
- Common::OutSaveFile *saveFile;
- if (!(saveFile = _saveFileMan->openForSaving(filename.c_str())))
+ Common::OutSaveFile *saveFile = _saveFileMan->openForSaving(filename);
+ if (!saveFile)
return false;
+
debug (0, "Saving game to \'%s\'", filename.c_str());
Common::MemoryWriteStreamDynamic *versSection = genVERSSection();
@@ -392,7 +403,7 @@ bool RivenSaveLoad::saveGame(Common::String filename) {
void RivenSaveLoad::deleteSave(Common::String saveName) {
debug (0, "Deleting save file \'%s\'", saveName.c_str());
- _saveFileMan->removeSavefile(saveName.c_str());
+ _saveFileMan->removeSavefile(saveName);
}
} // End of namespace Mohawk
diff --git a/engines/mohawk/riven_saveload.h b/engines/mohawk/riven_saveload.h
index c708f9d35d..9cc9bc3737 100644
--- a/engines/mohawk/riven_saveload.h
+++ b/engines/mohawk/riven_saveload.h
@@ -29,8 +29,6 @@
#include "common/savefile.h"
#include "common/str.h"
-#include "mohawk/resource.h"
-
namespace Mohawk {
class MohawkEngine_Riven;
@@ -53,7 +51,6 @@ public:
private:
MohawkEngine_Riven *_vm;
Common::SaveFileManager *_saveFileMan;
- MohawkArchive *_loadFile;
Common::MemoryWriteStreamDynamic *genVERSSection();
Common::MemoryWriteStreamDynamic *genNAMESection();
diff --git a/engines/mohawk/riven_scripts.cpp b/engines/mohawk/riven_scripts.cpp
index e809ad9642..1fcaba8ac0 100644
--- a/engines/mohawk/riven_scripts.cpp
+++ b/engines/mohawk/riven_scripts.cpp
@@ -28,40 +28,28 @@
#include "mohawk/riven_external.h"
#include "mohawk/riven_scripts.h"
#include "mohawk/sound.h"
-#include "mohawk/video/video.h"
+#include "mohawk/video.h"
#include "common/stream.h"
#include "graphics/cursorman.h"
namespace Mohawk {
-RivenScript::RivenScript(MohawkEngine_Riven *vm, Common::SeekableReadStream *stream, uint16 scriptType)
- : _vm(vm), _stream(stream), _scriptType(scriptType) {
+RivenScript::RivenScript(MohawkEngine_Riven *vm, Common::SeekableReadStream *stream, uint16 scriptType, uint16 parentStack, uint16 parentCard)
+ : _vm(vm), _stream(stream), _scriptType(scriptType), _parentStack(parentStack), _parentCard(parentCard) {
setupOpcodes();
+ _isRunning = false;
}
RivenScript::~RivenScript() {
delete _stream;
}
-RivenScriptList RivenScript::readScripts(MohawkEngine_Riven *vm, Common::SeekableReadStream *stream) {
- RivenScriptList scriptList;
-
- uint16 scriptCount = stream->readUint16BE();
- for (uint16 i = 0; i < scriptCount; i++) {
- uint16 scriptType = stream->readUint16BE();
- uint32 scriptSize = calculateScriptSize(stream);
- scriptList.push_back(Common::SharedPtr<RivenScript>(new RivenScript(vm, stream->readStream(scriptSize), scriptType)));
- }
-
- return scriptList;
-}
-
uint32 RivenScript::calculateCommandSize(Common::SeekableReadStream* script) {
uint16 command = script->readUint16BE();
uint32 commandSize = 2;
if (command == 8) {
- if (script->readUint16BE() != 2)
+ if (script->readUint16BE() != 2) // Arg count?
warning ("if-then-else unknown value is not 2");
script->readUint16BE(); // variable to check against
uint16 logicBlockCount = script->readUint16BE(); // number of logic blocks
@@ -161,7 +149,7 @@ void RivenScript::setupOpcodes() {
OPCODE(activateFLST),
OPCODE(zipMode),
OPCODE(activateMLST),
- OPCODE(activateSLSTWithVolume)
+ OPCODE(empty) // Activate an SLST with a volume parameter (not used)
};
_opcodes = riven_opcodes;
@@ -239,10 +227,13 @@ void RivenScript::dumpCommands(Common::StringArray varNames, Common::StringArray
}
void RivenScript::runScript() {
+ _isRunning = true;
+
if (_stream->pos() != 0)
_stream->seek(0);
processCommands(true);
+ _isRunning = false;
}
void RivenScript::processCommands(bool runCommands) {
@@ -298,13 +289,10 @@ void RivenScript::processCommands(bool runCommands) {
// Command 1: draw tBMP resource (tbmp_id, left, top, right, bottom, u0, u1, u2, u3)
void RivenScript::drawBitmap(uint16 op, uint16 argc, uint16 *argv) {
- if (argc < 5) {
- // Copy the image to the whole screen, ignoring the rest of the parameters
+ if (argc < 5) // Copy the image to the whole screen, ignoring the rest of the parameters
_vm->_gfx->copyImageToScreen(argv[0], 0, 0, 608, 392);
- } else {
- // Copy the image to a certain part of the screen
+ else // Copy the image to a certain part of the screen
_vm->_gfx->copyImageToScreen(argv[0], argv[1], argv[2], argv[3], argv[4]);
- }
// Now, update the screen
_vm->_gfx->updateScreen();
@@ -313,6 +301,12 @@ void RivenScript::drawBitmap(uint16 op, uint16 argc, uint16 *argv) {
// Command 2: go to card (card id)
void RivenScript::switchCard(uint16 op, uint16 argc, uint16 *argv) {
_vm->changeToCard(argv[0]);
+
+ // WORKAROUND: If we changed card on a mouse down event,
+ // we want to ignore the next mouse up event so we don't
+ // change card when lifting the mouse on the next card.
+ if (_scriptType == kMouseDownScript)
+ _vm->ignoreNextMouseUp();
}
// Command 3: play an SLST from the script
@@ -547,9 +541,8 @@ void RivenScript::activateSLST(uint16 op, uint16 argc, uint16 *argv) {
// Command 41: activate MLST record and play
void RivenScript::activateMLSTAndPlay(uint16 op, uint16 argc, uint16 *argv) {
- _vm->_video->enableMovie(argv[0] - 1);
_vm->_video->activateMLST(argv[0], _vm->getCurCard());
- // TODO: Play movie (blocking?)
+ _vm->_video->playMovie(argv[0]);
}
// Command 43: activate BLST record (card hotspot enabling lists)
@@ -608,9 +601,46 @@ void RivenScript::activateMLST(uint16 op, uint16 argc, uint16 *argv) {
_vm->_video->activateMLST(argv[0], _vm->getCurCard());
}
-// Command 47: activate SLST record with a volume argument
-void RivenScript::activateSLSTWithVolume(uint16 op, uint16 argc, uint16 *argv) {
- warning("STUB: activateSLSTWithVolume()");
+RivenScriptManager::RivenScriptManager(MohawkEngine_Riven *vm) {
+ _vm = vm;
+}
+
+RivenScriptManager::~RivenScriptManager() {
+ for (uint32 i = 0; i < _currentScripts.size(); i++)
+ delete _currentScripts[i];
+}
+
+RivenScriptList RivenScriptManager::readScripts(Common::SeekableReadStream *stream, bool garbageCollect) {
+ if (garbageCollect)
+ unloadUnusedScripts(); // Garbage collect!
+
+ RivenScriptList scriptList;
+
+ uint16 scriptCount = stream->readUint16BE();
+ for (uint16 i = 0; i < scriptCount; i++) {
+ uint16 scriptType = stream->readUint16BE();
+ uint32 scriptSize = RivenScript::calculateScriptSize(stream);
+ RivenScript *script = new RivenScript(_vm, stream->readStream(scriptSize), scriptType, _vm->getCurStack(), _vm->getCurCard());
+ scriptList.push_back(script);
+
+ // Only add it to the scripts that we will free later if it is requested.
+ // (ie. we don't want to store scripts from the dumpScript console command)
+ if (garbageCollect)
+ _currentScripts.push_back(script);
+ }
+
+ return scriptList;
+}
+
+void RivenScriptManager::unloadUnusedScripts() {
+ // Free any scripts that aren't part of the current card and aren't running
+ for (uint32 i = 0; i < _currentScripts.size(); i++) {
+ if ((_vm->getCurStack() != _currentScripts[i]->getParentStack() || _vm->getCurCard() != _currentScripts[i]->getParentCard()) && !_currentScripts[i]->isRunning()) {
+ delete _currentScripts[i];
+ _currentScripts.remove_at(i);
+ i--;
+ }
+ }
}
} // End of namespace Mohawk
diff --git a/engines/mohawk/riven_scripts.h b/engines/mohawk/riven_scripts.h
index a1512af697..5187bbde08 100644
--- a/engines/mohawk/riven_scripts.h
+++ b/engines/mohawk/riven_scripts.h
@@ -50,19 +50,20 @@ enum {
};
class RivenScript;
-typedef Common::Array<Common::SharedPtr<RivenScript> > RivenScriptList;
class RivenScript {
public:
- RivenScript(MohawkEngine_Riven *vm, Common::SeekableReadStream *stream, uint16 scriptType);
+ RivenScript(MohawkEngine_Riven *vm, Common::SeekableReadStream *stream, uint16 scriptType, uint16 parentStack, uint16 parentCard);
~RivenScript();
void runScript();
void dumpScript(Common::StringArray varNames, Common::StringArray xNames, byte tabs);
uint16 getScriptType() { return _scriptType; }
+ uint16 getParentStack() { return _parentStack; }
+ uint16 getParentCard() { return _parentCard; }
+ bool isRunning() { return _isRunning; }
- // Read in an array of script objects from a stream
- static RivenScriptList readScripts(MohawkEngine_Riven *vm, Common::SeekableReadStream *stream);
+ static uint32 calculateScriptSize(Common::SeekableReadStream *script);
private:
typedef void (RivenScript::*OpcodeProcRiven)(uint16 op, uint16 argc, uint16 *argv);
@@ -70,18 +71,18 @@ private:
OpcodeProcRiven proc;
const char *desc;
};
- const RivenOpcode* _opcodes;
+ const RivenOpcode *_opcodes;
void setupOpcodes();
MohawkEngine_Riven *_vm;
Common::SeekableReadStream *_stream;
- uint16 _scriptType;
+ uint16 _scriptType, _parentStack, _parentCard, _parentHotspot;
+ bool _isRunning;
void dumpCommands(Common::StringArray varNames, Common::StringArray xNames, byte tabs);
void processCommands(bool runCommands);
- static uint32 calculateCommandSize(Common::SeekableReadStream* script);
- static uint32 calculateScriptSize(Common::SeekableReadStream* script);
+ static uint32 calculateCommandSize(Common::SeekableReadStream *script);
DECLARE_OPCODE(empty) { warning ("Unknown Opcode %04x", op); }
@@ -120,7 +121,21 @@ private:
DECLARE_OPCODE(activateFLST);
DECLARE_OPCODE(zipMode);
DECLARE_OPCODE(activateMLST);
- DECLARE_OPCODE(activateSLSTWithVolume);
+};
+
+typedef Common::Array<RivenScript*> RivenScriptList;
+
+class RivenScriptManager {
+public:
+ RivenScriptManager(MohawkEngine_Riven *vm);
+ ~RivenScriptManager();
+
+ RivenScriptList readScripts(Common::SeekableReadStream *stream, bool garbageCollect = true);
+
+private:
+ void unloadUnusedScripts();
+ RivenScriptList _currentScripts;
+ MohawkEngine_Riven *_vm;
};
} // End of namespace Mohawk
diff --git a/engines/mohawk/riven_vars.cpp b/engines/mohawk/riven_vars.cpp
index 3f7cd5a8b6..b6d2dff315 100644
--- a/engines/mohawk/riven_vars.cpp
+++ b/engines/mohawk/riven_vars.cpp
@@ -319,6 +319,8 @@ void MohawkEngine_Riven::initVars() {
*matchVarToString("bheat") = 1;
*matchVarToString("waterenabled") = 1;
*matchVarToString("ogehnpage") = 1;
+ *matchVarToString("bblrsw") = 1;
+ *matchVarToString("ocage") = 1;
// Randomize the telescope combination
uint32 *teleCombo = matchVarToString("tcorrectorder");
diff --git a/engines/mohawk/sound.cpp b/engines/mohawk/sound.cpp
index b84573f011..091bd68021 100644
--- a/engines/mohawk/sound.cpp
+++ b/engines/mohawk/sound.cpp
@@ -27,12 +27,12 @@
#include "common/util.h"
+#include "sound/musicplugin.h"
#include "sound/audiostream.h"
#include "sound/decoders/mp3.h"
#include "sound/decoders/raw.h"
#include "sound/decoders/wave.h"
-
namespace Mohawk {
Sound::Sound(MohawkEngine* vm) : _vm(vm) {
@@ -79,7 +79,7 @@ void Sound::initMidi() {
// Let's get our MIDI parser/driver
_midiParser = MidiParser::createParser_SMF();
- _midiDriver = MidiDriver::createMidi(MidiDriver::detectMusicDriver(MDT_ADLIB|MDT_MIDI));
+ _midiDriver = MidiDriver::createMidi(MidiDriver::detectDevice(MDT_ADLIB|MDT_MIDI));
// Set up everything!
_midiDriver->open();
@@ -233,6 +233,10 @@ void Sound::playSLST(uint16 index, uint16 card) {
if (slstRecord.index == index) {
playSLST(slstRecord);
+ delete[] slstRecord.sound_ids;
+ delete[] slstRecord.volumes;
+ delete[] slstRecord.balances;
+ delete[] slstRecord.u2;
delete slstStream;
return;
}
@@ -244,6 +248,7 @@ void Sound::playSLST(uint16 index, uint16 card) {
}
delete slstStream;
+
// No matching records, assume we need to stop all SLST's
stopAllSLST();
}
@@ -277,8 +282,11 @@ void Sound::playSLST(SLSTRecord slstRecord) {
}
void Sound::stopAllSLST() {
- for (uint16 i = 0; i < _currentSLSTSounds.size(); i++)
+ for (uint16 i = 0; i < _currentSLSTSounds.size(); i++) {
_vm->_mixer->stopHandle(*_currentSLSTSounds[i].handle);
+ delete _currentSLSTSounds[i].handle;
+ }
+
_currentSLSTSounds.clear();
}
@@ -314,6 +322,7 @@ void Sound::playSLSTSound(uint16 id, bool fade, bool loop, uint16 volume, int16
void Sound::stopSLSTSound(uint16 index, bool fade) {
// TODO: Fade out, mixer needs to be extended to get volume on a handle
_vm->_mixer->stopHandle(*_currentSLSTSounds[index].handle);
+ delete _currentSLSTSounds[index].handle;
_currentSLSTSounds.remove_at(index);
}
diff --git a/engines/mohawk/video.cpp b/engines/mohawk/video.cpp
new file mode 100644
index 0000000000..17456b8ec3
--- /dev/null
+++ b/engines/mohawk/video.cpp
@@ -0,0 +1,415 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "mohawk/resource.h"
+#include "mohawk/video.h"
+
+#include "common/events.h"
+#include "graphics/video/qt_decoder.h"
+
+namespace Mohawk {
+
+VideoManager::VideoManager(MohawkEngine* vm) : _vm(vm) {
+}
+
+VideoManager::~VideoManager() {
+ stopVideos();
+}
+
+void VideoManager::pauseVideos() {
+ for (uint16 i = 0; i < _videoStreams.size(); i++)
+ if (_videoStreams[i].video)
+ _videoStreams[i]->pauseVideo(true);
+}
+
+void VideoManager::resumeVideos() {
+ for (uint16 i = 0; i < _videoStreams.size(); i++)
+ if (_videoStreams[i].video)
+ _videoStreams[i]->pauseVideo(false);
+}
+
+void VideoManager::stopVideos() {
+ for (uint16 i = 0; i < _videoStreams.size(); i++)
+ delete _videoStreams[i].video;
+ _videoStreams.clear();
+}
+
+void VideoManager::playMovie(Common::String filename, uint16 x, uint16 y, bool clearScreen) {
+ VideoHandle videoHandle = createVideoHandle(filename, x, y, false);
+ if (videoHandle == NULL_VID_HANDLE)
+ return;
+
+ // Clear screen if requested
+ if (clearScreen) {
+ _vm->_system->fillScreen(_vm->_system->getScreenFormat().RGBToColor(0, 0, 0));
+ _vm->_system->updateScreen();
+ }
+
+ waitUntilMovieEnds(videoHandle);
+}
+
+void VideoManager::playMovieCentered(Common::String filename, bool clearScreen) {
+ VideoHandle videoHandle = createVideoHandle(filename, 0, 0, false);
+ if (videoHandle == NULL_VID_HANDLE)
+ return;
+
+ // Clear screen if requested
+ if (clearScreen) {
+ _vm->_system->fillScreen(_vm->_system->getScreenFormat().RGBToColor(0, 0, 0));
+ _vm->_system->updateScreen();
+ }
+
+ _videoStreams[videoHandle].x = (_vm->_system->getWidth() - _videoStreams[videoHandle]->getWidth()) / 2;
+ _videoStreams[videoHandle].y = (_vm->_system->getHeight() - _videoStreams[videoHandle]->getHeight()) / 2;
+
+ waitUntilMovieEnds(videoHandle);
+}
+
+void VideoManager::waitUntilMovieEnds(VideoHandle videoHandle) {
+ bool continuePlaying = true;
+
+ while (_videoStreams[videoHandle].video && !_videoStreams[videoHandle]->endOfVideo() && !_vm->shouldQuit() && continuePlaying) {
+ if (updateBackgroundMovies())
+ _vm->_system->updateScreen();
+
+ Common::Event event;
+ while (_vm->_system->getEventManager()->pollEvent(event)) {
+ switch (event.type) {
+ case Common::EVENT_RTL:
+ case Common::EVENT_QUIT:
+ continuePlaying = false;
+ break;
+ case Common::EVENT_KEYDOWN:
+ switch (event.kbd.keycode) {
+ case Common::KEYCODE_SPACE:
+ _vm->pauseGame();
+ break;
+ case Common::KEYCODE_ESCAPE:
+ continuePlaying = false;
+ break;
+ default:
+ break;
+ }
+ default:
+ break;
+ }
+ }
+
+ // Cut down on CPU usage
+ _vm->_system->delayMillis(10);
+ }
+
+ delete _videoStreams[videoHandle].video;
+ _videoStreams[videoHandle].video = 0;
+ _videoStreams[videoHandle].id = 0;
+ _videoStreams[videoHandle].filename.clear();
+}
+
+void VideoManager::playBackgroundMovie(Common::String filename, int16 x, int16 y, bool loop) {
+ VideoHandle videoHandle = createVideoHandle(filename, x, y, loop);
+ if (videoHandle == NULL_VID_HANDLE)
+ return;
+
+ // Center x if requested
+ if (x < 0)
+ _videoStreams[videoHandle].x = (_vm->_system->getWidth() - _videoStreams[videoHandle]->getWidth()) / 2;
+
+ // Center y if requested
+ if (y < 0)
+ _videoStreams[videoHandle].y = (_vm->_system->getHeight() - _videoStreams[videoHandle]->getHeight()) / 2;
+}
+
+bool VideoManager::updateBackgroundMovies() {
+ bool updateScreen = false;
+
+ for (uint32 i = 0; i < _videoStreams.size() && !_vm->shouldQuit(); i++) {
+ // Skip deleted videos
+ if (!_videoStreams[i].video)
+ continue;
+
+ // Remove any videos that are over
+ if (_videoStreams[i]->endOfVideo()) {
+ if (_videoStreams[i].loop) {
+ _videoStreams[i]->rewind();
+ } else {
+ delete _videoStreams[i].video;
+ _videoStreams[i].video = 0;
+ _videoStreams[i].id = 0;
+ _videoStreams[i].filename.clear();
+ continue;
+ }
+ }
+
+ // Check if we need to draw a frame
+ if (_videoStreams[i]->needsUpdate()) {
+ Graphics::Surface *frame = _videoStreams[i]->decodeNextFrame();
+ bool deleteFrame = false;
+
+ if (frame && _videoStreams[i].enabled) {
+ // Convert from 8bpp to the current screen format if necessary
+ if (frame->bytesPerPixel == 1) {
+ Graphics::Surface *newFrame = new Graphics::Surface();
+ Graphics::PixelFormat pixelFormat = _vm->_system->getScreenFormat();
+ byte *palette = _videoStreams[i]->getPalette();
+ assert(palette);
+
+ newFrame->create(frame->w, frame->h, pixelFormat.bytesPerPixel);
+
+ for (uint16 j = 0; j < frame->h; j++) {
+ for (uint16 k = 0; k < frame->w; k++) {
+ byte palIndex = *((byte *)frame->getBasePtr(k, j));
+ byte r = palette[palIndex * 3];
+ byte g = palette[palIndex * 3 + 1];
+ byte b = palette[palIndex * 3 + 2];
+ if (pixelFormat.bytesPerPixel == 2)
+ *((uint16 *)newFrame->getBasePtr(k, j)) = pixelFormat.RGBToColor(r, g, b);
+ else
+ *((uint32 *)newFrame->getBasePtr(k, j)) = pixelFormat.RGBToColor(r, g, b);
+ }
+ }
+
+ frame = newFrame;
+ deleteFrame = true;
+ }
+
+ // Clip the width/height to make sure we stay on the screen (Myst does this a few times)
+ uint16 width = MIN<int32>(_videoStreams[i]->getWidth(), _vm->_system->getWidth() - _videoStreams[i].x);
+ uint16 height = MIN<int32>(_videoStreams[i]->getHeight(), _vm->_system->getHeight() - _videoStreams[i].y);
+ _vm->_system->copyRectToScreen((byte*)frame->pixels, frame->pitch, _videoStreams[i].x, _videoStreams[i].y, width, height);
+
+ // We've drawn something to the screen, make sure we update it
+ updateScreen = true;
+
+ // Delete the frame if we're using the buffer from the 8bpp conversion
+ if (deleteFrame) {
+ frame->free();
+ delete frame;
+ }
+ }
+ }
+
+ // Update the audio buffer too
+ _videoStreams[i]->updateAudioBuffer();
+ }
+
+ // Return true if we need to update the screen
+ return updateScreen;
+}
+
+void VideoManager::activateMLST(uint16 mlstId, uint16 card) {
+ Common::SeekableReadStream *mlstStream = _vm->getRawData(ID_MLST, card);
+ uint16 recordCount = mlstStream->readUint16BE();
+
+ for (uint16 i = 0; i < recordCount; i++) {
+ MLSTRecord mlstRecord;
+ mlstRecord.index = mlstStream->readUint16BE();
+ mlstRecord.movieID = mlstStream->readUint16BE();
+ mlstRecord.code = mlstStream->readUint16BE();
+ mlstRecord.left = mlstStream->readUint16BE();
+ mlstRecord.top = mlstStream->readUint16BE();
+
+ for (byte j = 0; j < 2; j++)
+ if (mlstStream->readUint16BE() != 0)
+ warning("u0[%d] in MLST non-zero", j);
+
+ if (mlstStream->readUint16BE() != 0xFFFF)
+ warning("u0[2] in MLST not 0xFFFF");
+
+ mlstRecord.loop = mlstStream->readUint16BE();
+ mlstRecord.volume = mlstStream->readUint16BE();
+ mlstRecord.u1 = mlstStream->readUint16BE();
+
+ if (mlstRecord.u1 != 1)
+ warning("mlstRecord.u1 not 1");
+
+ // We've found a match, add it
+ if (mlstRecord.index == mlstId) {
+ // Make sure we don't have any duplicates
+ for (uint32 j = 0; j < _mlstRecords.size(); j++)
+ if (_mlstRecords[j].index == mlstRecord.index || _mlstRecords[j].code == mlstRecord.code) {
+ _mlstRecords.remove_at(j);
+ j--;
+ }
+
+ _mlstRecords.push_back(mlstRecord);
+ break;
+ }
+ }
+
+ delete mlstStream;
+}
+
+void VideoManager::clearMLST() {
+ _mlstRecords.clear();
+}
+
+void VideoManager::playMovie(uint16 id) {
+ for (uint16 i = 0; i < _mlstRecords.size(); i++)
+ if (_mlstRecords[i].code == id) {
+ debug(1, "Play tMOV %d (non-blocking) at (%d, %d) %s", _mlstRecords[i].movieID, _mlstRecords[i].left, _mlstRecords[i].top, _mlstRecords[i].loop != 0 ? "looping" : "non-looping");
+ createVideoHandle(_mlstRecords[i].movieID, _mlstRecords[i].left, _mlstRecords[i].top, _mlstRecords[i].loop != 0);
+ return;
+ }
+}
+
+void VideoManager::playMovieBlocking(uint16 id) {
+ for (uint16 i = 0; i < _mlstRecords.size(); i++)
+ if (_mlstRecords[i].code == id) {
+ debug(1, "Play tMOV %d (blocking) at (%d, %d)", _mlstRecords[i].movieID, _mlstRecords[i].left, _mlstRecords[i].top);
+ VideoHandle videoHandle = createVideoHandle(_mlstRecords[i].movieID, _mlstRecords[i].left, _mlstRecords[i].top, false);
+ waitUntilMovieEnds(videoHandle);
+ return;
+ }
+}
+
+void VideoManager::stopMovie(uint16 id) {
+ debug(2, "Stopping movie %d", id);
+ for (uint16 i = 0; i < _mlstRecords.size(); i++)
+ if (_mlstRecords[i].code == id)
+ for (uint16 j = 0; j < _videoStreams.size(); j++)
+ if (_mlstRecords[i].movieID == _videoStreams[j].id) {
+ delete _videoStreams[j].video;
+ _videoStreams[j].video = 0;
+ _videoStreams[j].id = 0;
+ _videoStreams[j].filename.clear();
+ return;
+ }
+}
+
+void VideoManager::enableMovie(uint16 id) {
+ debug(2, "Enabling movie %d", id);
+ for (uint16 i = 0; i < _mlstRecords.size(); i++)
+ if (_mlstRecords[i].code == id)
+ for (uint16 j = 0; j < _videoStreams.size(); j++)
+ if (_mlstRecords[i].movieID == _videoStreams[j].id) {
+ _videoStreams[j].enabled = true;
+ return;
+ }
+}
+
+void VideoManager::disableMovie(uint16 id) {
+ debug(2, "Disabling movie %d", id);
+ for (uint16 i = 0; i < _mlstRecords.size(); i++)
+ if (_mlstRecords[i].code == id)
+ for (uint16 j = 0; j < _videoStreams.size(); j++)
+ if (_mlstRecords[i].movieID == _videoStreams[j].id) {
+ _videoStreams[j].enabled = false;
+ return;
+ }
+}
+
+void VideoManager::disableAllMovies() {
+ debug(2, "Disabling all movies");
+ for (uint16 i = 0; i < _videoStreams.size(); i++)
+ _videoStreams[i].enabled = false;
+}
+
+VideoHandle VideoManager::createVideoHandle(uint16 id, uint16 x, uint16 y, bool loop) {
+ // First, check to see if that video is already playing
+ for (uint32 i = 0; i < _videoStreams.size(); i++)
+ if (_videoStreams[i].id == id)
+ return i;
+
+ // Otherwise, create a new entry
+ VideoEntry entry;
+ entry.video = new Graphics::QuickTimeDecoder();
+ entry.x = x;
+ entry.y = y;
+ entry.filename = "";
+ entry.id = id;
+ entry.loop = loop;
+ entry.enabled = true;
+ entry->setChunkBeginOffset(_vm->getResourceOffset(ID_TMOV, id));
+ entry->load(_vm->getRawData(ID_TMOV, id));
+
+ // Search for any deleted videos so we can take a formerly used slot
+ for (uint32 i = 0; i < _videoStreams.size(); i++)
+ if (!_videoStreams[i].video) {
+ _videoStreams[i] = entry;
+ return i;
+ }
+
+ // Otherwise, just add it to the list
+ _videoStreams.push_back(entry);
+ return _videoStreams.size() - 1;
+}
+
+VideoHandle VideoManager::createVideoHandle(Common::String filename, uint16 x, uint16 y, bool loop) {
+ // First, check to see if that video is already playing
+ for (uint32 i = 0; i < _videoStreams.size(); i++)
+ if (_videoStreams[i].filename == filename)
+ return i;
+
+ // Otherwise, create a new entry
+ VideoEntry entry;
+ entry.video = new Graphics::QuickTimeDecoder();
+ entry.x = x;
+ entry.y = y;
+ entry.filename = filename;
+ entry.id = 0;
+ entry.loop = loop;
+ entry.enabled = true;
+
+ Common::File *file = new Common::File();
+ if (!file->open(filename)) {
+ delete file;
+ return NULL_VID_HANDLE;
+ }
+
+ entry->load(file);
+
+ // Search for any deleted videos so we can take a formerly used slot
+ for (uint32 i = 0; i < _videoStreams.size(); i++)
+ if (!_videoStreams[i].video) {
+ _videoStreams[i] = entry;
+ return i;
+ }
+
+ // Otherwise, just add it to the list
+ _videoStreams.push_back(entry);
+ return _videoStreams.size() - 1;
+}
+
+VideoHandle VideoManager::findVideoHandle(uint16 id) {
+ for (uint16 i = 0; i < _mlstRecords.size(); i++)
+ if (_mlstRecords[i].code == id)
+ for (uint16 j = 0; j < _videoStreams.size(); j++)
+ if (_videoStreams[j].video && _mlstRecords[i].movieID == _videoStreams[j].id)
+ return j;
+
+ return NULL_VID_HANDLE;
+}
+
+int32 VideoManager::getCurFrame(const VideoHandle &handle) {
+ assert(handle != NULL_VID_HANDLE);
+ return _videoStreams[handle]->getCurFrame();
+}
+
+uint32 VideoManager::getFrameCount(const VideoHandle &handle) {
+ assert(handle != NULL_VID_HANDLE);
+ return _videoStreams[handle]->getFrameCount();
+}
+
+} // End of namespace Mohawk
diff --git a/engines/mohawk/video.h b/engines/mohawk/video.h
new file mode 100644
index 0000000000..6aa553e26b
--- /dev/null
+++ b/engines/mohawk/video.h
@@ -0,0 +1,114 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef MOHAWK_VIDEO_H
+#define MOHAWK_VIDEO_H
+
+#include "graphics/pixelformat.h"
+
+namespace Graphics {
+ class QuickTimeDecoder;
+}
+
+namespace Mohawk {
+
+class MohawkEngine;
+
+struct MLSTRecord {
+ uint16 index;
+ uint16 movieID;
+ uint16 code;
+ uint16 left;
+ uint16 top;
+ uint16 u0[3];
+ uint16 loop;
+ uint16 volume;
+ uint16 u1;
+};
+
+struct VideoEntry {
+ Graphics::QuickTimeDecoder *video;
+ uint16 x;
+ uint16 y;
+ bool loop;
+ Common::String filename;
+ uint16 id; // Riven only
+ bool enabled;
+
+ Graphics::QuickTimeDecoder *operator->() const { assert(video); return video; }
+};
+
+typedef int32 VideoHandle;
+
+enum {
+ NULL_VID_HANDLE = -1
+};
+
+class VideoManager {
+public:
+ VideoManager(MohawkEngine *vm);
+ ~VideoManager();
+
+ // Generic movie functions
+ void playMovie(Common::String filename, uint16 x = 0, uint16 y = 0, bool clearScreen = false);
+ void playMovieCentered(Common::String filename, bool clearScreen = true);
+ void playBackgroundMovie(Common::String filename, int16 x = -1, int16 y = -1, bool loop = false);
+ bool updateBackgroundMovies();
+ void pauseVideos();
+ void resumeVideos();
+ void stopVideos();
+
+ // Riven-related functions
+ void activateMLST(uint16 mlstId, uint16 card);
+ void clearMLST();
+ void enableMovie(uint16 id);
+ void disableMovie(uint16 id);
+ void disableAllMovies();
+ void playMovie(uint16 id);
+ void stopMovie(uint16 id);
+ void playMovieBlocking(uint16 id);
+
+ // Handle functions
+ VideoHandle findVideoHandle(uint16 id);
+ int32 getCurFrame(const VideoHandle &handle);
+ uint32 getFrameCount(const VideoHandle &handle);
+
+private:
+ MohawkEngine *_vm;
+
+ // Riven-related variables
+ Common::Array<MLSTRecord> _mlstRecords;
+
+ // Keep tabs on any videos playing
+ Common::Array<VideoEntry> _videoStreams;
+
+ VideoHandle createVideoHandle(uint16 id, uint16 x, uint16 y, bool loop);
+ VideoHandle createVideoHandle(Common::String filename, uint16 x, uint16 y, bool loop);
+ void waitUntilMovieEnds(VideoHandle videoHandle);
+};
+
+} // End of namespace Mohawk
+
+#endif