From d58c5133f45879e617ae3017e7720b657c5a2eb6 Mon Sep 17 00:00:00 2001 From: D G Turner Date: Tue, 13 Mar 2012 13:20:44 +0000 Subject: SCI: Add detection entry for KQ6 French DOS Floppy. See bug #3503425. --- engines/sci/detection_tables.h | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'engines/sci') diff --git a/engines/sci/detection_tables.h b/engines/sci/detection_tables.h index 63eda1c348..2047f58c8b 100644 --- a/engines/sci/detection_tables.h +++ b/engines/sci/detection_tables.h @@ -1421,6 +1421,15 @@ static const struct ADGameDescription SciGameDescriptions[] = { AD_LISTEND}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO1(GUIO_NOSPEECH) }, + // King's Quest 6 - French DOS Floppy (supplied by misterhands in bug #3503425) + // SCI interpreter version ??? + {"kq6", "", { + {"resource.map", 0, "a362063318eebe7d6423b1d9dc6213e1", 8703}, + {"resource.000", 0, "f2b7f753992c56a0c7a08d6a5077c895", 7863324}, + {"resource.msg", 0, "adc2aa8adbdcc97507d44a6f492fbd77", 265194}, + AD_LISTEND}, + Common::FR_FRA, Common::kPlatformPC, 0, GUIO1(GUIO_NOSPEECH) }, + // King's Quest 6 - German DOS Floppy (supplied by markcoolio in bug report #2727156) // SCI interpreter version 1.001.054 {"kq6", "", { -- cgit v1.2.3 From 75efdd2d84e21f5d3d01afcc89d61289ae87e4a2 Mon Sep 17 00:00:00 2001 From: Christoph Mallon Date: Tue, 13 Mar 2012 10:40:41 +0100 Subject: JANITORIAL: Replace (x ? false : true) by !(x). --- engines/sci/engine/kmenu.cpp | 2 +- engines/sci/graphics/controls16.cpp | 2 +- engines/sci/graphics/menu.cpp | 4 ++-- engines/sci/graphics/paint16.cpp | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/engine/kmenu.cpp b/engines/sci/engine/kmenu.cpp index 02aa1d3ece..05ba7005d7 100644 --- a/engines/sci/engine/kmenu.cpp +++ b/engines/sci/engine/kmenu.cpp @@ -94,7 +94,7 @@ reg_t kDrawMenuBar(EngineState *s, int argc, reg_t *argv) { reg_t kMenuSelect(EngineState *s, int argc, reg_t *argv) { reg_t eventObject = argv[0]; - bool pauseSound = argc > 1 ? (argv[1].isNull() ? false : true) : true; + bool pauseSound = argc <= 1 || !argv[1].isNull(); return g_sci->_gfxMenu->kernelSelect(eventObject, pauseSound); } diff --git a/engines/sci/graphics/controls16.cpp b/engines/sci/graphics/controls16.cpp index ab54e468d1..7c09969717 100644 --- a/engines/sci/graphics/controls16.cpp +++ b/engines/sci/graphics/controls16.cpp @@ -297,7 +297,7 @@ void GfxControls16::kernelDrawButton(Common::Rect rect, reg_t obj, const char *t _paint16->eraseRect(rect); _paint16->frameRect(rect); rect.grow(-2); - _ports->textGreyedOutput(style & 1 ? false : true); + _ports->textGreyedOutput(!(style & SCI_CONTROLS_STYLE_ENABLED)); _text16->Box(text, false, rect, SCI_TEXT16_ALIGNMENT_CENTER, fontId); _ports->textGreyedOutput(false); rect.grow(1); diff --git a/engines/sci/graphics/menu.cpp b/engines/sci/graphics/menu.cpp index 673729784f..47f34cf99d 100644 --- a/engines/sci/graphics/menu.cpp +++ b/engines/sci/graphics/menu.cpp @@ -286,7 +286,7 @@ void GfxMenu::kernelSetAttribute(uint16 menuId, uint16 itemId, uint16 attributeI switch (attributeId) { case SCI_MENU_ATTRIBUTE_ENABLED: - itemEntry->enabled = value.isNull() ? false : true; + itemEntry->enabled = !value.isNull(); break; case SCI_MENU_ATTRIBUTE_SAID: itemEntry->saidVmPtr = value; @@ -606,7 +606,7 @@ void GfxMenu::drawMenu(uint16 oldMenuId, uint16 newMenuId) { listItemEntry = *listItemIterator; if (listItemEntry->menuId == newMenuId) { if (!listItemEntry->separatorLine) { - _ports->textGreyedOutput(listItemEntry->enabled ? false : true); + _ports->textGreyedOutput(!listItemEntry->enabled); _ports->moveTo(_menuRect.left, topPos); _text16->DrawString(listItemEntry->textSplit.c_str()); _ports->moveTo(_menuRect.right - listItemEntry->textRightAlignedWidth - 5, topPos); diff --git a/engines/sci/graphics/paint16.cpp b/engines/sci/graphics/paint16.cpp index 23177dfc7b..c951f3349d 100644 --- a/engines/sci/graphics/paint16.cpp +++ b/engines/sci/graphics/paint16.cpp @@ -513,7 +513,7 @@ reg_t GfxPaint16::kernelDisplay(const char *text, int argc, reg_t *argv) { argc--; argv++; break; case SCI_DISPLAY_SETGREYEDOUTPUT: - _ports->textGreyedOutput(argv[0].isNull() ? false : true); + _ports->textGreyedOutput(!argv[0].isNull()); argc--; argv++; break; case SCI_DISPLAY_SETFONT: -- cgit v1.2.3 From 96f132994f4919df8064683c2d7f22671d184fa3 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Mon, 19 Mar 2012 03:39:14 +0200 Subject: SCI: Add per-game GUI option support. --- engines/sci/detection.cpp | 76 ++++- engines/sci/detection_tables.h | 711 +++++++++++++++++++++-------------------- 2 files changed, 431 insertions(+), 356 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/detection.cpp b/engines/sci/detection.cpp index c43849056b..5cbe3633c7 100644 --- a/engines/sci/detection.cpp +++ b/engines/sci/detection.cpp @@ -26,6 +26,7 @@ #include "common/ptr.h" #include "common/savefile.h" #include "common/system.h" +#include "common/translation.h" #include "graphics/thumbnail.h" #include "graphics/surface.h" @@ -362,6 +363,73 @@ Common::String convertSierraGameId(Common::String sierraId, uint32 *gameFlags, R #include "sci/detection_tables.h" +static const ADExtraGuiOptionsMap optionsList[] = { + { + GAMEOPTION_PREFER_DIGITAL_SFX, + { + _s("Prefer digital sound effects"), + _s("Prefer digital sound effects instead of synthesized ones"), + "prefer_digitalsfx", + true + } + }, + + { + GAMEOPTION_ORIGINAL_SAVELOAD, + { + _s("Use original save/load screens"), + _s("Use the original save/load screens, instead of the ScummVM ones"), + "sci_originalsaveload", + false + } + }, + + { + GAMEOPTION_FB01_MIDI, + { + _s("Use IMF/Yahama FB-01 for MIDI output"), + _s("Use an IBM Music Feature card or a Yahama FB-01 FM synth module for MIDI output"), + "native_fb01", + false + } + }, + + // Jones in the Fast Lane - CD audio tracks or resource.snd + { + GAMEOPTION_JONES_CDAUDIO, + { + _s("Use CD audio"), + _s("Use CD audio instead of in-game audio, if available"), + "use_cdaudio", + true + } + }, + + // KQ6 Windows - windows cursors + { + GAMEOPTION_KQ6_WINDOWS_CURSORS, + { + _s("Use Windows cursors"), + _s("Use the Windows cursors (smaller and monochrome) instead of the DOS ones"), + "windows_cursors", + false + } + }, + + // SQ4 CD - silver cursors + { + GAMEOPTION_SQ4_SILVER_CURSORS, + { + _s("Use silver cursors"), + _s("Use the alternate set of silver cursors, instead of the normal golden ones"), + "silver_cursors", + false + } + }, + + AD_EXTRA_GUI_OPTIONS_TERMINATOR +}; + /** * The fallback game descriptor used by the SCI engine's fallbackDetector. * Contents of this struct are overwritten by the fallbackDetector. @@ -373,14 +441,14 @@ static ADGameDescription s_fallbackDesc = { Common::UNK_LANG, Common::kPlatformPC, ADGF_NO_FLAGS, - GUIO0() + GUIO3(GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }; static char s_fallbackGameIdBuf[256]; class SciMetaEngine : public AdvancedMetaEngine { public: - SciMetaEngine() : AdvancedMetaEngine(Sci::SciGameDescriptions, sizeof(ADGameDescription), s_sciGameTitles) { + SciMetaEngine() : AdvancedMetaEngine(Sci::SciGameDescriptions, sizeof(ADGameDescription), s_sciGameTitles, optionsList) { _singleid = "sci"; } @@ -435,7 +503,7 @@ const ADGameDescription *SciMetaEngine::fallbackDetect(const FileMap &allFiles, s_fallbackDesc.flags = ADGF_NO_FLAGS; s_fallbackDesc.platform = Common::kPlatformPC; // default to PC platform s_fallbackDesc.gameid = "sci"; - s_fallbackDesc.guioptions = GUIO0(); + s_fallbackDesc.guioptions = GUIO3(GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI); if (allFiles.contains("resource.map") || allFiles.contains("Data1") || allFiles.contains("resmap.001") || allFiles.contains("resmap.001")) { @@ -565,7 +633,7 @@ const ADGameDescription *SciMetaEngine::fallbackDetect(const FileMap &allFiles, const bool isCD = (s_fallbackDesc.flags & ADGF_CD); if (!isCD) - s_fallbackDesc.guioptions = GUIO1(GUIO_NOSPEECH); + s_fallbackDesc.guioptions = GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI); if (gameId.hasSuffix("sci")) { s_fallbackDesc.extra = "SCI"; diff --git a/engines/sci/detection_tables.h b/engines/sci/detection_tables.h index 2047f58c8b..7dd628f6b5 100644 --- a/engines/sci/detection_tables.h +++ b/engines/sci/detection_tables.h @@ -22,6 +22,13 @@ namespace Sci { +#define GAMEOPTION_PREFER_DIGITAL_SFX GUIO_GAMEOPTIONS1 +#define GAMEOPTION_ORIGINAL_SAVELOAD GUIO_GAMEOPTIONS2 +#define GAMEOPTION_FB01_MIDI GUIO_GAMEOPTIONS3 +#define GAMEOPTION_JONES_CDAUDIO GUIO_GAMEOPTIONS4 +#define GAMEOPTION_KQ6_WINDOWS_CURSORS GUIO_GAMEOPTIONS5 +#define GAMEOPTION_SQ4_SILVER_CURSORS GUIO_GAMEOPTIONS6 + // SCI3 games have a different script format (in CSC files) and are currently unsupported #define ENABLE_SCI3_GAMES @@ -29,7 +36,7 @@ namespace Sci { {"sci-fanmade", name, { \ {"resource.map", 0, resMapMd5, resMapSize}, \ {"resource.001", 0, resMd5, resSize}, \ - AD_LISTEND}, lang, Common::kPlatformPC, 0, GUIO1(GUIO_NOSPEECH) \ + AD_LISTEND}, lang, Common::kPlatformPC, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) \ } #define FANMADE(name, resMapMd5, resMapSize, resMd5, resSize) FANMADE_L(name, resMapMd5, resMapSize, resMd5, resSize, Common::EN_ANY) @@ -42,7 +49,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "f3d1be7752d30ba60614533d531e2e98", 474}, {"resource.001", 0, "6fd05926c2199af0af6f72f90d0d7260", 126895}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO2(GUIO_NOSPEECH, GUIO_EGAUNDITHER) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Castle of Dr. Brain - English Amiga (from www.back2roots.org) // Executable scanning reports "1.005.000" @@ -54,7 +61,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.002", 0, "d226d7d3b4f77c4a566913fc310487fc", 792380}, {"resource.003", 0, "d226d7d3b4f77c4a566913fc310487fc", 464348}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO1(GUIO_NOSPEECH) }, + Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Castle of Dr. Brain - German Amiga (from www.back2roots.org, also includes English language) // Executable scanning reports "1.005.001" @@ -66,7 +73,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.002", 0, "85e51acb5f9c539d66e3c8fe40e17da5", 826309}, {"resource.003", 0, "85e51acb5f9c539d66e3c8fe40e17da5", 493638}, AD_LISTEND}, - Common::DE_DEU, Common::kPlatformAmiga, ADGF_ADDENGLISH, GUIO1(GUIO_NOSPEECH) }, + Common::DE_DEU, Common::kPlatformAmiga, ADGF_ADDENGLISH, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Castle of Dr. Brain Macintosh (from omer_mor, bug report #3328251) {"castlebrain", "", { @@ -76,7 +83,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.002", 0, "e1a6b6f1060f60be9dcb6d28ad7a2a20", 1168310}, {"resource.003", 0, "6c3d1bb26ad532c94046bc9ac49b5ff4", 891295}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformMacintosh, 0, GUIO1(GUIO_NOSPEECH) }, + Common::EN_ANY, Common::kPlatformMacintosh, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Castle of Dr. Brain - English DOS Non-Interactive Demo // SCI interpreter version 1.000.005 @@ -85,7 +92,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.000", 0, "9780f040d58182994e22d2e34fab85b0", 67367}, {"resource.001", 0, "2af49dbd8f2e1db4ab09f9310dc91259", 570553}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO1(GUIO_NOSPEECH) }, + Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Castle of Dr. Brain - English DOS 5.25" Floppy EGA (from omer_mor, bug report #3035349) {"castlebrain", "EGA", { @@ -98,7 +105,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.005", 0, "8a5ed3ba96e2eaf18e36fedfaab89419", 297838}, {"resource.006", 0, "dceed92e709cad1bd9582809a235b0a0", 266682}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO2(GUIO_NOSPEECH, GUIO_EGAUNDITHER) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Castle of Dr. Brain - English DOS 3.5" Floppy EGA (from nozomi77, bug report #3405307) {"castlebrain", "EGA", { @@ -108,7 +115,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.002", 0, "de2f182529efaad2c4b510b452ab77ac", 633662}, {"resource.003", 0, "38b4b37febc6b4f5061c461a283df148", 430388}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO2(GUIO_NOSPEECH, GUIO_EGAUNDITHER) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Castle of Dr. Brain - English DOS Floppy (from jvprat) // Executable scanning reports "1.000.044", Floppy label reports "1.0, 10.30.91", VERSION file reports "1.000" @@ -119,7 +126,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.001", 0, "d2f5a1be74ed963fa849a76892be5290", 794832}, {"resource.002", 0, "c0c29c51af66d65cb53f49e785a2d978", 1280907}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO1(GUIO_NOSPEECH) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Castle of Dr. Brain - English DOS Floppy 1.1 {"castlebrain", "", { @@ -128,7 +135,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.001", 0, "13e81e1839cd7b216d2bb5615c1ca160", 796776}, {"resource.002", 0, "930e416bec196b9703a331d81b3d66f2", 1283812}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO1(GUIO_NOSPEECH) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Castle of Dr. Brain - English DOS Floppy 1.000 // Reported by graxer in bug report #3037942 @@ -143,7 +150,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.006", 0, "1d778a0c65cac9ddbab65495e50a94ee", 335281}, {"resource.007", 0, "063bb8ce4157c778cf30d1c912c006f1", 335631}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO1(GUIO_NOSPEECH) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Castle of Dr. Brain - Spanish DOS (also includes english language) // SCI interpreter version 1.000.510 @@ -152,7 +159,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.000", 0, "27ec5fa09cd12a7fd16e86d96a2ed245", 1197694}, {"resource.001", 0, "735be4e58957180cfc807d5e18fdffcd", 1433302}, AD_LISTEND}, - Common::ES_ESP, Common::kPlatformPC, ADGF_ADDENGLISH, GUIO1(GUIO_NOSPEECH) }, + Common::ES_ESP, Common::kPlatformPC, ADGF_ADDENGLISH, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Christmas Card 1988 - English DOS // SCI interpreter version 0.000.294 @@ -160,7 +167,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "39485580d34a72997f3d5b3aba4d24f1", 426}, {"resource.001", 0, "11391434f41c834090d7a1e9488ce936", 129739}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO2(GUIO_NOSPEECH, GUIO_EGAUNDITHER) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Christmas Card 1990: The Seasoned Professional - English DOS (16 Colors) // SCI interpreter version 1.000.172 @@ -168,7 +175,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "8f656714a05b94423ac6eb10ee8797d0", 600}, {"resource.001", 0, "acde93e58fca4f7a2a5a220558a94aa8", 272629}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO1(GUIO_NOSPEECH) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Christmas Card 1990: The Seasoned Professional - English DOS (256 Colors) // SCI interpreter version 1.000.174 @@ -176,7 +183,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "44b8f45b841b9b5e17e939a35e443988", 600}, {"resource.001", 0, "acde93e58fca4f7a2a5a220558a94aa8", 335362}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO1(GUIO_NOSPEECH) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Christmas Card 1992 - English DOS // SCI interpreter version 1.001.055 @@ -184,7 +191,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "f1f8c8a8443f523422af70b4ec85b71c", 318}, {"resource.000", 0, "62fb9256f8e7e6e65a6875efdb7939ac", 203396}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO1(GUIO_NOSPEECH) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Codename: Iceman - English Amiga (from www.back2roots.org) // Executable scanning reports "1.002.031" @@ -198,7 +205,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.004", 0, "8613c45fc771d658e5a505b9a4a54f31", 713382}, {"resource.005", 0, "605b67a9ef199a9bb015745e7c004cf4", 478384}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO2(GUIO_NOSPEECH, GUIO_EGAUNDITHER) }, + Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Codename: Iceman - English DOS Non-Interactive Demo // Executable scanning reports "0.000.685" @@ -206,7 +213,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "782974f29d8a824782d2d4aea39964e3", 1056}, {"resource.001", 0, "d4b75e280d1c3a97cfef1b0bebff387c", 573647}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO2(GUIO_NOSPEECH, GUIO_EGAUNDITHER) }, + Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Codename: Iceman - English DOS (from jvprat) // Executable scanning reports "0.000.685", Floppy label reports "1.033, 6.8.90", VERSION file reports "1.033" @@ -219,7 +226,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.003", 0, "d97a96f1ab91b41cf46a02cc89b0a04e", 624303}, {"resource.004", 0, "8613c45fc771d658e5a505b9a4a54f31", 670883}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO2(GUIO_NOSPEECH, GUIO_EGAUNDITHER) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Codename: Iceman - English DOS (from FRG) // SCI interpreter version 0.000.668 @@ -231,7 +238,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.003", 0, "dc7c5280e7acfaffe6ef2a6c963c5f94", 622118}, {"resource.004", 0, "64f342463f6f35ba71b3509ef696ae3f", 669188}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO2(GUIO_NOSPEECH, GUIO_EGAUNDITHER) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Codename: Iceman - English DOS (supplied by ssburnout in bug report #3049193) // 1.022 9x5.25" (label: Int#0.000.668) @@ -246,7 +253,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.006", 0, "08050329aa113a9f14ed99cbfe3536ec", 232942}, {"resource.007", 0, "64f342463f6f35ba71b3509ef696ae3f", 267811}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO2(GUIO_NOSPEECH, GUIO_EGAUNDITHER) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Codename: Iceman - English DOS 1.023 (from abevi, bug report #2612718) {"iceman", "", { @@ -260,7 +267,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.006", 0, "08050329aa113a9f14ed99cbfe3536ec", 232942}, {"resource.007", 0, "64f342463f6f35ba71b3509ef696ae3f", 267702}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO1(GUIO_NOSPEECH) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Conquests of Camelot - English Amiga (from www.back2roots.org) // Executable scanning reports "1.002.030" @@ -275,7 +282,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.005", 0, "c6e551bdc24f0acc193159038d4ca767", 605882}, {"resource.006", 0, "8f880a536908ab496bbc552f7f5c3738", 585255}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO2(GUIO_NOSPEECH, GUIO_EGAUNDITHER) }, + Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Conquests of Camelot - English DOS Non-Interactive Demo // SCI interpreter version 0.000.668 @@ -283,7 +290,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "f4cd75c15be75e04cdca3acda2c0b0ea", 468}, {"resource.001", 0, "4930708722f34bfbaa4945fb08f55f61", 232523}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO2(GUIO_NOSPEECH, GUIO_EGAUNDITHER) }, + Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Conquests of Camelot - English DOS (from jvprat) // Executable scanning reports "0.000.685", Floppy label reports "1.001, 0.000.685", VERSION file reports "1.001.000" @@ -295,7 +302,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.003", 0, "8e1a3a8c588007404b532b8dfacc1460", 723712}, {"resource.004", 0, "8e1a3a8c588007404b532b8dfacc1460", 729143}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO2(GUIO_NOSPEECH, GUIO_EGAUNDITHER) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Conquests of Camelot - English DOS // SCI interpreter version 0.000.685 @@ -309,7 +316,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.006", 0, "8e1a3a8c588007404b532b8dfacc1460", 332446}, {"resource.007", 0, "8e1a3a8c588007404b532b8dfacc1460", 358182}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO2(GUIO_NOSPEECH, GUIO_EGAUNDITHER) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Conquests of the Longbow - English Amiga (from www.back2roots.org) // Executable scanning reports "1.005.001" @@ -324,7 +331,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.005", 0, "1c3804e56b114028c5873a35c2f06d13", 653002}, {"resource.006", 0, "f9487732289a4f4966b4e34eea413325", 842817}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO1(GUIO_NOSPEECH) }, + Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Conquests of the Longbow - English DOS // SCI interpreter version 1.000.510 @@ -338,7 +345,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.005", 0, "d036df0872f2db19bca34601276be2d7", 1154950}, {"resource.006", 0, "b367a6a59f29ee30dde1d88a5a41152d", 1042966}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO1(GUIO_NOSPEECH) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Conquests of the Longbow - English DOS Floppy (from jvprat) // Executable scanning reports "1.000.168", Floppy label reports "1.1, 1.13.92", VERSION file reports "1.1" @@ -352,7 +359,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.004", 0, "9cfce07e204a329e94fda8b5657621da", 1261462}, {"resource.005", 0, "21ebe6b39b57a73fc449f67f013765aa", 1284720}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO1(GUIO_NOSPEECH) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Conquests of the Longbow - English DOS // SCI interpreter version 1.000.510 @@ -365,7 +372,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.004", 0, "9cfce07e204a329e94fda8b5657621da", 1260237}, {"resource.005", 0, "21ebe6b39b57a73fc449f67f013765aa", 1284609}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO1(GUIO_NOSPEECH) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Conquests of the Longbow EGA - English DOS // SCI interpreter version 1.000.510 @@ -378,7 +385,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.004", 0, "b7bb35c027bb424ecefcd122768e5e60", 705631}, {"resource.005", 0, "58942b1aa6d6ffeb66e9f8897fd4435f", 469243}, {"resource.006", 0, "8c767b3939add63d11274065e46aad04", 713158}, - AD_LISTEND}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO2(GUIO_NOSPEECH, GUIO_EGAUNDITHER) }, + AD_LISTEND}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Conquests of the Longbow DOS 1.0 EGA (4 x 5.25" disks) // Provided by ssburnout in bug report #3046802 @@ -388,7 +395,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.001", 0, "76c729e563809170e6cc8b2f3f6cf0a4", 1196133}, {"resource.002", 0, "8c767b3939add63d11274065e46aad04", 1152478}, {"resource.003", 0, "7025b87e735b1df3f0e9488a621f4333", 1171439}, - AD_LISTEND}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO2(GUIO_NOSPEECH, GUIO_EGAUNDITHER) }, + AD_LISTEND}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Conquests of the Longbow - English DOS Non-Interactive Demo // SCI interpreter version 1.000.510 @@ -396,7 +403,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "cbc5cb73341de1bff1b1e20a640af220", 588}, {"resource.001", 0, "f05a20cc07eee85da8e999d0ac0f596b", 869916}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO1(GUIO_NOSPEECH) }, + Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Conquests of the Longbow - German DOS (suplied by markcoolio in bug report #2727681, also includes english language) // SCI interpreter version 1.000.510 @@ -410,7 +417,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.005", 0, "d036df0872f2db19bca34601276be2d7", 1176914}, {"resource.006", 0, "b367a6a59f29ee30dde1d88a5a41152d", 1123585}, AD_LISTEND}, - Common::DE_DEU, Common::kPlatformPC, ADGF_ADDENGLISH, GUIO1(GUIO_NOSPEECH) }, + Common::DE_DEU, Common::kPlatformPC, ADGF_ADDENGLISH, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Eco Quest - English DOS Non-Interactive Demo (from FRG) // Executable scanning reports "x.yyy.zzz" @@ -419,7 +426,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "c819e171359b7c95f4c13b846d5c034e", 873}, {"resource.001", 0, "baf9393a9bfa73098adb501e5bc5487b", 657518}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO1(GUIO_NOSPEECH) }, + Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Eco Quest - English DOS CD 1.1 // SCI interpreter version 1.001.064 @@ -427,7 +434,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "a4b73d5d2b55bdb6e44345e99c8fbdd0", 4804}, {"resource.000", 0, "d908dbef56816ac6c60dd145fdeafb2b", 3536046}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, ADGF_CD, GUIO0() }, + Common::EN_ANY, Common::kPlatformPC, ADGF_CD, GUIO3(GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Eco Quest - English DOS CD 1.1 // SCI interpreter version 1.001.064 @@ -448,7 +455,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.002", 0, "28fe9b4f0567e71feb198bc9f3a2c605", 1241816}, {"resource.003", 0, "f3146df0ad4297f5ce35aa8c4753bf6c", 586832}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO1(GUIO_NOSPEECH) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Eco Quest - English DOS Floppy // SCI interpreter version 1.000.510 @@ -459,7 +466,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.002", 0, "323b3b12f43d53f27d259beb225f0aa7", 1129316}, {"resource.003", 0, "83ac03e4bddb2c1ac2d36d2a587d0536", 1145616}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO1(GUIO_NOSPEECH) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Eco Quest - German DOS Floppy (supplied by markcoolio in bug report #2723744, also includes english language) // SCI interpreter version 1.000.510 @@ -470,7 +477,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.002", 0, "02d7d0411f7903aacb3bc8b0f8ca8a9a", 1202581}, {"resource.003", 0, "84dd11b6825255671c703aee5ceff620", 1175835}, AD_LISTEND}, - Common::DE_DEU, Common::kPlatformPC, ADGF_ADDENGLISH, GUIO1(GUIO_NOSPEECH) }, + Common::DE_DEU, Common::kPlatformPC, ADGF_ADDENGLISH, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Eco Quest - Spanish DOS Floppy (from jvprat, also includes english language) // Executable scanning reports "1.ECO.013", VERSION file reports "1.000, 11.12.92" @@ -482,7 +489,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.002", 0, "2d21a1d2dcbffa551552e3e0725d2284", 1186033}, {"resource.003", 0, "84dd11b6825255671c703aee5ceff620", 1174993}, AD_LISTEND}, - Common::ES_ESP, Common::kPlatformPC, ADGF_ADDENGLISH, GUIO1(GUIO_NOSPEECH) }, + Common::ES_ESP, Common::kPlatformPC, ADGF_ADDENGLISH, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Eco Quest - French DOS Floppy (from Strangerke, also includes english language) // SCI interpreter version 1.ECO.013 @@ -493,7 +500,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.002", 0, "b836c6ee9de67d814ac5d1b05f5b9858", 1173872}, {"resource.003", 0, "f8f767f9d6351432621c6e54c1b2ba8c", 1141520}, AD_LISTEND}, - Common::FR_FRA, Common::kPlatformPC, ADGF_ADDENGLISH, GUIO1(GUIO_NOSPEECH) }, + Common::FR_FRA, Common::kPlatformPC, ADGF_ADDENGLISH, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Eco Quest 2 - English DOS Non-Interactive Demo // SCI interpreter version 1.001.055 @@ -501,7 +508,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "607cfa0d8a03b7d348c06ee727e3d939", 1321}, {"resource.000", 0, "dd6f614c43c029f063e93cd243af90a4", 525992}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO1(GUIO_NOSPEECH) }, + Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Eco Quest 2 - English DOS Floppy (supplied by markcoolio in bug report #2723761) // SCI interpreter version 1.001.065 @@ -509,7 +516,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "28fb7b6abb9fc1cb8882d7c2e701b63f", 5658}, {"resource.000", 0, "cc1d17e5637528dbe4a812699e1cbfc6", 4208192}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO1(GUIO_NOSPEECH) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Eco Quest 2 - French DOS Floppy (from Strangerke) // SCI interpreter version 1.001.081 @@ -517,7 +524,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "c22ab8b33c339c138b6b1697b77b9e79", 5588}, {"resource.000", 0, "1c4093f7248240329121fdf8c0d59152", 4231946}, AD_LISTEND}, - Common::FR_FRA, Common::kPlatformPC, 0, GUIO1(GUIO_NOSPEECH) }, + Common::FR_FRA, Common::kPlatformPC, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Eco Quest 2 - Spanish DOS Floppy (supplied by umbrio in bug report #3313962) {"ecoquest2", "Floppy", { @@ -525,7 +532,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.000", 0, "1c4093f7248240329121fdf8c0d59152", 4209150}, {"resource.msg", 0, "eff8be1925d42288de55e405983e9314", 117810}, AD_LISTEND}, - Common::ES_ESP, Common::kPlatformPC, 0, GUIO1(GUIO_NOSPEECH) }, + Common::ES_ESP, Common::kPlatformPC, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Freddy Pharkas - English DOS demo (from FRG) // SCI interpreter version 1.001.069 @@ -533,7 +540,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "97aa9fcfe84c9993a64debd28c32393a", 1909}, {"resource.000", 0, "5ea8e7a3ea10cce6efd5c106dc62fd8c", 867724}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO1(GUIO_NOSPEECH) }, + Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Freddy Pharkas - English CD DOS (from FRG) // SCI interpreter version 1.001.132 @@ -541,7 +548,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "d46b282f228a67ba13bd4b4009e95f8f", 6058}, {"resource.000", 0, "ee3c64ffff0ba9fb08bea2624631c598", 5490246}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, ADGF_CD, GUIO0() }, + Common::EN_ANY, Common::kPlatformPC, ADGF_CD, GUIO3(GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Freddy Pharkas - English DOS Floppy (updated information from markcoolio in bug reports #2723773 and #2724720) // Executable scanning reports "1.cfs.081" @@ -551,7 +558,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.000", 0, "96b07e9b914dba1c8dc6c78a176326df", 5233230}, {"resource.msg", 0, "554f65315d851184f6e38211489fdd8f", -1}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO1(GUIO_NOSPEECH) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Freddy Pharkas - Windows (supplied by abevi in bug report #2612718) // Executable scanning reports "1.cfs.081" @@ -560,7 +567,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "a32674e7fbf7b213b4a066c8037f16b6", 5816}, {"resource.000", 0, "fed4808fdb72486908ac7ad0044b14d8", 5233230}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformWindows, 0, GUIO1(GUIO_NOSPEECH) }, + Common::EN_ANY, Common::kPlatformWindows, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Freddy Pharkas - German DOS Floppy (from Tobis87, updated information from markcoolio in bug reports #2723772 and #2724720) // Executable scanning reports "1.cfs.081" @@ -570,7 +577,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.000", 0, "96b07e9b914dba1c8dc6c78a176326df", 5233230}, {"resource.msg", 0, "304b5a5781800affd2235152a5794fa8", -1}, AD_LISTEND}, - Common::DE_DEU, Common::kPlatformPC, 0, GUIO1(GUIO_NOSPEECH) }, + Common::DE_DEU, Common::kPlatformPC, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Freddy Pharkas - Spanish DOS (from jvprat) // Executable scanning reports "1.cfs.081", VERSION file reports "1.000, March 30, 1995" @@ -583,7 +590,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.003", 0, "05acdc256c742e79c50b9fe7ec2cc898", 863310}, {"resource.msg", 0, "45b5bf74933ac3727e4cc844446dc052", 796156}, AD_LISTEND}, - Common::ES_ESP, Common::kPlatformPC, ADGF_CD, GUIO0() }, + Common::ES_ESP, Common::kPlatformPC, ADGF_CD, GUIO3(GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Freddy Pharkas - Spanish DOS (from jvprat) // Executable scanning reports "1.cfs.081", VERSION file reports "1.000, March 30, 1995" @@ -593,7 +600,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.000", 0, "96b07e9b914dba1c8dc6c78a176326df", 5233230}, {"resource.msg", 0, "45b5bf74933ac3727e4cc844446dc052", 796156}, AD_LISTEND}, - Common::ES_ESP, Common::kPlatformPC, 0, GUIO1(GUIO_NOSPEECH) }, + Common::ES_ESP, Common::kPlatformPC, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Freddy Pharkas - English DOS CD Demo // SCI interpreter version 1.001.095 @@ -601,14 +608,14 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "a62a7eae85dd1e6b07f39662b278437e", 1918}, {"resource.000", 0, "4962a3c4dd44e36e78ea4a7a374c2220", 957382}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO0() }, + Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO3(GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Freddy Pharkas - English Macintosh {"freddypharkas", "", { {"Data1", 0, "ef7cbd62727989818f1cfae69c9fd61d", 3038492}, {"Data2", 0, "2424b418f7d52c385cea4701f529c69a", 4721732}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformMacintosh, ADGF_MACRESFORK, GUIO1(GUIO_NOSPEECH) }, + Common::EN_ANY, Common::kPlatformMacintosh, ADGF_MACRESFORK, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Fun Seeker's Guide - English DOS // SCI interpreter version 0.000.506 @@ -616,7 +623,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "7ee6859ef74314f6d91938c3595348a9", 282}, {"resource.001", 0, "f1e680095424e31f7fae1255d36bacba", 40692}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO2(GUIO_NOSPEECH, GUIO_EGAUNDITHER) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Gabriel Knight - English DOS CD Demo // SCI interpreter version 1.001.092 @@ -624,7 +631,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "39645952ae0ed8072c7e838f31b75464", 2490}, {"resource.000", 0, "eb3ed7477ca4110813fe1fcf35928561", 1718450}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO0() }, + Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO3(GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, #ifdef ENABLE_SCI32 // Gabriel Knight - English DOS Floppy @@ -633,7 +640,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "372d059f75856afa6d73dd84cbb8913d", 10783}, {"resource.000", 0, "69b7516962510f780d38519cc15fcc7c", 13022630}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, ADGF_UNSTABLE, GUIO1(GUIO_NOSPEECH) }, + Common::EN_ANY, Common::kPlatformPC, ADGF_UNSTABLE, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Gabriel Knight - English DOS Floppy (supplied my markcoolio in bug report #2723777) // SCI interpreter version 2.000.000 @@ -641,7 +648,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "65e8c14092e4c9b3b3538b7602c8c5ec", 10783}, {"resource.000", 0, "69b7516962510f780d38519cc15fcc7c", 13022630}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, ADGF_UNSTABLE, GUIO1(GUIO_NOSPEECH) }, + Common::EN_ANY, Common::kPlatformPC, ADGF_UNSTABLE, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Gabriel Knight - English DOS Floppy // SCI interpreter version 2.000.000, VERSION file reports "1.0\nGabriel Knight\n11/22/10:33 pm\n\x1A" @@ -649,7 +656,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "ef41df08cf2c1f680216cdbeed0f8311", 10783}, {"resource.000", 0, "69b7516962510f780d38519cc15fcc7c", 13022630}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, ADGF_UNSTABLE, GUIO1(GUIO_NOSPEECH) }, + Common::EN_ANY, Common::kPlatformPC, ADGF_UNSTABLE, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Gabriel Knight - German DOS Floppy (supplied my markcoolio in bug report #2723775) // SCI interpreter version 2.000.000 @@ -657,7 +664,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "ad6508b0296b25c07b1f58828dc33696", 10789}, {"resource.000", 0, "091cf08910780feabc56f8551b09cb36", 13077029}, AD_LISTEND}, - Common::DE_DEU, Common::kPlatformPC, ADGF_UNSTABLE, GUIO1(GUIO_NOSPEECH) }, + Common::DE_DEU, Common::kPlatformPC, ADGF_UNSTABLE, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Gabriel Knight - English DOS CD (from jvprat) // Executable scanning reports "2.000.000", VERSION file reports "01.100.000" @@ -665,7 +672,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "372d059f75856afa6d73dd84cbb8913d", 10996}, {"resource.000", 0, "69b7516962510f780d38519cc15fcc7c", 12581736}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, ADGF_CD | ADGF_UNSTABLE, GUIO0() }, + Common::EN_ANY, Common::kPlatformPC, ADGF_CD | ADGF_UNSTABLE, GUIO3(GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Gabriel Knight - English Windows CD (from jvprat) // Executable scanning reports "2.000.000", VERSION file reports "01.100.000" @@ -673,7 +680,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "372d059f75856afa6d73dd84cbb8913d", 10996}, {"resource.000", 0, "69b7516962510f780d38519cc15fcc7c", 12581736}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformWindows, ADGF_CD | ADGF_UNSTABLE, GUIO1(GUIO_NOASPECT) }, + Common::EN_ANY, Common::kPlatformWindows, ADGF_CD | ADGF_UNSTABLE, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Gabriel Knight - German DOS CD (from Tobis87) // SCI interpreter version 2.000.000 @@ -681,7 +688,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "a7d3e55114c65647310373cb390815ba", 11392}, {"resource.000", 0, "091cf08910780feabc56f8551b09cb36", 13400497}, AD_LISTEND}, - Common::DE_DEU, Common::kPlatformPC, ADGF_CD | ADGF_UNSTABLE, GUIO0() }, + Common::DE_DEU, Common::kPlatformPC, ADGF_CD | ADGF_UNSTABLE, GUIO3(GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Gabriel Knight - Spanish DOS CD (from jvprat) // Executable scanning reports "2.000.000", VERSION file reports "1.000.000, April 13, 1995" @@ -689,7 +696,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "7cb6e9bba15b544ec7a635c45bde9953", 11404}, {"resource.000", 0, "091cf08910780feabc56f8551b09cb36", 13381599}, AD_LISTEND}, - Common::ES_ESP, Common::kPlatformPC, ADGF_CD | ADGF_UNSTABLE, GUIO0() }, + Common::ES_ESP, Common::kPlatformPC, ADGF_CD | ADGF_UNSTABLE, GUIO3(GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Gabriel Knight - French DOS CD (from Hkz) // VERSION file reports "1.000.000, May 3, 1994" @@ -697,7 +704,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "55f909ba93a2515042a08d8a2da8414e", 11392}, {"resource.000", 0, "091cf08910780feabc56f8551b09cb36", 13325145}, AD_LISTEND}, - Common::FR_FRA, Common::kPlatformPC, ADGF_CD | ADGF_UNSTABLE, GUIO0() }, + Common::FR_FRA, Common::kPlatformPC, ADGF_CD | ADGF_UNSTABLE, GUIO3(GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Gabriel Knight - German Windows CD (from Tobis87) // SCI interpreter version 2.000.000 @@ -705,7 +712,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "a7d3e55114c65647310373cb390815ba", 11392}, {"resource.000", 0, "091cf08910780feabc56f8551b09cb36", 13400497}, AD_LISTEND}, - Common::DE_DEU, Common::kPlatformWindows, ADGF_CD | ADGF_UNSTABLE, GUIO1(GUIO_NOASPECT) }, + Common::DE_DEU, Common::kPlatformWindows, ADGF_CD | ADGF_UNSTABLE, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Gabriel Knight - Spanish Windows CD (from jvprat) // Executable scanning reports "2.000.000", VERSION file reports "1.000.000, April 13, 1995" @@ -713,7 +720,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "7cb6e9bba15b544ec7a635c45bde9953", 11404}, {"resource.000", 0, "091cf08910780feabc56f8551b09cb36", 13381599}, AD_LISTEND}, - Common::ES_ESP, Common::kPlatformWindows, ADGF_CD | ADGF_UNSTABLE, GUIO1(GUIO_NOASPECT) }, + Common::ES_ESP, Common::kPlatformWindows, ADGF_CD | ADGF_UNSTABLE, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Gabriel Knight - English Macintosh {"gk1", "", { @@ -722,7 +729,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"Data3", 0, "f25068b408b09275d8b698866462f578", 3677599}, {"Data4", 0, "1cceebbe411b26c860a74f91c337fdf3", 3230086}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformMacintosh, ADGF_MACRESFORK | ADGF_UNSTABLE, GUIO1(GUIO_NOASPECT) }, + Common::EN_ANY, Common::kPlatformMacintosh, ADGF_MACRESFORK | ADGF_UNSTABLE, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Gabriel Knight 2 - English Windows Non-Interactive Demo // Executable scanning reports "2.100.002" @@ -730,7 +737,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "e0effce11c4908f4b91838741716c83d", 1351}, {"resource.000", 0, "d04cfc7f04b6f74d13025378be49ec2b", 4640330}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformWindows, ADGF_DEMO | ADGF_UNSTABLE, GUIO2(GUIO_NOSPEECH, GUIO_NOASPECT) }, + Common::EN_ANY, Common::kPlatformWindows, ADGF_DEMO | ADGF_UNSTABLE, GUIO5(GUIO_NOSPEECH, GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Gabriel Knight 2 - English DOS (GOG version) - ressci.* merged in ressci.000 // using Enrico Rolfi's HD/DVD installer: http://gkpatches.vogons.zetafleet.com/ @@ -738,7 +745,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resmap.000", 0, "b996fa1e57389a1e179a00a0049de1f4", 8110}, {"ressci.000", 0, "a19fc3604c6e5407abcf03d59ee87217", 168522221}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, ADGF_UNSTABLE, GUIO1(GUIO_NOASPECT) }, + Common::EN_ANY, Common::kPlatformPC, ADGF_UNSTABLE, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Gabriel Knight 2 - English DOS (from jvprat) // Executable scanning reports "2.100.002", VERSION file reports "1.1" @@ -756,7 +763,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resmap.006", 0, "ce9359037277b7d7976da185c2fa0aad", 2977}, {"ressci.006", 0, "8e44e03890205a7be12f45aaba9644b4", 60659424}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, ADGF_UNSTABLE, GUIO1(GUIO_NOASPECT) }, + Common::EN_ANY, Common::kPlatformPC, ADGF_UNSTABLE, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Gabriel Knight 2 - French DOS (6-CDs Sierra Originals reedition) // Executable scanning reports "2.100.002", VERSION file reports "1.0" @@ -774,7 +781,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resmap.006", 0, "11b2e722170b8c93fdaa5428e2c7676f", 3001}, {"ressci.006", 0, "4037d941aec39d2e654e20960429aefc", 60568486}, AD_LISTEND}, - Common::FR_FRA, Common::kPlatformPC, ADGF_UNSTABLE, GUIO1(GUIO_NOASPECT) }, + Common::FR_FRA, Common::kPlatformPC, ADGF_UNSTABLE, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Gabriel Knight 2 - English Macintosh // NOTE: This only contains disc 1 files (as well as the persistent file: @@ -786,7 +793,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"Data4", 0, "8b843c62eb53136a855d6e0087e3cb0d", 5889553}, {"Data5", 0, "f9fcf9ab2eb13b2125c33a1cda03a093", 14349984}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformMacintosh, ADGF_MACRESFORK | ADGF_UNSTABLE, GUIO1(GUIO_NOASPECT) }, + Common::EN_ANY, Common::kPlatformMacintosh, ADGF_MACRESFORK | ADGF_UNSTABLE, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, #endif // ENABLE_SCI32 @@ -798,7 +805,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.002", 0, "e0dd44069a62a463fd124974b915f10d", 342149}, {"resource.003", 0, "e0dd44069a62a463fd124974b915f10d", 328925}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO1(GUIO_NOSPEECH) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Hoyle 1 - English DOS (supplied by wibble92 in bug report #2644547) // SCI interpreter version 0.000.530 @@ -808,7 +815,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.002", 0, "e0dd44069a62a463fd124974b915f10d", 342309}, {"resource.003", 0, "e0dd44069a62a463fd124974b915f10d", 328912}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO2(GUIO_NOSPEECH, GUIO_EGAUNDITHER) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Hoyle 1 - English DOS (supplied by merkur in bug report #2719227) // SCI interpreter version 0.000.530 @@ -816,14 +823,14 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "1034a218943d12f1f36e753fa10c95b8", 4386}, {"resource.001", 0, "e0dd44069a62a463fd124974b915f10d", 518308}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO2(GUIO_NOSPEECH, GUIO_EGAUNDITHER) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Hoyle 1 3.5' - English DOS (supplied by eddydrama in bug report #3052366 and dinnerx in bug report #3090841) {"hoyle1", "", { {"resource.map", 0, "0af9a3dcd72a091960de070432e1f524", 4386}, {"resource.001", 0, "e0dd44069a62a463fd124974b915f10d", 518127}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO2(GUIO_NOSPEECH, GUIO_EGAUNDITHER) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, #if 0 // TODO: unknown if these files are corrupt // Hoyle 1 - English Amiga (from www.back2roots.org) @@ -833,7 +840,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.001", 0, "e0dd44069a62a463fd124974b915f10d", 218755}, {"resource.002", 0, "e0dd44069a62a463fd124974b915f10d", 439502}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO1(GUIO_NOSPEECH) }, + Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, #endif // Hoyle 2 - English DOS @@ -843,7 +850,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.001", 0, "8f2dd70abe01112eca464cda818b5eb6", 98138}, {"resource.002", 0, "8f2dd70abe01112eca464cda818b5eb6", 196631}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO2(GUIO_NOSPEECH, GUIO_EGAUNDITHER) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Hoyle 2 - English DOS (supplied by ssburnout in bug report #3049193) // 1.000.011 1x3.5" (label:Int#6.21.90) @@ -851,7 +858,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "db0ba08b953e9904a4960ad99cd29c20", 1356}, {"resource.001", 0, "8f2dd70abe01112eca464cda818b5eb6", 216315}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO2(GUIO_NOSPEECH, GUIO_EGAUNDITHER) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Hoyle 2 - English Amiga (from www.back2roots.org) // Executable scanning reports "1.002.032" @@ -860,7 +867,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "62ed48d20c580e5a98f102f7cd93706a", 1356}, {"resource.001", 0, "8f2dd70abe01112eca464cda818b5eb6", 222704}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO1(GUIO_NOSPEECH) }, + Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Hoyle 2 - English Macintosh // Executable scanning reports "x.yyy.zzz" @@ -868,7 +875,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "1af1d3aa3cf564f93477c9f87e53f495", 1728}, {"resource.001", 0, "b73b8131669d69d41a326415e4519138", 482882}, {NULL, 0, NULL, 0}}, - Common::EN_ANY, Common::kPlatformMacintosh, 0, GUIO1(GUIO_NOSPEECH) }, + Common::EN_ANY, Common::kPlatformMacintosh, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, #if 0 // TODO: unknown if these files are corrupt // Hoyle 3 - English Amiga (from www.back2roots.org) @@ -879,7 +886,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.000", 0, "595b6039ea1356e7f96a52c58eedcf22", 355791}, {"resource.001", 0, "143df8aef214a2db34c2d48190742012", 632273}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO1(GUIO_NOSPEECH) }, + Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, #endif // Hoyle 3 - English DOS Non-Interactive Demo @@ -889,7 +896,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "0d06cacc87dc21a08cd017e73036f905", 735}, {"resource.001", 0, "24db2bccda0a3c43ac4a7b5edb116c7e", 797678}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO1(GUIO_NOSPEECH) }, + Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Hoyle 3 - English DOS Floppy (from jvprat) // Executable scanning reports "x.yyy.zzz", Floppy label reports "1.0, 11.2.91", VERSION file reports "1.000" @@ -899,7 +906,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.000", 0, "6ef28cac094dcd97fdb461662ead6f92", 541845}, {"resource.001", 0, "0a98a268ee99b92c233a0d7187c1f0fa", 845795}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO1(GUIO_NOSPEECH) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Hoyle 3 - English DOS Floppy (supplied by eddydrama in bug report #3038837) {"hoyle3", "", { @@ -910,7 +917,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.003", 0, "97cfd72633f8f9b2a0b1d4116cf3ee81", 346116}, {"resource.004", 0, "2884fb91b225fabd9ca87ea231293b48", 351218}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO1(GUIO_NOSPEECH) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Hoyle 3 EGA - English DOS Floppy 1.0 (supplied by abevi in bug report #2612718) {"hoyle3", "EGA", { @@ -918,14 +925,14 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.000", 0, "6ef28cac094dcd97fdb461662ead6f92", 319905}, {"resource.001", 0, "0a98a268ee99b92c233a0d7187c1f0fa", 526438}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO2(GUIO_NOSPEECH, GUIO_EGAUNDITHER) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Hoyle 4 (Hoyle Classic Card Games) - English DOS Demo {"hoyle4", "Demo", { {"resource.map", 0, "60f764020a6b788bbbe415dbc2ccb9f3", 931}, {"resource.000", 0, "5fe3670e3ddcd4f85c10013b5453141a", 615522}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO1(GUIO_NOSPEECH) }, + Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Hoyle 4 (Hoyle Classic Card Games) - English DOS Demo // SCI interpreter version 1.001.200 (just a guess) @@ -934,7 +941,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "662087cb383e52e3cc4ae7ecb10e20aa", 938}, {"resource.000", 0, "24c10844792c54d476d272213cbac300", 675252}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO1(GUIO_NOSPEECH) }, + Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Hoyle 4 (Hoyle Classic Card Games) - English DOS/Win // Supplied by abevi in bug report #3039291 @@ -942,7 +949,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "2b577c975cc8d8d43f61b6a756129fe3", 4352}, {"resource.000", 0, "43e2c15ce436aab611a462ad0603e12d", 2000132}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO1(GUIO_NOSPEECH) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Hoyle 4 (Hoyle Classic Card Games) - English Macintosh Floppy // VERSION file reports "2.0" @@ -950,7 +957,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"Data1", 0, "99575fae4579540a314bbedd72d51e8c", 7682887}, {"Data2", 0, "7d4bf5bdf3c02edbf35cb8471c84ec13", 1539134}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformMacintosh, ADGF_MACRESFORK, GUIO1(GUIO_NOSPEECH) }, + Common::EN_ANY, Common::kPlatformMacintosh, ADGF_MACRESFORK, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Jones in the Fast Lane EGA - English DOS // SCI interpreter version 1.000.172 (not 100% sure FIXME) @@ -959,14 +966,14 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.001", 0, "bac3ec6cb3e3920984ab0f32becf5163", 202105}, {"resource.002", 0, "b86daa3ba2784d1502da881eedb80d9b", 341771}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO2(GUIO_NOSPEECH, GUIO_EGAUNDITHER) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Jones in the Fast Lane EGA - English DOS (supplied by EddyDrama in bug report #3038761) {"jones", "EGA", { {"resource.map", 0, "8e92cf319180cc8b5b87b2ce93a4fe22", 1602}, {"resource.001", 0, "bac3ec6cb3e3920984ab0f32becf5163", 511528}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO2(GUIO_NOSPEECH, GUIO_EGAUNDITHER) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Jones in the Fast Lane VGA - English DOS // SCI interpreter version 1.000.172 @@ -975,7 +982,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.001", 0, "bac3ec6cb3e3920984ab0f32becf5163", 313476}, {"resource.002", 0, "b86daa3ba2784d1502da881eedb80d9b", 719747}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO1(GUIO_NOSPEECH) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Jones in the Fast Lane VGA - English DOS (supplied by omer_mor in bug report #3037054) // VERSION file reports "1.000.060" @@ -983,14 +990,14 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "db175ab494ab0666f19ab8f2597a8e49", 1602}, {"resource.001", 0, "bac3ec6cb3e3920984ab0f32becf5163", 994487}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO1(GUIO_NOSPEECH) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Jones in the Fast Lane - English DOS CD {"jones", "CD", { {"resource.map", 0, "459f5b04467bc2107aec02f5c4b71b37", 4878}, {"resource.001", 0, "3876da2ce16fb7dea2f5d943d946fa84", 1652150}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, ADGF_CD, GUIO0() }, + Common::EN_ANY, Common::kPlatformPC, ADGF_CD, GUIO1(GAMEOPTION_JONES_CDAUDIO) }, // Jones in the Fast Lane - English DOS CD // Same entry as the DOS version above. This one is used for the alternate @@ -999,7 +1006,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "459f5b04467bc2107aec02f5c4b71b37", 4878}, {"resource.001", 0, "3876da2ce16fb7dea2f5d943d946fa84", 1652150}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformWindows, ADGF_CD, GUIO1(GUIO_MIDIGM) }, + Common::EN_ANY, Common::kPlatformWindows, ADGF_CD, GUIO2(GUIO_MIDIGM, GAMEOPTION_JONES_CDAUDIO) }, // King's Quest 1 SCI Remake - English Amiga (from www.back2roots.org) // Executable scanning reports "1.003.007" @@ -1011,7 +1018,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.003", 0, "9ae2a13708d691cd42f9129173c4b39d", 763224}, {"resource.004", 0, "9ae2a13708d691cd42f9129173c4b39d", 820443}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO1(GUIO_NOSPEECH) }, + Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // King's Quest 1 SCI Remake - English DOS Non-Interactive Demo // Executable scanning reports "S.old.010" @@ -1019,7 +1026,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "59b13619078bd47011421468959ee5d4", 954}, {"resource.001", 0, "4cfb9040db152868f7cb6a1e8151c910", 296555}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO2(GUIO_NOSPEECH, GUIO_EGAUNDITHER) }, + Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // King's Quest 1 SCI Remake - English DOS (from the King's Quest Collection) // Executable scanning reports "S.old.010", VERSION file reports "1.000.051" @@ -1030,7 +1037,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.002", 0, "fed9e0072ffd511d248674e60dee2099", 714062}, {"resource.003", 0, "fed9e0072ffd511d248674e60dee2099", 717478}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO2(GUIO_NOSPEECH, GUIO_EGAUNDITHER) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // King's Quest 1 SCI Remake - English DOS (supplied by ssburnout in bug report #3049193) // 1.000.051 9x5.25" (label: INT#9.19.90) @@ -1044,7 +1051,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.006", 0, "fed9e0072ffd511d248674e60dee2099", 351062}, {"resource.007", 0, "fed9e0072ffd511d248674e60dee2099", 330472}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO1(GUIO_NOSPEECH) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // King's Quest 4 - English Amiga (from www.back2roots.org) // Executable scanning reports "1.002.032" @@ -1057,7 +1064,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.003", 0, "fd16c9c223f7dc5b65f06447615224ff", 683016}, {"resource.004", 0, "3fac034c7d130e055d05bc43a1f8d5f8", 549993}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO2(GUIO_NOSPEECH, GUIO_EGAUNDITHER) }, + Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // King's Quest 4 - English DOS Non-Interactive Demo // Executable scanning reports "0.000.494" @@ -1065,7 +1072,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "992ac7cc31d3717fe53818a9bb6d1dae", 594}, {"resource.001", 0, "143e1c14f15ad0fbfc714f648a65f661", 205330}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO2(GUIO_NOSPEECH, GUIO_EGAUNDITHER) }, + Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // King's Quest 4 - English DOS (original boxed release, 3 1/2" disks) // SCI interpreter version 0.000.247 @@ -1076,7 +1083,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.003", 0, "851a62d00972dc4002f472cc0d84e71d", 683145}, {"resource.004", 0, "851a62d00972dc4002f472cc0d84e71d", 649441}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO2(GUIO_NOSPEECH, GUIO_EGAUNDITHER) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // King's Quest 4 - English DOS (from the King's Quest Collection) // Executable scanning reports "0.000.502" @@ -1088,7 +1095,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.003", 0, "77615c595388acf3d1df8e107bfb6b52", 707591}, {"resource.004", 0, "77615c595388acf3d1df8e107bfb6b52", 479562}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO2(GUIO_NOSPEECH, GUIO_EGAUNDITHER) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // King's Quest 4 - English DOS (supplied by ssburnout in bug report #3049193) // 1.006.003 8x5.25" (label: Int.#0.000.502) @@ -1102,7 +1109,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.006", 0, "6db7de6f93c6ea62dca78abee677f8c0", 324789}, {"resource.007", 0, "6db7de6f93c6ea62dca78abee677f8c0", 334441}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO2(GUIO_NOSPEECH, GUIO_EGAUNDITHER) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // King's Quest 4 - English DOS // SCI interpreter version 0.000.274 @@ -1116,7 +1123,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.006", 0, "851a62d00972dc4002f472cc0d84e71d", 333777}, {"resource.007", 0, "851a62d00972dc4002f472cc0d84e71d", 341038}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO2(GUIO_NOSPEECH, GUIO_EGAUNDITHER) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // King's Quest 4 - English DOS // SCI interpreter version 0.000.253 @@ -1130,7 +1137,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.006", 0, "0c8566848a76eea19a6d6220914030a7", 337288}, {"resource.007", 0, "0c8566848a76eea19a6d6220914030a7", 343882}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO2(GUIO_NOSPEECH, GUIO_EGAUNDITHER) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // King's Quest 4 - English Atari ST (double-sided diskettes) // Game version 1.003.006 (January 12, 1989) @@ -1143,7 +1150,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.003", 0, "a3cdb4848fb859fdd302976fff56490f", 705074}, {"resource.004", 0, "a3cdb4848fb859fdd302976fff56490f", 478366}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformAtariST, 0, GUIO2(GUIO_NOSPEECH, GUIO_EGAUNDITHER) }, + Common::EN_ANY, Common::kPlatformAtariST, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // King's Quest 5 - English Amiga (from www.back2roots.org) // Executable scanning reports "1.004.018" @@ -1159,7 +1166,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.006", 0, "26c0c25399b6715fec03fc3e12544fe3", 823048}, {"resource.007", 0, "b914b5901e786327213e779725d30dd1", 778772}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO1(GUIO_NOSPEECH) }, + Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // King's Quest 5 - German Amiga (also includes english language) // Executable scanning reports "1.004.024" @@ -1175,7 +1182,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.006", 0, "56546b20db11a4836f900efa6d3a3e74", 672099}, {"resource.007", 0, "56546b20db11a4836f900efa6d3a3e74", 794194}, AD_LISTEND}, - Common::DE_DEU, Common::kPlatformAmiga, ADGF_ADDENGLISH, GUIO1(GUIO_NOSPEECH) }, + Common::DE_DEU, Common::kPlatformAmiga, ADGF_ADDENGLISH, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // King's Quest 5 - Italian Amiga (also includes english language) // Executable scanning reports "1.004.024" @@ -1191,7 +1198,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.006", 0, "11cb750f5f816445ad0f4b9f50a4f59a", 672527}, {"resource.007", 0, "11cb750f5f816445ad0f4b9f50a4f59a", 794259}, AD_LISTEND}, - Common::IT_ITA, Common::kPlatformAmiga, ADGF_ADDENGLISH, GUIO1(GUIO_NOSPEECH) }, + Common::IT_ITA, Common::kPlatformAmiga, ADGF_ADDENGLISH, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // King's Quest 5 - English DOS CD (from the King's Quest Collection) // Executable scanning reports "x.yyy.zzz", VERSION file reports "1.000.052" @@ -1201,7 +1208,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.000", 0, "449471bfd77be52f18a3773c7f7d843d", 571368}, {"resource.001", 0, "b45a581ff8751e052c7e364f58d3617f", 16800210}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, ADGF_CD, GUIO0() }, + Common::EN_ANY, Common::kPlatformPC, ADGF_CD, GUIO3(GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // King's Quest 5 - English DOS CD (from the King's Quest Collection) // Executable scanning reports "x.yyy.zzz", VERSION file reports "1.000.052" @@ -1228,7 +1235,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.006", 0, "672ede1136e9e401658538e51bd5dc22", 1172619}, {"resource.007", 0, "2f48faf27666b58c276dda20f91f4a93", 1240456}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO1(GUIO_NOSPEECH) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // King's Quest 5 - English DOS Floppy (supplied by omer_mor in bug report #3036996) // VERSION file reports "0.000.051" @@ -1243,7 +1250,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.006", 0, "06cb3f689836086ebe08b1efc0126592", 921113}, {"resource.007", 0, "252249753c6e850eacceb8af634986d3", 1133608}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO1(GUIO_NOSPEECH) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // King's Quest 5 EGA (supplied by markcoolio in bug report #2829470) // SCI interpreter version 1.000.060 @@ -1259,7 +1266,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.006", 0, "698c698570cde9015e4d51eb8d2e9db1", 666527}, {"resource.007", 0, "703d8df30e89541af337d7706540d5c4", 541743}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO2(GUIO_NOSPEECH, GUIO_EGAUNDITHER) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // King's Quest 5 EGA 1.2M disk version (from LordHoto) // VERSION file reports "0.000.055" @@ -1271,7 +1278,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "53206afb4fd73871a484e83acab80f31", 7608}, {"resource.004", 0, "83568edf7fde18b3eed988bc5d22ceb1", 1188053}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO2(GUIO_NOSPEECH, GUIO_EGAUNDITHER) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // King's Quest 5 EGA (supplied by omer_mor in bug report #3035421) // VERSION file reports "0.000.062" @@ -1286,7 +1293,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.006", 0, "698c698570cde9015e4d51eb8d2e9db1", 666541}, {"resource.007", 0, "703d8df30e89541af337d7706540d5c4", 541762}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO2(GUIO_NOSPEECH, GUIO_EGAUNDITHER) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // King's Quest V DOS 0.000.062 EGA (5 x 5.25" disks) // Supplied by ssburnout in bug report #3046780 @@ -1298,7 +1305,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.003", 0, "3cca5b2dae8afe94532edfdc98d7edbe", 1092325}, {"resource.004", 0, "8e5c1bc4d738cf7316ff506f59d265e2", 1187803}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO2(GUIO_NOSPEECH, GUIO_EGAUNDITHER) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // King's Quest 5 - German DOS Floppy (supplied by markcoolio in bug report #2727101, also includes english language) // SCI interpreter version 1.000.060 @@ -1313,7 +1320,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.006", 0, "d1a75fdc01840664d00366cff6919366", 1208972}, {"resource.007", 0, "c07494f0cce7c05210893938786a955b", 1337361}, AD_LISTEND}, - Common::DE_DEU, Common::kPlatformPC, ADGF_ADDENGLISH, GUIO1(GUIO_NOSPEECH) }, + Common::DE_DEU, Common::kPlatformPC, ADGF_ADDENGLISH, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // King's Quest 5 - French DOS Floppy (from the King's Quest Collector's Edition 1994, also includes english language) // Supplied by aroenai in bug report #2812611 @@ -1329,7 +1336,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.006", 0, "f7dc85307632ef657ceb1651204f6f51", 1210081}, {"resource.007", 0, "7db4d0a1d8d547c0019cb7d2a6acbdd4", 1338473}, AD_LISTEND}, - Common::FR_FRA, Common::kPlatformPC, ADGF_ADDENGLISH, GUIO1(GUIO_NOSPEECH) }, + Common::FR_FRA, Common::kPlatformPC, ADGF_ADDENGLISH, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // King's Quest 5 - Italian DOS Floppy (from glorifindel, includes english language) // SCI interpreter version 1.000.060 @@ -1344,7 +1351,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.006", 0, "8eeabd92af71e766e323db2100879102", 1209325}, {"resource.007", 0, "dc10c107e0923b902326a040b9c166b9", 1337859}, AD_LISTEND}, - Common::IT_ITA, Common::kPlatformPC, ADGF_ADDENGLISH, GUIO1(GUIO_NOSPEECH) }, + Common::IT_ITA, Common::kPlatformPC, ADGF_ADDENGLISH, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // King's Quest 5 - Polish DOS Floppy (supplied by jacek909 in bug report #2725722, includes english language?!) // SCI interpreter version 1.000.060 @@ -1359,7 +1366,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.006", 0, "da82e4beb744731d0a151f1d4922fafa", 1170456}, {"resource.007", 0, "431def14ca29cdb5e6a5e84d3f38f679", 1240176}, AD_LISTEND}, - Common::PL_POL, Common::kPlatformPC, ADGF_ADDENGLISH, GUIO1(GUIO_NOSPEECH) }, + Common::PL_POL, Common::kPlatformPC, ADGF_ADDENGLISH, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // King's Quest 5 - English Macintosh // VERSION file reports "1.000.055" @@ -1374,7 +1381,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.006", 0, "3d22904a374c192f51e5665b74364133", 1264079}, {"resource.007", 0, "ffe17e23d5833a79f3695addfc149a56", 1361965}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformMacintosh, 0, GUIO1(GUIO_NOSPEECH) }, + Common::EN_ANY, Common::kPlatformMacintosh, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // King's Quest 5 - FM-Towns (supplied by abevi in bug report #3038720) {"kq5", "", { @@ -1400,7 +1407,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.004", 0, "e114ce8f884601c43308fb5cbbea4874", 1174129}, {"resource.005", 0, "349ad9438172265d00680075c5a988d0", 1019669}, AD_LISTEND}, - Common::JA_JPN, Common::kPlatformPC98, ADGF_ADDENGLISH, GUIO2(GUIO_NOSPEECH, GUIO_NOASPECT) }, + Common::JA_JPN, Common::kPlatformPC98, ADGF_ADDENGLISH, GUIO5(GUIO_NOSPEECH, GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // King's Quest 6 - English DOS Non-Interactive Demo // Executable scanning reports "1.001.055", VERSION file reports "1.000.000" @@ -1410,7 +1417,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.000", 0, "535b1b920441ec73f42eaa4ccfd47b89", 264116}, {"resource.msg", 0, "54d1fdc936f98c81f9e4c19e04fb1510", 8260}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO1(GUIO_NOSPEECH) }, + Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // King's Quest 6 - English DOS Floppy // SCI interpreter version 1.001.054 @@ -1419,7 +1426,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.000", 0, "f2b7f753992c56a0c7a08d6a5077c895", 7863324}, {"resource.msg", 0, "3cf5de44de36191f109d425b8450efc8", 258590}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO1(GUIO_NOSPEECH) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // King's Quest 6 - French DOS Floppy (supplied by misterhands in bug #3503425) // SCI interpreter version ??? @@ -1428,7 +1435,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.000", 0, "f2b7f753992c56a0c7a08d6a5077c895", 7863324}, {"resource.msg", 0, "adc2aa8adbdcc97507d44a6f492fbd77", 265194}, AD_LISTEND}, - Common::FR_FRA, Common::kPlatformPC, 0, GUIO1(GUIO_NOSPEECH) }, + Common::FR_FRA, Common::kPlatformPC, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // King's Quest 6 - German DOS Floppy (supplied by markcoolio in bug report #2727156) // SCI interpreter version 1.001.054 @@ -1437,7 +1444,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.000", 0, "f2b7f753992c56a0c7a08d6a5077c895", 7863324}, {"resource.msg", 0, "756297b2155db9e43f621c6f6fb763c3", 282822}, AD_LISTEND}, - Common::DE_DEU, Common::kPlatformPC, 0, GUIO1(GUIO_NOSPEECH) }, + Common::DE_DEU, Common::kPlatformPC, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // King's Quest 6 - English DOS CD (from the King's Quest Collection) // Executable scanning reports "1.cfs.158", VERSION file reports "1.034 9/11/94 - KQ6 version 1.000.00G" @@ -1446,7 +1453,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "7a550ebfeae2575ca00d47703a6a774c", 9215}, {"resource.000", 0, "233394a5f33b475ae5975e7e9a420865", 8376352}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, ADGF_CD, GUIO0() }, + Common::EN_ANY, Common::kPlatformPC, ADGF_CD, GUIO3(GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // King's Quest 6 - English Windows CD (from the King's Quest Collection) // Executable scanning reports "1.cfs.158", VERSION file reports "1.034 9/11/94 - KQ6 version 1.000.00G" @@ -1455,7 +1462,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "7a550ebfeae2575ca00d47703a6a774c", 9215}, {"resource.000", 0, "233394a5f33b475ae5975e7e9a420865", 8376352}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformWindows, ADGF_CD, GUIO1(GUIO_NOASPECT) }, + Common::EN_ANY, Common::kPlatformWindows, ADGF_CD, GUIO5(GUIO_NOASPECT, GAMEOPTION_KQ6_WINDOWS_CURSORS, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // King's Quest 6 - Spanish DOS CD (from jvprat) // Executable scanning reports "1.cfs.158", VERSION file reports "1.000.000, July 5, 1994" @@ -1465,7 +1472,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.000", 0, "4da3ad5868a775549a7cc4f72770a58e", 8537260}, {"resource.msg", 0, "41eed2d3893e1ca6c3695deba4e9d2e8", 267102}, AD_LISTEND}, - Common::ES_ESP, Common::kPlatformPC, ADGF_CD, GUIO0() }, + Common::ES_ESP, Common::kPlatformPC, ADGF_CD, GUIO3(GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // King's Quest 6 - English Macintosh Floppy // VERSION file reports "1.0" @@ -1473,7 +1480,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"Data1", 0, "a183fc0c22fcbd9be4c8800d974b5599", 3892124}, {"Data2", 0, "b3722460dfd3097a1fbaf99a21ad8ea5", 15031272}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformMacintosh, ADGF_MACRESFORK, GUIO1(GUIO_NOSPEECH) }, + Common::EN_ANY, Common::kPlatformMacintosh, ADGF_MACRESFORK, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, #ifdef ENABLE_SCI32 @@ -1484,7 +1491,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.000", 0, "4948e4e1506f1e1c4e1d47abfa06b7f8", 204385195}, {"resource.map", 0, "40ccafb2195301504eba2e4f4f2c7f3d", 18925}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformWindows, ADGF_UNSTABLE, GUIO2(GUIO_NOSPEECH, GUIO_NOASPECT) }, + Common::EN_ANY, Common::kPlatformWindows, ADGF_UNSTABLE, GUIO5(GUIO_NOSPEECH, GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // King's Quest 7 - English Windows (from the King's Quest Collection) // Executable scanning reports "2.100.002", VERSION file reports "1.4" @@ -1492,7 +1499,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "2be9ab94429c721af8e05c507e048a15", 18697}, {"resource.000", 0, "eb63ea3a2c2469dc2d777d351c626404", 203882535}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformWindows, ADGF_UNSTABLE, GUIO2(GUIO_NOSPEECH, GUIO_NOASPECT) }, + Common::EN_ANY, Common::kPlatformWindows, ADGF_UNSTABLE, GUIO5(GUIO_NOSPEECH, GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // King's Quest 7 - English DOS (from FRG) // SCI interpreter version 2.100.002, VERSION file reports "2.00b" @@ -1500,7 +1507,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "8676b0fbbd7362989a029fe72fea14c6", 18709}, {"resource.000", 0, "51c1ead1163e19a2de8f121c39df7a76", 200764100}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, ADGF_UNSTABLE, GUIO2(GUIO_NOSPEECH, GUIO_NOASPECT) }, + Common::EN_ANY, Common::kPlatformPC, ADGF_UNSTABLE, GUIO5(GUIO_NOSPEECH, GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // King's Quest 7 - English Windows (from FRG) // SCI interpreter version 2.100.002, VERSION file reports "2.00b" @@ -1508,7 +1515,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "8676b0fbbd7362989a029fe72fea14c6", 18709}, {"resource.000", 0, "51c1ead1163e19a2de8f121c39df7a76", 200764100}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformWindows, ADGF_UNSTABLE, GUIO2(GUIO_NOSPEECH, GUIO_NOASPECT) }, + Common::EN_ANY, Common::kPlatformWindows, ADGF_UNSTABLE, GUIO5(GUIO_NOSPEECH, GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // King's Quest 7 - German Windows (supplied by markcoolio in bug report #2727402) // SCI interpreter version 2.100.002 @@ -1516,7 +1523,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "838b9ff132bd6962026fee832e8a7ddb", 18697}, {"resource.000", 0, "eb63ea3a2c2469dc2d777d351c626404", 206626576}, AD_LISTEND}, - Common::DE_DEU, Common::kPlatformPC, ADGF_UNSTABLE, GUIO2(GUIO_NOSPEECH, GUIO_NOASPECT) }, + Common::DE_DEU, Common::kPlatformPC, ADGF_UNSTABLE, GUIO5(GUIO_NOSPEECH, GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // King's Quest 7 - Spanish DOS (from jvprat) // Executable scanning reports "2.100.002", VERSION file reports "2.00" @@ -1524,7 +1531,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "0b62693cbe87e3aaca3e8655a437f27f", 18709}, {"resource.000", 0, "51c1ead1163e19a2de8f121c39df7a76", 200764100}, AD_LISTEND}, - Common::ES_ESP, Common::kPlatformPC, ADGF_UNSTABLE, GUIO2(GUIO_NOSPEECH, GUIO_NOASPECT) }, + Common::ES_ESP, Common::kPlatformPC, ADGF_UNSTABLE, GUIO5(GUIO_NOSPEECH, GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // King's Quest 7 - English DOS Non-Interactive Demo // SCI interpreter version 2.100.002 @@ -1532,7 +1539,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "b44f774108d63faa1d021101221c5a54", 1690}, {"resource.000", 0, "d9659d2cf0c269c6a9dc776707f5bea0", 2433827}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO | ADGF_UNSTABLE, GUIO2(GUIO_NOSPEECH, GUIO_NOASPECT) }, + Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO | ADGF_UNSTABLE, GUIO5(GUIO_NOSPEECH, GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, #endif // ENABLE_SCI32 @@ -1548,7 +1555,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.004", 0, "aa553977f7e5804081de293800d3bcce", 695067}, {"resource.005", 0, "bfd870d51dc97729f0914095f58e6957", 676881}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO2(GUIO_NOSPEECH, GUIO_EGAUNDITHER) }, + Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Laura Bow - English Atari ST (from jvprat) // Executable scanning reports "1.002.030", Floppy label reports "1.000.062, 9.23.90" @@ -1560,7 +1567,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.003", 0, "e45c888d9c7c04aec0a20e9f820b79ff", 667365}, {"resource.004", 0, "e45c888d9c7c04aec0a20e9f820b79ff", 683737}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformAtariST, 0, GUIO2(GUIO_NOSPEECH, GUIO_EGAUNDITHER) }, + Common::EN_ANY, Common::kPlatformAtariST, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Laura Bow - English DOS Non-Interactive Demo // Executable scanning reports "x.yyy.zzz" @@ -1568,7 +1575,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "e625726268ff4e123ada11f31f0249f3", 768}, {"resource.001", 0, "0c8912290af0890f8d95faeb4ddb2d68", 333031}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO2(GUIO_NOSPEECH, GUIO_EGAUNDITHER) }, + Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Laura Bow - English DOS 3.5" Floppy (from "The Roberta Williams Anthology"/1996) // SCI interpreter version 0.000.631 @@ -1579,7 +1586,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.003", 0, "e45c888d9c7c04aec0a20e9f820b79ff", 667468}, {"resource.004", 0, "e45c888d9c7c04aec0a20e9f820b79ff", 683807}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO2(GUIO_NOSPEECH, GUIO_EGAUNDITHER) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Laura Bow - English DOS (from FRG) // SCI interpreter version 0.000.631 @@ -1593,7 +1600,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.006", 0, "e45c888d9c7c04aec0a20e9f820b79ff", 328390}, {"resource.007", 0, "e45c888d9c7c04aec0a20e9f820b79ff", 317687}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO2(GUIO_NOSPEECH, GUIO_EGAUNDITHER) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Laura Bow 2 - English DOS Non-Interactive Demo (from FRG) // Executable scanning reports "x.yyy.zzz" @@ -1602,7 +1609,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "24dffc5db1d88c7999f13e8767ed7346", 855}, {"resource.000", 0, "2b2b1b4f7584f9b38fd13f6ab95634d1", 781912}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO1(GUIO_NOSPEECH) }, + Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Laura Bow 2 - English DOS Floppy // Executable scanning reports "2.000.274" @@ -1611,7 +1618,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "610bfd9a852004222f0faaf5fc9e630a", 6489}, {"resource.000", 0, "57084910bc923bff5d6d9bc1b56e9604", 5035964}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO1(GUIO_NOSPEECH) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Laura Bow 2 - English DOS CD (from "The Roberta Williams Antology"/1996) // Executable scanning reports "1.001.072", VERSION file reports "1.1" (from jvprat) @@ -1620,7 +1627,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "a70945e61ba7ac7bfea6b7bd72c6aec5", 7274}, {"resource.000", 0, "82578b8d5a7e09c4c58891ca49fae35b", 5598672}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, ADGF_CD, GUIO0() }, + Common::EN_ANY, Common::kPlatformPC, ADGF_CD, GUIO3(GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Laura Bow 2 v1.1 - French DOS Floppy (from Hkz) {"laurabow2", "", { @@ -1628,7 +1635,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.000", 0, "57084910bc923bff5d6d9bc1b56e9604", 5028766}, {"resource.msg", 0, "0fceedfbdd85a4bc7851fdd9dd2d2f19", 278253}, AD_LISTEND}, - Common::FR_FRA, Common::kPlatformPC, 0, GUIO1(GUIO_NOSPEECH) }, + Common::FR_FRA, Common::kPlatformPC, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Laura Bow 2 v1.1 - German DOS Floppy (from Tobis87, updated info from markcoolio in bug report #2723787, updated info from #2797962)) // Executable scanning reports "2.000.274" @@ -1637,7 +1644,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.000", 0, "57084910bc923bff5d6d9bc1b56e9604", 5028766}, {"resource.msg", 0, "795c928cd00dfec9fbc62ebcd12e1f65", 303185}, AD_LISTEND}, - Common::DE_DEU, Common::kPlatformPC, 0, GUIO1(GUIO_NOSPEECH) }, + Common::DE_DEU, Common::kPlatformPC, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Laura Bow 2 - Spanish DOS CD (from jvprat) // Executable scanning reports "2.000.274", VERSION file reports "1.000.000, May 10, 1994" @@ -1646,7 +1653,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.000", 0, "57084910bc923bff5d6d9bc1b56e9604", 5028766}, {"resource.msg", 0, "71f1f0cd9f082da2e750c793a8ed9d84", 286141}, AD_LISTEND}, - Common::ES_ESP, Common::kPlatformPC, ADGF_CD, GUIO0() }, + Common::ES_ESP, Common::kPlatformPC, ADGF_CD, GUIO3(GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Larry 1 EGA Remake - English DOS (from spookypeanut) // SCI interpreter version 0.000.510 (or 0.000.577?) @@ -1657,7 +1664,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.002", 0, "24c958bc922b07f91e25e8c93aa01fcf", 491230}, {"resource.003", 0, "685cd6c1e05a695ab1e0db826337ee2a", 553279}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO2(GUIO_NOSPEECH, GUIO_EGAUNDITHER) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, #if 0 // The resource.002 file, contained in disk 3, is broken in this version @@ -1675,7 +1682,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.002", 0, "5790ac0505f7ca98d4567132b875eb1e", 681041}, {"resource.003", 0, "4a34c3367c2fe7eb380d741374da1989", 572251}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO1(GUIO_NOSPEECH) }, + Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, #endif // Larry 1 VGA Remake - English DOS (from spookypeanut) @@ -1686,7 +1693,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.001", 0, "ec20246209d7b19f38989261e5c8f5b8", 1111226}, {"resource.002", 0, "85d6935ef77e6b0e16bc307640a0d913", 1088312}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO1(GUIO_NOSPEECH) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Larry 1 VGA Remake - English DOS (from FRG) // SCI interpreter version 1.000.510 @@ -1696,7 +1703,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.001", 0, "d34cadb11e1aefbb497cf91bc1d3baa7", 1114688}, {"resource.002", 0, "85b030bb66d5342b0a068f1208c431a8", 1078443}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO1(GUIO_NOSPEECH) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Larry 1 VGA Remake - English Macintosh (from omer_mor, bug report #3328262) {"lsl1sci", "SCI", { @@ -1705,7 +1712,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.001", 0, "aa6f153f70f1e32d1bde465fff08eecf", 1137418}, {"resource.002", 0, "b22c616aa789ebef990290c7ffd86548", 1097477}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformMacintosh, 0, GUIO1(GUIO_NOSPEECH) }, + Common::EN_ANY, Common::kPlatformMacintosh, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Larry 1 VGA Remake - English DOS Non-Interactive Demo // SCI interpreter version 1.000.084 @@ -1713,7 +1720,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "434e1f6c39d71647b34f0ee57b2bbd68", 444}, {"resource.001", 0, "0c0768215c562d9dace4a5ca53696cf3", 359913}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO1(GUIO_NOSPEECH) }, + Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Larry 1 VGA Remake - Spanish DOS (from the Leisure Suit Larry Collection, also includes english language) // Executable scanning reports "1.SQ4.057", VERSION file reports "1.000" @@ -1726,7 +1733,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.002", 0, "3fe2a3aec0ed53c7d6db1845a67e3aa2", 1095908}, {"resource.003", 0, "ac175df0ea9a2cba57f0248651856d27", 376556}, AD_LISTEND}, - Common::ES_ESP, Common::kPlatformPC, ADGF_ADDENGLISH, GUIO1(GUIO_NOSPEECH) }, + Common::ES_ESP, Common::kPlatformPC, ADGF_ADDENGLISH, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Larry 1 VGA Remake - Russian DOS (also includes english language?!) // Executable scanning reports "1.000.510", VERSION file reports "2.0" @@ -1737,7 +1744,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.001", 0, "bc8ca10c807515d959cbd91f9ba47735", 1123759}, {"resource.002", 0, "b7409ab32bc3bee2d6cce887cd33f2b6", 1092160}, AD_LISTEND}, - Common::RU_RUS, Common::kPlatformPC, ADGF_ADDENGLISH, GUIO1(GUIO_NOSPEECH) }, + Common::RU_RUS, Common::kPlatformPC, ADGF_ADDENGLISH, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Larry 1 VGA Remake - Polish DOS (from Polish Leisure Suit Larry Collection, official release) // SCI interpreter version 1.000.577, VERSION file reports "2.1" (this release does NOT include english text) @@ -1745,7 +1752,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "58330a85767e42a2487129913283ab5b", 3228}, {"resource.000", 0, "b6097ff35cdc8469f02150fe2f824198", 4781210}, AD_LISTEND}, - Common::PL_POL, Common::kPlatformPC, 0, GUIO1(GUIO_NOSPEECH) }, + Common::PL_POL, Common::kPlatformPC, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Larry 2 - English Amiga (from www.back2roots.org) // Executable scanning reports "x.yyy.zzz" @@ -1757,7 +1764,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.003", 0, "a0d4a625311d307257da7fc43d00459d", 570356}, {"resource.004", 0, "a0d4a625311d307257da7fc43d00459d", 717844}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO2(GUIO_NOSPEECH, GUIO_EGAUNDITHER) }, + Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Larry 2 - English DOS Non-Interactive Demo // Executable scanning reports "x.yyy.zzz" @@ -1766,7 +1773,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "03dba704bb77da55a91ad27b5a3cac09", 528}, {"resource.001", 0, "9f5520f0297206928df0b0b36493cd33", 127532}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO2(GUIO_NOSPEECH, GUIO_EGAUNDITHER) }, + Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Larry 2 - English DOS // SCI interpreter version 0.000.409 @@ -1779,7 +1786,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.005", 0, "4a24443a25e2b1492462a52809605dc2", 277732}, {"resource.006", 0, "4a24443a25e2b1492462a52809605dc2", 345683}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO2(GUIO_NOSPEECH, GUIO_EGAUNDITHER) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Larry 2 - English DOS // SCI interpreter version 0.000.343 @@ -1794,7 +1801,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { //{"resource.006", 0, "96033f57accfca903750413fd09193c8", 345818}, {"resource.006", 0, "96033f57accfca903750413fd09193c8", -1}, // 345818 or 208739 AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO2(GUIO_NOSPEECH, GUIO_EGAUNDITHER) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Larry 2 - English DOS (supplied by ssburnout in bug report #3049193) // 1.000.011 3x3.5" (label: Int. #0.000.343) @@ -1804,7 +1811,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.002", 0, "96033f57accfca903750413fd09193c8", 407014}, {"resource.003", 0, "96033f57accfca903750413fd09193c8", 592834}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO2(GUIO_NOSPEECH, GUIO_EGAUNDITHER) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Larry 2 - English DOS (supplied by ssburnout in bug report #3049193) // 1.002.000 3x3.5" (label: INT#0.000.409) @@ -1814,7 +1821,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.002", 0, "4a24443a25e2b1492462a52809605dc2", 406935}, {"resource.003", 0, "4a24443a25e2b1492462a52809605dc2", 592533}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO2(GUIO_NOSPEECH, GUIO_EGAUNDITHER) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Larry 3 - English Amiga (from www.back2roots.org) // Executable scanning reports "1.002.032" @@ -1828,7 +1835,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.004", 0, "f408e59cbee1457f042e5773b8c53951", 651634}, {"resource.005", 0, "433911eb764089d493aed1f958a5615a", 524259}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO1(GUIO_NOSPEECH) }, + Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Larry 3 - English DOS // SCI interpreter version 0.000.572 @@ -1839,7 +1846,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.003", 0, "f18441027154292836b973c655fa3175", 506807}, {"resource.004", 0, "f18441027154292836b973c655fa3175", 513651}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO2(GUIO_NOSPEECH, GUIO_EGAUNDITHER) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Larry 3 - English DOS (supplied by ssburnout in bug report #3049193) // 1.021 8x5.25" (label: Int#5.15.90) @@ -1853,7 +1860,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.006", 0, "f18441027154292836b973c655fa3175", 282649}, {"resource.007", 0, "f18441027154292836b973c655fa3175", 257178}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO2(GUIO_NOSPEECH, GUIO_EGAUNDITHER) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Larry 3 - English DOS // SCI interpreter version 0.000.572 @@ -1867,7 +1874,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.006", 0, "f18441027154292836b973c655fa3175", 282465}, {"resource.007", 0, "f18441027154292836b973c655fa3175", 257174}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO2(GUIO_NOSPEECH, GUIO_EGAUNDITHER) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Larry 3 - English DOS Non-Interactive Demo // SCI interpreter version 0.000.530 @@ -1876,7 +1883,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.001", 0, "f773d79b93dfd4052ec8c1cc64c1e6ab", 76525}, {"resource.002", 0, "f773d79b93dfd4052ec8c1cc64c1e6ab", 268299}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO2(GUIO_NOSPEECH, GUIO_EGAUNDITHER) }, + Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Larry 3 - German DOS (from Tobis87, updated info from markcoolio in bug report #2723832, also includes english language) // Executable scanning reports "S.old.123" @@ -1888,7 +1895,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.003", 0, "3827a9b17b926e12dcc336860f50612a", 587036}, {"resource.004", 0, "3827a9b17b926e12dcc336860f50612a", 691932}, AD_LISTEND}, - Common::DE_DEU, Common::kPlatformPC, ADGF_ADDENGLISH, GUIO2(GUIO_NOSPEECH, GUIO_EGAUNDITHER) }, + Common::DE_DEU, Common::kPlatformPC, ADGF_ADDENGLISH, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Larry 3 - French DOS (provided by richiefs in bug report #2670691, also includes english language) // Executable scanning reports "S.old.123" @@ -1900,7 +1907,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.003", 0, "65f1bdaa20f6d0470e9d969f22473873", 586921}, {"resource.004", 0, "65f1bdaa20f6d0470e9d969f22473873", 690826}, AD_LISTEND}, - Common::FR_FRA, Common::kPlatformPC, ADGF_ADDENGLISH, GUIO2(GUIO_NOSPEECH, GUIO_EGAUNDITHER) }, + Common::FR_FRA, Common::kPlatformPC, ADGF_ADDENGLISH, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Larry 3 1.050 Fr/En (9 x 5.25" disks) // Provided by ssburnout in bug report #3046779 @@ -1914,7 +1921,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.006", 0, "65f1bdaa20f6d0470e9d969f22473873", 325292}, {"resource.007", 0, "65f1bdaa20f6d0470e9d969f22473873", 308982}, AD_LISTEND}, - Common::FR_FRA, Common::kPlatformPC, ADGF_ADDENGLISH, GUIO1(GUIO_NOSPEECH) }, + Common::FR_FRA, Common::kPlatformPC, ADGF_ADDENGLISH, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Larry 5 - English Amiga // Executable scanning reports "1.004.023" @@ -1929,7 +1936,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.005", 0, "f8b2d1137bb767e5d232056b99dd69eb", 623621}, {"resource.006", 0, "bafc64e3144f115dc58c6aee02de98fb", 715598}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO1(GUIO_NOSPEECH) }, + Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Larry 5 - German Amiga (also includes english language) // Executable scanning reports "1.004.024" @@ -1945,7 +1952,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.006", 0, "bafc64e3144f115dc58c6aee02de98fb", 754966}, {"resource.007", 0, "59eba83ad465b08d763b44f86afa86f6", 683135}, AD_LISTEND}, - Common::DE_DEU, Common::kPlatformAmiga, ADGF_ADDENGLISH, GUIO1(GUIO_NOSPEECH) }, + Common::DE_DEU, Common::kPlatformAmiga, ADGF_ADDENGLISH, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Larry 5 - English DOS Non-Interactive Demo (from FRG) // SCI interpreter version 1.000.181 @@ -1953,7 +1960,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "efe8d3f45ce4f6bd9a6643e0ac8d2a97", 504}, {"resource.001", 0, "8bd8d9c0b5f455ee1269d63ce86c50dd", 531380}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO1(GUIO_NOSPEECH) }, + Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Larry 5 - English DOS (from spookypeanut) // SCI interpreter version 1.000.510 @@ -1968,7 +1975,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.006", 0, "dda27ce00682aa76198dac124bbbe334", 1024810}, {"resource.007", 0, "ac443fae1285fb359bf2b2bc6a7301ae", 1030656}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO1(GUIO_NOSPEECH) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Larry 5 - English Macintosh (from omer_mor, bug report #3328257) {"lsl5", "", { @@ -1982,7 +1989,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.006", 0, "dda27ce00682aa76198dac124bbbe334", 1110043}, {"resource.007", 0, "ac443fae1285fb359bf2b2bc6a7301ae", 989801}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformMacintosh, 0, GUIO1(GUIO_NOSPEECH) }, + Common::EN_ANY, Common::kPlatformMacintosh, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Larry 5 - German DOS (from Tobis87) // SCI interpreter version T.A00.196 @@ -1997,7 +2004,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.006", 0, "dda27ce00682aa76198dac124bbbe334", 1021774}, {"resource.007", 0, "ac443fae1285fb359bf2b2bc6a7301ae", 993408}, AD_LISTEND}, - Common::DE_DEU, Common::kPlatformPC, ADGF_ADDENGLISH, GUIO1(GUIO_NOSPEECH) }, + Common::DE_DEU, Common::kPlatformPC, ADGF_ADDENGLISH, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Larry 5 - French DOS (provided by richiefs in bug report #2670691) // Executable scanning reports "1.lsl5.019" @@ -2013,7 +2020,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.006", 0, "dda27ce00682aa76198dac124bbbe334", 946540}, {"resource.007", 0, "ac443fae1285fb359bf2b2bc6a7301ae", 958842}, AD_LISTEND}, - Common::FR_FRA, Common::kPlatformPC, ADGF_ADDENGLISH, GUIO1(GUIO_NOSPEECH) }, + Common::FR_FRA, Common::kPlatformPC, ADGF_ADDENGLISH, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Larry 5 - Spanish DOS (from the Leisure Suit Larry Collection) // Executable scanning reports "1.ls5.006", VERSION file reports "1.000, 4/21/92" @@ -2029,7 +2036,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.006", 0, "dda27ce00682aa76198dac124bbbe334", 1015136}, {"resource.007", 0, "ac443fae1285fb359bf2b2bc6a7301ae", 987222}, AD_LISTEND}, - Common::ES_ESP, Common::kPlatformPC, ADGF_ADDENGLISH, GUIO1(GUIO_NOSPEECH) }, + Common::ES_ESP, Common::kPlatformPC, ADGF_ADDENGLISH, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Larry 5 - Italian DOS Floppy (from glorifindel) // SCI interpreter version 1.000.510 (just a guess) @@ -2037,7 +2044,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "a99776df795127f387cb35dae872d4e4", 5919}, {"resource.000", 0, "a8989a5a89e7d4f702b26b378c7a357a", 7001981}, AD_LISTEND}, - Common::IT_ITA, Common::kPlatformPC, 0, GUIO1(GUIO_NOSPEECH) }, + Common::IT_ITA, Common::kPlatformPC, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Larry 5 1.0 EGA DOS (8 x 3.5" disks) // Provided by ssburnout in bug report #3046806 @@ -2052,7 +2059,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.006", 0, "f6046a8445422f17d40b1b10ab21ebf3", 568551}, {"resource.007", 0, "640ee65595d40372ef95462f2c1ae28a", 593429}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO2(GUIO_NOSPEECH, GUIO_EGAUNDITHER) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Larry 5 EGA // Supplied by omer_mor in bug report #3049771 @@ -2063,7 +2070,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.002", 0, "5a55af4e40728b1a8103dc47ad2afa8d", 1100539}, {"resource.003", 0, "16f4d8fb1b526125edaca4fc6cbb7530", 1064563}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO2(GUIO_NOSPEECH, GUIO_EGAUNDITHER) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Larry 6 - English DOS (from spookypeanut) // SCI interpreter version 1.001.113 @@ -2071,7 +2078,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "bb8a39d9e2a77ba449a1e591109ad9a8", 6973}, {"resource.000", 0, "4462fe48c7452d98fddcec327a3e738d", 5789138}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO1(GUIO_NOSPEECH) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Larry 6 - English/German/French DOS CD - LOWRES // SCI interpreter version 1.001.115 @@ -2079,7 +2086,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "0b91234b7112782962cb480b7791b6e2", 7263}, {"resource.000", 0, "57d5fe8bb9e044158514476ea7678eb0", 5754790}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, ADGF_CD, GUIO0() }, + Common::EN_ANY, Common::kPlatformPC, ADGF_CD, GUIO3(GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Larry 6 - German DOS CD - LOWRES (provided by richiefs in bug report #2670691) // SCI interpreter version 1.001.115 @@ -2087,7 +2094,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "bafe85f32738854135991d4324ad147e", 7268}, {"resource.000", 0, "f6cbc6da7b90ea135883e0759848ca2c", 5773160}, AD_LISTEND}, - Common::DE_DEU, Common::kPlatformPC, ADGF_CD, GUIO0() }, + Common::DE_DEU, Common::kPlatformPC, ADGF_CD, GUIO3(GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Larry 6 - French DOS CD - LOWRES (provided by richiefs in bug report #2670691) // SCI interpreter version 1.001.115 @@ -2095,7 +2102,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "97797ea775baaf18a1907d357d3c0ea6", 7268}, {"resource.000", 0, "f6cbc6da7b90ea135883e0759848ca2c", 5776092}, AD_LISTEND}, - Common::FR_FRA, Common::kPlatformPC, ADGF_CD, GUIO0() }, + Common::FR_FRA, Common::kPlatformPC, ADGF_CD, GUIO3(GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Larry 6 - Spanish DOS - LOWRES (from the Leisure Suit Larry Collection) // Executable scanning reports "1.001.113", VERSION file reports "1.000, 11.06.93, FIVE PATCHES ADDED TO DISK 6 ON 11-18-93" @@ -2103,7 +2110,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "633bf8f42170b6271019917c8009989b", 6943}, {"resource.000", 0, "7884a8db9253e29e6b37a2651fd90ba3", 5733116}, AD_LISTEND}, - Common::ES_ESP, Common::kPlatformPC, 0, GUIO1(GUIO_NOSPEECH) }, + Common::ES_ESP, Common::kPlatformPC, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Crazy Nick's Software Picks: Leisure Suit Larry's Casino - English DOS (from the Leisure Suit Larry Collection) // Executable scanning reports "1.001.029", VERSION file reports "1.000" @@ -2111,35 +2118,35 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "194f1578f2624db813c9072359ad1639", 783}, {"resource.001", 0, "3733433b517ec3d14a3331d9ab3842ae", 344830}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO1(GUIO_NOSPEECH) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Crazy Nick's Software Picks: King Graham's Board Game Challenge {"cnick-kq", "", { {"resource.map", 0, "44bc538a5cd24b39ffccc967c0ebf84d", 1137}, {"resource.001", 0, "470e7a4a3504635e70b623c44461e1ac", 451272}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO1(GUIO_NOSPEECH) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Crazy Nick's Software Picks: Parlor Games with Laura Bow {"cnick-laurabow", "", { {"resource.map", 0, "3b826bfe64f8ff1ccf30eef93cd2f727", 999}, {"resource.001", 0, "985ac8db6f636f2b4334c04b0fbb44fb", 336698}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO1(GUIO_NOSPEECH) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Crazy Nick's Software Picks: Robin Hood's Game of Skill and Chance {"cnick-longbow", "", { {"resource.map", 0, "4a5c81f485a2416bde12978506f2fb5f", 897}, {"resource.001", 0, "ef16dc9e867eb8eeb5b13e110b90bd4b", 571466}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO1(GUIO_NOSPEECH) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Crazy Nick's Software Picks: Roger Wilco's Spaced Out Game Pack {"cnick-sq", "", { {"resource.map", 0, "b4d95b02d84e297441bd999d34eaa6b1", 879}, {"resource.001", 0, "82ff2b64a60117886fbcd6a3a8c977c6", 364921}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO1(GUIO_NOSPEECH) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, #ifdef ENABLE_SCI32 // Larry 6 - English/German DOS CD - HIRES @@ -2148,7 +2155,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "0c0804434ea62278dd15032b1947426c", 8872}, {"resource.000", 0, "9a9f4870504444cda863dd14d077a680", 18520872}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, ADGF_UNSTABLE, GUIO1(GUIO_NOASPECT) }, + Common::EN_ANY, Common::kPlatformPC, ADGF_UNSTABLE, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Larry 6 - German DOS CD - HIRES (provided by richiefs in bug report #2670691) // SCI interpreter version 2.100.002 @@ -2156,7 +2163,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "badfdf446ffed569a310d2c63a249421", 8896}, {"resource.000", 0, "bd944d2b06614a5b39f1586906f0ee88", 18534274}, AD_LISTEND}, - Common::DE_DEU, Common::kPlatformPC, ADGF_UNSTABLE, GUIO1(GUIO_NOASPECT) }, + Common::DE_DEU, Common::kPlatformPC, ADGF_UNSTABLE, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Larry 6 - French DOS CD - HIRES (provided by richiefs in bug report #2670691) // SCI interpreter version 2.100.002 @@ -2164,7 +2171,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "d184e9aa4f2d4b5670ddb3669db82cda", 8896}, {"resource.000", 0, "bd944d2b06614a5b39f1586906f0ee88", 18538987}, AD_LISTEND}, - Common::FR_FRA, Common::kPlatformPC, ADGF_UNSTABLE, GUIO1(GUIO_NOASPECT) }, + Common::FR_FRA, Common::kPlatformPC, ADGF_UNSTABLE, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Larry 7 - English DOS Demo (provided by richiefs in bug report #2670691) // SCI interpreter version 2.100.002 @@ -2172,7 +2179,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"ressci.000", 0, "5cc6159688b2dc03790a67c90ccc67f9", 10195878}, {"resmap.000", 0, "6a2b2811eef82e87cde91cf1de845af8", 2695}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO | ADGF_UNSTABLE, GUIO2(GUIO_NOSPEECH, GUIO_NOASPECT) }, + Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO | ADGF_UNSTABLE, GUIO5(GUIO_NOSPEECH, GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, #ifdef ENABLE_SCI3_GAMES // Larry 7 - English DOS CD (from spookypeanut) @@ -2181,7 +2188,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resmap.000", 0, "eae93e1b1d1ccc58b4691c371281c95d", 8188}, {"ressci.000", 0, "89353723488219e25589165d73ed663e", 66965678}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, ADGF_UNSTABLE, GUIO1(GUIO_NOASPECT) }, + Common::EN_ANY, Common::kPlatformPC, ADGF_UNSTABLE, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Larry 7 - German DOS (from Tobis87) // SCI interpreter version 3.000.000 @@ -2189,7 +2196,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resmap.000", 0, "c11e6bfcfc2f2d05da47e5a7df3e9b1a", 8188}, {"ressci.000", 0, "a8c6817bb94f332ff498a71c8b47f893", 66971724}, AD_LISTEND}, - Common::DE_DEU, Common::kPlatformPC, ADGF_UNSTABLE, GUIO2(GUIO_NOSPEECH, GUIO_NOASPECT) }, + Common::DE_DEU, Common::kPlatformPC, ADGF_UNSTABLE, GUIO5(GUIO_NOSPEECH, GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Larry 7 - French DOS (provided by richiefs in bug report #2670691) // SCI interpreter version 3.000.000 @@ -2197,7 +2204,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resmap.000", 0, "4407849fd52fe3efb0c30fba60cd5cd4", 8206}, {"ressci.000", 0, "dc37c3055fffbefb494ff22b145d377b", 66964472}, AD_LISTEND}, - Common::DE_DEU, Common::kPlatformPC, ADGF_UNSTABLE, GUIO2(GUIO_NOSPEECH, GUIO_NOASPECT) }, + Common::DE_DEU, Common::kPlatformPC, ADGF_UNSTABLE, GUIO5(GUIO_NOSPEECH, GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Larry 7 - Italian DOS CD (from glorifindel) // SCI interpreter version 3.000.000 @@ -2205,7 +2212,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resmap.000", 0, "9852a97141f789413f29bf956052acdb", 8212}, {"ressci.000", 0, "440b9fed89590abb4e4386ed6f948ee2", 67140181}, AD_LISTEND}, - Common::IT_ITA, Common::kPlatformPC, ADGF_UNSTABLE, GUIO1(GUIO_NOASPECT) }, + Common::IT_ITA, Common::kPlatformPC, ADGF_UNSTABLE, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Larry 7 - Spanish DOS (from the Leisure Suit Larry Collection) // Executable scanning reports "3.000.000", VERSION file reports "1.0s" @@ -2213,7 +2220,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resmap.000", 0, "8f3d603e1acc834a5d598b30cdfc93f3", 8188}, {"ressci.000", 0, "32792f9bc1bf3633a88b382bb3f6e40d", 67071418}, AD_LISTEND}, - Common::ES_ESP, Common::kPlatformPC, ADGF_UNSTABLE, GUIO2(GUIO_NOSPEECH, GUIO_NOASPECT) }, + Common::ES_ESP, Common::kPlatformPC, ADGF_UNSTABLE, GUIO5(GUIO_NOSPEECH, GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, #endif // Lighthouse - English Windows Demo (from jvprat) @@ -2222,7 +2229,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "543124606352bfa5e07696ddf2a669be", 64}, {"resource.000", 0, "5d7714416b612463d750fb9c5690c859", 28952}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO | ADGF_UNSTABLE, GUIO2(GUIO_NOSPEECH, GUIO_NOASPECT) }, + Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO | ADGF_UNSTABLE, GUIO5(GUIO_NOSPEECH, GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, #ifdef ENABLE_SCI3_GAMES // Lighthouse - English Windows Demo @@ -2231,7 +2238,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resmap.000", 0, "3bdee7a16926975a4729f75cf6b80a92", 1525}, {"ressci.000", 0, "3c585827fa4a82f4c04a56a0bc52ccee", 11494351}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO | ADGF_UNSTABLE, GUIO2(GUIO_NOSPEECH, GUIO_NOASPECT) }, + Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO | ADGF_UNSTABLE, GUIO5(GUIO_NOSPEECH, GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Lighthouse - English DOS (from jvprat) // Executable scanning reports "3.000.000", VERSION file reports "1.1" @@ -2241,7 +2248,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resmap.002", 0, "c68db5333f152fea6ca2dfc75cad8b34", 7573}, {"ressci.002", 0, "175468431a979b9f317c294ce3bc1430", 94628315}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, ADGF_UNSTABLE, GUIO2(GUIO_NOSPEECH, GUIO_NOASPECT) }, + Common::EN_ANY, Common::kPlatformPC, ADGF_UNSTABLE, GUIO5(GUIO_NOSPEECH, GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Lighthouse - Spanish DOS (from jvprat) // Executable scanning reports "3.000.000", VERSION file reports "1.1" @@ -2251,7 +2258,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resmap.002", 0, "e7dc85884a2417e2eff9de0c63dd65fa", 7630}, {"ressci.002", 0, "3c8d627c555b0e3e4f1d9955bc0f0df4", 94631127}, AD_LISTEND}, - Common::ES_ESP, Common::kPlatformPC, ADGF_UNSTABLE, GUIO2(GUIO_NOSPEECH, GUIO_NOASPECT) }, + Common::ES_ESP, Common::kPlatformPC, ADGF_UNSTABLE, GUIO5(GUIO_NOSPEECH, GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, #endif // ENABLE_SCI3_GAMES #endif // ENABLE_SCI32 @@ -2262,7 +2269,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.000", 0, "8be56a3a88c065ee00c02c0e29199f3a", 14643}, {"resource.001", 0, "9e33566515b18bee7915db448063bba2", 871853}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO1(GUIO_NOSPEECH) }, + Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Mixed-Up Fairy Tales - English DOS Floppy EGA (from omer_mor, bug report #3035350) {"fairytales", "EGA", { @@ -2273,7 +2280,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.003", 0, "509b2467ba779100d5933ed51a9ae32f", 560255}, {"resource.004", 0, "93afc85d5ffa60ea555d6cc336d22c03", 651109}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO2(GUIO_NOSPEECH, GUIO_EGAUNDITHER) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Mixed-Up Fairy Tales v1.000 - English DOS (supplied by markcoolio in bug report #2723791) // Executable scanning reports "1.000.145" @@ -2285,7 +2292,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.003", 0, "b1288e0821ee358d1ffe877e5900c8ec", 1047565}, {"resource.004", 0, "f79daa70390d73746742ffcfc3dc4471", 937580}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO1(GUIO_NOSPEECH) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Mixed-Up Fairy Tales - English DOS Floppy (from jvprat) // Executable scanning reports "1.000.145", Floppy label reports "1.0, 11.13.91", VERSION file reports "1.000" @@ -2296,7 +2303,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.002", 0, "564f516d991032e781492592a4eaa275", 1414142}, {"resource.003", 0, "dd6cef0c592eadb7e6be9a25307c57a2", 1344719}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO1(GUIO_NOSPEECH) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Mixed-Up Mother Goose - English Amiga (from www.back2roots.org) // Executable scanning reports "1.003.009" @@ -2306,7 +2313,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.001", 0, "fb552ae550ca1dac19ed8f6a3767612d", 262885}, {"resource.002", 0, "fb552ae550ca1dac19ed8f6a3767612d", 817191}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO1(GUIO_NOSPEECH) }, + Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Mixed-Up Mother Goose - English DOS Floppy EGA (from omer_mor, bug report #3035354) {"mothergoose", "EGA", { @@ -2314,7 +2321,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.001", 0, "d893892d62b3f061357291d66775e360", 239906}, {"resource.002", 0, "d893892d62b3f061357291d66775e360", 719398}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO2(GUIO_NOSPEECH, GUIO_EGAUNDITHER) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Mixed-Up Mother Goose - English DOS Floppy EGA (supplied by ssburnout in bug report #3049193) // 1.011 5x5.25" (label: Int#8.2.90) @@ -2327,7 +2334,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.004", 0, "dbbc22f124533ce308bc386b08956326", 146251}, {"resource.005", 0, "2ba5348e7fad641b9c4c7ff7c7cf4e68", 110979}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO2(GUIO_NOSPEECH, GUIO_EGAUNDITHER) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Mixed-Up Mother Goose v2.000 - English DOS Floppy (supplied by markcoolio in bug report #2723795) // Executable scanning reports "1.001.031" @@ -2335,7 +2342,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "52aae15e493cafd1da7e1c9b657a5bb9", 7026}, {"resource.000", 0, "b7ecd8ae9e254e80310b5a668b276e6e", 2948975}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO1(GUIO_NOSPEECH) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Mixed-Up Mother Goose - English DOS CD (from jvprat) // Executable scanning reports "x.yyy.zzz" @@ -2344,7 +2351,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "1c7f311b0a2c927b2fbe81ae341fb2f6", 5790}, {"resource.001", 0, "5a0ed1d745855148364de1b3be099bac", 4369438}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, ADGF_CD, GUIO0() }, + Common::EN_ANY, Common::kPlatformPC, ADGF_CD, GUIO3(GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Mixed-Up Mother Goose - English Windows Interactive Demo // Executable scanning reports "x.yyy.zzz" @@ -2352,19 +2359,19 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "87f9dc1cafc4d4fa835fb2f00cf3a6ef", 4560}, {"resource.001", 0, "5a0ed1d745855148364de1b3be099bac", 2070072}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformWindows, ADGF_DEMO, GUIO1(GUIO_NOSPEECH) }, + Common::EN_ANY, Common::kPlatformWindows, ADGF_DEMO, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Mixed-Up Mother Goose - FM-Towns (supplied by abevi in bug report #3038720) {"mothergoose256", "", { {"resource.map", 0, "b11e971ccd2040bebba59dfb409a08ef", 5772}, {"resource.001", 0, "d49625d9b8005ec01c852f8322a82867", 4330713}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformFMTowns, 0, GUIO1(GUIO_NOASPECT) }, + Common::EN_ANY, Common::kPlatformFMTowns, 0, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, {"mothergoose256", "", { {"resource.map", 0, "b11e971ccd2040bebba59dfb409a08ef", 5772}, {"resource.001", 0, "d49625d9b8005ec01c852f8322a82867", 4330713}, AD_LISTEND}, - Common::JA_JPN, Common::kPlatformFMTowns, 0, GUIO1(GUIO_NOASPECT) }, + Common::JA_JPN, Common::kPlatformFMTowns, 0, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, #ifdef ENABLE_SCI32 // Mixed-Up Mother Goose Deluxe - English Windows/DOS CD (supplied by markcoolio in bug report #2723810) @@ -2373,7 +2380,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "5159a1578c4306bfe070a3e4d8c2e1d3", 4741}, {"resource.000", 0, "1926925c95d82f0999590e93b02887c5", 15150768}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, ADGF_UNSTABLE, GUIO1(GUIO_NOASPECT) }, + Common::EN_ANY, Common::kPlatformPC, ADGF_UNSTABLE, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Mixed-Up Mother Goose Deluxe - Multilingual Windows CD (English/French/German/Spanish) // Executable scanning reports "2.100.002" @@ -2381,7 +2388,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resmap.000", 0, "ef611af561898dcfea87846919ebf3eb", 4969}, {"ressci.000", 0, "227685bc59d90821978d330713e44a7a", 17205800}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, ADGF_UNSTABLE, GUIO1(GUIO_NOASPECT) }, + Common::EN_ANY, Common::kPlatformPC, ADGF_UNSTABLE, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, #endif // ENABLE_SCI32 // Ms. Astro Chicken - English DOS @@ -2390,7 +2397,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "5b457cbe5042f557e5b610148171f6c0", 1158}, {"resource.001", 0, "453ea81ef66a50cbe33ce06302afe47f", 229737}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO1(GUIO_NOSPEECH) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, #ifdef ENABLE_SCI32 // Phantasmagoria - English DOS (from jvprat) @@ -2411,7 +2418,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resmap.007", 0, "afbd16ea77869a720afa1c5371de107d", 7972}, //{"ressci.007", 0, "3aae6559aa1df273bc542d5ac6330d75", 25859038}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, ADGF_UNSTABLE, GUIO2(GUIO_NOSPEECH, GUIO_NOASPECT) }, + Common::EN_ANY, Common::kPlatformPC, ADGF_UNSTABLE, GUIO5(GUIO_NOSPEECH, GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Phantasmagoria - English DOS Demo // Executable scanning reports "2.100.002" @@ -2419,7 +2426,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resmap.001", 0, "416138651ea828219ca454cae18341a3", 11518}, {"ressci.001", 0, "3aae6559aa1df273bc542d5ac6330d75", 65844612}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO | ADGF_UNSTABLE, GUIO2(GUIO_NOSPEECH, GUIO_NOASPECT) }, + Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO | ADGF_UNSTABLE, GUIO5(GUIO_NOSPEECH, GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Phantasmagoria - English DOS/Windows (GOG version) - ressci.* merged in ressci.000 // Windows executable scanning reports "2.100.002" - "Sep 19 1995 15:09:43" @@ -2430,7 +2437,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"ressci.000", 0, "cd5967f9b9586e3380645961c0765be3", 116822037}, {"resmap.000", 0, "3cafc1c6a53945c1f3babbfd6380c64c", 16468}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, ADGF_UNSTABLE, GUIO2(GUIO_NOSPEECH, GUIO_NOASPECT) }, + Common::EN_ANY, Common::kPlatformPC, ADGF_UNSTABLE, GUIO5(GUIO_NOSPEECH, GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Phantasmagoria - English Macintosh // NOTE: This only contains disc 1 files (as well as the two persistent files: @@ -2446,7 +2453,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { // Data8-12 are empty {"Data13", 0, "6d2c450fca19a69b5af74ed5b03c0a17", 14923328}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformMacintosh, ADGF_MACRESFORK | ADGF_UNSTABLE, GUIO1(GUIO_NOASPECT) }, + Common::EN_ANY, Common::kPlatformMacintosh, ADGF_MACRESFORK | ADGF_UNSTABLE, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, #ifdef ENABLE_SCI3_GAMES // Phantasmagoria 2 - English Windows (from jvprat) @@ -2463,7 +2470,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resmap.005", 0, "8bd5ceeedcbe16dfe55d1b90dcd4be84", 1942}, {"ressci.005", 0, "05f9fe2bee749659acb3cd2c90252fc5", 67905112}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformWindows, ADGF_UNSTABLE, GUIO2(GUIO_NOSPEECH, GUIO_NOASPECT) }, + Common::EN_ANY, Common::kPlatformWindows, ADGF_UNSTABLE, GUIO5(GUIO_NOSPEECH, GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Phantasmagoria 2 - English DOS (GOG version) - ressci.* merged in ressci.000 // Executable scanning reports "3.000.000" - "Dec 07 1996 09:29:03" @@ -2473,7 +2480,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"ressci.000", 0, "c54f26d9f43f908151263254b6d97053", 108134481}, {"resmap.000", 0, "de154a223a9ef4ea7358b76adc38ef5b", 2956}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformWindows, ADGF_UNSTABLE, GUIO2(GUIO_NOSPEECH, GUIO_NOASPECT) }, + Common::EN_ANY, Common::kPlatformWindows, ADGF_UNSTABLE, GUIO5(GUIO_NOSPEECH, GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, #endif // ENABLE_SCI3_GAMES #endif // ENABLE_SCI32 @@ -2484,7 +2491,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "72726dc81c1b4c1110c486be77369bc8", 5179}, {"resource.000", 0, "670d0c53622429f4b11275caf7f8d292", 5459574}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO1(GUIO_NOSPEECH) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Pepper - English DOS Non-Interactive Demo // Executable scanning reports "1.001.060", VERSION file reports "1.000" @@ -2492,7 +2499,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "379bb4fb896630b14f2d91ed21e36ba1", 984}, {"resource.000", 0, "118f6c31a93ec7fd9a231c61125229e3", 645494}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO1(GUIO_NOSPEECH) }, + Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Pepper - English DOS/Windows Interactive Demo // Executable scanning reports "1.001.069", VERSION file reports ".001" @@ -2500,7 +2507,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "975e8df76106a5c13d12ab674f906a02", 2514}, {"resource.000", 0, "e6a918a2dd7a4bcecd8fb389f43287c2", 1698164}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO1(GUIO_NOSPEECH) }, + Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Pepper - English DOS Interactive Demo // Executable scanning reports "1.001.072", VERSION file reports "1.000" @@ -2508,7 +2515,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "9c9b7b900651a370dd3fb38d478b1798", 2524}, {"resource.000", 0, "e6a918a2dd7a4bcecd8fb389f43287c2", 1713544}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO1(GUIO_NOSPEECH) }, + Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Police Quest 1 VGA Remake - English DOS (from the Police Quest Collection) // Executable scanning reports "1.001.029", VERSION file reports "2.000" @@ -2516,7 +2523,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "35efa814fb994b1cbdac9611e401da67", 5013}, {"resource.000", 0, "e0d5ddf34eda903a38f0837e2aa7145b", 6401433}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO1(GUIO_NOSPEECH) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Police Quest 2 - English Amiga (from www.back2roots.org) // SCI interpreter version 0.000.685 (just a guess) @@ -2527,7 +2534,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.002", 0, "499737c21a28ac026e11ab817100d610", 511099}, {"resource.003", 0, "e008f5d6e2a7c4d4a0da0173e4fa8f8b", 553970}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO2(GUIO_NOSPEECH, GUIO_EGAUNDITHER) }, + Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Police Quest 2 - English DOS Non-Interactive Demo // Executable scanning reports "0.000.413" @@ -2535,7 +2542,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "8b77d0d4650c2052b356cece28294b58", 576}, {"resource.001", 0, "376ef6d6eaaeed66e1424bd219c4b9ab", 215398}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO2(GUIO_NOSPEECH, GUIO_EGAUNDITHER) }, + Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Police Quest 2 - English DOS (provided by richiefs in bug report #2670691) // SCI interpreter version 0.000.395 @@ -2548,7 +2555,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.005", 0, "77f02def3094af804fd2371db25b7100", 349899}, {"resource.006", 0, "77f02def3094af804fd2371db25b7100", 354991}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO2(GUIO_NOSPEECH, GUIO_EGAUNDITHER) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Police Quest 2 - English DOS (from the Police Quest Collection) // Executable scanning reports "0.000.490" @@ -2558,7 +2565,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.002", 0, "77f02def3094af804fd2371db25b7100", 546000}, {"resource.003", 0, "77f02def3094af804fd2371db25b7100", 591851}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO2(GUIO_NOSPEECH, GUIO_EGAUNDITHER) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Police Quest 2 - English DOS (from FRG) // SCI interpreter version 0.000.395 @@ -2568,7 +2575,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.002", 0, "77f02def3094af804fd2371db25b7100", 542897}, {"resource.003", 0, "77f02def3094af804fd2371db25b7100", 586857}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO2(GUIO_NOSPEECH, GUIO_EGAUNDITHER) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Police Quest 2 English DOS 1.001.006 (supplied by merkur-kun in bug report #3028479) {"pq2", "", { @@ -2577,7 +2584,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.002", 0, "77f02def3094af804fd2371db25b7100", 541261}, {"resource.003", 0, "77f02def3094af804fd2371db25b7100", 587511}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO2(GUIO_NOSPEECH, GUIO_EGAUNDITHER) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Police Quest 2 - Japanese PC-98 (also includes english language) // SCI interpreter version unknown @@ -2587,7 +2594,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.002", 0, "05fdee43a228dd6ea4d1a92ccae3f788", 637662}, {"resource.003", 0, "05fdee43a228dd6ea4d1a92ccae3f788", 684395}, AD_LISTEND}, - Common::JA_JPN, Common::kPlatformPC98, ADGF_ADDENGLISH, GUIO2(GUIO_NOSPEECH, GUIO_NOASPECT) }, + Common::JA_JPN, Common::kPlatformPC98, ADGF_ADDENGLISH, GUIO5(GUIO_NOSPEECH, GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Police Quest 3 - English Amiga // Executable scanning reports "1.004.024" @@ -2600,7 +2607,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.003", 0, "630bfa65beb05f743552704ac2899dae", 759891}, {"resource.004", 0, "7b229fbdf30d670d0728cede3e984a7e", 838663}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO1(GUIO_NOSPEECH) }, + Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Police Quest 3 - German Amiga (also includes english language) // Executable scanning reports "1.004.024" @@ -2614,7 +2621,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.004", 0, "6258d5dd85898d8e218eb8113ebc9059", 722738}, {"resource.005", 0, "6258d5dd85898d8e218eb8113ebc9059", 704485}, AD_LISTEND}, - Common::DE_DEU, Common::kPlatformAmiga, ADGF_ADDENGLISH, GUIO1(GUIO_NOSPEECH) }, + Common::DE_DEU, Common::kPlatformAmiga, ADGF_ADDENGLISH, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Police Quest 3 - English DOS (from the Police Quest Collection) // Executable scanning reports "T.A00.178", VERSION file reports "1.00" @@ -2627,7 +2634,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.003", 0, "8791b9eef53edf77c2dac950142221d3", 1159791}, {"resource.004", 0, "1b91e891a3c60a941dac0eecdf83375b", 1143606}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO1(GUIO_NOSPEECH) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Police Quest 3 - English DOS Non-Interactive Demo // Executable scanning reports "T.A00.052" @@ -2637,7 +2644,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.000", 0, "277f97771f7a6d89677141f02da313d6", 65150}, {"resource.001", 0, "5c5a551b6c86cce2ee75becb90e0b586", 624411}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO1(GUIO_NOSPEECH) }, + Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Police Quest 3 - German DOS (supplied by markcoolio in bug report #2723837, also includes english language) // Executable scanning reports "T.A00.178" @@ -2650,7 +2657,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.003", 0, "4836f460f4cfc8de61e2df4c45775504", 1180956}, {"resource.004", 0, "0c3eb84b9755852d9e795e0d5c9373c7", 1171760}, AD_LISTEND}, - Common::DE_DEU, Common::kPlatformPC, ADGF_ADDENGLISH, GUIO1(GUIO_NOSPEECH) }, + Common::DE_DEU, Common::kPlatformPC, ADGF_ADDENGLISH, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Police Quest 3 EGA // Reported by musiclyinspired in bug report #3046573 @@ -2663,7 +2670,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.004", 0, "b96a86ab681769e4cbb439670d967ca6", 449682}, {"resource.005", 0, "9e6c53a0e7eef53694d260fade8b1fc7", 724000}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO2(GUIO_NOSPEECH, GUIO_EGAUNDITHER) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Police Quest 4 - English DOS Non-Interactive Demo (from FRG) // SCI interpreter version 1.001.096 @@ -2671,7 +2678,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "be56f87a1c4a13062a30a362df860c2f", 1472}, {"resource.000", 0, "527d5684016e6816157cd15d9071b11b", 1121310}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO1(GUIO_NOSPEECH) }, + Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, #ifdef ENABLE_SCI32 // Police Quest 4 - English DOS CD (from the Police Quest Collection) @@ -2680,7 +2687,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "379dfe80ed6bd16c47e4b950c4722eac", 11374}, {"resource.000", 0, "fd316a09b628b7032248139003369022", 18841068}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, ADGF_CD | ADGF_UNSTABLE, GUIO0() }, + Common::EN_ANY, Common::kPlatformPC, ADGF_CD | ADGF_UNSTABLE, GUIO3(GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Police Quest 4 - German DOS CD (German text, English speech) // Supplied by markcoolio in bug report #3392955 @@ -2688,7 +2695,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "a398076371ed0e1e706c8f9fb9fc7ac5", 11386}, {"resource.000", 0, "6ff21954e0a2c5992279e7eb787c8d56", 18918747}, AD_LISTEND}, - Common::DE_DEU, Common::kPlatformPC, ADGF_CD | ADGF_UNSTABLE, GUIO0() }, + Common::DE_DEU, Common::kPlatformPC, ADGF_CD | ADGF_UNSTABLE, GUIO3(GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Police Quest 4 - English DOS // SCI interpreter version 2.000.000 (a guess?) @@ -2696,7 +2703,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "aed9643158ccf01b71f359db33137f82", 9895}, {"resource.000", 0, "da383857b3be1e4514daeba2524359e0", 15141432}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, ADGF_UNSTABLE, GUIO1(GUIO_NOSPEECH) }, + Common::EN_ANY, Common::kPlatformPC, ADGF_UNSTABLE, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Police Quest 4 - French DOS (supplied by abevi in bug report #2612718) // SCI interpreter version 2.000.000 @@ -2704,7 +2711,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "008030846edcc7c5c7a812c7f4ae4ceb", 9256}, {"resource.000", 0, "6ba98bd2e436739d87ecd2a9b99cabb4", 14730153}, AD_LISTEND}, - Common::FR_FRA, Common::kPlatformPC, ADGF_UNSTABLE, GUIO1(GUIO_NOSPEECH) }, + Common::FR_FRA, Common::kPlatformPC, ADGF_UNSTABLE, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Police Quest 4 - German DOS (supplied by markcoolio in bug report #2723840) // SCI interpreter version 2.000.000 (a guess?) @@ -2712,7 +2719,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "2393ee728ab930b2762cb5889f9b5aff", 9256}, {"resource.000", 0, "6ba98bd2e436739d87ecd2a9b99cabb4", 14730155}, AD_LISTEND}, - Common::DE_DEU, Common::kPlatformPC, ADGF_UNSTABLE, GUIO1(GUIO_NOSPEECH) }, + Common::DE_DEU, Common::kPlatformPC, ADGF_UNSTABLE, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Police Quest: SWAT - English DOS/Windows Demo (from jvprat) // Executable scanning reports "2.100.002", VERSION file reports "0.001.200" @@ -2720,7 +2727,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "8c96733ef94c21526792f7ca4e3f2120", 1648}, {"resource.000", 0, "d8892f1b8c56c8f7704325460f49b300", 3676175}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO | ADGF_UNSTABLE, GUIO2(GUIO_NOSPEECH, GUIO_NOASPECT) }, + Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO | ADGF_UNSTABLE, GUIO5(GUIO_NOSPEECH, GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Police Quest: SWAT - English DOS (from GOG.com) // Executable scanning reports "2.100.002", VERSION file reports "1.0c" @@ -2728,7 +2735,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resmap.000", 0, "1c2563fee189885e29d9348f37306d94", 12175}, {"ressci.000", 0, "b2e1826ca81ce2e7e764587f5a14eee9", 127149181}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, ADGF_UNSTABLE, GUIO1(GUIO_NOASPECT) }, + Common::EN_ANY, Common::kPlatformPC, ADGF_UNSTABLE, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Police Quest: SWAT - English Windows (from the Police Quest Collection) // Executable scanning reports "2.100.002", VERSION file reports "1.0c" @@ -2743,7 +2750,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resmap.004", 0, "4228038906f041623e65789500b22285", 6835}, {"ressci.004", 0, "b7e619e6ecf62fe65d5116a3a422e5f0", 46223872}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformWindows, ADGF_UNSTABLE, GUIO1(GUIO_NOASPECT) }, + Common::EN_ANY, Common::kPlatformWindows, ADGF_UNSTABLE, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, #endif // ENABLE_SCI32 // Quest for Glory 1 / Hero's Quest - English DOS 3.5" Floppy (supplied by merkur in bug report #2718784) @@ -2756,7 +2763,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.003", 0, "7ab2bf8e224b57f75e0cd6e4ba790761", 642203}, {"resource.004", 0, "7ab2bf8e224b57f75e0cd6e4ba790761", 641688}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO2(GUIO_NOSPEECH, GUIO_EGAUNDITHER) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Quest for Glory 1 / Hero's Quest - English DOS 3.5" Floppy (supplied by alonzotg in bug report #3206006) {"qfg1", "", { @@ -2767,7 +2774,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.003", 0, "7ab2bf8e224b57f75e0cd6e4ba790761", 642203}, {"resource.004", 0, "7ab2bf8e224b57f75e0cd6e4ba790761", 641688}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO2(GUIO_NOSPEECH, GUIO_EGAUNDITHER) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Quest for Glory 1 / Hero's Quest - English DOS 5.25" Floppy (supplied by markcoolio in bug report #2723843) // Executable scanning reports "0.000.566" @@ -2782,7 +2789,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.006", 0, "69366c2a2f99917199fe1b60a4fee19d", 267852}, {"resource.007", 0, "7ab2bf8e224b57f75e0cd6e4ba790761", 272747}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO2(GUIO_NOSPEECH, GUIO_EGAUNDITHER) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Quest for Glory 1 / Hero's Quest - English DOS 5.25" Floppy (supplied by ssburnout in bug report #3049193) // 1.001 10x5.25" (label: INT.#0.000.566) @@ -2797,7 +2804,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.006", 0, "69366c2a2f99917199fe1b60a4fee19d", 267852}, {"resource.007", 0, "7ab2bf8e224b57f75e0cd6e4ba790761", 272747}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO2(GUIO_NOSPEECH, GUIO_EGAUNDITHER) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Quest for Glory 1 / Hero's Quest - English DOS 5.25" Floppy (supplied by ssburnout in bug report #3049193) // 1.200 10x5.25" (label: INT#9.10.90) @@ -2812,7 +2819,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.006", 0, "f46690dca714abc8c89357d30e363dd3", 278387}, {"resource.007", 0, "951299a82a8134ed12c5c18118d45c2f", 269173}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO2(GUIO_NOSPEECH, GUIO_EGAUNDITHER) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Quest for Glory 1 / Hero's Quest - English DOS Demo // Executable scanning reports "0.000.685" @@ -2820,7 +2827,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "df34c758cbb9026da175793ff686b0e6", 882}, {"resource.001", 0, "73fbaafdd313b39aeedb80fbf85ecef1", 389884}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO2(GUIO_NOSPEECH, GUIO_EGAUNDITHER) }, + Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Quest for Glory 1 - Japanese PC-98 5.25" Floppy (also includes English language) // Executable scanning reports "S.old.201" @@ -2854,7 +2861,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.004", 0, "16cd4414c37ae3bb6d6da33dce8e25e8", 689124}, {"resource.005", 0, "5f3386ef2f2b1254e4a066f5d9027324", 609529}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO2(GUIO_NOSPEECH, GUIO_EGAUNDITHER) }, + Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Quest for Glory 1 (from abevi, bug report #2612718) {"qfg1", "", { @@ -2865,7 +2872,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.003", 0, "f0af87c60ec869946da442833aa5afa8", 640502}, {"resource.004", 0, "f0af87c60ec869946da442833aa5afa8", 644575}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO2(GUIO_NOSPEECH, GUIO_EGAUNDITHER) }, + Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Quest for Glory 1 - English DOS // SCI interpreter version 0.000.629 @@ -2877,7 +2884,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.003", 0, "951299a82a8134ed12c5c18118d45c2f", 640483}, {"resource.004", 0, "951299a82a8134ed12c5c18118d45c2f", 644443}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO2(GUIO_NOSPEECH, GUIO_EGAUNDITHER) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Quest for Glory 1 VGA Remake - English DOS // Executable scanning reports "2.000.411" @@ -2885,7 +2892,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "a731fb6c9c0b282443f7027bc8694d4c", 8469}, {"resource.000", 0, "ecace1a2771846b1a8aa1afdd44111a0", 6570147}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO1(GUIO_NOSPEECH) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Quest for Glory 1 VGA Remake - English DOS Non-Interactive Demo (from FRG) // SCI interpreter version 1.001.029 @@ -2893,7 +2900,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "ac0257051c95a59c0cdc0be24d9b11fa", 729}, {"resource.000", 0, "ec6f5cf369054dd3e5392995e9975b9e", 768218}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO1(GUIO_NOSPEECH) }, + Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Quest for Glory 1 VGA Remake - English Macintosh Floppy // VERSION file reports "2.0" @@ -2901,7 +2908,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"Data1", 0, "106527ff8756e4e1a795d63d23e8b833", 1752358}, {"Data2", 0, "5cdd92033231159c6e9c71d43e9f194d", 6574746}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformMacintosh, ADGF_MACRESFORK, GUIO1(GUIO_NOSPEECH) }, + Common::EN_ANY, Common::kPlatformMacintosh, ADGF_MACRESFORK, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Quest for Glory 2 - English Amiga // Executable scanning reports "1.003.004" @@ -2917,7 +2924,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.006", 0, "ccf5dba33e5cab6d5872838c0f8db44c", 500039}, {"resource.007", 0, "4c9fc1587545879295cb9627f56a2cb8", 575056}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO1(GUIO_NOSPEECH) }, + Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Quest for Glory 2 - English (supplied by ssburnout in bug report #3049193) // 1.000 5x5.25" (label: INT#10.31.90) @@ -2929,7 +2936,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.003", 0, "0790f67d87642132be515cab05026baa", 972144}, {"resource.004", 0, "2ac1e6fea9aa1f5b91a06693a67b9766", 982830}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO1(GUIO_NOSPEECH) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Quest for Glory 2 - English (supplied by ssburnout in bug report #3049193) // 1.000 9x3.5" (label: INT#10.31.90) @@ -2944,7 +2951,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.006", 0, "5e9deacbdb17198ad844988e04833520", 498593}, {"resource.007", 0, "2ac1e6fea9aa1f5b91a06693a67b9766", 490151}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO1(GUIO_NOSPEECH) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Quest for Glory 2 - English (from FRG) // Executable scanning reports "1.000.072" @@ -2956,7 +2963,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.003", 0, "b192607c42f6960ecdf2ad2e4f90e9bc", 972804}, {"resource.004", 0, "cd2de58e27665d5853530de93fae7cd6", 983617}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO1(GUIO_NOSPEECH) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Quest for Glory 2 - English DOS // Executable scanning reports "1.000.072" @@ -2971,7 +2978,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.006", 0, "b1944bd664ddbd2859cdaa0c4a0d6281", 507489}, {"resource.007", 0, "cd2de58e27665d5853530de93fae7cd6", 490794}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO1(GUIO_NOSPEECH) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Quest for Glory 2 - English DOS Non-Interactive Demo // Executable scanning reports "1.000.046" @@ -2979,7 +2986,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "e75eb86bdd517b3ef709058249986a87", 906}, {"resource.001", 0, "9b098f9e1008abe30e56c93b896494e6", 362123}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO1(GUIO_NOSPEECH) }, + Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Quest for Glory 3 - English DOS Non-Interactive Demo (from FRG) // Executable scanning reports "1.001.021", VERSION file reports "1.000, 0.001.059, 6.12.92" @@ -2987,7 +2994,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "fd71de9b588a45f085317caacf050e91", 687}, {"resource.000", 0, "b6c69bf6c18bf177492249fe81fc6a6d", 648702}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO1(GUIO_NOSPEECH) }, + Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Quest for Glory 3 - English DOS // SCI interpreter version 1.001.050 @@ -2995,7 +3002,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "19e2bf9b693932b5e2bb59b9f9ab86c9", 5958}, {"resource.000", 0, "6178ad2e83e58e4671ca03315f7a6498", 5868000}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO1(GUIO_NOSPEECH) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Quest for Glory 3 - English DOS (supplied by abevi in bug report #2612718) // SCI interpreter version 1.001.050 @@ -3003,7 +3010,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "62c185d190363d7df06330fa0cc45b36", 5958}, {"resource.000", 0, "6178ad2e83e58e4671ca03315f7a6498", 5867442}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO1(GUIO_NOSPEECH) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Quest for Glory 3 - English DOS (supplied by dknute in bug report #3125559) {"qfg3", "", { @@ -3011,7 +3018,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.000", 0, "6178ad2e83e58e4671ca03315f7a6498", 5868042}, {"resource.msg", 0, "27e5419c98ce444253f88c95dced14a9", 246888}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO1(GUIO_NOSPEECH) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Quest for Glory 3 - German DOS (supplied by markcoolio in bug report #2723846) // Executable scanning reports "L.rry.083" @@ -3019,7 +3026,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "19e2bf9b693932b5e2bb59b9f9ab86c9", 5958}, {"resource.000", 0, "6178ad2e83e58e4671ca03315f7a6498", 5868042}, AD_LISTEND}, - Common::DE_DEU, Common::kPlatformPC, 0, GUIO1(GUIO_NOSPEECH) }, + Common::DE_DEU, Common::kPlatformPC, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Quest for Glory 3 - Spanish DOS CD (from jvprat) // Executable scanning reports "L.rry.083", VERSION file reports "1.000.000, June 30, 1994" @@ -3028,7 +3035,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.000", 0, "ba7ac86155e4c531e46cd73c86daa80a", 5884098}, {"resource.msg", 0, "a63974730d294dec0bea10057c36e506", 256014}, AD_LISTEND}, - Common::ES_ESP, Common::kPlatformPC, 0, GUIO0() }, + Common::ES_ESP, Common::kPlatformPC, 0, GUIO3(GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Quest for Glory 3 - Italian DOS // Supplied by ghoost in bug report #3053457 @@ -3037,7 +3044,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.000", 0, "6178ad2e83e58e4671ca03315f7a6498", 5868000}, {"resource.msg", 0, "5a0a896ff3e4a628db38a75eb6c84114", 259018}, AD_LISTEND}, - Common::IT_ITA, Common::kPlatformPC, 0, GUIO0() }, + Common::IT_ITA, Common::kPlatformPC, 0, GUIO3(GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Quest for Glory 4 - English DOS Non-Interactive Demo (from FRG) // SCI interpreter version 1.001.069 (just a guess) @@ -3045,7 +3052,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "1ba7c7ae1efb315326d45cb931569b1b", 922}, {"resource.000", 0, "41ba03f0b188b029132daa3ece0d3e14", 623154}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO1(GUIO_NOSPEECH) }, + Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, #ifdef ENABLE_SCI32 // Quest for Glory 4 1.1 Floppy - English DOS (supplied by markcool in bug report #2723852) @@ -3054,7 +3061,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "685bdb1ed47bbbb0e5e25db392da83ce", 9301}, {"resource.000", 0, "f64fd6aa3977939a86ff30783dd677e1", 11004993}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, ADGF_UNSTABLE, GUIO1(GUIO_NOSPEECH) }, + Common::EN_ANY, Common::kPlatformPC, ADGF_UNSTABLE, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Quest for Glory 4 1.1 Floppy - English DOS (supplied by abevi in bug report #2612718) // SCI interpreter version 2.000.000 @@ -3062,7 +3069,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "d10a4cc177d2091d744e2ad8c049b0ae", 9295}, {"resource.000", 0, "f64fd6aa3977939a86ff30783dd677e1", 11003589}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, ADGF_UNSTABLE, GUIO1(GUIO_NOSPEECH) }, + Common::EN_ANY, Common::kPlatformPC, ADGF_UNSTABLE, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Quest for Glory 4 1.1 Floppy - German DOS (supplied by markcool in bug report #2723850) // Executable scanning reports "2.000.000", VERSION file reports "1.1" @@ -3070,7 +3077,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "9e0abba8746f40565bc7eb5720522ecd", 9301}, {"resource.000", 0, "57f22cdc54eeb35fce1f26b31b5c3ee1", 11076197}, AD_LISTEND}, - Common::DE_DEU, Common::kPlatformPC, ADGF_UNSTABLE, GUIO1(GUIO_NOSPEECH) }, + Common::DE_DEU, Common::kPlatformPC, ADGF_UNSTABLE, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Quest for Glory 4 CD - English DOS/Windows (from jvprat) // Executable scanning reports "2.100.002", VERSION file reports "1.0" @@ -3078,7 +3085,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "aba367f2102e81782d961b14fbe3d630", 10246}, {"resource.000", 0, "263dce4aa34c49d3ad29bec889007b1c", 11571394}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, ADGF_CD | ADGF_UNSTABLE, GUIO1(GUIO_NOASPECT) }, + Common::EN_ANY, Common::kPlatformPC, ADGF_CD | ADGF_UNSTABLE, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // RAMA - English DOS/Windows Demo // Executable scanning reports "2.100.002", VERSION file reports "000.000.008" @@ -3086,7 +3093,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resmap.001", 0, "775304e9b2a545156be4d94209550094", 1393}, {"ressci.001", 0, "259437fd75fdf51e8207fda8c01fa4fd", 2334384}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformWindows, ADGF_DEMO | ADGF_UNSTABLE, GUIO1(GUIO_NOASPECT) }, + Common::EN_ANY, Common::kPlatformWindows, ADGF_DEMO | ADGF_UNSTABLE, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, #ifdef ENABLE_SCI3_GAMES // RAMA - English Windows (from jvprat) @@ -3099,7 +3106,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resmap.003", 0, "31ef4c0621711585d031f0ae81707251", 1636}, {"ressci.003", 0, "2a68edd064e5e4937b5e9c74b38f2082", 6860492}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformWindows, ADGF_UNSTABLE, GUIO1(GUIO_NOASPECT) }, + Common::EN_ANY, Common::kPlatformWindows, ADGF_UNSTABLE, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // RAMA - English Windows (from Quietust, in bug report #2850645) {"rama", "", { @@ -3110,7 +3117,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resmap.003", 0, "48841e4b84ef1b98b48d43566fda9e13", 1636}, {"ressci.003", 0, "2a68edd064e5e4937b5e9c74b38f2082", 6870356}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformWindows, ADGF_UNSTABLE, GUIO1(GUIO_NOASPECT) }, + Common::EN_ANY, Common::kPlatformWindows, ADGF_UNSTABLE, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // RAMA - Italian Windows CD (from glorifindel) // SCI interpreter version 3.000.000 (a guess?) @@ -3118,7 +3125,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"ressci.001", 0, "2a68edd064e5e4937b5e9c74b38f2082", 70611091}, {"resmap.001", 0, "70ba2ff04a2b7fb2c52420ba7fbd47c2", 8338}, AD_LISTEND}, - Common::IT_ITA, Common::kPlatformWindows, ADGF_UNSTABLE, GUIO1(GUIO_NOASPECT) }, + Common::IT_ITA, Common::kPlatformWindows, ADGF_UNSTABLE, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, #endif // ENABLE_SCI3_GAMES // Shivers - English Windows (from jvprat) @@ -3127,14 +3134,14 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resmap.000", 0, "f2ead37749ed8f6535a2445a7d05a0cc", 46525}, {"ressci.000", 0, "4294c6d7510935f2e0a52e302073c951", 262654836}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformWindows, ADGF_UNSTABLE, GUIO1(GUIO_NOASPECT) }, + Common::EN_ANY, Common::kPlatformWindows, ADGF_UNSTABLE, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Shivers - German Windows (from Tobis87) {"shivers", "", { {"resmap.000", 0, "f483d0a1f78334c18052e92785c3086e", 46537}, {"ressci.000", 0, "6751b144671e2deed919eb9d284b07eb", 262390692}, AD_LISTEND}, - Common::DE_DEU, Common::kPlatformWindows, ADGF_UNSTABLE, GUIO1(GUIO_NOASPECT) }, + Common::DE_DEU, Common::kPlatformWindows, ADGF_UNSTABLE, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Shivers - English Windows Demo // Executable scanning reports "2.100.002" @@ -3142,7 +3149,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resmap.000", 0, "d9e0bc5eddefcbe47f528760085d8927", 1186}, {"ressci.000", 0, "3a93c6340b54e07e65d0e5583354d186", 10505469}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformWindows, ADGF_DEMO | ADGF_UNSTABLE, GUIO1(GUIO_NOASPECT) }, + Common::EN_ANY, Common::kPlatformWindows, ADGF_DEMO | ADGF_UNSTABLE, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Shivers 2 doesn't contain SCI scripts. The whole game logic has // been reimplemented from SCI in native code placed in DLL files. @@ -3160,7 +3167,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resmap.000", 0, "d8659188b84beaef076bd869837cd530", 634}, {"ressci.000", 0, "7fbac0807a044c9543e8ac376d200e59", 4925003}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformWindows, ADGF_DEMO | ADGF_UNSTABLE, GUIO1(GUIO_NOASPECT) }, + Common::EN_ANY, Common::kPlatformWindows, ADGF_DEMO | ADGF_UNSTABLE, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Shivers 2 - English Windows (from abevi) // VERSION.TXT Version 1.0 (3/25/97) @@ -3168,7 +3175,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"ressci.001", 0, "a79d03d6eb75be0a79324f14e3d2ace4", 95346793}, {"resmap.001", 0, "a4804d436d90c4ec2e46b537f5e954db", 6268}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformWindows, ADGF_UNSTABLE, GUIO2(GUIO_NOSPEECH, GUIO_NOASPECT) }, + Common::EN_ANY, Common::kPlatformWindows, ADGF_UNSTABLE, GUIO5(GUIO_NOSPEECH, GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, #endif @@ -3181,7 +3188,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.msg", 0, "1aeafe2b495de288d002109650b66614", 1364}, {"resource.000", 0, "8e10d4f05c1fd9f883384fa38a898489", 377394}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO1(GUIO_NOSPEECH) }, + Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Slater & Charlie Go Camping - English DOS/Windows {"slater", "", { @@ -3189,7 +3196,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "21f85414124dc23e54544a5536dc35cd", 4044}, {"resource.msg", 0, "c44f51fb955eae266fecf360ebcd5ad2", 1132}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO1(GUIO_NOSPEECH) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Slater & Charlie Go Camping - English DOS/Windows (Sierra Originals) @@ -3198,7 +3205,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "21f85414124dc23e54544a5536dc35cd", 4044}, {"resource.msg", 0, "c44f51fb955eae266fecf360ebcd5ad2", 1132}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO1(GUIO_NOSPEECH) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Slater & Charlie Go Camping - English Macintosh {"slater", "", { @@ -3218,7 +3225,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.004", 0, "b25a1539c71701f7715f738c5037e9a6", 775515}, {"resource.005", 0, "640ffe1a9acde392cc33cc1b1a528328", 806324}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO1(GUIO_NOSPEECH) }, + Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Space Quest 1 VGA Remake - English DOS (from the Space Quest Collection) // Executable scanning reports "T.A00.081", VERSION file reports "2.000" @@ -3231,7 +3238,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.003", 0, "c47600e50c6fc591957ae0c5020ee7b8", 1213262}, {"resource.004", 0, "e19ea4ad131472f9238590f2e1d40289", 1203051}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO1(GUIO_NOSPEECH) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Space Quest 1 VGA Remake - English Mac (from Fingolfin) {"sq1sci", "SCI", { @@ -3242,7 +3249,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.003", 0, "ae46e195e66df5a131917f0aa80b5669", 1242794}, {"resource.004", 0, "91d58a9eb2187c38424990afe4c12bc6", 1250949}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformMacintosh, 0, GUIO1(GUIO_NOSPEECH) }, + Common::EN_ANY, Common::kPlatformMacintosh, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Space Quest 1 VGA Remake - English Non-Interactive Demo (from FRG) // SCI interpreter version 1.000.181 @@ -3250,7 +3257,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "5af709ac5e0e923e0b8174f49978c30e", 636}, {"resource.001", 0, "fd99ea43f57576ded7c86036996346cf", 507642}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO1(GUIO_NOSPEECH) }, + Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Space Quest 1 VGA Remake - Spanish DOS Floppy (from jvprat) // Executable scanning reports "T.A00.081", VERSION file reports "2.000" @@ -3264,7 +3271,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.004", 0, "9b78228ad4f9f335fedf74f1812dcfca", 513325}, {"resource.005", 0, "7d4ebcb745c0bf8fc42e4013f52ecd49", 1101812}, AD_LISTEND}, - Common::ES_ESP, Common::kPlatformPC, 0, GUIO1(GUIO_NOSPEECH) }, + Common::ES_ESP, Common::kPlatformPC, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Space Quest I 2.0 EGA DOS (6 x 3.5" disks) // Provided by ssburnout in bug report #3046805 @@ -3277,7 +3284,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.004", 0, "975c6e81194ae6b65e960a248129ecaa", 684119}, {"resource.005", 0, "13d96f7905637552c0647175ff816145", 695589}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO2(GUIO_NOSPEECH, GUIO_EGAUNDITHER) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Space Quest 3 - English Amiga (from www.back2roots.org) // SCI interpreter version 0.000.453 (just a guess) @@ -3288,7 +3295,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.003", 0, "ceeda7202b96e5c85ecaa88a40a540fc", 746496}, {"resource.004", 0, "ceeda7202b96e5c85ecaa88a40a540fc", 761984}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO2(GUIO_NOSPEECH, GUIO_EGAUNDITHER) }, + Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Space Quest 3 - German Amiga (also includes english language) // Executable scanning reports "1.004.006" @@ -3301,7 +3308,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.004", 0, "6d8f34090503ce937e7dbef6cb6cdb6a", 545053}, {"resource.005", 0, "6d8f34090503ce937e7dbef6cb6cdb6a", 687507}, AD_LISTEND}, - Common::DE_DEU, Common::kPlatformAmiga, ADGF_ADDENGLISH, GUIO2(GUIO_NOSPEECH, GUIO_EGAUNDITHER) }, + Common::DE_DEU, Common::kPlatformAmiga, ADGF_ADDENGLISH, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Space Quest 3 - English DOS Non-Interactive Demo // SCI interpreter version 0.000.453 @@ -3309,7 +3316,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "ec66ac2b1ce58b2575ba00b65058de1a", 612}, {"resource.001", 0, "ceeda7202b96e5c85ecaa88a40a540fc", 180245}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO2(GUIO_NOSPEECH, GUIO_EGAUNDITHER) }, + Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Space Quest 3 - English DOS (provided by richiefs in bug report #2670691) // SCI interpreter version 0.000.453 @@ -3319,7 +3326,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.002", 0, "ceeda7202b96e5c85ecaa88a40a540fc", 720244}, {"resource.003", 0, "ceeda7202b96e5c85ecaa88a40a540fc", 688367}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO2(GUIO_NOSPEECH, GUIO_EGAUNDITHER) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Space Quest 3 - English DOS (from the Space Quest Collection) // Executable scanning reports "0.000.685", VERSION file reports "1.018" @@ -3329,7 +3336,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.002", 0, "8b55c4875298f45ea5696a5ee8f6a7fe", 715777}, {"resource.003", 0, "8b55c4875298f45ea5696a5ee8f6a7fe", 703370}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO2(GUIO_NOSPEECH, GUIO_EGAUNDITHER) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Space Quest 3 - English DOS (from abevi, bug report #2612718) {"sq3", "", { @@ -3341,7 +3348,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.005", 0, "ceeda7202b96e5c85ecaa88a40a540fc", 328278}, {"resource.006", 0, "ceeda7202b96e5c85ecaa88a40a540fc", 356702}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO2(GUIO_NOSPEECH, GUIO_EGAUNDITHER) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Space Quest 3 - English Mac (from Fingolfin) {"sq3", "", { @@ -3350,7 +3357,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.002", 0, "0d8dfe42683b46f3131823233a91ce6a", 794072}, {"resource.003", 0, "0d8dfe42683b46f3131823233a91ce6a", 776536}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformMacintosh, 0, GUIO2(GUIO_NOSPEECH, GUIO_EGAUNDITHER) }, + Common::EN_ANY, Common::kPlatformMacintosh, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Space Quest 3 - German DOS (from Tobis87, also includes english language) // SCI interpreter version 0.000.453 (?) @@ -3364,7 +3371,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.006", 0, "9107c2aa5398e28b5c5406df13491f85", 320643}, {"resource.007", 0, "9107c2aa5398e28b5c5406df13491f85", 344287}, AD_LISTEND}, - Common::DE_DEU, Common::kPlatformPC, ADGF_ADDENGLISH, GUIO2(GUIO_NOSPEECH, GUIO_EGAUNDITHER) }, + Common::DE_DEU, Common::kPlatformPC, ADGF_ADDENGLISH, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Space Quest 3 v1.052 - German DOS (supplied by markcoolio in bug report #2723860, also includes english language) // Executable scanning reports "S.old.114" @@ -3374,7 +3381,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.002", 0, "9107c2aa5398e28b5c5406df13491f85", 596768}, {"resource.003", 0, "9107c2aa5398e28b5c5406df13491f85", 693573}, AD_LISTEND}, - Common::DE_DEU, Common::kPlatformPC, ADGF_ADDENGLISH, GUIO1(GUIO_NOSPEECH) }, + Common::DE_DEU, Common::kPlatformPC, ADGF_ADDENGLISH, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Space Quest 4 - English Amiga // Executable scanning reports "1.004.024" @@ -3389,7 +3396,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.005", 0, "3540d1cc84d674cf4b2c898b88a3b563", 790296}, {"resource.006", 0, "ade814bc4d56244c156d9e9bcfebbc11", 664085}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO1(GUIO_NOSPEECH) }, + Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Space Quest 4 - German Amiga (from www.back2roots.org, also includes english language) // SCI interpreter version 1.000.200 (just a guess) @@ -3403,7 +3410,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.005", 0, "10ee1709e6559c724676d058199b75b5", 818745}, {"resource.006", 0, "67fb188b191d88efe8414af6ea297b93", 672675}, AD_LISTEND}, - Common::DE_DEU, Common::kPlatformAmiga, ADGF_ADDENGLISH, GUIO1(GUIO_NOSPEECH) }, + Common::DE_DEU, Common::kPlatformAmiga, ADGF_ADDENGLISH, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Space Quest 4 - English DOS - THIS VERSION IS PIRATED/CRACKED AND REPACKAGED =DO NOT RE-ADD= // Executable scanning reports "1.000.753" @@ -3412,7 +3419,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "a18088c8aceb06025dbc945f29e02935", 5124}, {"resource.000", 0, "e1f46832cd2458796028e054a0466031", 5502009}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, ADGF_PIRATED, GUIO1(GUIO_NOSPEECH) }, + Common::EN_ANY, Common::kPlatformPC, ADGF_PIRATED, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Space Quest 4 - English DOS // Executable scanning reports "1.000.753" @@ -3421,7 +3428,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "71ccf4f82ac4efb588731acfb7bf2603", 5646}, {"resource.000", 0, "e1f46832cd2458796028e054a0466031", 933928}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO1(GUIO_NOSPEECH) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Space Quest 4 1.052 - English DOS Floppy (supplied by markcoolio in bug report #2723865) // Executable scanning reports "1.000.753" @@ -3435,7 +3442,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.004", 0, "ff9c87da3bc53473fdee8b9d3edbc93c", 1200631}, {"resource.005", 0, "e33019ac19f755ae33fbf49b4fc9066c", 1053294}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO1(GUIO_NOSPEECH) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Space Quest 4 1.000 - English DOS Floppy (from abevi, bug report #2612718) {"sq4", "", { @@ -3447,7 +3454,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.004", 0, "c06350184a490c10eb4585fff0aa3192", 1254368}, {"resource.005", 0, "b8d6efbd3235329bfe844c794097b2c9", 1098717}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO1(GUIO_NOSPEECH) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Space Quest IV DOS 1.060 EGA (6 x 3.5" disks) // Supplied by ssburnout in bug report #3046781 @@ -3460,7 +3467,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.004", 0, "9a673e33c3f6dd560b993ffed77eeb49", 534994}, {"resource.005", 0, "3c4841d0a3ebba4404af588c93620c22", 595465}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO2(GUIO_NOSPEECH, GUIO_EGAUNDITHER) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Space Quest 4 - German DOS (from Tobis87, also includes english language) // SCI interpreter version 1.000.200 (just a guess) @@ -3474,7 +3481,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.005", 0, "47ee647b5b12232d27e63cc627c25899", 1156765}, {"resource.006", 0, "dfb023e4e2a1e7a00fa18f9ede72a91b", 924059}, AD_LISTEND}, - Common::DE_DEU, Common::kPlatformPC, ADGF_ADDENGLISH, GUIO1(GUIO_NOSPEECH) }, + Common::DE_DEU, Common::kPlatformPC, ADGF_ADDENGLISH, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Space Quest 4 - Italian DOS Floppy (from glorifindel, also includes english language) // SCI interpreter version 1.000.200 (just a guess) @@ -3487,7 +3494,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.004", 0, "4277c61bed40a50dadc4b5a344520af2", 1251000}, {"resource.005", 0, "5f885abd335978e2fd4e5f886d7676c8", 1102880}, AD_LISTEND}, - Common::IT_ITA, Common::kPlatformPC, ADGF_ADDENGLISH, GUIO1(GUIO_NOSPEECH) }, + Common::IT_ITA, Common::kPlatformPC, ADGF_ADDENGLISH, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Space Quest 4 - Japanese PC-98 5.25" Floppy (also includes english language) // SCI interpreter version 1.000.1068 @@ -3497,7 +3504,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.001", 0, "454684e3a7a68cbca073945e50778447", 1187088}, {"resource.002", 0, "6dc668326cc22cb9e8bd8ca9e68d2a66", 1181249}, AD_LISTEND}, - Common::JA_JPN, Common::kPlatformPC98, ADGF_ADDENGLISH, GUIO2(GUIO_NOSPEECH, GUIO_NOASPECT) }, + Common::JA_JPN, Common::kPlatformPC98, ADGF_ADDENGLISH, GUIO5(GUIO_NOSPEECH, GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Space Quest 4 - Japanese PC-98 5.25" Floppy (also includes english language) // SCI interpreter version 1.000.1068 @@ -3507,7 +3514,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.001", 0, "454684e3a7a68cbca073945e50778447", 1187088}, {"resource.002", 0, "6dc668326cc22cb9e8bd8ca9e68d2a66", 1181249}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC98, ADGF_ADDENGLISH, GUIO2(GUIO_NOSPEECH, GUIO_NOASPECT) }, + Common::EN_ANY, Common::kPlatformPC98, ADGF_ADDENGLISH, GUIO5(GUIO_NOSPEECH, GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Space Quest 4 - English DOS CD (from the Space Quest Collection) // Executable scanning reports "1.001.064", VERSION file reports "1.0" @@ -3515,7 +3522,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "ed90a8e3ccc53af6633ff6ab58392bae", 7054}, {"resource.000", 0, "63247e3901ab8963d4eece73747832e0", 5157378}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, ADGF_CD, GUIO0() }, + Common::EN_ANY, Common::kPlatformPC, ADGF_CD, GUIO1(GAMEOPTION_SQ4_SILVER_CURSORS) }, // Space Quest 4 - English Windows CD (from the Space Quest Collection) // Executable scanning reports "1.001.064", VERSION file reports "1.0" @@ -3525,7 +3532,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "ed90a8e3ccc53af6633ff6ab58392bae", 7054}, {"resource.000", 0, "63247e3901ab8963d4eece73747832e0", 5157378}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformWindows, ADGF_CD, GUIO1(GUIO_MIDIGM) }, + Common::EN_ANY, Common::kPlatformWindows, ADGF_CD, GUIO5(GUIO_MIDIGM, GAMEOPTION_SQ4_SILVER_CURSORS, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Space Quest 4 - Spanish DOS CD (from jvprat, is still text only, not talkie, also includes english language) // Executable scanning reports "1.SQ4.057", VERSION file reports "1.000" @@ -3539,7 +3546,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.004", 0, "776fba81c110d1908776232cbe190e20", 1253752}, {"resource.005", 0, "55fae26c2a92f16ef72c1e216e827c0f", 1098328}, AD_LISTEND}, - Common::ES_ESP, Common::kPlatformPC, ADGF_ADDENGLISH, GUIO0() }, + Common::ES_ESP, Common::kPlatformPC, ADGF_ADDENGLISH, GUIO4(GAMEOPTION_SQ4_SILVER_CURSORS, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Space Quest 4 - Spanish DOS Floppy (from jvprat, also includes english language) // Executable scanning reports "1.SQ4.056", VERSION file reports "1.000" @@ -3551,7 +3558,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.002", 0, "74c62fa2146ff3b3b2ea2b3fb95b9af9", 1140801}, {"resource.003", 0, "42a307941edeb1a3be31daeb2e4be90b", 1088408}, AD_LISTEND}, - Common::ES_ESP, Common::kPlatformPC, ADGF_ADDENGLISH, GUIO1(GUIO_NOSPEECH) }, + Common::ES_ESP, Common::kPlatformPC, ADGF_ADDENGLISH, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Space Quest 4 1.000 - German DOS Floppy (supplied by markcoolio in bug report #2723862, also includes english language) // Executable scanning reports "1.SQ4.030" @@ -3565,7 +3572,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.004", 0, "c06350184a490c10eb4585fff0aa3192", 1254368}, {"resource.005", 0, "b8d6efbd3235329bfe844c794097b2c9", 1098717}, AD_LISTEND}, - Common::DE_DEU, Common::kPlatformPC, ADGF_ADDENGLISH, GUIO1(GUIO_NOSPEECH) }, + Common::DE_DEU, Common::kPlatformPC, ADGF_ADDENGLISH, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Space Quest 4 - English Macintosh // Executable scanning reports "x.yyy.zzz" @@ -3580,7 +3587,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.005", 0, "869d16cab6641c80b06f4dcee18f86bc", 1426228}, {"resource.006", 0, "91d23407bc0447a3722fbeb952d7edee", 1402451}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformMacintosh, 0, GUIO1(GUIO_NOSPEECH) }, + Common::EN_ANY, Common::kPlatformMacintosh, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Space Quest 4 - Russian DOS // Executable scanning reports "1.000.753", VERSION file reports "1.994" @@ -3593,7 +3600,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.004", 0, "2763fe4f0cb74df716ec8b0c464b0988", 1217428}, {"resource.005", 0, "d608713197c5ba1cd8c6ed46299c3069", 1057924}, AD_LISTEND}, - Common::RU_RUS, Common::kPlatformPC, 0, GUIO1(GUIO_NOSPEECH) }, + Common::RU_RUS, Common::kPlatformPC, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Space Quest 5 - English DOS (from the Space Quest Collection) // Executable scanning reports "1.001.068", VERSION file reports "1.04" @@ -3602,7 +3609,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.000", 0, "4147edc5045e6d62998018b5614c58ec", 5496486}, {"resource.msg", 0, "bb8ad78793c26bdb3f77498b1d6515a9", 125988}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO1(GUIO_NOSPEECH) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Space Quest 5 - English DOS - THIS IS THE UNOFFICIAL BETA VERSION, WHICH IS OBVIOUSLY PIRATED AND CONTAINS MANY BUGS // ffs. http://www.akril15.com/sr/sq5alt/sq5alt.html =DO NOT RE-ADD= @@ -3611,7 +3618,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "8bde0a9adb9a3e9aaa861826874c9834", 6473}, {"resource.000", 0, "f4a48705764544d7cc64a7bb22a610df", 6025184}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, ADGF_PIRATED, GUIO1(GUIO_NOSPEECH) }, + Common::EN_ANY, Common::kPlatformPC, ADGF_PIRATED, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Space Quest 5 v1.04 - German DOS (from Tobis87, updated information by markcool from bug reports #2723935 and #2724762) // SCI interpreter version 1.001.068 @@ -3620,7 +3627,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.000", 0, "4147edc5045e6d62998018b5614c58ec", 5496486}, {"resource.msg", 0, "7c71cfc36153cfe07b450423a51f7e68", 146282}, AD_LISTEND}, - Common::DE_DEU, Common::kPlatformPC, 0, GUIO1(GUIO_NOSPEECH) }, + Common::DE_DEU, Common::kPlatformPC, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Space Quest 5 v1.04 - French DOS (from Hkz, Included in Space Quest Collector's Edition, with chapters I-V) {"sq5", "", { @@ -3628,7 +3635,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.000", 0, "4147edc5045e6d62998018b5614c58ec", 5496486}, {"resource.msg", 0, "877c42380320eb1db7dad83ccd261214", 140374}, AD_LISTEND}, - Common::FR_FRA, Common::kPlatformPC, 0, GUIO1(GUIO_NOSPEECH) }, + Common::FR_FRA, Common::kPlatformPC, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Space Quest 5 - Italian DOS Floppy (from glorifindel) // SCI interpreter version 1.001.068 (just a guess) @@ -3636,7 +3643,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.000", 0, "5040026519f37199f3616fb1d4704dff", 6047170}, {"resource.map", 0, "5b09168baa2f6e2e22787429b2d72f54", 6492}, AD_LISTEND}, - Common::IT_ITA, Common::kPlatformPC, 0, GUIO1(GUIO_NOSPEECH) }, + Common::IT_ITA, Common::kPlatformPC, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Space Quest 5 - Spanish DOS Floppy (from mirir, bug report #3090664) {"sq5", "", { @@ -3644,7 +3651,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "5714a899033bdebf2d61ad333c8c6637", 6492}, {"resource.msg", 0, "46deca7ef9cf057f7d442df98c1a2ae2", 134612}, AD_LISTEND}, - Common::ES_ESP, Common::kPlatformPC, 0, GUIO1(GUIO_NOSPEECH) }, + Common::ES_ESP, Common::kPlatformPC, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Space Quest 5 - Russian DOS // Executable scanning reports "1.001.068", VERSION file reports "1.994" @@ -3653,7 +3660,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.000", 0, "6f9ed21e1001526b4137f6703ed476af", 6103778}, {"resource.msg", 0, "0a8931990cd2eac1691602391c68ab85", 147580}, AD_LISTEND}, - Common::RU_RUS, Common::kPlatformPC, 0, GUIO1(GUIO_NOSPEECH) }, + Common::RU_RUS, Common::kPlatformPC, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, #ifdef ENABLE_SCI32 // Space Quest 6 - English DOS/Win3.11 CD (from the Space Quest Collection) @@ -3662,7 +3669,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "6dddfa3a8f3a3a513ec9dfdfae955005", 10528}, {"resource.000", 0, "c4259ab7355aead07773397b1052827d", 41150806}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, ADGF_CD | ADGF_UNSTABLE, GUIO1(GUIO_NOASPECT) }, + Common::EN_ANY, Common::kPlatformPC, ADGF_CD | ADGF_UNSTABLE, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Space Quest 6 - English DOS/Win3.11 CD ver 1.11 (from FRG) // SCI interpreter version 2.100.002 (just a guess) @@ -3670,7 +3677,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "e0615d6e4e10e37ae42e6a2a95aaf145", 10528}, {"resource.000", 0, "c4259ab7355aead07773397b1052827d", 41150806}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, ADGF_CD | ADGF_UNSTABLE, GUIO1(GUIO_NOASPECT) }, + Common::EN_ANY, Common::kPlatformPC, ADGF_CD | ADGF_UNSTABLE, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Space Quest 6 - French DOS/Win3.11 CD (from French magazine Joystick - September 1997) // Executable scanning reports "2.100.002", VERSION file reports "1.0" @@ -3678,7 +3685,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "3c831625931d5079b73ae8c275f52c95", 10534}, {"resource.000", 0, "4195ca940f759424f62b90e262cc1737", 40932397}, AD_LISTEND}, - Common::FR_FRA, Common::kPlatformPC, ADGF_CD | ADGF_UNSTABLE, GUIO1(GUIO_NOASPECT) }, + Common::FR_FRA, Common::kPlatformPC, ADGF_CD | ADGF_UNSTABLE, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Space Quest 6 - German DOS (from Tobis87, updated info from markcoolio in bug report #2723884) // SCI interpreter version 2.100.002 (just a guess) @@ -3686,7 +3693,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "664d797415484f85c90b1b45aedc7686", 10534}, {"resource.000", 0, "ba87ba91e5bdabb4169dd0df75777722", 40933685}, AD_LISTEND}, - Common::DE_DEU, Common::kPlatformPC, ADGF_CD | ADGF_UNSTABLE, GUIO1(GUIO_NOASPECT) }, + Common::DE_DEU, Common::kPlatformPC, ADGF_CD | ADGF_UNSTABLE, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Space Quest 6 - English DOS/Win3.11 Interactive Demo (from FRG) // SCI interpreter version 2.100.002 (just a guess) @@ -3694,7 +3701,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "368f07b07433db3f819fa3fa0e5efee5", 2572}, {"resource.000", 0, "ab12724e078dea34b624e0d2a38dcd7c", 2272050}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO | ADGF_UNSTABLE, GUIO2(GUIO_NOSPEECH, GUIO_NOASPECT) }, + Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO | ADGF_UNSTABLE, GUIO5(GUIO_NOSPEECH, GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, #endif // ENABLE_SCI32 // The Island of Dr. Brain - English DOS CD (from jvprat) @@ -3703,7 +3710,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "2388efef8430b041b0f3b00b9050e4a2", 3281}, {"resource.000", 0, "b3acd9b9dd7fe53c4ee133ac9a1acfab", 2103560}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO0() }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO3(GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // The Island of Dr. Brain - English DOS (from Quietust) // Executable scanning reports "1.001.053", VERSION file reports "1.1 2.3.93" @@ -3711,7 +3718,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "3c07da06bdd1689f9d07af78fb94d0ec", 3101}, {"resource.000", 0, "ecc686e0034fb4d41de077ac7167b3cf", 1947866}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO1(GUIO_NOSPEECH) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // The Island of Dr. Brain - English DOS Non-Interactive Demo // SCI interpreter version 1.001.053 (just a guess) @@ -3719,7 +3726,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "a8e5ca8ed1996974afa59f4c45e06195", 986}, {"resource.000", 0, "b3acd9b9dd7fe53c4ee133ac9a1acfab", 586560}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO1(GUIO_NOSPEECH) }, + Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, #ifdef ENABLE_SCI32 // Torin's Passage - English Windows Interactive Demo @@ -3728,7 +3735,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resmap.000", 0, "9a3e172cde9963d0a969f26469318cec", 3403}, {"ressci.000", 0, "db3e290481c35c3224e9602e71e4a1f1", 5073868}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformWindows, ADGF_DEMO | ADGF_UNSTABLE, GUIO2(GUIO_NOSPEECH, GUIO_NOASPECT) }, + Common::EN_ANY, Common::kPlatformWindows, ADGF_DEMO | ADGF_UNSTABLE, GUIO5(GUIO_NOSPEECH, GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Torin's Passage - English Windows // SCI interpreter version 2.100.002 (just a guess) @@ -3736,7 +3743,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resmap.000", 0, "bb3b0b22ff08df54fbe2d06263409be6", 9799}, {"ressci.000", 0, "693a259d346c9360f4a0c11fdaae430a", 55973887}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformWindows, ADGF_UNSTABLE, GUIO2(GUIO_NOSPEECH, GUIO_NOASPECT) }, + Common::EN_ANY, Common::kPlatformWindows, ADGF_UNSTABLE, GUIO5(GUIO_NOSPEECH, GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Torin's Passage - Spanish Windows (from jvprat) // Executable scanning reports "2.100.002", VERSION file reports "1.0" @@ -3745,7 +3752,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"ressci.000", 0, "693a259d346c9360f4a0c11fdaae430a", 55973887}, // TODO: depend on one of the patches? AD_LISTEND}, - Common::ES_ESP, Common::kPlatformWindows, ADGF_UNSTABLE, GUIO2(GUIO_NOSPEECH, GUIO_NOASPECT) }, + Common::ES_ESP, Common::kPlatformWindows, ADGF_UNSTABLE, GUIO5(GUIO_NOSPEECH, GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Torin's Passage - French Windows // SCI interpreter version 2.100.002 (just a guess) @@ -3753,7 +3760,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resmap.000", 0, "bb3b0b22ff08df54fbe2d06263409be6", 9799}, {"ressci.000", 0, "693a259d346c9360f4a0c11fdaae430a", 55973887}, AD_LISTEND}, - Common::FR_FRA, Common::kPlatformWindows, ADGF_UNSTABLE, GUIO2(GUIO_NOSPEECH, GUIO_NOASPECT) }, + Common::FR_FRA, Common::kPlatformWindows, ADGF_UNSTABLE, GUIO5(GUIO_NOSPEECH, GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Torin's Passage - German Windows // SCI interpreter version 2.100.002 (just a guess) @@ -3761,7 +3768,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resmap.000", 0, "bb3b0b22ff08df54fbe2d06263409be6", 9799}, {"ressci.000", 0, "693a259d346c9360f4a0c11fdaae430a", 55973887}, AD_LISTEND}, - Common::DE_DEU, Common::kPlatformWindows, ADGF_UNSTABLE, GUIO2(GUIO_NOSPEECH, GUIO_NOASPECT) }, + Common::DE_DEU, Common::kPlatformWindows, ADGF_UNSTABLE, GUIO5(GUIO_NOSPEECH, GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Torin's Passage - Italian Windows CD (from glorifindel) // SCI interpreter version 2.100.002 (just a guess) @@ -3769,7 +3776,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resmap.000", 0, "bb3b0b22ff08df54fbe2d06263409be6", 9799}, {"ressci.000", 0, "693a259d346c9360f4a0c11fdaae430a", 55973887}, AD_LISTEND}, - Common::IT_ITA, Common::kPlatformWindows, ADGF_UNSTABLE, GUIO1(GUIO_NOASPECT) }, + Common::IT_ITA, Common::kPlatformWindows, ADGF_UNSTABLE, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, #endif // ENABLE_SCI32 // SCI Fanmade Games -- cgit v1.2.3 From 4516b5ea24e6c0056984a65fe4fff33553931487 Mon Sep 17 00:00:00 2001 From: Matthew Hoops Date: Sat, 2 Jul 2011 21:02:58 -0400 Subject: GRAPHICS: Convert PictDecoder to the ImageDecoder API --- engines/sci/graphics/maciconbar.cpp | 18 ++++++++++-------- engines/sci/graphics/maciconbar.h | 2 +- 2 files changed, 11 insertions(+), 9 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/graphics/maciconbar.cpp b/engines/sci/graphics/maciconbar.cpp index bff145ad53..7ecba5a24d 100644 --- a/engines/sci/graphics/maciconbar.cpp +++ b/engines/sci/graphics/maciconbar.cpp @@ -31,8 +31,8 @@ #include "common/memstream.h" #include "common/system.h" -#include "graphics/pict.h" #include "graphics/surface.h" +#include "graphics/decoders/pict.h" namespace Sci { @@ -201,18 +201,20 @@ void GfxMacIconBar::setInventoryIcon(int16 icon) { } Graphics::Surface *GfxMacIconBar::loadPict(ResourceId id) { - Graphics::PictDecoder pictDecoder(Graphics::PixelFormat::createFormatCLUT8()); + Graphics::PICTDecoder pictDecoder; Resource *res = g_sci->getResMan()->findResource(id, false); if (!res || res->size == 0) return 0; - byte palette[256 * 3]; - Common::SeekableReadStream *stream = new Common::MemoryReadStream(res->data, res->size); - Graphics::Surface *surface = pictDecoder.decodeImage(stream, palette); - remapColors(surface, palette); + Common::MemoryReadStream stream(res->data, res->size); + if (!pictDecoder.loadStream(stream)) + return 0; + + Graphics::Surface *surface = new Graphics::Surface(); + surface->copyFrom(*pictDecoder.getSurface()); + remapColors(surface, pictDecoder.getPalette()); - delete stream; return surface; } @@ -221,7 +223,7 @@ Graphics::Surface *GfxMacIconBar::createImage(uint32 iconIndex, bool isSelected) return loadPict(ResourceId(type, iconIndex + 1)); } -void GfxMacIconBar::remapColors(Graphics::Surface *surf, byte *palette) { +void GfxMacIconBar::remapColors(Graphics::Surface *surf, const byte *palette) { byte *pixels = (byte *)surf->pixels; // Remap to the screen palette diff --git a/engines/sci/graphics/maciconbar.h b/engines/sci/graphics/maciconbar.h index 43de37a904..eca10b804c 100644 --- a/engines/sci/graphics/maciconbar.h +++ b/engines/sci/graphics/maciconbar.h @@ -61,7 +61,7 @@ private: Graphics::Surface *loadPict(ResourceId id); Graphics::Surface *createImage(uint32 iconIndex, bool isSelected); - void remapColors(Graphics::Surface *surf, byte *palette); + void remapColors(Graphics::Surface *surf, const byte *palette); void drawIcon(uint16 index, bool selected); void drawSelectedImage(uint16 index); -- cgit v1.2.3 From 536a7e407f97d7f5ed6db563424f1a7b576688b1 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sun, 25 Mar 2012 16:40:49 +0300 Subject: SCI: Hook up the digital SFX and CD audio options The relevant code wasn't added in the newer commits - this was an oversight from my part --- engines/sci/engine/features.cpp | 3 +++ engines/sci/sound/soundcmd.cpp | 13 ++++--------- 2 files changed, 7 insertions(+), 9 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/engine/features.cpp b/engines/sci/engine/features.cpp index b3cfee873c..a284c319c0 100644 --- a/engines/sci/engine/features.cpp +++ b/engines/sci/engine/features.cpp @@ -26,6 +26,7 @@ #include "sci/engine/selector.h" #include "sci/engine/vm.h" +#include "common/config-manager.h" #include "common/file.h" namespace Sci { @@ -42,6 +43,8 @@ GameFeatures::GameFeatures(SegManager *segMan, Kernel *kernel) : _segMan(segMan) _sci2StringFunctionType = kSci2StringFunctionUninitialized; #endif _usesCdTrack = Common::File::exists("cdaudio.map"); + if (ConfMan.hasKey("use_cdaudio") && !ConfMan.getBool("use_cdaudio")) + _usesCdTrack = false; } reg_t GameFeatures::getDetectionAddr(const Common::String &objName, Selector slc, int methodNum) { diff --git a/engines/sci/sound/soundcmd.cpp b/engines/sci/sound/soundcmd.cpp index b8be898abc..8481f10171 100644 --- a/engines/sci/sound/soundcmd.cpp +++ b/engines/sci/sound/soundcmd.cpp @@ -32,14 +32,11 @@ namespace Sci { -//#define ENABLE_SFX_TYPE_SELECTION - SoundCommandParser::SoundCommandParser(ResourceManager *resMan, SegManager *segMan, Kernel *kernel, AudioPlayer *audio, SciVersion soundVersion) : _resMan(resMan), _segMan(segMan), _kernel(kernel), _audio(audio), _soundVersion(soundVersion) { -#ifdef ENABLE_SFX_TYPE_SELECTION // Check if the user wants synthesized or digital sound effects in SCI1.1 - // games based on the multi_midi config setting + // games based on the prefer_digitalsfx config setting // In SCI2 and later games, this check should always be true - there was // always only one version of each sound effect or digital music track @@ -48,11 +45,9 @@ SoundCommandParser::SoundCommandParser(ResourceManager *resMan, SegManager *segM // The GK1 demo (very late SCI1.1) does the same thing // TODO: Check the QFG4 demo - _useDigitalSFX = (getSciVersion() >= SCI_VERSION_2 || g_sci->getGameId() == GID_GK1 || ConfMan.getBool("multi_midi")); -#else - // Always prefer digital sound effects - _useDigitalSFX = true; -#endif + // If the prefer_digitalsfx key is missing, default to enable digital SFX + bool preferDigitalSfx = !ConfMan.hasKey("prefer_digitalsfx") || ConfMan.getBool("prefer_digitalsfx"); + _useDigitalSFX = (getSciVersion() >= SCI_VERSION_2 || g_sci->getGameId() == GID_GK1 || preferDigitalSfx); _music = new SciMusic(_soundVersion, _useDigitalSFX); _music->init(); -- cgit v1.2.3 From 1938d95c4e17bd50f96c75fa7ecb826b4e83f65b Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sun, 25 Mar 2012 17:48:38 +0300 Subject: SCI: Rename the sci_originalsavedload option to originalsaveload This changes its naming to be like the rest of the game options --- engines/sci/detection.cpp | 2 +- engines/sci/sci.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/detection.cpp b/engines/sci/detection.cpp index 5cbe3633c7..35666b2bf4 100644 --- a/engines/sci/detection.cpp +++ b/engines/sci/detection.cpp @@ -379,7 +379,7 @@ static const ADExtraGuiOptionsMap optionsList[] = { { _s("Use original save/load screens"), _s("Use the original save/load screens, instead of the ScummVM ones"), - "sci_originalsaveload", + "originalsaveload", false } }, diff --git a/engines/sci/sci.cpp b/engines/sci/sci.cpp index 4ae55cbcba..9b0ee6924b 100644 --- a/engines/sci/sci.cpp +++ b/engines/sci/sci.cpp @@ -191,7 +191,7 @@ extern void showScummVMDialog(const Common::String &message); Common::Error SciEngine::run() { // Assign default values to the config manager, in case settings are missing - ConfMan.registerDefault("sci_originalsaveload", "false"); + ConfMan.registerDefault("originalsaveload", "false"); ConfMan.registerDefault("native_fb01", "false"); ConfMan.registerDefault("windows_cursors", "false"); // Windows cursors for KQ6 Windows ConfMan.registerDefault("silver_cursors", "false"); // Silver cursors for SQ4 CD @@ -492,7 +492,7 @@ void SciEngine::patchGameSaveRestore() { break; } - if (ConfMan.getBool("sci_originalsaveload")) + if (ConfMan.getBool("originalsaveload")) return; uint16 kernelNamesSize = _kernel->getKernelNamesSize(); -- cgit v1.2.3 From 346c1fe46120ef89348971a55b0181ca37d0582b Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sun, 25 Mar 2012 18:51:23 +0300 Subject: GUI: Change the undithering checkbox to be an engine-specific option --- engines/sci/detection.cpp | 10 +++ engines/sci/detection_tables.h | 179 +++++++++++++++++++++-------------------- 2 files changed, 100 insertions(+), 89 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/detection.cpp b/engines/sci/detection.cpp index 35666b2bf4..78df3065b2 100644 --- a/engines/sci/detection.cpp +++ b/engines/sci/detection.cpp @@ -364,6 +364,16 @@ Common::String convertSierraGameId(Common::String sierraId, uint32 *gameFlags, R #include "sci/detection_tables.h" static const ADExtraGuiOptionsMap optionsList[] = { + { + GAMEOPTION_EGA_UNDITHER, + { + _s("EGA undithering"), + _s("Enable undithering in EGA games"), + "disable_dithering", + false + } + }, + { GAMEOPTION_PREFER_DIGITAL_SFX, { diff --git a/engines/sci/detection_tables.h b/engines/sci/detection_tables.h index 7dd628f6b5..d741bb801f 100644 --- a/engines/sci/detection_tables.h +++ b/engines/sci/detection_tables.h @@ -28,6 +28,7 @@ namespace Sci { #define GAMEOPTION_JONES_CDAUDIO GUIO_GAMEOPTIONS4 #define GAMEOPTION_KQ6_WINDOWS_CURSORS GUIO_GAMEOPTIONS5 #define GAMEOPTION_SQ4_SILVER_CURSORS GUIO_GAMEOPTIONS6 +#define GAMEOPTION_EGA_UNDITHER GUIO_GAMEOPTIONS7 // SCI3 games have a different script format (in CSC files) and are currently unsupported #define ENABLE_SCI3_GAMES @@ -49,7 +50,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "f3d1be7752d30ba60614533d531e2e98", 474}, {"resource.001", 0, "6fd05926c2199af0af6f72f90d0d7260", 126895}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Castle of Dr. Brain - English Amiga (from www.back2roots.org) // Executable scanning reports "1.005.000" @@ -105,7 +106,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.005", 0, "8a5ed3ba96e2eaf18e36fedfaab89419", 297838}, {"resource.006", 0, "dceed92e709cad1bd9582809a235b0a0", 266682}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Castle of Dr. Brain - English DOS 3.5" Floppy EGA (from nozomi77, bug report #3405307) {"castlebrain", "EGA", { @@ -115,7 +116,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.002", 0, "de2f182529efaad2c4b510b452ab77ac", 633662}, {"resource.003", 0, "38b4b37febc6b4f5061c461a283df148", 430388}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Castle of Dr. Brain - English DOS Floppy (from jvprat) // Executable scanning reports "1.000.044", Floppy label reports "1.0, 10.30.91", VERSION file reports "1.000" @@ -167,7 +168,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "39485580d34a72997f3d5b3aba4d24f1", 426}, {"resource.001", 0, "11391434f41c834090d7a1e9488ce936", 129739}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Christmas Card 1990: The Seasoned Professional - English DOS (16 Colors) // SCI interpreter version 1.000.172 @@ -205,7 +206,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.004", 0, "8613c45fc771d658e5a505b9a4a54f31", 713382}, {"resource.005", 0, "605b67a9ef199a9bb015745e7c004cf4", 478384}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Codename: Iceman - English DOS Non-Interactive Demo // Executable scanning reports "0.000.685" @@ -213,7 +214,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "782974f29d8a824782d2d4aea39964e3", 1056}, {"resource.001", 0, "d4b75e280d1c3a97cfef1b0bebff387c", 573647}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Codename: Iceman - English DOS (from jvprat) // Executable scanning reports "0.000.685", Floppy label reports "1.033, 6.8.90", VERSION file reports "1.033" @@ -226,7 +227,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.003", 0, "d97a96f1ab91b41cf46a02cc89b0a04e", 624303}, {"resource.004", 0, "8613c45fc771d658e5a505b9a4a54f31", 670883}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Codename: Iceman - English DOS (from FRG) // SCI interpreter version 0.000.668 @@ -238,7 +239,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.003", 0, "dc7c5280e7acfaffe6ef2a6c963c5f94", 622118}, {"resource.004", 0, "64f342463f6f35ba71b3509ef696ae3f", 669188}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Codename: Iceman - English DOS (supplied by ssburnout in bug report #3049193) // 1.022 9x5.25" (label: Int#0.000.668) @@ -253,7 +254,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.006", 0, "08050329aa113a9f14ed99cbfe3536ec", 232942}, {"resource.007", 0, "64f342463f6f35ba71b3509ef696ae3f", 267811}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Codename: Iceman - English DOS 1.023 (from abevi, bug report #2612718) {"iceman", "", { @@ -282,7 +283,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.005", 0, "c6e551bdc24f0acc193159038d4ca767", 605882}, {"resource.006", 0, "8f880a536908ab496bbc552f7f5c3738", 585255}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Conquests of Camelot - English DOS Non-Interactive Demo // SCI interpreter version 0.000.668 @@ -290,7 +291,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "f4cd75c15be75e04cdca3acda2c0b0ea", 468}, {"resource.001", 0, "4930708722f34bfbaa4945fb08f55f61", 232523}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Conquests of Camelot - English DOS (from jvprat) // Executable scanning reports "0.000.685", Floppy label reports "1.001, 0.000.685", VERSION file reports "1.001.000" @@ -302,7 +303,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.003", 0, "8e1a3a8c588007404b532b8dfacc1460", 723712}, {"resource.004", 0, "8e1a3a8c588007404b532b8dfacc1460", 729143}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Conquests of Camelot - English DOS // SCI interpreter version 0.000.685 @@ -316,7 +317,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.006", 0, "8e1a3a8c588007404b532b8dfacc1460", 332446}, {"resource.007", 0, "8e1a3a8c588007404b532b8dfacc1460", 358182}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Conquests of the Longbow - English Amiga (from www.back2roots.org) // Executable scanning reports "1.005.001" @@ -385,7 +386,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.004", 0, "b7bb35c027bb424ecefcd122768e5e60", 705631}, {"resource.005", 0, "58942b1aa6d6ffeb66e9f8897fd4435f", 469243}, {"resource.006", 0, "8c767b3939add63d11274065e46aad04", 713158}, - AD_LISTEND}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + AD_LISTEND}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Conquests of the Longbow DOS 1.0 EGA (4 x 5.25" disks) // Provided by ssburnout in bug report #3046802 @@ -395,7 +396,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.001", 0, "76c729e563809170e6cc8b2f3f6cf0a4", 1196133}, {"resource.002", 0, "8c767b3939add63d11274065e46aad04", 1152478}, {"resource.003", 0, "7025b87e735b1df3f0e9488a621f4333", 1171439}, - AD_LISTEND}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + AD_LISTEND}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Conquests of the Longbow - English DOS Non-Interactive Demo // SCI interpreter version 1.000.510 @@ -623,7 +624,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "7ee6859ef74314f6d91938c3595348a9", 282}, {"resource.001", 0, "f1e680095424e31f7fae1255d36bacba", 40692}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Gabriel Knight - English DOS CD Demo // SCI interpreter version 1.001.092 @@ -815,7 +816,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.002", 0, "e0dd44069a62a463fd124974b915f10d", 342309}, {"resource.003", 0, "e0dd44069a62a463fd124974b915f10d", 328912}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Hoyle 1 - English DOS (supplied by merkur in bug report #2719227) // SCI interpreter version 0.000.530 @@ -823,14 +824,14 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "1034a218943d12f1f36e753fa10c95b8", 4386}, {"resource.001", 0, "e0dd44069a62a463fd124974b915f10d", 518308}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Hoyle 1 3.5' - English DOS (supplied by eddydrama in bug report #3052366 and dinnerx in bug report #3090841) {"hoyle1", "", { {"resource.map", 0, "0af9a3dcd72a091960de070432e1f524", 4386}, {"resource.001", 0, "e0dd44069a62a463fd124974b915f10d", 518127}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, #if 0 // TODO: unknown if these files are corrupt // Hoyle 1 - English Amiga (from www.back2roots.org) @@ -850,7 +851,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.001", 0, "8f2dd70abe01112eca464cda818b5eb6", 98138}, {"resource.002", 0, "8f2dd70abe01112eca464cda818b5eb6", 196631}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Hoyle 2 - English DOS (supplied by ssburnout in bug report #3049193) // 1.000.011 1x3.5" (label:Int#6.21.90) @@ -858,7 +859,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "db0ba08b953e9904a4960ad99cd29c20", 1356}, {"resource.001", 0, "8f2dd70abe01112eca464cda818b5eb6", 216315}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Hoyle 2 - English Amiga (from www.back2roots.org) // Executable scanning reports "1.002.032" @@ -925,7 +926,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.000", 0, "6ef28cac094dcd97fdb461662ead6f92", 319905}, {"resource.001", 0, "0a98a268ee99b92c233a0d7187c1f0fa", 526438}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Hoyle 4 (Hoyle Classic Card Games) - English DOS Demo {"hoyle4", "Demo", { @@ -966,14 +967,14 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.001", 0, "bac3ec6cb3e3920984ab0f32becf5163", 202105}, {"resource.002", 0, "b86daa3ba2784d1502da881eedb80d9b", 341771}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Jones in the Fast Lane EGA - English DOS (supplied by EddyDrama in bug report #3038761) {"jones", "EGA", { {"resource.map", 0, "8e92cf319180cc8b5b87b2ce93a4fe22", 1602}, {"resource.001", 0, "bac3ec6cb3e3920984ab0f32becf5163", 511528}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Jones in the Fast Lane VGA - English DOS // SCI interpreter version 1.000.172 @@ -1026,7 +1027,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "59b13619078bd47011421468959ee5d4", 954}, {"resource.001", 0, "4cfb9040db152868f7cb6a1e8151c910", 296555}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // King's Quest 1 SCI Remake - English DOS (from the King's Quest Collection) // Executable scanning reports "S.old.010", VERSION file reports "1.000.051" @@ -1037,7 +1038,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.002", 0, "fed9e0072ffd511d248674e60dee2099", 714062}, {"resource.003", 0, "fed9e0072ffd511d248674e60dee2099", 717478}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // King's Quest 1 SCI Remake - English DOS (supplied by ssburnout in bug report #3049193) // 1.000.051 9x5.25" (label: INT#9.19.90) @@ -1064,7 +1065,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.003", 0, "fd16c9c223f7dc5b65f06447615224ff", 683016}, {"resource.004", 0, "3fac034c7d130e055d05bc43a1f8d5f8", 549993}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // King's Quest 4 - English DOS Non-Interactive Demo // Executable scanning reports "0.000.494" @@ -1072,7 +1073,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "992ac7cc31d3717fe53818a9bb6d1dae", 594}, {"resource.001", 0, "143e1c14f15ad0fbfc714f648a65f661", 205330}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // King's Quest 4 - English DOS (original boxed release, 3 1/2" disks) // SCI interpreter version 0.000.247 @@ -1083,7 +1084,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.003", 0, "851a62d00972dc4002f472cc0d84e71d", 683145}, {"resource.004", 0, "851a62d00972dc4002f472cc0d84e71d", 649441}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // King's Quest 4 - English DOS (from the King's Quest Collection) // Executable scanning reports "0.000.502" @@ -1095,7 +1096,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.003", 0, "77615c595388acf3d1df8e107bfb6b52", 707591}, {"resource.004", 0, "77615c595388acf3d1df8e107bfb6b52", 479562}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // King's Quest 4 - English DOS (supplied by ssburnout in bug report #3049193) // 1.006.003 8x5.25" (label: Int.#0.000.502) @@ -1109,7 +1110,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.006", 0, "6db7de6f93c6ea62dca78abee677f8c0", 324789}, {"resource.007", 0, "6db7de6f93c6ea62dca78abee677f8c0", 334441}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // King's Quest 4 - English DOS // SCI interpreter version 0.000.274 @@ -1123,7 +1124,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.006", 0, "851a62d00972dc4002f472cc0d84e71d", 333777}, {"resource.007", 0, "851a62d00972dc4002f472cc0d84e71d", 341038}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // King's Quest 4 - English DOS // SCI interpreter version 0.000.253 @@ -1137,7 +1138,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.006", 0, "0c8566848a76eea19a6d6220914030a7", 337288}, {"resource.007", 0, "0c8566848a76eea19a6d6220914030a7", 343882}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // King's Quest 4 - English Atari ST (double-sided diskettes) // Game version 1.003.006 (January 12, 1989) @@ -1150,7 +1151,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.003", 0, "a3cdb4848fb859fdd302976fff56490f", 705074}, {"resource.004", 0, "a3cdb4848fb859fdd302976fff56490f", 478366}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformAtariST, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + Common::EN_ANY, Common::kPlatformAtariST, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // King's Quest 5 - English Amiga (from www.back2roots.org) // Executable scanning reports "1.004.018" @@ -1266,7 +1267,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.006", 0, "698c698570cde9015e4d51eb8d2e9db1", 666527}, {"resource.007", 0, "703d8df30e89541af337d7706540d5c4", 541743}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // King's Quest 5 EGA 1.2M disk version (from LordHoto) // VERSION file reports "0.000.055" @@ -1278,7 +1279,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "53206afb4fd73871a484e83acab80f31", 7608}, {"resource.004", 0, "83568edf7fde18b3eed988bc5d22ceb1", 1188053}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // King's Quest 5 EGA (supplied by omer_mor in bug report #3035421) // VERSION file reports "0.000.062" @@ -1293,7 +1294,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.006", 0, "698c698570cde9015e4d51eb8d2e9db1", 666541}, {"resource.007", 0, "703d8df30e89541af337d7706540d5c4", 541762}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // King's Quest V DOS 0.000.062 EGA (5 x 5.25" disks) // Supplied by ssburnout in bug report #3046780 @@ -1305,7 +1306,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.003", 0, "3cca5b2dae8afe94532edfdc98d7edbe", 1092325}, {"resource.004", 0, "8e5c1bc4d738cf7316ff506f59d265e2", 1187803}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // King's Quest 5 - German DOS Floppy (supplied by markcoolio in bug report #2727101, also includes english language) // SCI interpreter version 1.000.060 @@ -1555,7 +1556,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.004", 0, "aa553977f7e5804081de293800d3bcce", 695067}, {"resource.005", 0, "bfd870d51dc97729f0914095f58e6957", 676881}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Laura Bow - English Atari ST (from jvprat) // Executable scanning reports "1.002.030", Floppy label reports "1.000.062, 9.23.90" @@ -1567,7 +1568,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.003", 0, "e45c888d9c7c04aec0a20e9f820b79ff", 667365}, {"resource.004", 0, "e45c888d9c7c04aec0a20e9f820b79ff", 683737}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformAtariST, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + Common::EN_ANY, Common::kPlatformAtariST, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Laura Bow - English DOS Non-Interactive Demo // Executable scanning reports "x.yyy.zzz" @@ -1575,7 +1576,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "e625726268ff4e123ada11f31f0249f3", 768}, {"resource.001", 0, "0c8912290af0890f8d95faeb4ddb2d68", 333031}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Laura Bow - English DOS 3.5" Floppy (from "The Roberta Williams Anthology"/1996) // SCI interpreter version 0.000.631 @@ -1586,7 +1587,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.003", 0, "e45c888d9c7c04aec0a20e9f820b79ff", 667468}, {"resource.004", 0, "e45c888d9c7c04aec0a20e9f820b79ff", 683807}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Laura Bow - English DOS (from FRG) // SCI interpreter version 0.000.631 @@ -1600,7 +1601,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.006", 0, "e45c888d9c7c04aec0a20e9f820b79ff", 328390}, {"resource.007", 0, "e45c888d9c7c04aec0a20e9f820b79ff", 317687}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Laura Bow 2 - English DOS Non-Interactive Demo (from FRG) // Executable scanning reports "x.yyy.zzz" @@ -1664,7 +1665,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.002", 0, "24c958bc922b07f91e25e8c93aa01fcf", 491230}, {"resource.003", 0, "685cd6c1e05a695ab1e0db826337ee2a", 553279}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, #if 0 // The resource.002 file, contained in disk 3, is broken in this version @@ -1764,7 +1765,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.003", 0, "a0d4a625311d307257da7fc43d00459d", 570356}, {"resource.004", 0, "a0d4a625311d307257da7fc43d00459d", 717844}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Larry 2 - English DOS Non-Interactive Demo // Executable scanning reports "x.yyy.zzz" @@ -1773,7 +1774,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "03dba704bb77da55a91ad27b5a3cac09", 528}, {"resource.001", 0, "9f5520f0297206928df0b0b36493cd33", 127532}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Larry 2 - English DOS // SCI interpreter version 0.000.409 @@ -1786,7 +1787,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.005", 0, "4a24443a25e2b1492462a52809605dc2", 277732}, {"resource.006", 0, "4a24443a25e2b1492462a52809605dc2", 345683}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Larry 2 - English DOS // SCI interpreter version 0.000.343 @@ -1801,7 +1802,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { //{"resource.006", 0, "96033f57accfca903750413fd09193c8", 345818}, {"resource.006", 0, "96033f57accfca903750413fd09193c8", -1}, // 345818 or 208739 AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Larry 2 - English DOS (supplied by ssburnout in bug report #3049193) // 1.000.011 3x3.5" (label: Int. #0.000.343) @@ -1811,7 +1812,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.002", 0, "96033f57accfca903750413fd09193c8", 407014}, {"resource.003", 0, "96033f57accfca903750413fd09193c8", 592834}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Larry 2 - English DOS (supplied by ssburnout in bug report #3049193) // 1.002.000 3x3.5" (label: INT#0.000.409) @@ -1821,7 +1822,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.002", 0, "4a24443a25e2b1492462a52809605dc2", 406935}, {"resource.003", 0, "4a24443a25e2b1492462a52809605dc2", 592533}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Larry 3 - English Amiga (from www.back2roots.org) // Executable scanning reports "1.002.032" @@ -1846,7 +1847,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.003", 0, "f18441027154292836b973c655fa3175", 506807}, {"resource.004", 0, "f18441027154292836b973c655fa3175", 513651}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Larry 3 - English DOS (supplied by ssburnout in bug report #3049193) // 1.021 8x5.25" (label: Int#5.15.90) @@ -1860,7 +1861,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.006", 0, "f18441027154292836b973c655fa3175", 282649}, {"resource.007", 0, "f18441027154292836b973c655fa3175", 257178}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Larry 3 - English DOS // SCI interpreter version 0.000.572 @@ -1874,7 +1875,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.006", 0, "f18441027154292836b973c655fa3175", 282465}, {"resource.007", 0, "f18441027154292836b973c655fa3175", 257174}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Larry 3 - English DOS Non-Interactive Demo // SCI interpreter version 0.000.530 @@ -1883,7 +1884,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.001", 0, "f773d79b93dfd4052ec8c1cc64c1e6ab", 76525}, {"resource.002", 0, "f773d79b93dfd4052ec8c1cc64c1e6ab", 268299}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Larry 3 - German DOS (from Tobis87, updated info from markcoolio in bug report #2723832, also includes english language) // Executable scanning reports "S.old.123" @@ -1895,7 +1896,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.003", 0, "3827a9b17b926e12dcc336860f50612a", 587036}, {"resource.004", 0, "3827a9b17b926e12dcc336860f50612a", 691932}, AD_LISTEND}, - Common::DE_DEU, Common::kPlatformPC, ADGF_ADDENGLISH, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + Common::DE_DEU, Common::kPlatformPC, ADGF_ADDENGLISH, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Larry 3 - French DOS (provided by richiefs in bug report #2670691, also includes english language) // Executable scanning reports "S.old.123" @@ -1907,7 +1908,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.003", 0, "65f1bdaa20f6d0470e9d969f22473873", 586921}, {"resource.004", 0, "65f1bdaa20f6d0470e9d969f22473873", 690826}, AD_LISTEND}, - Common::FR_FRA, Common::kPlatformPC, ADGF_ADDENGLISH, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + Common::FR_FRA, Common::kPlatformPC, ADGF_ADDENGLISH, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Larry 3 1.050 Fr/En (9 x 5.25" disks) // Provided by ssburnout in bug report #3046779 @@ -2059,7 +2060,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.006", 0, "f6046a8445422f17d40b1b10ab21ebf3", 568551}, {"resource.007", 0, "640ee65595d40372ef95462f2c1ae28a", 593429}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Larry 5 EGA // Supplied by omer_mor in bug report #3049771 @@ -2070,7 +2071,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.002", 0, "5a55af4e40728b1a8103dc47ad2afa8d", 1100539}, {"resource.003", 0, "16f4d8fb1b526125edaca4fc6cbb7530", 1064563}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Larry 6 - English DOS (from spookypeanut) // SCI interpreter version 1.001.113 @@ -2280,7 +2281,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.003", 0, "509b2467ba779100d5933ed51a9ae32f", 560255}, {"resource.004", 0, "93afc85d5ffa60ea555d6cc336d22c03", 651109}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Mixed-Up Fairy Tales v1.000 - English DOS (supplied by markcoolio in bug report #2723791) // Executable scanning reports "1.000.145" @@ -2321,7 +2322,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.001", 0, "d893892d62b3f061357291d66775e360", 239906}, {"resource.002", 0, "d893892d62b3f061357291d66775e360", 719398}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Mixed-Up Mother Goose - English DOS Floppy EGA (supplied by ssburnout in bug report #3049193) // 1.011 5x5.25" (label: Int#8.2.90) @@ -2334,7 +2335,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.004", 0, "dbbc22f124533ce308bc386b08956326", 146251}, {"resource.005", 0, "2ba5348e7fad641b9c4c7ff7c7cf4e68", 110979}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Mixed-Up Mother Goose v2.000 - English DOS Floppy (supplied by markcoolio in bug report #2723795) // Executable scanning reports "1.001.031" @@ -2534,7 +2535,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.002", 0, "499737c21a28ac026e11ab817100d610", 511099}, {"resource.003", 0, "e008f5d6e2a7c4d4a0da0173e4fa8f8b", 553970}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Police Quest 2 - English DOS Non-Interactive Demo // Executable scanning reports "0.000.413" @@ -2542,7 +2543,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "8b77d0d4650c2052b356cece28294b58", 576}, {"resource.001", 0, "376ef6d6eaaeed66e1424bd219c4b9ab", 215398}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Police Quest 2 - English DOS (provided by richiefs in bug report #2670691) // SCI interpreter version 0.000.395 @@ -2555,7 +2556,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.005", 0, "77f02def3094af804fd2371db25b7100", 349899}, {"resource.006", 0, "77f02def3094af804fd2371db25b7100", 354991}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Police Quest 2 - English DOS (from the Police Quest Collection) // Executable scanning reports "0.000.490" @@ -2565,7 +2566,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.002", 0, "77f02def3094af804fd2371db25b7100", 546000}, {"resource.003", 0, "77f02def3094af804fd2371db25b7100", 591851}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Police Quest 2 - English DOS (from FRG) // SCI interpreter version 0.000.395 @@ -2575,7 +2576,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.002", 0, "77f02def3094af804fd2371db25b7100", 542897}, {"resource.003", 0, "77f02def3094af804fd2371db25b7100", 586857}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Police Quest 2 English DOS 1.001.006 (supplied by merkur-kun in bug report #3028479) {"pq2", "", { @@ -2584,7 +2585,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.002", 0, "77f02def3094af804fd2371db25b7100", 541261}, {"resource.003", 0, "77f02def3094af804fd2371db25b7100", 587511}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Police Quest 2 - Japanese PC-98 (also includes english language) // SCI interpreter version unknown @@ -2670,7 +2671,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.004", 0, "b96a86ab681769e4cbb439670d967ca6", 449682}, {"resource.005", 0, "9e6c53a0e7eef53694d260fade8b1fc7", 724000}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Police Quest 4 - English DOS Non-Interactive Demo (from FRG) // SCI interpreter version 1.001.096 @@ -2763,7 +2764,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.003", 0, "7ab2bf8e224b57f75e0cd6e4ba790761", 642203}, {"resource.004", 0, "7ab2bf8e224b57f75e0cd6e4ba790761", 641688}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Quest for Glory 1 / Hero's Quest - English DOS 3.5" Floppy (supplied by alonzotg in bug report #3206006) {"qfg1", "", { @@ -2774,7 +2775,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.003", 0, "7ab2bf8e224b57f75e0cd6e4ba790761", 642203}, {"resource.004", 0, "7ab2bf8e224b57f75e0cd6e4ba790761", 641688}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Quest for Glory 1 / Hero's Quest - English DOS 5.25" Floppy (supplied by markcoolio in bug report #2723843) // Executable scanning reports "0.000.566" @@ -2789,7 +2790,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.006", 0, "69366c2a2f99917199fe1b60a4fee19d", 267852}, {"resource.007", 0, "7ab2bf8e224b57f75e0cd6e4ba790761", 272747}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Quest for Glory 1 / Hero's Quest - English DOS 5.25" Floppy (supplied by ssburnout in bug report #3049193) // 1.001 10x5.25" (label: INT.#0.000.566) @@ -2804,7 +2805,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.006", 0, "69366c2a2f99917199fe1b60a4fee19d", 267852}, {"resource.007", 0, "7ab2bf8e224b57f75e0cd6e4ba790761", 272747}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Quest for Glory 1 / Hero's Quest - English DOS 5.25" Floppy (supplied by ssburnout in bug report #3049193) // 1.200 10x5.25" (label: INT#9.10.90) @@ -2819,7 +2820,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.006", 0, "f46690dca714abc8c89357d30e363dd3", 278387}, {"resource.007", 0, "951299a82a8134ed12c5c18118d45c2f", 269173}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Quest for Glory 1 / Hero's Quest - English DOS Demo // Executable scanning reports "0.000.685" @@ -2827,7 +2828,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "df34c758cbb9026da175793ff686b0e6", 882}, {"resource.001", 0, "73fbaafdd313b39aeedb80fbf85ecef1", 389884}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Quest for Glory 1 - Japanese PC-98 5.25" Floppy (also includes English language) // Executable scanning reports "S.old.201" @@ -2837,7 +2838,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.002", 0, "a21451ef6fa8179bd4b22c4950004c44", 1136968}, {"resource.003", 0, "a21451ef6fa8179bd4b22c4950004c44", 769897}, AD_LISTEND}, - Common::JA_JPN, Common::kPlatformPC98, ADGF_ADDENGLISH, GUIO3(GUIO_NOSPEECH, GUIO_NOASPECT, GUIO_EGAUNDITHER) }, + Common::JA_JPN, Common::kPlatformPC98, ADGF_ADDENGLISH, GUIO3(GUIO_NOSPEECH, GUIO_NOASPECT, GAMEOPTION_EGA_UNDITHER) }, // Quest for Glory 1 - Japanese PC-98 5.25" Floppy (also includes English language) // Executable scanning reports "S.old.201" @@ -2847,7 +2848,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.002", 0, "a21451ef6fa8179bd4b22c4950004c44", 1147121}, {"resource.003", 0, "a21451ef6fa8179bd4b22c4950004c44", 777575}, AD_LISTEND}, - Common::JA_JPN, Common::kPlatformPC98, ADGF_ADDENGLISH, GUIO3(GUIO_NOSPEECH, GUIO_NOASPECT, GUIO_EGAUNDITHER) }, + Common::JA_JPN, Common::kPlatformPC98, ADGF_ADDENGLISH, GUIO3(GUIO_NOSPEECH, GUIO_NOASPECT, GAMEOPTION_EGA_UNDITHER) }, // Quest for Glory 1 - English Amiga // Executable scanning reports "1.002.020" @@ -2861,7 +2862,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.004", 0, "16cd4414c37ae3bb6d6da33dce8e25e8", 689124}, {"resource.005", 0, "5f3386ef2f2b1254e4a066f5d9027324", 609529}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Quest for Glory 1 (from abevi, bug report #2612718) {"qfg1", "", { @@ -2872,7 +2873,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.003", 0, "f0af87c60ec869946da442833aa5afa8", 640502}, {"resource.004", 0, "f0af87c60ec869946da442833aa5afa8", 644575}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Quest for Glory 1 - English DOS // SCI interpreter version 0.000.629 @@ -2884,7 +2885,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.003", 0, "951299a82a8134ed12c5c18118d45c2f", 640483}, {"resource.004", 0, "951299a82a8134ed12c5c18118d45c2f", 644443}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Quest for Glory 1 VGA Remake - English DOS // Executable scanning reports "2.000.411" @@ -3284,7 +3285,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.004", 0, "975c6e81194ae6b65e960a248129ecaa", 684119}, {"resource.005", 0, "13d96f7905637552c0647175ff816145", 695589}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Space Quest 3 - English Amiga (from www.back2roots.org) // SCI interpreter version 0.000.453 (just a guess) @@ -3295,7 +3296,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.003", 0, "ceeda7202b96e5c85ecaa88a40a540fc", 746496}, {"resource.004", 0, "ceeda7202b96e5c85ecaa88a40a540fc", 761984}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Space Quest 3 - German Amiga (also includes english language) // Executable scanning reports "1.004.006" @@ -3308,7 +3309,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.004", 0, "6d8f34090503ce937e7dbef6cb6cdb6a", 545053}, {"resource.005", 0, "6d8f34090503ce937e7dbef6cb6cdb6a", 687507}, AD_LISTEND}, - Common::DE_DEU, Common::kPlatformAmiga, ADGF_ADDENGLISH, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + Common::DE_DEU, Common::kPlatformAmiga, ADGF_ADDENGLISH, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Space Quest 3 - English DOS Non-Interactive Demo // SCI interpreter version 0.000.453 @@ -3316,7 +3317,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "ec66ac2b1ce58b2575ba00b65058de1a", 612}, {"resource.001", 0, "ceeda7202b96e5c85ecaa88a40a540fc", 180245}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Space Quest 3 - English DOS (provided by richiefs in bug report #2670691) // SCI interpreter version 0.000.453 @@ -3326,7 +3327,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.002", 0, "ceeda7202b96e5c85ecaa88a40a540fc", 720244}, {"resource.003", 0, "ceeda7202b96e5c85ecaa88a40a540fc", 688367}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Space Quest 3 - English DOS (from the Space Quest Collection) // Executable scanning reports "0.000.685", VERSION file reports "1.018" @@ -3336,7 +3337,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.002", 0, "8b55c4875298f45ea5696a5ee8f6a7fe", 715777}, {"resource.003", 0, "8b55c4875298f45ea5696a5ee8f6a7fe", 703370}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Space Quest 3 - English DOS (from abevi, bug report #2612718) {"sq3", "", { @@ -3348,7 +3349,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.005", 0, "ceeda7202b96e5c85ecaa88a40a540fc", 328278}, {"resource.006", 0, "ceeda7202b96e5c85ecaa88a40a540fc", 356702}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Space Quest 3 - English Mac (from Fingolfin) {"sq3", "", { @@ -3357,7 +3358,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.002", 0, "0d8dfe42683b46f3131823233a91ce6a", 794072}, {"resource.003", 0, "0d8dfe42683b46f3131823233a91ce6a", 776536}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformMacintosh, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + Common::EN_ANY, Common::kPlatformMacintosh, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Space Quest 3 - German DOS (from Tobis87, also includes english language) // SCI interpreter version 0.000.453 (?) @@ -3371,7 +3372,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.006", 0, "9107c2aa5398e28b5c5406df13491f85", 320643}, {"resource.007", 0, "9107c2aa5398e28b5c5406df13491f85", 344287}, AD_LISTEND}, - Common::DE_DEU, Common::kPlatformPC, ADGF_ADDENGLISH, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + Common::DE_DEU, Common::kPlatformPC, ADGF_ADDENGLISH, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Space Quest 3 v1.052 - German DOS (supplied by markcoolio in bug report #2723860, also includes english language) // Executable scanning reports "S.old.114" @@ -3467,7 +3468,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.004", 0, "9a673e33c3f6dd560b993ffed77eeb49", 534994}, {"resource.005", 0, "3c4841d0a3ebba4404af588c93620c22", 595465}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GUIO_EGAUNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Space Quest 4 - German DOS (from Tobis87, also includes english language) // SCI interpreter version 1.000.200 (just a guess) -- cgit v1.2.3 From d801186185672b9df93184a11e8d980a2fafaead Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sun, 25 Mar 2012 19:22:31 +0300 Subject: SCI: Fix cursor coordinates for SCI01. Fixes a crash in KQ1 (bug #3503932) --- engines/sci/graphics/cursor.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines/sci') diff --git a/engines/sci/graphics/cursor.cpp b/engines/sci/graphics/cursor.cpp index 52a5961070..71f4598afc 100644 --- a/engines/sci/graphics/cursor.cpp +++ b/engines/sci/graphics/cursor.cpp @@ -132,7 +132,7 @@ void GfxCursor::kernelSetShape(GuiResourceId resourceId) { resourceData = resource->data; - if (getSciVersion() <= SCI_VERSION_0_LATE) { + if (getSciVersion() <= SCI_VERSION_01) { // SCI0 cursors contain hotspot flags, not actual hotspot coordinates. // If bit 0 of resourceData[3] is set, the hotspot should be centered, // otherwise it's in the top left of the mouse cursor. -- cgit v1.2.3 From 834e9184e5f797038574bd6ed6d6537339304b31 Mon Sep 17 00:00:00 2001 From: D G Turner Date: Sat, 31 Mar 2012 01:39:03 +0100 Subject: SCI: Add workaround for SQ1SCI to fix engine abort in bug #3513207. This occurs while Roger is trying to move around the Pilot Droid in various narrow cases. --- engines/sci/engine/workarounds.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'engines/sci') diff --git a/engines/sci/engine/workarounds.cpp b/engines/sci/engine/workarounds.cpp index a556134e32..9993862b52 100644 --- a/engines/sci/engine/workarounds.cpp +++ b/engines/sci/engine/workarounds.cpp @@ -252,6 +252,7 @@ const SciWorkaroundEntry kDoSoundFade_workarounds[] = { const SciWorkaroundEntry kGetAngle_workarounds[] = { { GID_FANMADE, 516, 992, 0, "Motion", "init", -1, 0, { WORKAROUND_IGNORE, 0 } }, // The Legend of the Lost Jewel Demo (fan made): called with third/fourth parameters as objects { GID_KQ6, -1, 752, 0, "throwDazzle", "changeState", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // room 740/790 after the Genie is exposed in the Palace (short and long ending), it starts shooting lightning bolts around. An extra 5th parameter is passed - bug #3034610 & #3041734 + { GID_SQ1, -1, 927, 0, "PAvoider", "doit", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // room 47 Roger moving around Pilot Droid. Only a single parameter is passed - bug #3513207 SCI_WORKAROUNDENTRY_TERMINATOR }; -- cgit v1.2.3 From 5bbfd008b6f6d625f33a6924dec99482eac9aae8 Mon Sep 17 00:00:00 2001 From: D G Turner Date: Sat, 31 Mar 2012 02:25:20 +0100 Subject: SCI: Minor formatting fix to workarounds table. --- engines/sci/engine/workarounds.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines/sci') diff --git a/engines/sci/engine/workarounds.cpp b/engines/sci/engine/workarounds.cpp index 9993862b52..23d65804a5 100644 --- a/engines/sci/engine/workarounds.cpp +++ b/engines/sci/engine/workarounds.cpp @@ -252,7 +252,7 @@ const SciWorkaroundEntry kDoSoundFade_workarounds[] = { const SciWorkaroundEntry kGetAngle_workarounds[] = { { GID_FANMADE, 516, 992, 0, "Motion", "init", -1, 0, { WORKAROUND_IGNORE, 0 } }, // The Legend of the Lost Jewel Demo (fan made): called with third/fourth parameters as objects { GID_KQ6, -1, 752, 0, "throwDazzle", "changeState", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // room 740/790 after the Genie is exposed in the Palace (short and long ending), it starts shooting lightning bolts around. An extra 5th parameter is passed - bug #3034610 & #3041734 - { GID_SQ1, -1, 927, 0, "PAvoider", "doit", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // room 47 Roger moving around Pilot Droid. Only a single parameter is passed - bug #3513207 + { GID_SQ1, -1, 927, 0, "PAvoider", "doit", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // room 47 Roger moving around Pilot Droid. Only a single parameter is passed - bug #3513207 SCI_WORKAROUNDENTRY_TERMINATOR }; -- cgit v1.2.3 From 21e8f2f44135f32fa2e448f98da3fa05afef8880 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sat, 31 Mar 2012 05:53:29 +0300 Subject: SCI: Fix workaround for bug #3513207 The associated call contains too few parameters, thus it shouldn't be made at all --- engines/sci/engine/workarounds.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines/sci') diff --git a/engines/sci/engine/workarounds.cpp b/engines/sci/engine/workarounds.cpp index 23d65804a5..c31a2dc9dc 100644 --- a/engines/sci/engine/workarounds.cpp +++ b/engines/sci/engine/workarounds.cpp @@ -252,7 +252,7 @@ const SciWorkaroundEntry kDoSoundFade_workarounds[] = { const SciWorkaroundEntry kGetAngle_workarounds[] = { { GID_FANMADE, 516, 992, 0, "Motion", "init", -1, 0, { WORKAROUND_IGNORE, 0 } }, // The Legend of the Lost Jewel Demo (fan made): called with third/fourth parameters as objects { GID_KQ6, -1, 752, 0, "throwDazzle", "changeState", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // room 740/790 after the Genie is exposed in the Palace (short and long ending), it starts shooting lightning bolts around. An extra 5th parameter is passed - bug #3034610 & #3041734 - { GID_SQ1, -1, 927, 0, "PAvoider", "doit", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // room 47 Roger moving around Pilot Droid. Only a single parameter is passed - bug #3513207 + { GID_SQ1, 47, 927, 0, "PAvoider", "doit", -1, 0, { WORKAROUND_IGNORE, 0 } }, // room 47 Roger moving around Pilot Droid. Only a single parameter is passed - bug #3513207 SCI_WORKAROUNDENTRY_TERMINATOR }; -- cgit v1.2.3 From 7f9c63239b2f360b6d96e8ff4dd007b80d990e46 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sat, 31 Mar 2012 05:54:30 +0300 Subject: SCI: Make sure that the disable_dithering key exists --- engines/sci/sci.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'engines/sci') diff --git a/engines/sci/sci.cpp b/engines/sci/sci.cpp index 9b0ee6924b..c77b49400f 100644 --- a/engines/sci/sci.cpp +++ b/engines/sci/sci.cpp @@ -221,7 +221,8 @@ Common::Error SciEngine::run() { // Initialize the game screen _gfxScreen = new GfxScreen(_resMan); - _gfxScreen->enableUndithering(ConfMan.getBool("disable_dithering")); + bool enableUnDitheringFlag = ConfMan.hasKey("disable_dithering") && ConfMan.getBool("disable_dithering"); + _gfxScreen->enableUndithering(enableUnDitheringFlag); _kernel = new Kernel(_resMan, segMan); -- cgit v1.2.3 From 6a49d3eadd7555a4f5f539ceb73fdfe370fce9da Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sat, 31 Mar 2012 13:55:03 +0300 Subject: ENGINES: Return all available custom GUI options if no target is specified This is used to set default settings for all custom game options when an engine starts --- engines/sci/engine/features.cpp | 2 +- engines/sci/sci.cpp | 3 +-- engines/sci/sound/soundcmd.cpp | 5 +---- 3 files changed, 3 insertions(+), 7 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/engine/features.cpp b/engines/sci/engine/features.cpp index a284c319c0..cad95b1c18 100644 --- a/engines/sci/engine/features.cpp +++ b/engines/sci/engine/features.cpp @@ -43,7 +43,7 @@ GameFeatures::GameFeatures(SegManager *segMan, Kernel *kernel) : _segMan(segMan) _sci2StringFunctionType = kSci2StringFunctionUninitialized; #endif _usesCdTrack = Common::File::exists("cdaudio.map"); - if (ConfMan.hasKey("use_cdaudio") && !ConfMan.getBool("use_cdaudio")) + if (!ConfMan.getBool("use_cdaudio")) _usesCdTrack = false; } diff --git a/engines/sci/sci.cpp b/engines/sci/sci.cpp index c77b49400f..9b0ee6924b 100644 --- a/engines/sci/sci.cpp +++ b/engines/sci/sci.cpp @@ -221,8 +221,7 @@ Common::Error SciEngine::run() { // Initialize the game screen _gfxScreen = new GfxScreen(_resMan); - bool enableUnDitheringFlag = ConfMan.hasKey("disable_dithering") && ConfMan.getBool("disable_dithering"); - _gfxScreen->enableUndithering(enableUnDitheringFlag); + _gfxScreen->enableUndithering(ConfMan.getBool("disable_dithering")); _kernel = new Kernel(_resMan, segMan); diff --git a/engines/sci/sound/soundcmd.cpp b/engines/sci/sound/soundcmd.cpp index 8481f10171..05bb90332a 100644 --- a/engines/sci/sound/soundcmd.cpp +++ b/engines/sci/sound/soundcmd.cpp @@ -44,10 +44,7 @@ SoundCommandParser::SoundCommandParser(ResourceManager *resMan, SegManager *segM // resource number, but it's totally unrelated to the menu music). // The GK1 demo (very late SCI1.1) does the same thing // TODO: Check the QFG4 demo - - // If the prefer_digitalsfx key is missing, default to enable digital SFX - bool preferDigitalSfx = !ConfMan.hasKey("prefer_digitalsfx") || ConfMan.getBool("prefer_digitalsfx"); - _useDigitalSFX = (getSciVersion() >= SCI_VERSION_2 || g_sci->getGameId() == GID_GK1 || preferDigitalSfx); + _useDigitalSFX = (getSciVersion() >= SCI_VERSION_2 || g_sci->getGameId() == GID_GK1 || ConfMan.getBool("prefer_digitalsfx")); _music = new SciMusic(_soundVersion, _useDigitalSFX); _music->init(); -- cgit v1.2.3 From 95fb73bcc58ca45b177ae6ead88edebfb70ec8b9 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sun, 1 Apr 2012 01:32:03 +0300 Subject: SCI: Change the fix for the SQ1 PAvoider call to apply in all rooms again This bad call can be made in all rooms in Ulence Flats, after getting the Pilot Droid. Properly fixes script bug #3513207 --- engines/sci/engine/workarounds.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines/sci') diff --git a/engines/sci/engine/workarounds.cpp b/engines/sci/engine/workarounds.cpp index c31a2dc9dc..59de5fec1a 100644 --- a/engines/sci/engine/workarounds.cpp +++ b/engines/sci/engine/workarounds.cpp @@ -252,7 +252,7 @@ const SciWorkaroundEntry kDoSoundFade_workarounds[] = { const SciWorkaroundEntry kGetAngle_workarounds[] = { { GID_FANMADE, 516, 992, 0, "Motion", "init", -1, 0, { WORKAROUND_IGNORE, 0 } }, // The Legend of the Lost Jewel Demo (fan made): called with third/fourth parameters as objects { GID_KQ6, -1, 752, 0, "throwDazzle", "changeState", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // room 740/790 after the Genie is exposed in the Palace (short and long ending), it starts shooting lightning bolts around. An extra 5th parameter is passed - bug #3034610 & #3041734 - { GID_SQ1, 47, 927, 0, "PAvoider", "doit", -1, 0, { WORKAROUND_IGNORE, 0 } }, // room 47 Roger moving around Pilot Droid. Only a single parameter is passed - bug #3513207 + { GID_SQ1, -1, 927, 0, "PAvoider", "doit", -1, 0, { WORKAROUND_IGNORE, 0 } }, // all rooms in Ulence Flats after getting the Pilot Droid: called with a single parameter when the droid is in Roger's path - bug #3513207 SCI_WORKAROUNDENTRY_TERMINATOR }; -- cgit v1.2.3 From 639c54a306f985a6ae5715312075722e818b14ec Mon Sep 17 00:00:00 2001 From: D G Turner Date: Sun, 1 Apr 2012 01:50:08 +0100 Subject: SCI: Add workaround for SQ1SCI to fix engine abort in bug #3513765. This occurs while Roger is trying to move around the Pilot Droid in Ulence Flats. --- engines/sci/engine/workarounds.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'engines/sci') diff --git a/engines/sci/engine/workarounds.cpp b/engines/sci/engine/workarounds.cpp index 59de5fec1a..d7ade85173 100644 --- a/engines/sci/engine/workarounds.cpp +++ b/engines/sci/engine/workarounds.cpp @@ -337,6 +337,7 @@ const SciWorkaroundEntry kIsObject_workarounds[] = { // gameID, room,script,lvl, object-name, method-name, call,index, workaround const SciWorkaroundEntry kMemory_workarounds[] = { { GID_LAURABOW2, -1, 999, 0, "", "export 6", -1, 0, { WORKAROUND_FAKE, 0 } }, // during the intro, when exiting the train (room 160), talking to Mr. Augustini, etc. - bug #3034490 + { GID_SQ1, -1, 999, 0, "", "export 6", -1, 0, { WORKAROUND_FAKE, 0 } }, // during walking Roger around Ulence Flats - bug #3513765 SCI_WORKAROUNDENTRY_TERMINATOR }; -- cgit v1.2.3 From 793dcda650478ff56d4a6125fbd37f729a70bc8b Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Wed, 4 Apr 2012 07:38:42 +0300 Subject: SCI: Bugfix for the GetAngle workarounds Return a fake value instead of leaving random values in the accumulator --- engines/sci/engine/workarounds.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/engine/workarounds.cpp b/engines/sci/engine/workarounds.cpp index d7ade85173..4a0aea81ff 100644 --- a/engines/sci/engine/workarounds.cpp +++ b/engines/sci/engine/workarounds.cpp @@ -250,9 +250,9 @@ const SciWorkaroundEntry kDoSoundFade_workarounds[] = { // gameID, room,script,lvl, object-name, method-name, call,index, workaround const SciWorkaroundEntry kGetAngle_workarounds[] = { - { GID_FANMADE, 516, 992, 0, "Motion", "init", -1, 0, { WORKAROUND_IGNORE, 0 } }, // The Legend of the Lost Jewel Demo (fan made): called with third/fourth parameters as objects + { GID_FANMADE, 516, 992, 0, "Motion", "init", -1, 0, { WORKAROUND_FAKE, 0 } }, // The Legend of the Lost Jewel Demo (fan made): called with third/fourth parameters as objects { GID_KQ6, -1, 752, 0, "throwDazzle", "changeState", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // room 740/790 after the Genie is exposed in the Palace (short and long ending), it starts shooting lightning bolts around. An extra 5th parameter is passed - bug #3034610 & #3041734 - { GID_SQ1, -1, 927, 0, "PAvoider", "doit", -1, 0, { WORKAROUND_IGNORE, 0 } }, // all rooms in Ulence Flats after getting the Pilot Droid: called with a single parameter when the droid is in Roger's path - bug #3513207 + { GID_SQ1, -1, 927, 0, "PAvoider", "doit", -1, 0, { WORKAROUND_FAKE, 0 } }, // all rooms in Ulence Flats after getting the Pilot Droid: called with a single parameter when the droid is in Roger's path - bug #3513207 SCI_WORKAROUNDENTRY_TERMINATOR }; -- cgit v1.2.3 From 56e826807376b7fb213c6bc6497c8a286e4446f5 Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Thu, 5 Apr 2012 00:31:35 +0200 Subject: SCI: Do not cast away const qualifier. --- engines/sci/sound/drivers/midi.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines/sci') diff --git a/engines/sci/sound/drivers/midi.cpp b/engines/sci/sound/drivers/midi.cpp index 93a2308410..37eb37b292 100644 --- a/engines/sci/sound/drivers/midi.cpp +++ b/engines/sci/sound/drivers/midi.cpp @@ -563,7 +563,7 @@ void MidiPlayer_Midi::readMt32GmPatch(const byte *data, int size) { switch (command & 0xf0) { case 0xf0: { - byte *sysExEnd = (byte *)memchr(midi + i, 0xf7, midiSize - i); + const byte *sysExEnd = (const byte *)memchr(midi + i, 0xf7, midiSize - i); if (!sysExEnd) error("Failed to find end of sysEx"); -- cgit v1.2.3 From ad248c9b0b28a50208930c3b49fa4b51420f1f56 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sun, 29 Apr 2012 20:21:52 +0300 Subject: SCI: Add the French floppy version of SQ4 (bug #3515247) --- engines/sci/detection_tables.h | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'engines/sci') diff --git a/engines/sci/detection_tables.h b/engines/sci/detection_tables.h index d741bb801f..ff78d4f18b 100644 --- a/engines/sci/detection_tables.h +++ b/engines/sci/detection_tables.h @@ -3445,6 +3445,19 @@ static const struct ADGameDescription SciGameDescriptions[] = { AD_LISTEND}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + // Space Quest 4 1.000 - French DOS Floppy (supplied by misterhands in bug report #3515247) + {"sq4", "", { + + {"resource.map", 0, "1fd6f356f6a59ad2057686ce6573caeb", 6159}, + {"resource.000", 0, "8000a55aebc50a68b7cce07a8c33758c", 205287}, + {"resource.001", 0, "99a6df6d366b3f061271ff3450ac0d32", 1269850}, + {"resource.002", 0, "a6a8d7a24dbb7a266a26b084e7275e89", 1242668}, + {"resource.003", 0, "482a99c8103b4bcb5706e5969d1c1193", 1323083}, + {"resource.004", 0, "b2cca3afcf2e013b8ce86b64155af766", 1254353}, + {"resource.005", 0, "9e520577e035547c4b5149a6d12ef85b", 1098814}, + AD_LISTEND}, + Common::FR_FRA, Common::kPlatformPC, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + // Space Quest 4 1.000 - English DOS Floppy (from abevi, bug report #2612718) {"sq4", "", { {"resource.map", 0, "8f08b97ca093f370c56d99715b015554", 6153}, -- cgit v1.2.3 From 24e57808aa946ad38379b43ca205af6ef151c66a Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sun, 29 Apr 2012 20:26:05 +0300 Subject: SCI: Add a hack to fix the cursor colors in Longbow (bug #3489101) --- engines/sci/graphics/cursor.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/graphics/cursor.cpp b/engines/sci/graphics/cursor.cpp index 71f4598afc..14ffa69f91 100644 --- a/engines/sci/graphics/cursor.cpp +++ b/engines/sci/graphics/cursor.cpp @@ -148,11 +148,13 @@ void GfxCursor::kernelSetShape(GuiResourceId resourceId) { colorMapping[1] = _screen->getColorWhite(); // White is also hardcoded colorMapping[2] = SCI_CURSOR_SCI0_TRANSPARENCYCOLOR; colorMapping[3] = _palette->matchColor(170, 170, 170); // Grey - // Special case for the magnifier cursor in LB1 (bug #3487092). - // No other SCI0 game has a cursor resource of 1, so this is handled - // specifically for LB1. + // TODO: Figure out if the grey color is hardcoded + // HACK for the magnifier cursor in LB1, fixes its color (bug #3487092) if (g_sci->getGameId() == GID_LAURABOW && resourceId == 1) colorMapping[3] = _screen->getColorWhite(); + // HACK for Longbow cursors, fixes the shade of grey they're using (bug #3489101) + if (g_sci->getGameId() == GID_LONGBOW) + colorMapping[3] = _palette->matchColor(223, 223, 223); // Light Grey // Seek to actual data resourceData += 4; -- cgit v1.2.3 From e41e412c9ee6c277233ef9f7a5304f8cc40fa370 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sun, 29 Apr 2012 20:43:04 +0300 Subject: SCI: Fix for bug #3522046 "Detection of SQ4CD as Windows breaks Music" Fall back to the DOS soundtracks in Windows CD versions if the user picks a non-General MIDI music device, as the Windows tracks only contain MIDI music --- engines/sci/engine/features.cpp | 3 ++- engines/sci/engine/features.h | 7 +++++++ engines/sci/sound/music.cpp | 6 ++++++ 3 files changed, 15 insertions(+), 1 deletion(-) (limited to 'engines/sci') diff --git a/engines/sci/engine/features.cpp b/engines/sci/engine/features.cpp index cad95b1c18..8a932232f8 100644 --- a/engines/sci/engine/features.cpp +++ b/engines/sci/engine/features.cpp @@ -45,6 +45,7 @@ GameFeatures::GameFeatures(SegManager *segMan, Kernel *kernel) : _segMan(segMan) _usesCdTrack = Common::File::exists("cdaudio.map"); if (!ConfMan.getBool("use_cdaudio")) _usesCdTrack = false; + _forceDOSTracks = false; } reg_t GameFeatures::getDetectionAddr(const Common::String &objName, Selector slc, int methodNum) { @@ -642,7 +643,7 @@ MoveCountType GameFeatures::detectMoveCountType() { } bool GameFeatures::useAltWinGMSound() { - if (g_sci && g_sci->getPlatform() == Common::kPlatformWindows && g_sci->isCD()) { + if (g_sci && g_sci->getPlatform() == Common::kPlatformWindows && g_sci->isCD() && !_forceDOSTracks) { SciGameId id = g_sci->getGameId(); return (id == GID_ECOQUEST || id == GID_JONES || diff --git a/engines/sci/engine/features.h b/engines/sci/engine/features.h index 4592c5be9c..f6bb0b5759 100644 --- a/engines/sci/engine/features.h +++ b/engines/sci/engine/features.h @@ -117,6 +117,12 @@ public: */ bool useAltWinGMSound(); + /** + * Forces DOS soundtracks in Windows CD versions when the user hasn't + * selected a MIDI output device + */ + void forceDOSTracks() { _forceDOSTracks = true; } + private: reg_t getDetectionAddr(const Common::String &objName, Selector slc, int methodNum = -1); @@ -137,6 +143,7 @@ private: MoveCountType _moveCountType; bool _usesCdTrack; + bool _forceDOSTracks; SegManager *_segMan; Kernel *_kernel; diff --git a/engines/sci/sound/music.cpp b/engines/sci/sound/music.cpp index 09cab75c39..918b045cb9 100644 --- a/engines/sci/sound/music.cpp +++ b/engines/sci/sound/music.cpp @@ -88,6 +88,12 @@ void SciMusic::init() { uint32 dev = MidiDriver::detectDevice(deviceFlags); _musicType = MidiDriver::getMusicType(dev); + if (g_sci->_features->useAltWinGMSound() && _musicType != MT_GM) { + warning("A Windows CD version with an alternate MIDI soundtrack has been chosen, " + "but no MIDI music device has been selected. Reverting to the DOS soundtrack"); + g_sci->_features->forceDOSTracks(); + } + switch (_musicType) { case MT_ADLIB: // FIXME: There's no Amiga sound option, so we hook it up to AdLib -- cgit v1.2.3 From c424c22f19a050b1a2ee421e80172f7dda571dac Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Fri, 11 May 2012 12:54:06 +0300 Subject: SCI: Fix bug #3040625 - "SCI: ECOQUEST French/German: Speech balloon graphic glitch" This bug is caused by the fact that the sprites in that scene and the speech bubble share the same priority, so we compensate for that with a workaround --- engines/sci/graphics/view.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'engines/sci') diff --git a/engines/sci/graphics/view.cpp b/engines/sci/graphics/view.cpp index a77bcccc52..4e5c4da8b2 100644 --- a/engines/sci/graphics/view.cpp +++ b/engines/sci/graphics/view.cpp @@ -720,6 +720,19 @@ void GfxView::draw(const Common::Rect &rect, const Common::Rect &clipRect, const bitmap += (clipRect.top - rect.top) * celWidth + (clipRect.left - rect.left); + // WORKAROUND: EcoQuest French and German draw the fish and anemone sprites + // with priority 15 in scene 440. Afterwards, a dialog is shown on top of + // these sprites with priority 15 as well. This is undefined behavior + // actually, as the sprites and dialog share the same priority, so in our + // implementation the sprites get drawn incorrectly on top of the dialog. + // Perhaps this worked by mistake in SSCI because of subtle differences in + // how sprites are drawn. We compensate for this by resetting the priority + // of all sprites that have a priority of 15 in scene 440 to priority 14, + // so that the speech bubble can be drawn correctly on top of them. Fixes + // bug #3040625. + if (g_sci->getGameId() == GID_ECOQUEST && g_sci->getEngineState()->currentRoomNumber() == 440 && priority == 15) + priority = 14; + if (!_EGAmapping) { for (y = 0; y < height; y++, bitmap += celWidth) { for (x = 0; x < width; x++) { -- cgit v1.2.3 From 4f6d42d77b5284552b12a7c0f427e060b27c3077 Mon Sep 17 00:00:00 2001 From: Willem Jan Palenstijn Date: Sun, 13 May 2012 16:23:15 +0200 Subject: SCI: Add a few FIXMEs --- engines/sci/resource.cpp | 2 ++ engines/sci/resource.h | 2 ++ 2 files changed, 4 insertions(+) (limited to 'engines/sci') diff --git a/engines/sci/resource.cpp b/engines/sci/resource.cpp index 77a6a40a92..11c3e2bab5 100644 --- a/engines/sci/resource.cpp +++ b/engines/sci/resource.cpp @@ -93,6 +93,8 @@ const char *getSciVersionDesc(SciVersion version) { //#define SCI_VERBOSE_RESMAN 1 +// FIXME: This list is out of sync with the enum in resource.h with +// its indices. static const char *const sci_error_types[] = { "No error", "I/O error", diff --git a/engines/sci/resource.h b/engines/sci/resource.h index 294a4672e2..6c2eb0b025 100644 --- a/engines/sci/resource.h +++ b/engines/sci/resource.h @@ -54,6 +54,7 @@ enum ResourceStatus { kResStatusLocked /**< Allocated and in use */ }; +// FIXME: This enum is out of sync with its textual descriptions in resource.cpp /** Initialization result types */ enum { SCI_ERROR_IO_ERROR = 1, @@ -64,6 +65,7 @@ enum { SCI_ERROR_DECOMPRESSION_ERROR = 6, /**< sanity checks failed during decompression */ SCI_ERROR_RESOURCE_TOO_BIG = 8 /**< Resource size exceeds SCI_MAX_RESOURCE_SIZE */ + // FIXME: This comment makes no sense. Track down in history what it means: /* the first critical error number */ }; -- cgit v1.2.3 From 398d0ffceffc2dc1241b3f667c180573c288ccbf Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Mon, 14 May 2012 02:30:15 +0300 Subject: SCI: Check for object visibility, if an object defines it Fixes the inventory in GK1 --- engines/sci/engine/selector.cpp | 1 + engines/sci/engine/selector.h | 1 + engines/sci/graphics/frameout.cpp | 10 ++++++++++ engines/sci/graphics/frameout.h | 1 + 4 files changed, 13 insertions(+) (limited to 'engines/sci') diff --git a/engines/sci/engine/selector.cpp b/engines/sci/engine/selector.cpp index a8b1cf7ec2..2f6b4d58dd 100644 --- a/engines/sci/engine/selector.cpp +++ b/engines/sci/engine/selector.cpp @@ -181,6 +181,7 @@ void Kernel::mapSelectors() { FIND_SELECTOR(skip); FIND_SELECTOR(fixPriority); FIND_SELECTOR(mirrored); + FIND_SELECTOR(visible); FIND_SELECTOR(useInsetRect); FIND_SELECTOR(inTop); FIND_SELECTOR(inLeft); diff --git a/engines/sci/engine/selector.h b/engines/sci/engine/selector.h index 4b913a866a..2308a6c387 100644 --- a/engines/sci/engine/selector.h +++ b/engines/sci/engine/selector.h @@ -149,6 +149,7 @@ struct SelectorCache { Selector fixPriority; Selector mirrored; + Selector visible; Selector useInsetRect; Selector inTop, inLeft, inBottom, inRight; diff --git a/engines/sci/graphics/frameout.cpp b/engines/sci/graphics/frameout.cpp index b12413ab69..42b51e409d 100644 --- a/engines/sci/graphics/frameout.cpp +++ b/engines/sci/graphics/frameout.cpp @@ -237,6 +237,7 @@ void GfxFrameout::kernelAddScreenItem(reg_t object) { memset(itemEntry, 0, sizeof(FrameoutEntry)); itemEntry->object = object; itemEntry->givenOrderNr = _screenItems.size(); + itemEntry->visible = true; _screenItems.push_back(itemEntry); kernelUpdateScreenItem(object); @@ -266,6 +267,11 @@ void GfxFrameout::kernelUpdateScreenItem(reg_t object) { itemEntry->signal = readSelectorValue(_segMan, object, SELECTOR(signal)); itemEntry->scaleX = readSelectorValue(_segMan, object, SELECTOR(scaleX)); itemEntry->scaleY = readSelectorValue(_segMan, object, SELECTOR(scaleY)); + itemEntry->visible = true; + + // Check if the entry can be hidden + if (lookupSelector(_segMan, object, SELECTOR(visible), NULL, NULL) != kSelectorNone) + itemEntry->visible = readSelectorValue(_segMan, object, SELECTOR(visible)); } void GfxFrameout::kernelDeleteScreenItem(reg_t object) { @@ -433,6 +439,7 @@ void GfxFrameout::createPlaneItemList(reg_t planeObject, FrameoutList &itemList) picEntry->x = planePicture->getSci32celX(pictureCelNr); picEntry->picStartX = pictureIt->startX; picEntry->picStartY = pictureIt->startY; + picEntry->visible = true; picEntry->priority = planePicture->getSci32celPriority(pictureCelNr); @@ -541,6 +548,9 @@ void GfxFrameout::kernelFrameout() { for (FrameoutList::iterator listIterator = itemList.begin(); listIterator != itemList.end(); listIterator++) { FrameoutEntry *itemEntry = *listIterator; + if (!itemEntry->visible) + continue; + if (itemEntry->object.isNull()) { // Picture cel data itemEntry->x = upscaleHorizontalCoordinate(itemEntry->x); diff --git a/engines/sci/graphics/frameout.h b/engines/sci/graphics/frameout.h index 8c3cc261d5..a3d686c592 100644 --- a/engines/sci/graphics/frameout.h +++ b/engines/sci/graphics/frameout.h @@ -60,6 +60,7 @@ struct FrameoutEntry { GfxPicture *picture; int16 picStartX; int16 picStartY; + bool visible; }; typedef Common::List FrameoutList; -- cgit v1.2.3 From 6b38731d393cdc85937c74b301df5f3b3de5af9e Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Mon, 14 May 2012 11:04:58 +0300 Subject: SCI: Implement savegame deletion functionality in SCI32 This is based on two kernel functions, kMakeSaveCatName and kMakeSaveFileName --- engines/sci/engine/kernel.h | 2 ++ engines/sci/engine/kernel_tables.h | 14 ++----------- engines/sci/engine/kfile.cpp | 42 ++++++++++++++++++++++++++++++++------ engines/sci/graphics/text32.cpp | 7 +++++-- 4 files changed, 45 insertions(+), 20 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/engine/kernel.h b/engines/sci/engine/kernel.h index e549c1f8ae..42651ec4a5 100644 --- a/engines/sci/engine/kernel.h +++ b/engines/sci/engine/kernel.h @@ -458,6 +458,8 @@ reg_t kListAllTrue(EngineState *s, int argc, reg_t *argv); reg_t kInPolygon(EngineState *s, int argc, reg_t *argv); reg_t kObjectIntersect(EngineState *s, int argc, reg_t *argv); reg_t kEditText(EngineState *s, int argc, reg_t *argv); +reg_t kMakeSaveCatName(EngineState *s, int argc, reg_t *argv); +reg_t kMakeSaveFileName(EngineState *s, int argc, reg_t *argv); // SCI2.1 Kernel Functions reg_t kText(EngineState *s, int argc, reg_t *argv); diff --git a/engines/sci/engine/kernel_tables.h b/engines/sci/engine/kernel_tables.h index 622511c906..ff06b79d72 100644 --- a/engines/sci/engine/kernel_tables.h +++ b/engines/sci/engine/kernel_tables.h @@ -500,6 +500,8 @@ static SciKernelMapEntry s_kernelMap[] = { { MAP_CALL(UpdateScreenItem), SIG_EVERYWHERE, "o", NULL, NULL }, { MAP_CALL(ObjectIntersect), SIG_EVERYWHERE, "oo", NULL, NULL }, { MAP_CALL(EditText), SIG_EVERYWHERE, "o", NULL, NULL }, + { MAP_CALL(MakeSaveCatName), SIG_EVERYWHERE, "rr", NULL, NULL }, + { MAP_CALL(MakeSaveFileName), SIG_EVERYWHERE, "rri", NULL, NULL }, // SCI2 unmapped functions - TODO! @@ -512,18 +514,6 @@ static SciKernelMapEntry s_kernelMap[] = { // Debug function used to track resources { MAP_EMPTY(ResourceTrack), SIG_EVERYWHERE, "(.*)", NULL, NULL }, - // SCI2 functions that are used in the original save/load menus. Marked as dummy, so - // that the engine errors out on purpose. TODO: Implement once the original save/load - // menus are implemented. - - // Creates the name of the save catalogue/directory to save into. - // TODO: Implement once the original save/load menus are implemented. - { MAP_DUMMY(MakeSaveCatName), SIG_EVERYWHERE, "(.*)", NULL, NULL }, - - // Creates the name of the save file to save into - // TODO: Implement once the original save/load menus are implemented. - { MAP_DUMMY(MakeSaveFileName), SIG_EVERYWHERE, "(.*)", NULL, NULL }, - // Unused / debug SCI2 unused functions, always mapped to kDummy // AddMagnify/DeleteMagnify are both called by script 64979 (the Magnifier diff --git a/engines/sci/engine/kfile.cpp b/engines/sci/engine/kfile.cpp index 312497720a..24ef500d80 100644 --- a/engines/sci/engine/kfile.cpp +++ b/engines/sci/engine/kfile.cpp @@ -863,6 +863,10 @@ reg_t kFileIOUnlink(EngineState *s, int argc, reg_t *argv) { int savedir_nr = saves[slotNum].id; name = g_sci->getSavegameName(savedir_nr); result = saveFileMan->removeSavefile(name); + } else if (getSciVersion() >= SCI_VERSION_2) { + // We don't need to wrap the filename in SCI32 games, as it's already + // constructed here + result = saveFileMan->removeSavefile(name); } else { const Common::String wrappedName = g_sci->wrapFilename(name); result = saveFileMan->removeSavefile(wrappedName); @@ -1168,6 +1172,35 @@ reg_t kCD(EngineState *s, int argc, reg_t *argv) { return NULL_REG; } +reg_t kMakeSaveCatName(EngineState *s, int argc, reg_t *argv) { + // Normally, this creates the name of the save catalogue/directory to save into. + // First parameter is the string to save the result into. Second is a string + // with game parameters. We don't have a use for this at all, as we have our own + // savegame directory management, thus we always return an empty string. + return argv[0]; +} + +reg_t kMakeSaveFileName(EngineState *s, int argc, reg_t *argv) { + // Creates a savegame name from a slot number. Used when deleting saved games. + // Param 0: the output buffer (same as in kMakeSaveCatName) + // Param 1: a string with game parameters, ignored + // Param 2: the selected slot + + SciString *resultString = s->_segMan->lookupString(argv[0]); + uint16 saveSlot = argv[2].toUint16(); + // For some reason, the save slot is incremented by 100... fix it here + if (saveSlot > 100) + saveSlot -= 100; + + Common::Array saves; + listSavegames(saves); + + Common::String filename = g_sci->getSavegameName(saveSlot); + resultString->fromString(filename); + + return argv[0]; +} + reg_t kSave(EngineState *s, int argc, reg_t *argv) { switch (argv[0].toUint16()) { case 0: @@ -1181,12 +1214,9 @@ reg_t kSave(EngineState *s, int argc, reg_t *argv) { case 5: return kGetSaveFiles(s, argc - 1, argv + 1); case 6: - // This is used in Shivers to delete saved games, however it - // always passes the same file name (SHIVER), so it doesn't - // actually delete anything... - // TODO: Check why this happens - // argv[1] is a string (most likely the save game directory) - return kFileIOUnlink(s, argc - 2, argv + 2); + return kMakeSaveCatName(s, argc - 1, argv + 1); + case 7: + return kMakeSaveFileName(s, argc - 1, argv + 1); case 8: // TODO // This is a timer callback, with 1 parameter: the timer object diff --git a/engines/sci/graphics/text32.cpp b/engines/sci/graphics/text32.cpp index 7894c7109c..cd24ca5a99 100644 --- a/engines/sci/graphics/text32.cpp +++ b/engines/sci/graphics/text32.cpp @@ -187,8 +187,11 @@ void GfxText32::drawTextBitmap(int16 x, int16 y, Common::Rect planeRect, reg_t t byte *memoryPtr = _segMan->getHunkPointer(hunkId); - if (!memoryPtr) - error("Attempt to draw an invalid text bitmap"); + if (!memoryPtr) { + // Happens when restoring in some SCI32 games + warning("Attempt to draw an invalid text bitmap"); + return; + } byte *surface = memoryPtr + BITMAP_HEADER_SIZE; -- cgit v1.2.3 From c3f0a426fcbe2c8991b29c0e4bda1e7f0c9263b9 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Mon, 14 May 2012 11:14:10 +0300 Subject: SCI: kMakeSaveFileName is actually using virtual savegame IDs --- engines/sci/engine/kfile.cpp | 12 ++++++------ engines/sci/engine/script_patches.cpp | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/engine/kfile.cpp b/engines/sci/engine/kfile.cpp index 24ef500d80..af438bdaff 100644 --- a/engines/sci/engine/kfile.cpp +++ b/engines/sci/engine/kfile.cpp @@ -331,7 +331,7 @@ reg_t kDeviceInfo(EngineState *s, int argc, reg_t *argv) { s->_segMan->strcpy(argv[1], "__throwaway"); debug(3, "K_DEVICE_INFO_GET_SAVEFILE_NAME(%s,%d) -> %s", game_prefix.c_str(), virtualId, "__throwaway"); if ((virtualId < SAVEGAMEID_OFFICIALRANGE_START) || (virtualId > SAVEGAMEID_OFFICIALRANGE_END)) - error("kDeviceInfo(deleteSave): invalid savegame-id specified"); + error("kDeviceInfo(deleteSave): invalid savegame ID specified"); uint savegameId = virtualId - SAVEGAMEID_OFFICIALRANGE_START; Common::Array saves; listSavegames(saves); @@ -526,7 +526,7 @@ reg_t kGetSaveFiles(EngineState *s, int argc, reg_t *argv) { char *saveNamePtr = saveNames; for (uint i = 0; i < totalSaves; i++) { - *slot++ = make_reg(0, saves[i].id + SAVEGAMEID_OFFICIALRANGE_START); // Store the virtual savegame-id ffs. see above + *slot++ = make_reg(0, saves[i].id + SAVEGAMEID_OFFICIALRANGE_START); // Store the virtual savegame ID ffs. see above strcpy(saveNamePtr, saves[i].name); saveNamePtr += SCI_MAX_SAVENAME_LENGTH; } @@ -1187,10 +1187,10 @@ reg_t kMakeSaveFileName(EngineState *s, int argc, reg_t *argv) { // Param 2: the selected slot SciString *resultString = s->_segMan->lookupString(argv[0]); - uint16 saveSlot = argv[2].toUint16(); - // For some reason, the save slot is incremented by 100... fix it here - if (saveSlot > 100) - saveSlot -= 100; + uint16 virtualId = argv[2].toUint16(); + if ((virtualId < SAVEGAMEID_OFFICIALRANGE_START) || (virtualId > SAVEGAMEID_OFFICIALRANGE_END)) + error("kMakeSaveFileName: invalid savegame ID specified"); + uint saveSlot = virtualId - SAVEGAMEID_OFFICIALRANGE_START; Common::Array saves; listSavegames(saves); diff --git a/engines/sci/engine/script_patches.cpp b/engines/sci/engine/script_patches.cpp index 187f1ce021..69eb377684 100644 --- a/engines/sci/engine/script_patches.cpp +++ b/engines/sci/engine/script_patches.cpp @@ -775,7 +775,7 @@ const uint16 mothergoose256PatchReplay[] = { PATCH_END }; -// when saving, it also checks if the savegame-id is below 13. +// when saving, it also checks if the savegame ID is below 13. // we change this to check if below 113 instead const byte mothergoose256SignatureSaveLimit[] = { 5, -- cgit v1.2.3 From c64a69c363093df946d2a8555d3e7264f16441ef Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Tue, 15 May 2012 03:05:08 +0300 Subject: SCI: Resolve some resource related FIXMEs These were introduced in 4f6d42d. The odd comment dates back to FreeSCI, as far as our history goes, and seems to be a leftover from an old refactoring during FreeSCI's history --- engines/sci/resource.cpp | 17 ++++++++--------- engines/sci/resource.h | 20 +++++++++----------- 2 files changed, 17 insertions(+), 20 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/resource.cpp b/engines/sci/resource.cpp index 11c3e2bab5..f8ddf64551 100644 --- a/engines/sci/resource.cpp +++ b/engines/sci/resource.cpp @@ -93,9 +93,7 @@ const char *getSciVersionDesc(SciVersion version) { //#define SCI_VERBOSE_RESMAN 1 -// FIXME: This list is out of sync with the enum in resource.h with -// its indices. -static const char *const sci_error_types[] = { +static const char *const s_errorDescriptions[] = { "No error", "I/O error", "Resource is empty (size 0)", @@ -103,10 +101,8 @@ static const char *const sci_error_types[] = { "resource.map file not found", "No resource files found", "Unknown compression method", - "Decompression failed: Decompression buffer overflow", "Decompression failed: Sanity check failed", - "Decompression failed: Resource too big", - "SCI version is unsupported" + "Decompression failed: Resource too big" }; static const char *const s_resourceTypeNames[] = { @@ -578,7 +574,7 @@ void ResourceSource::loadResource(ResourceManager *resMan, Resource *res) { if (error) { warning("Error %d occurred while reading %s from resource file %s: %s", error, res->_id.toString().c_str(), res->getResourceLocation().c_str(), - sci_error_types[error]); + s_errorDescriptions[error]); res->unalloc(); } @@ -1878,6 +1874,9 @@ int Resource::readResourceInfo(ResVersion volVersion, Common::SeekableReadStream uint32 wCompression, szUnpacked; ResourceType type; + if (file->size() == 0) + return SCI_ERROR_EMPTY_RESOURCE; + switch (volVersion) { case kResVersionSci0Sci1Early: case kResVersionSci1Middle: @@ -1922,7 +1921,7 @@ int Resource::readResourceInfo(ResVersion volVersion, Common::SeekableReadStream break; #endif default: - return SCI_ERROR_INVALID_RESMAP_ENTRY; + return SCI_ERROR_RESMAP_INVALID_ENTRY; } // check if there were errors while reading @@ -1963,7 +1962,7 @@ int Resource::readResourceInfo(ResVersion volVersion, Common::SeekableReadStream compression = kCompUnknown; } - return compression == kCompUnknown ? SCI_ERROR_UNKNOWN_COMPRESSION : 0; + return (compression == kCompUnknown) ? SCI_ERROR_UNKNOWN_COMPRESSION : SCI_ERROR_NONE; } int Resource::decompress(ResVersion volVersion, Common::SeekableReadStream *file) { diff --git a/engines/sci/resource.h b/engines/sci/resource.h index 6c2eb0b025..4baf39c67f 100644 --- a/engines/sci/resource.h +++ b/engines/sci/resource.h @@ -54,19 +54,17 @@ enum ResourceStatus { kResStatusLocked /**< Allocated and in use */ }; -// FIXME: This enum is out of sync with its textual descriptions in resource.cpp -/** Initialization result types */ -enum { +/** Resource error codes. Should be in sync with s_errorDescriptions */ +enum ResourceErrorCodes { + SCI_ERROR_NONE = 0, SCI_ERROR_IO_ERROR = 1, - SCI_ERROR_INVALID_RESMAP_ENTRY = 2, /**< Invalid resource.map entry */ - SCI_ERROR_RESMAP_NOT_FOUND = 3, - SCI_ERROR_NO_RESOURCE_FILES_FOUND = 4, /**< No resource at all was found */ - SCI_ERROR_UNKNOWN_COMPRESSION = 5, - SCI_ERROR_DECOMPRESSION_ERROR = 6, /**< sanity checks failed during decompression */ + SCI_ERROR_EMPTY_RESOURCE = 2, + SCI_ERROR_RESMAP_INVALID_ENTRY = 3, /**< Invalid resource.map entry */ + SCI_ERROR_RESMAP_NOT_FOUND = 4, + SCI_ERROR_NO_RESOURCE_FILES_FOUND = 5, /**< No resource at all was found */ + SCI_ERROR_UNKNOWN_COMPRESSION = 6, + SCI_ERROR_DECOMPRESSION_ERROR = 7, /**< sanity checks failed during decompression */ SCI_ERROR_RESOURCE_TOO_BIG = 8 /**< Resource size exceeds SCI_MAX_RESOURCE_SIZE */ - - // FIXME: This comment makes no sense. Track down in history what it means: - /* the first critical error number */ }; enum { -- cgit v1.2.3 From 6f9e49faeb1e6e2839fce4b0ef4cd418ecdb8573 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sun, 20 May 2012 19:54:08 +0300 Subject: SCI: Add another workaround for the map scene in TMM Thanks to TMM for details on reproducing this --- engines/sci/engine/workarounds.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'engines/sci') diff --git a/engines/sci/engine/workarounds.cpp b/engines/sci/engine/workarounds.cpp index 4a0aea81ff..81c6fbb246 100644 --- a/engines/sci/engine/workarounds.cpp +++ b/engines/sci/engine/workarounds.cpp @@ -321,8 +321,9 @@ const SciWorkaroundEntry kGraphRedrawBox_workarounds[] = { // gameID, room,script,lvl, object-name, method-name, call,index, workaround const SciWorkaroundEntry kGraphUpdateBox_workarounds[] = { { GID_ECOQUEST2, 100, 333, 0, "showEcorder", "changeState", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // necessary workaround for our ecorder script patch, because there isn't enough space to patch the function - { GID_PQ3, 202, 202, 0, "MapEdit", "movePt", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // when plotting crimes, gets called with 2 extra parameters - bug #3038077 { GID_PQ3, 202, 202, 0, "MapEdit", "addPt", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // when plotting crimes, gets called with 2 extra parameters - bug #3038077 + { GID_PQ3, 202, 202, 0, "MapEdit", "movePt", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // when plotting crimes, gets called with 2 extra parameters - bug #3038077 + { GID_PQ3, 202, 202, 0, "MapEdit", "dispose", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // when plotting crimes, gets called with 2 extra parameters SCI_WORKAROUNDENTRY_TERMINATOR }; -- cgit v1.2.3 From fceeca266600b82c0ef3ab4488a93f7509ff8d96 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sun, 20 May 2012 19:56:22 +0300 Subject: SCI: Change sci_opcodes to CamelCase --- engines/sci/engine/vm.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines/sci') diff --git a/engines/sci/engine/vm.h b/engines/sci/engine/vm.h index 334d224baf..23f5a09d34 100644 --- a/engines/sci/engine/vm.h +++ b/engines/sci/engine/vm.h @@ -139,7 +139,7 @@ enum { GC_INTERVAL = 0x8000 }; -enum sci_opcodes { +enum sciOpcodes { op_bnot = 0x00, // 000 op_add = 0x01, // 001 op_sub = 0x02, // 002 -- cgit v1.2.3 From f8c24b5d8847f512c559ff5b5d7e385eebecd79e Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sun, 20 May 2012 19:57:34 +0300 Subject: SCI: Split the SCI32 graphics kernel functions in a separate file --- engines/sci/engine/kgraphics.cpp | 623 ---------------------------------- engines/sci/engine/kgraphics32.cpp | 679 +++++++++++++++++++++++++++++++++++++ engines/sci/module.mk | 1 + 3 files changed, 680 insertions(+), 623 deletions(-) create mode 100644 engines/sci/engine/kgraphics32.cpp (limited to 'engines/sci') diff --git a/engines/sci/engine/kgraphics.cpp b/engines/sci/engine/kgraphics.cpp index caae562d67..8bf7be4ca3 100644 --- a/engines/sci/engine/kgraphics.cpp +++ b/engines/sci/engine/kgraphics.cpp @@ -25,12 +25,10 @@ #include "engines/util.h" #include "graphics/cursorman.h" #include "graphics/surface.h" -#include "graphics/palette.h" // temporary, for the fadeIn()/fadeOut() functions below #include "gui/message.h" #include "sci/sci.h" -#include "sci/debug.h" // for g_debug_sleeptime_factor #include "sci/event.h" #include "sci/resource.h" #include "sci/engine/features.h" @@ -50,10 +48,7 @@ #include "sci/graphics/text16.h" #include "sci/graphics/view.h" #ifdef ENABLE_SCI32 -#include "sci/graphics/controls32.h" -#include "sci/graphics/font.h" // TODO: remove once kBitmap is moved in a separate class #include "sci/graphics/text32.h" -#include "sci/graphics/frameout.h" #endif namespace Sci { @@ -1275,622 +1270,4 @@ reg_t kRemapColors(EngineState *s, int argc, reg_t *argv) { return s->r_acc; } -#ifdef ENABLE_SCI32 - -reg_t kIsHiRes(EngineState *s, int argc, reg_t *argv) { - // Returns 0 if the screen width or height is less than 640 or 400, - // respectively. - if (g_system->getWidth() < 640 || g_system->getHeight() < 400) - return make_reg(0, 0); - - return make_reg(0, 1); -} - -// SCI32 variant, can't work like sci16 variants -reg_t kCantBeHere32(EngineState *s, int argc, reg_t *argv) { - // TODO -// reg_t curObject = argv[0]; -// reg_t listReference = (argc > 1) ? argv[1] : NULL_REG; - - return NULL_REG; -} - -reg_t kAddScreenItem(EngineState *s, int argc, reg_t *argv) { - if (g_sci->_gfxFrameout->findScreenItem(argv[0]) == NULL) - g_sci->_gfxFrameout->kernelAddScreenItem(argv[0]); - else - g_sci->_gfxFrameout->kernelUpdateScreenItem(argv[0]); - return s->r_acc; -} - -reg_t kUpdateScreenItem(EngineState *s, int argc, reg_t *argv) { - g_sci->_gfxFrameout->kernelUpdateScreenItem(argv[0]); - return s->r_acc; -} - -reg_t kDeleteScreenItem(EngineState *s, int argc, reg_t *argv) { - g_sci->_gfxFrameout->kernelDeleteScreenItem(argv[0]); - return s->r_acc; -} - -reg_t kAddPlane(EngineState *s, int argc, reg_t *argv) { - g_sci->_gfxFrameout->kernelAddPlane(argv[0]); - return s->r_acc; -} - -reg_t kDeletePlane(EngineState *s, int argc, reg_t *argv) { - g_sci->_gfxFrameout->kernelDeletePlane(argv[0]); - return s->r_acc; -} - -reg_t kUpdatePlane(EngineState *s, int argc, reg_t *argv) { - g_sci->_gfxFrameout->kernelUpdatePlane(argv[0]); - return s->r_acc; -} - -reg_t kAddPicAt(EngineState *s, int argc, reg_t *argv) { - reg_t planeObj = argv[0]; - GuiResourceId pictureId = argv[1].toUint16(); - int16 pictureX = argv[2].toSint16(); - int16 pictureY = argv[3].toSint16(); - - g_sci->_gfxFrameout->kernelAddPicAt(planeObj, pictureId, pictureX, pictureY); - return s->r_acc; -} - -reg_t kGetHighPlanePri(EngineState *s, int argc, reg_t *argv) { - return make_reg(0, g_sci->_gfxFrameout->kernelGetHighPlanePri()); -} - -reg_t kFrameOut(EngineState *s, int argc, reg_t *argv) { - g_sci->_gfxFrameout->kernelFrameout(); - return NULL_REG; -} - -reg_t kObjectIntersect(EngineState *s, int argc, reg_t *argv) { - Common::Rect objRect1 = g_sci->_gfxCompare->getNSRect(argv[0]); - Common::Rect objRect2 = g_sci->_gfxCompare->getNSRect(argv[1]); - return make_reg(0, objRect1.intersects(objRect2)); -} - -// Tests if the coordinate is on the passed object -reg_t kIsOnMe(EngineState *s, int argc, reg_t *argv) { - uint16 x = argv[0].toUint16(); - uint16 y = argv[1].toUint16(); - reg_t targetObject = argv[2]; - uint16 illegalBits = argv[3].offset; - Common::Rect nsRect = g_sci->_gfxCompare->getNSRect(targetObject, true); - - // we assume that x, y are local coordinates - - bool contained = nsRect.contains(x, y); - if (contained && illegalBits) { - // If illegalbits are set, we check the color of the pixel that got clicked on - // for now, we return false if the pixel is transparent - // although illegalBits may get differently set, don't know yet how this really works out - uint16 viewId = readSelectorValue(s->_segMan, targetObject, SELECTOR(view)); - int16 loopNo = readSelectorValue(s->_segMan, targetObject, SELECTOR(loop)); - int16 celNo = readSelectorValue(s->_segMan, targetObject, SELECTOR(cel)); - if (g_sci->_gfxCompare->kernelIsItSkip(viewId, loopNo, celNo, Common::Point(x - nsRect.left, y - nsRect.top))) - contained = false; - } - return make_reg(0, contained); -} - -reg_t kCreateTextBitmap(EngineState *s, int argc, reg_t *argv) { - switch (argv[0].toUint16()) { - case 0: { - if (argc != 4) { - warning("kCreateTextBitmap(0): expected 4 arguments, got %i", argc); - return NULL_REG; - } - reg_t object = argv[3]; - Common::String text = s->_segMan->getString(readSelector(s->_segMan, object, SELECTOR(text))); - debugC(kDebugLevelStrings, "kCreateTextBitmap case 0 (%04x:%04x, %04x:%04x, %04x:%04x)", - PRINT_REG(argv[1]), PRINT_REG(argv[2]), PRINT_REG(argv[3])); - debugC(kDebugLevelStrings, "%s", text.c_str()); - uint16 maxWidth = argv[1].toUint16(); // nsRight - nsLeft + 1 - uint16 maxHeight = argv[2].toUint16(); // nsBottom - nsTop + 1 - return g_sci->_gfxText32->createTextBitmap(object, maxWidth, maxHeight); - } - case 1: { - if (argc != 2) { - warning("kCreateTextBitmap(1): expected 2 arguments, got %i", argc); - return NULL_REG; - } - reg_t object = argv[1]; - Common::String text = s->_segMan->getString(readSelector(s->_segMan, object, SELECTOR(text))); - debugC(kDebugLevelStrings, "kCreateTextBitmap case 1 (%04x:%04x)", PRINT_REG(argv[1])); - debugC(kDebugLevelStrings, "%s", text.c_str()); - return g_sci->_gfxText32->createTextBitmap(object); - } - default: - warning("CreateTextBitmap(%d)", argv[0].toUint16()); - return NULL_REG; - } -} - -reg_t kDisposeTextBitmap(EngineState *s, int argc, reg_t *argv) { - g_sci->_gfxText32->disposeTextBitmap(argv[0]); - return s->r_acc; -} - -reg_t kGetWindowsOption(EngineState *s, int argc, reg_t *argv) { - uint16 windowsOption = argv[0].toUint16(); - switch (windowsOption) { - case 0: - // Title bar on/off in Phantasmagoria, we return 0 (off) - return NULL_REG; - default: - warning("GetWindowsOption: Unknown option %d", windowsOption); - return NULL_REG; - } -} - -reg_t kWinHelp(EngineState *s, int argc, reg_t *argv) { - switch (argv[0].toUint16()) { - case 1: - // Load a help file - // Maybe in the future we can implement this, but for now this message should suffice - showScummVMDialog("Please use an external viewer to open the game's help file: " + s->_segMan->getString(argv[1])); - break; - case 2: - // Looks like some init function - break; - default: - warning("Unknown kWinHelp subop %d", argv[0].toUint16()); - } - - return s->r_acc; -} - -// Taken from the SCI16 GfxTransitions class -static void fadeOut() { - byte oldPalette[3 * 256], workPalette[3 * 256]; - int16 stepNr, colorNr; - // Sierra did not fade in/out color 255 for sci1.1, but they used it in - // several pictures (e.g. qfg3 demo/intro), so the fading looked weird - int16 tillColorNr = getSciVersion() >= SCI_VERSION_1_1 ? 255 : 254; - - g_system->getPaletteManager()->grabPalette(oldPalette, 0, 256); - - for (stepNr = 100; stepNr >= 0; stepNr -= 10) { - for (colorNr = 1; colorNr <= tillColorNr; colorNr++) { - if (g_sci->_gfxPalette->colorIsFromMacClut(colorNr)) { - workPalette[colorNr * 3 + 0] = oldPalette[colorNr * 3]; - workPalette[colorNr * 3 + 1] = oldPalette[colorNr * 3 + 1]; - workPalette[colorNr * 3 + 2] = oldPalette[colorNr * 3 + 2]; - } else { - workPalette[colorNr * 3 + 0] = oldPalette[colorNr * 3] * stepNr / 100; - workPalette[colorNr * 3 + 1] = oldPalette[colorNr * 3 + 1] * stepNr / 100; - workPalette[colorNr * 3 + 2] = oldPalette[colorNr * 3 + 2] * stepNr / 100; - } - } - g_system->getPaletteManager()->setPalette(workPalette + 3, 1, tillColorNr); - g_sci->getEngineState()->wait(2); - } -} - -// Taken from the SCI16 GfxTransitions class -static void fadeIn() { - int16 stepNr; - // Sierra did not fade in/out color 255 for sci1.1, but they used it in - // several pictures (e.g. qfg3 demo/intro), so the fading looked weird - int16 tillColorNr = getSciVersion() >= SCI_VERSION_1_1 ? 255 : 254; - - for (stepNr = 0; stepNr <= 100; stepNr += 10) { - g_sci->_gfxPalette->kernelSetIntensity(1, tillColorNr + 1, stepNr, true); - g_sci->getEngineState()->wait(2); - } -} - -/** - * Used for scene transitions, replacing (but reusing parts of) the old - * transition code. - */ -reg_t kSetShowStyle(EngineState *s, int argc, reg_t *argv) { - // Can be called with 7 or 8 parameters - // The style defines which transition to perform. Related to the transition - // tables inside graphics/transitions.cpp - uint16 showStyle = argv[0].toUint16(); // 0 - 15 - reg_t planeObj = argv[1]; // the affected plane - uint16 seconds = argv[2].toUint16(); // seconds that the transition lasts - uint16 backColor = argv[3].toUint16(); // target back color(?). When fading out, it's 0x0000. When fading in, it's 0xffff - int16 priority = argv[4].toSint16(); // always 0xc8 (200) when fading in/out - uint16 animate = argv[5].toUint16(); // boolean, animate or not while the transition lasts - uint16 refFrame = argv[6].toUint16(); // refFrame, always 0 when fading in/out - int16 divisions; - - // If the game has the pFadeArray selector, another parameter is used here, - // before the optional last parameter - bool hasFadeArray = g_sci->getKernel()->findSelector("pFadeArray") > 0; - if (hasFadeArray) { - // argv[7] - divisions = (argc >= 9) ? argv[8].toSint16() : -1; // divisions (transition steps?) - } else { - divisions = (argc >= 8) ? argv[7].toSint16() : -1; // divisions (transition steps?) - } - - if (showStyle > 15) { - warning("kSetShowStyle: Illegal style %d for plane %04x:%04x", showStyle, PRINT_REG(planeObj)); - return s->r_acc; - } - - // TODO: Proper implementation. This is a very basic version. I'm not even - // sure if the rest of the styles will work with this mechanism. - - // Check if the passed parameters are the ones we expect - if (showStyle == 13 || showStyle == 14) { // fade out / fade in - if (seconds != 1) - warning("kSetShowStyle(fade): seconds isn't 1, it's %d", seconds); - if (backColor != 0 && backColor != 0xFFFF) - warning("kSetShowStyle(fade): backColor isn't 0 or 0xFFFF, it's %d", backColor); - if (priority != 200) - warning("kSetShowStyle(fade): priority isn't 200, it's %d", priority); - if (animate != 0) - warning("kSetShowStyle(fade): animate isn't 0, it's %d", animate); - if (refFrame != 0) - warning("kSetShowStyle(fade): refFrame isn't 0, it's %d", refFrame); - if (divisions >= 0 && divisions != 20) - warning("kSetShowStyle(fade): divisions isn't 20, it's %d", divisions); - } - - // TODO: Check if the plane is in the list of planes to draw - - switch (showStyle) { - //case 0: // no transition, perhaps? (like in the previous SCI versions) - case 13: // fade out - // TODO: Temporary implementation, which ignores all additional parameters - fadeOut(); - break; - case 14: // fade in - // TODO: Temporary implementation, which ignores all additional parameters - g_sci->_gfxFrameout->kernelFrameout(); // draw new scene before fading in - fadeIn(); - break; - default: - // TODO: This is all a stub/skeleton, thus we're invoking kStub() for now - kStub(s, argc, argv); - break; - } - - return s->r_acc; -} - -reg_t kCelInfo(EngineState *s, int argc, reg_t *argv) { - // Used by Shivers 1, room 23601 to determine what blocks on the red door puzzle board - // are occupied by pieces already - - switch (argv[0].toUint16()) { // subops 0 - 4 - // 0 - return the view - // 1 - return the loop - // 2, 3 - nop - case 4: { - GuiResourceId viewId = argv[1].toSint16(); - int16 loopNo = argv[2].toSint16(); - int16 celNo = argv[3].toSint16(); - int16 x = argv[4].toUint16(); - int16 y = argv[5].toUint16(); - byte color = g_sci->_gfxCache->kernelViewGetColorAtCoordinate(viewId, loopNo, celNo, x, y); - return make_reg(0, color); - } - default: { - kStub(s, argc, argv); - return s->r_acc; - } - } -} - -reg_t kScrollWindow(EngineState *s, int argc, reg_t *argv) { - // Used by Phantasmagoria 1 and SQ6. In SQ6, it is used for the messages - // shown in the scroll window at the bottom of the screen. - - // TODO: This is all a stub/skeleton, thus we're invoking kStub() for now - kStub(s, argc, argv); - - switch (argv[0].toUint16()) { - case 0: // Init - // 2 parameters - // argv[1] points to the scroll object (e.g. textScroller in SQ6) - // argv[2] is an integer (e.g. 0x32) - break; - case 1: // Show message - // 5 or 6 parameters - // Seems to be called with 5 parameters when the narrator speaks, and - // with 6 when Roger speaks - // argv[1] unknown (usually 0) - // argv[2] the text to show - // argv[3] a small integer (e.g. 0x32) - // argv[4] a small integer (e.g. 0x54) - // argv[5] optional, unknown (usually 0) - warning("kScrollWindow: '%s'", s->_segMan->getString(argv[2]).c_str()); - break; - case 2: // Clear - // 2 parameters - // TODO - break; - case 3: // Page up - // 2 parameters - // TODO - break; - case 4: // Page down - // 2 parameters - // TODO - break; - case 5: // Up arrow - // 2 parameters - // TODO - break; - case 6: // Down arrow - // 2 parameters - // TODO - break; - case 7: // Home - // 2 parameters - // TODO - break; - case 8: // End - // 2 parameters - // TODO - break; - case 9: // Resize - // 3 parameters - // TODO - break; - case 10: // Where - // 3 parameters - // TODO - break; - case 11: // Go - // 4 parameters - // TODO - break; - case 12: // Insert - // 7 parameters - // TODO - break; - case 13: // Delete - // 3 parameters - // TODO - break; - case 14: // Modify - // 7 or 8 parameters - // TODO - break; - case 15: // Hide - // 2 parameters - // TODO - break; - case 16: // Show - // 2 parameters - // TODO - break; - case 17: // Destroy - // 2 parameters - // TODO - break; - case 18: // Text - // 2 parameters - // TODO - break; - case 19: // Reconstruct - // 3 parameters - // TODO - break; - default: - error("kScrollWindow: unknown subop %d", argv[0].toUint16()); - break; - } - - return s->r_acc; -} - -reg_t kSetFontRes(EngineState *s, int argc, reg_t *argv) { - // TODO: This defines the resolution that the fonts are supposed to be displayed - // in. Currently, this is only used for showing high-res fonts in GK1 Mac, but - // should be extended to handle other font resolutions such as those - - int xResolution = argv[0].toUint16(); - //int yResolution = argv[1].toUint16(); - - g_sci->_gfxScreen->setFontIsUpscaled(xResolution == 640 && - g_sci->_gfxScreen->getUpscaledHires() != GFX_SCREEN_UPSCALED_DISABLED); - - return s->r_acc; -} - -reg_t kFont(EngineState *s, int argc, reg_t *argv) { - // Handle font settings for SCI2.1 - - switch (argv[0].toUint16()) { - case 1: - // Set font resolution - return kSetFontRes(s, argc - 1, argv + 1); - default: - warning("kFont: unknown subop %d", argv[0].toUint16()); - } - - return s->r_acc; -} - -// TODO: Eventually, all of the kBitmap operations should be put -// in a separate class - -#define BITMAP_HEADER_SIZE 46 - -reg_t kBitmap(EngineState *s, int argc, reg_t *argv) { - // Used for bitmap operations in SCI2.1 and SCI3. - // This is the SCI2.1 version, the functionality seems to have changed in SCI3. - - switch (argv[0].toUint16()) { - case 0: // init bitmap surface - { - // 6 params, called e.g. from TextView::init() in Torin's Passage, - // script 64890 and TransView::init() in script 64884 - uint16 width = argv[1].toUint16(); - uint16 height = argv[2].toUint16(); - //uint16 skip = argv[3].toUint16(); - uint16 back = argv[4].toUint16(); // usually equals skip - //uint16 width2 = (argc >= 6) ? argv[5].toUint16() : 0; - //uint16 height2 = (argc >= 7) ? argv[6].toUint16() : 0; - //uint16 transparentFlag = (argc >= 8) ? argv[7].toUint16() : 0; - - // TODO: skip, width2, height2, transparentFlag - // (used for transparent bitmaps) - int entrySize = width * height + BITMAP_HEADER_SIZE; - reg_t memoryId = s->_segMan->allocateHunkEntry("Bitmap()", entrySize); - byte *memoryPtr = s->_segMan->getHunkPointer(memoryId); - memset(memoryPtr, 0, BITMAP_HEADER_SIZE); // zero out the bitmap header - memset(memoryPtr + BITMAP_HEADER_SIZE, back, width * height); - // Save totalWidth, totalHeight - // TODO: Save the whole bitmap header, like SSCI does - WRITE_LE_UINT16(memoryPtr, width); - WRITE_LE_UINT16(memoryPtr + 2, height); - return memoryId; - } - break; - case 1: // dispose text bitmap surface - return kDisposeTextBitmap(s, argc - 1, argv + 1); - case 2: // dispose bitmap surface, with extra param - // 2 params, called e.g. from MenuItem::dispose in Torin's Passage, - // script 64893 - warning("kBitmap(2), unk1 %d, bitmap ptr %04x:%04x", argv[1].toUint16(), PRINT_REG(argv[2])); - break; - case 3: // tiled surface - { - // 6 params, called e.g. from TiledBitmap::resize() in Torin's Passage, - // script 64869 - reg_t hunkId = argv[1]; // obtained from kBitmap(0) - // The tiled view seems to always have 2 loops. - // These loops need to have 1 cel in loop 0 and 8 cels in loop 1. - uint16 viewNum = argv[2].toUint16(); // vTiles selector - uint16 loop = argv[3].toUint16(); - uint16 cel = argv[4].toUint16(); - uint16 x = argv[5].toUint16(); - uint16 y = argv[6].toUint16(); - - byte *memoryPtr = s->_segMan->getHunkPointer(hunkId); - // Get totalWidth, totalHeight - uint16 totalWidth = READ_LE_UINT16(memoryPtr); - uint16 totalHeight = READ_LE_UINT16(memoryPtr + 2); - byte *bitmap = memoryPtr + BITMAP_HEADER_SIZE; - - GfxView *view = g_sci->_gfxCache->getView(viewNum); - uint16 tileWidth = view->getWidth(loop, cel); - uint16 tileHeight = view->getHeight(loop, cel); - const byte *tileBitmap = view->getBitmap(loop, cel); - uint16 width = MIN(totalWidth - x, tileWidth); - uint16 height = MIN(totalHeight - y, tileHeight); - - for (uint16 curY = 0; curY < height; curY++) { - for (uint16 curX = 0; curX < width; curX++) { - bitmap[(curY + y) * totalWidth + (curX + x)] = tileBitmap[curY * tileWidth + curX]; - } - } - - } - break; - case 4: // add text to bitmap - { - // 13 params, called e.g. from TextButton::createBitmap() in Torin's Passage, - // script 64894 - reg_t hunkId = argv[1]; // obtained from kBitmap(0) - Common::String text = s->_segMan->getString(argv[2]); - uint16 textX = argv[3].toUint16(); - uint16 textY = argv[4].toUint16(); - //reg_t unk5 = argv[5]; - //reg_t unk6 = argv[6]; - //reg_t unk7 = argv[7]; // skip? - //reg_t unk8 = argv[8]; // back? - //reg_t unk9 = argv[9]; - uint16 fontId = argv[10].toUint16(); - //uint16 mode = argv[11].toUint16(); - uint16 dimmed = argv[12].toUint16(); - //warning("kBitmap(4): bitmap ptr %04x:%04x, font %d, mode %d, dimmed %d - text: \"%s\"", - // PRINT_REG(bitmapPtr), font, mode, dimmed, text.c_str()); - uint16 foreColor = 255; // TODO - - byte *memoryPtr = s->_segMan->getHunkPointer(hunkId); - // Get totalWidth, totalHeight - uint16 totalWidth = READ_LE_UINT16(memoryPtr); - uint16 totalHeight = READ_LE_UINT16(memoryPtr + 2); - byte *bitmap = memoryPtr + BITMAP_HEADER_SIZE; - - GfxFont *font = g_sci->_gfxCache->getFont(fontId); - - int16 charCount = 0; - uint16 curX = textX, curY = textY; - const char *txt = text.c_str(); - - while (*txt) { - charCount = g_sci->_gfxText32->GetLongest(txt, totalWidth, font); - if (charCount == 0) - break; - - for (int i = 0; i < charCount; i++) { - unsigned char curChar = txt[i]; - font->drawToBuffer(curChar, curY, curX, foreColor, dimmed, bitmap, totalWidth, totalHeight); - curX += font->getCharWidth(curChar); - } - - curX = textX; - curY += font->getHeight(); - txt += charCount; - while (*txt == ' ') - txt++; // skip over breaking spaces - } - - } - break; - case 5: // fill with color - { - // 6 params, called e.g. from TextView::init() and TextView::draw() - // in Torin's Passage, script 64890 - reg_t hunkId = argv[1]; // obtained from kBitmap(0) - uint16 x = argv[2].toUint16(); - uint16 y = argv[3].toUint16(); - uint16 fillWidth = argv[4].toUint16(); // width - 1 - uint16 fillHeight = argv[5].toUint16(); // height - 1 - uint16 back = argv[6].toUint16(); - - byte *memoryPtr = s->_segMan->getHunkPointer(hunkId); - // Get totalWidth, totalHeight - uint16 totalWidth = READ_LE_UINT16(memoryPtr); - uint16 totalHeight = READ_LE_UINT16(memoryPtr + 2); - uint16 width = MIN(totalWidth - x, fillWidth); - uint16 height = MIN(totalHeight - y, fillHeight); - byte *bitmap = memoryPtr + BITMAP_HEADER_SIZE; - - for (uint16 curY = 0; curY < height; curY++) { - for (uint16 curX = 0; curX < width; curX++) { - bitmap[(curY + y) * totalWidth + (curX + x)] = back; - } - } - - } - break; - default: - kStub(s, argc, argv); - break; - } - - return s->r_acc; -} - -// Used for edit boxes in save/load dialogs. It's a rewritten version of kEditControl, -// but it handles events on its own, using an internal loop, instead of using SCI -// scripts for event management like kEditControl does. Called by script 64914, -// DEdit::hilite(). -reg_t kEditText(EngineState *s, int argc, reg_t *argv) { - reg_t controlObject = argv[0]; - - if (!controlObject.isNull()) { - g_sci->_gfxControls32->kernelTexteditChange(controlObject); - } - - return s->r_acc; -} - -#endif - } // End of namespace Sci diff --git a/engines/sci/engine/kgraphics32.cpp b/engines/sci/engine/kgraphics32.cpp new file mode 100644 index 0000000000..178c5d6e43 --- /dev/null +++ b/engines/sci/engine/kgraphics32.cpp @@ -0,0 +1,679 @@ +/* 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. + * + */ + +#include "common/system.h" + +#include "engines/util.h" +#include "graphics/cursorman.h" +#include "graphics/surface.h" +#include "graphics/palette.h" // temporary, for the fadeIn()/fadeOut() functions below + +#include "gui/message.h" + +#include "sci/sci.h" +#include "sci/event.h" +#include "sci/resource.h" +#include "sci/engine/features.h" +#include "sci/engine/state.h" +#include "sci/engine/selector.h" +#include "sci/engine/kernel.h" +#include "sci/graphics/animate.h" +#include "sci/graphics/cache.h" +#include "sci/graphics/compare.h" +#include "sci/graphics/controls16.h" +#include "sci/graphics/cursor.h" +#include "sci/graphics/palette.h" +#include "sci/graphics/paint16.h" +#include "sci/graphics/picture.h" +#include "sci/graphics/ports.h" +#include "sci/graphics/screen.h" +#include "sci/graphics/text16.h" +#include "sci/graphics/view.h" +#ifdef ENABLE_SCI32 +#include "sci/graphics/controls32.h" +#include "sci/graphics/font.h" // TODO: remove once kBitmap is moved in a separate class +#include "sci/graphics/text32.h" +#include "sci/graphics/frameout.h" +#endif + +namespace Sci { +#ifdef ENABLE_SCI32 + +extern void showScummVMDialog(const Common::String &message); + +reg_t kIsHiRes(EngineState *s, int argc, reg_t *argv) { + // Returns 0 if the screen width or height is less than 640 or 400, + // respectively. + if (g_system->getWidth() < 640 || g_system->getHeight() < 400) + return make_reg(0, 0); + + return make_reg(0, 1); +} + +// SCI32 variant, can't work like sci16 variants +reg_t kCantBeHere32(EngineState *s, int argc, reg_t *argv) { + // TODO +// reg_t curObject = argv[0]; +// reg_t listReference = (argc > 1) ? argv[1] : NULL_REG; + + return NULL_REG; +} + +reg_t kAddScreenItem(EngineState *s, int argc, reg_t *argv) { + if (g_sci->_gfxFrameout->findScreenItem(argv[0]) == NULL) + g_sci->_gfxFrameout->kernelAddScreenItem(argv[0]); + else + g_sci->_gfxFrameout->kernelUpdateScreenItem(argv[0]); + return s->r_acc; +} + +reg_t kUpdateScreenItem(EngineState *s, int argc, reg_t *argv) { + g_sci->_gfxFrameout->kernelUpdateScreenItem(argv[0]); + return s->r_acc; +} + +reg_t kDeleteScreenItem(EngineState *s, int argc, reg_t *argv) { + g_sci->_gfxFrameout->kernelDeleteScreenItem(argv[0]); + return s->r_acc; +} + +reg_t kAddPlane(EngineState *s, int argc, reg_t *argv) { + g_sci->_gfxFrameout->kernelAddPlane(argv[0]); + return s->r_acc; +} + +reg_t kDeletePlane(EngineState *s, int argc, reg_t *argv) { + g_sci->_gfxFrameout->kernelDeletePlane(argv[0]); + return s->r_acc; +} + +reg_t kUpdatePlane(EngineState *s, int argc, reg_t *argv) { + g_sci->_gfxFrameout->kernelUpdatePlane(argv[0]); + return s->r_acc; +} + +reg_t kAddPicAt(EngineState *s, int argc, reg_t *argv) { + reg_t planeObj = argv[0]; + GuiResourceId pictureId = argv[1].toUint16(); + int16 pictureX = argv[2].toSint16(); + int16 pictureY = argv[3].toSint16(); + + g_sci->_gfxFrameout->kernelAddPicAt(planeObj, pictureId, pictureX, pictureY); + return s->r_acc; +} + +reg_t kGetHighPlanePri(EngineState *s, int argc, reg_t *argv) { + return make_reg(0, g_sci->_gfxFrameout->kernelGetHighPlanePri()); +} + +reg_t kFrameOut(EngineState *s, int argc, reg_t *argv) { + g_sci->_gfxFrameout->kernelFrameout(); + return NULL_REG; +} + +reg_t kObjectIntersect(EngineState *s, int argc, reg_t *argv) { + Common::Rect objRect1 = g_sci->_gfxCompare->getNSRect(argv[0]); + Common::Rect objRect2 = g_sci->_gfxCompare->getNSRect(argv[1]); + return make_reg(0, objRect1.intersects(objRect2)); +} + +// Tests if the coordinate is on the passed object +reg_t kIsOnMe(EngineState *s, int argc, reg_t *argv) { + uint16 x = argv[0].toUint16(); + uint16 y = argv[1].toUint16(); + reg_t targetObject = argv[2]; + uint16 illegalBits = argv[3].offset; + Common::Rect nsRect = g_sci->_gfxCompare->getNSRect(targetObject, true); + + // we assume that x, y are local coordinates + + bool contained = nsRect.contains(x, y); + if (contained && illegalBits) { + // If illegalbits are set, we check the color of the pixel that got clicked on + // for now, we return false if the pixel is transparent + // although illegalBits may get differently set, don't know yet how this really works out + uint16 viewId = readSelectorValue(s->_segMan, targetObject, SELECTOR(view)); + int16 loopNo = readSelectorValue(s->_segMan, targetObject, SELECTOR(loop)); + int16 celNo = readSelectorValue(s->_segMan, targetObject, SELECTOR(cel)); + if (g_sci->_gfxCompare->kernelIsItSkip(viewId, loopNo, celNo, Common::Point(x - nsRect.left, y - nsRect.top))) + contained = false; + } + return make_reg(0, contained); +} + +reg_t kCreateTextBitmap(EngineState *s, int argc, reg_t *argv) { + switch (argv[0].toUint16()) { + case 0: { + if (argc != 4) { + warning("kCreateTextBitmap(0): expected 4 arguments, got %i", argc); + return NULL_REG; + } + reg_t object = argv[3]; + Common::String text = s->_segMan->getString(readSelector(s->_segMan, object, SELECTOR(text))); + debugC(kDebugLevelStrings, "kCreateTextBitmap case 0 (%04x:%04x, %04x:%04x, %04x:%04x)", + PRINT_REG(argv[1]), PRINT_REG(argv[2]), PRINT_REG(argv[3])); + debugC(kDebugLevelStrings, "%s", text.c_str()); + uint16 maxWidth = argv[1].toUint16(); // nsRight - nsLeft + 1 + uint16 maxHeight = argv[2].toUint16(); // nsBottom - nsTop + 1 + return g_sci->_gfxText32->createTextBitmap(object, maxWidth, maxHeight); + } + case 1: { + if (argc != 2) { + warning("kCreateTextBitmap(1): expected 2 arguments, got %i", argc); + return NULL_REG; + } + reg_t object = argv[1]; + Common::String text = s->_segMan->getString(readSelector(s->_segMan, object, SELECTOR(text))); + debugC(kDebugLevelStrings, "kCreateTextBitmap case 1 (%04x:%04x)", PRINT_REG(argv[1])); + debugC(kDebugLevelStrings, "%s", text.c_str()); + return g_sci->_gfxText32->createTextBitmap(object); + } + default: + warning("CreateTextBitmap(%d)", argv[0].toUint16()); + return NULL_REG; + } +} + +reg_t kDisposeTextBitmap(EngineState *s, int argc, reg_t *argv) { + g_sci->_gfxText32->disposeTextBitmap(argv[0]); + return s->r_acc; +} + +reg_t kGetWindowsOption(EngineState *s, int argc, reg_t *argv) { + uint16 windowsOption = argv[0].toUint16(); + switch (windowsOption) { + case 0: + // Title bar on/off in Phantasmagoria, we return 0 (off) + return NULL_REG; + default: + warning("GetWindowsOption: Unknown option %d", windowsOption); + return NULL_REG; + } +} + +reg_t kWinHelp(EngineState *s, int argc, reg_t *argv) { + switch (argv[0].toUint16()) { + case 1: + // Load a help file + // Maybe in the future we can implement this, but for now this message should suffice + showScummVMDialog("Please use an external viewer to open the game's help file: " + s->_segMan->getString(argv[1])); + break; + case 2: + // Looks like some init function + break; + default: + warning("Unknown kWinHelp subop %d", argv[0].toUint16()); + } + + return s->r_acc; +} + +// Taken from the SCI16 GfxTransitions class +static void fadeOut() { + byte oldPalette[3 * 256], workPalette[3 * 256]; + int16 stepNr, colorNr; + // Sierra did not fade in/out color 255 for sci1.1, but they used it in + // several pictures (e.g. qfg3 demo/intro), so the fading looked weird + int16 tillColorNr = getSciVersion() >= SCI_VERSION_1_1 ? 255 : 254; + + g_system->getPaletteManager()->grabPalette(oldPalette, 0, 256); + + for (stepNr = 100; stepNr >= 0; stepNr -= 10) { + for (colorNr = 1; colorNr <= tillColorNr; colorNr++) { + if (g_sci->_gfxPalette->colorIsFromMacClut(colorNr)) { + workPalette[colorNr * 3 + 0] = oldPalette[colorNr * 3]; + workPalette[colorNr * 3 + 1] = oldPalette[colorNr * 3 + 1]; + workPalette[colorNr * 3 + 2] = oldPalette[colorNr * 3 + 2]; + } else { + workPalette[colorNr * 3 + 0] = oldPalette[colorNr * 3] * stepNr / 100; + workPalette[colorNr * 3 + 1] = oldPalette[colorNr * 3 + 1] * stepNr / 100; + workPalette[colorNr * 3 + 2] = oldPalette[colorNr * 3 + 2] * stepNr / 100; + } + } + g_system->getPaletteManager()->setPalette(workPalette + 3, 1, tillColorNr); + g_sci->getEngineState()->wait(2); + } +} + +// Taken from the SCI16 GfxTransitions class +static void fadeIn() { + int16 stepNr; + // Sierra did not fade in/out color 255 for sci1.1, but they used it in + // several pictures (e.g. qfg3 demo/intro), so the fading looked weird + int16 tillColorNr = getSciVersion() >= SCI_VERSION_1_1 ? 255 : 254; + + for (stepNr = 0; stepNr <= 100; stepNr += 10) { + g_sci->_gfxPalette->kernelSetIntensity(1, tillColorNr + 1, stepNr, true); + g_sci->getEngineState()->wait(2); + } +} + +/** + * Used for scene transitions, replacing (but reusing parts of) the old + * transition code. + */ +reg_t kSetShowStyle(EngineState *s, int argc, reg_t *argv) { + // Can be called with 7 or 8 parameters + // The style defines which transition to perform. Related to the transition + // tables inside graphics/transitions.cpp + uint16 showStyle = argv[0].toUint16(); // 0 - 15 + reg_t planeObj = argv[1]; // the affected plane + uint16 seconds = argv[2].toUint16(); // seconds that the transition lasts + uint16 backColor = argv[3].toUint16(); // target back color(?). When fading out, it's 0x0000. When fading in, it's 0xffff + int16 priority = argv[4].toSint16(); // always 0xc8 (200) when fading in/out + uint16 animate = argv[5].toUint16(); // boolean, animate or not while the transition lasts + uint16 refFrame = argv[6].toUint16(); // refFrame, always 0 when fading in/out + int16 divisions; + + // If the game has the pFadeArray selector, another parameter is used here, + // before the optional last parameter + bool hasFadeArray = g_sci->getKernel()->findSelector("pFadeArray") > 0; + if (hasFadeArray) { + // argv[7] + divisions = (argc >= 9) ? argv[8].toSint16() : -1; // divisions (transition steps?) + } else { + divisions = (argc >= 8) ? argv[7].toSint16() : -1; // divisions (transition steps?) + } + + if (showStyle > 15) { + warning("kSetShowStyle: Illegal style %d for plane %04x:%04x", showStyle, PRINT_REG(planeObj)); + return s->r_acc; + } + + // TODO: Proper implementation. This is a very basic version. I'm not even + // sure if the rest of the styles will work with this mechanism. + + // Check if the passed parameters are the ones we expect + if (showStyle == 13 || showStyle == 14) { // fade out / fade in + if (seconds != 1) + warning("kSetShowStyle(fade): seconds isn't 1, it's %d", seconds); + if (backColor != 0 && backColor != 0xFFFF) + warning("kSetShowStyle(fade): backColor isn't 0 or 0xFFFF, it's %d", backColor); + if (priority != 200) + warning("kSetShowStyle(fade): priority isn't 200, it's %d", priority); + if (animate != 0) + warning("kSetShowStyle(fade): animate isn't 0, it's %d", animate); + if (refFrame != 0) + warning("kSetShowStyle(fade): refFrame isn't 0, it's %d", refFrame); + if (divisions >= 0 && divisions != 20) + warning("kSetShowStyle(fade): divisions isn't 20, it's %d", divisions); + } + + // TODO: Check if the plane is in the list of planes to draw + + switch (showStyle) { + //case 0: // no transition, perhaps? (like in the previous SCI versions) + case 13: // fade out + // TODO: Temporary implementation, which ignores all additional parameters + fadeOut(); + break; + case 14: // fade in + // TODO: Temporary implementation, which ignores all additional parameters + g_sci->_gfxFrameout->kernelFrameout(); // draw new scene before fading in + fadeIn(); + break; + default: + // TODO: This is all a stub/skeleton, thus we're invoking kStub() for now + kStub(s, argc, argv); + break; + } + + return s->r_acc; +} + +reg_t kCelInfo(EngineState *s, int argc, reg_t *argv) { + // Used by Shivers 1, room 23601 to determine what blocks on the red door puzzle board + // are occupied by pieces already + + switch (argv[0].toUint16()) { // subops 0 - 4 + // 0 - return the view + // 1 - return the loop + // 2, 3 - nop + case 4: { + GuiResourceId viewId = argv[1].toSint16(); + int16 loopNo = argv[2].toSint16(); + int16 celNo = argv[3].toSint16(); + int16 x = argv[4].toUint16(); + int16 y = argv[5].toUint16(); + byte color = g_sci->_gfxCache->kernelViewGetColorAtCoordinate(viewId, loopNo, celNo, x, y); + return make_reg(0, color); + } + default: { + kStub(s, argc, argv); + return s->r_acc; + } + } +} + +reg_t kScrollWindow(EngineState *s, int argc, reg_t *argv) { + // Used by Phantasmagoria 1 and SQ6. In SQ6, it is used for the messages + // shown in the scroll window at the bottom of the screen. + + // TODO: This is all a stub/skeleton, thus we're invoking kStub() for now + kStub(s, argc, argv); + + switch (argv[0].toUint16()) { + case 0: // Init + // 2 parameters + // argv[1] points to the scroll object (e.g. textScroller in SQ6) + // argv[2] is an integer (e.g. 0x32) + break; + case 1: // Show message + // 5 or 6 parameters + // Seems to be called with 5 parameters when the narrator speaks, and + // with 6 when Roger speaks + // argv[1] unknown (usually 0) + // argv[2] the text to show + // argv[3] a small integer (e.g. 0x32) + // argv[4] a small integer (e.g. 0x54) + // argv[5] optional, unknown (usually 0) + warning("kScrollWindow: '%s'", s->_segMan->getString(argv[2]).c_str()); + break; + case 2: // Clear + // 2 parameters + // TODO + break; + case 3: // Page up + // 2 parameters + // TODO + break; + case 4: // Page down + // 2 parameters + // TODO + break; + case 5: // Up arrow + // 2 parameters + // TODO + break; + case 6: // Down arrow + // 2 parameters + // TODO + break; + case 7: // Home + // 2 parameters + // TODO + break; + case 8: // End + // 2 parameters + // TODO + break; + case 9: // Resize + // 3 parameters + // TODO + break; + case 10: // Where + // 3 parameters + // TODO + break; + case 11: // Go + // 4 parameters + // TODO + break; + case 12: // Insert + // 7 parameters + // TODO + break; + case 13: // Delete + // 3 parameters + // TODO + break; + case 14: // Modify + // 7 or 8 parameters + // TODO + break; + case 15: // Hide + // 2 parameters + // TODO + break; + case 16: // Show + // 2 parameters + // TODO + break; + case 17: // Destroy + // 2 parameters + // TODO + break; + case 18: // Text + // 2 parameters + // TODO + break; + case 19: // Reconstruct + // 3 parameters + // TODO + break; + default: + error("kScrollWindow: unknown subop %d", argv[0].toUint16()); + break; + } + + return s->r_acc; +} + +reg_t kSetFontRes(EngineState *s, int argc, reg_t *argv) { + // TODO: This defines the resolution that the fonts are supposed to be displayed + // in. Currently, this is only used for showing high-res fonts in GK1 Mac, but + // should be extended to handle other font resolutions such as those + + int xResolution = argv[0].toUint16(); + //int yResolution = argv[1].toUint16(); + + g_sci->_gfxScreen->setFontIsUpscaled(xResolution == 640 && + g_sci->_gfxScreen->getUpscaledHires() != GFX_SCREEN_UPSCALED_DISABLED); + + return s->r_acc; +} + +reg_t kFont(EngineState *s, int argc, reg_t *argv) { + // Handle font settings for SCI2.1 + + switch (argv[0].toUint16()) { + case 1: + // Set font resolution + return kSetFontRes(s, argc - 1, argv + 1); + default: + warning("kFont: unknown subop %d", argv[0].toUint16()); + } + + return s->r_acc; +} + +// TODO: Eventually, all of the kBitmap operations should be put +// in a separate class + +#define BITMAP_HEADER_SIZE 46 + +reg_t kBitmap(EngineState *s, int argc, reg_t *argv) { + // Used for bitmap operations in SCI2.1 and SCI3. + // This is the SCI2.1 version, the functionality seems to have changed in SCI3. + + switch (argv[0].toUint16()) { + case 0: // init bitmap surface + { + // 6 params, called e.g. from TextView::init() in Torin's Passage, + // script 64890 and TransView::init() in script 64884 + uint16 width = argv[1].toUint16(); + uint16 height = argv[2].toUint16(); + //uint16 skip = argv[3].toUint16(); + uint16 back = argv[4].toUint16(); // usually equals skip + //uint16 width2 = (argc >= 6) ? argv[5].toUint16() : 0; + //uint16 height2 = (argc >= 7) ? argv[6].toUint16() : 0; + //uint16 transparentFlag = (argc >= 8) ? argv[7].toUint16() : 0; + + // TODO: skip, width2, height2, transparentFlag + // (used for transparent bitmaps) + int entrySize = width * height + BITMAP_HEADER_SIZE; + reg_t memoryId = s->_segMan->allocateHunkEntry("Bitmap()", entrySize); + byte *memoryPtr = s->_segMan->getHunkPointer(memoryId); + memset(memoryPtr, 0, BITMAP_HEADER_SIZE); // zero out the bitmap header + memset(memoryPtr + BITMAP_HEADER_SIZE, back, width * height); + // Save totalWidth, totalHeight + // TODO: Save the whole bitmap header, like SSCI does + WRITE_LE_UINT16(memoryPtr, width); + WRITE_LE_UINT16(memoryPtr + 2, height); + return memoryId; + } + break; + case 1: // dispose text bitmap surface + return kDisposeTextBitmap(s, argc - 1, argv + 1); + case 2: // dispose bitmap surface, with extra param + // 2 params, called e.g. from MenuItem::dispose in Torin's Passage, + // script 64893 + warning("kBitmap(2), unk1 %d, bitmap ptr %04x:%04x", argv[1].toUint16(), PRINT_REG(argv[2])); + break; + case 3: // tiled surface + { + // 6 params, called e.g. from TiledBitmap::resize() in Torin's Passage, + // script 64869 + reg_t hunkId = argv[1]; // obtained from kBitmap(0) + // The tiled view seems to always have 2 loops. + // These loops need to have 1 cel in loop 0 and 8 cels in loop 1. + uint16 viewNum = argv[2].toUint16(); // vTiles selector + uint16 loop = argv[3].toUint16(); + uint16 cel = argv[4].toUint16(); + uint16 x = argv[5].toUint16(); + uint16 y = argv[6].toUint16(); + + byte *memoryPtr = s->_segMan->getHunkPointer(hunkId); + // Get totalWidth, totalHeight + uint16 totalWidth = READ_LE_UINT16(memoryPtr); + uint16 totalHeight = READ_LE_UINT16(memoryPtr + 2); + byte *bitmap = memoryPtr + BITMAP_HEADER_SIZE; + + GfxView *view = g_sci->_gfxCache->getView(viewNum); + uint16 tileWidth = view->getWidth(loop, cel); + uint16 tileHeight = view->getHeight(loop, cel); + const byte *tileBitmap = view->getBitmap(loop, cel); + uint16 width = MIN(totalWidth - x, tileWidth); + uint16 height = MIN(totalHeight - y, tileHeight); + + for (uint16 curY = 0; curY < height; curY++) { + for (uint16 curX = 0; curX < width; curX++) { + bitmap[(curY + y) * totalWidth + (curX + x)] = tileBitmap[curY * tileWidth + curX]; + } + } + + } + break; + case 4: // add text to bitmap + { + // 13 params, called e.g. from TextButton::createBitmap() in Torin's Passage, + // script 64894 + reg_t hunkId = argv[1]; // obtained from kBitmap(0) + Common::String text = s->_segMan->getString(argv[2]); + uint16 textX = argv[3].toUint16(); + uint16 textY = argv[4].toUint16(); + //reg_t unk5 = argv[5]; + //reg_t unk6 = argv[6]; + //reg_t unk7 = argv[7]; // skip? + //reg_t unk8 = argv[8]; // back? + //reg_t unk9 = argv[9]; + uint16 fontId = argv[10].toUint16(); + //uint16 mode = argv[11].toUint16(); + uint16 dimmed = argv[12].toUint16(); + //warning("kBitmap(4): bitmap ptr %04x:%04x, font %d, mode %d, dimmed %d - text: \"%s\"", + // PRINT_REG(bitmapPtr), font, mode, dimmed, text.c_str()); + uint16 foreColor = 255; // TODO + + byte *memoryPtr = s->_segMan->getHunkPointer(hunkId); + // Get totalWidth, totalHeight + uint16 totalWidth = READ_LE_UINT16(memoryPtr); + uint16 totalHeight = READ_LE_UINT16(memoryPtr + 2); + byte *bitmap = memoryPtr + BITMAP_HEADER_SIZE; + + GfxFont *font = g_sci->_gfxCache->getFont(fontId); + + int16 charCount = 0; + uint16 curX = textX, curY = textY; + const char *txt = text.c_str(); + + while (*txt) { + charCount = g_sci->_gfxText32->GetLongest(txt, totalWidth, font); + if (charCount == 0) + break; + + for (int i = 0; i < charCount; i++) { + unsigned char curChar = txt[i]; + font->drawToBuffer(curChar, curY, curX, foreColor, dimmed, bitmap, totalWidth, totalHeight); + curX += font->getCharWidth(curChar); + } + + curX = textX; + curY += font->getHeight(); + txt += charCount; + while (*txt == ' ') + txt++; // skip over breaking spaces + } + + } + break; + case 5: // fill with color + { + // 6 params, called e.g. from TextView::init() and TextView::draw() + // in Torin's Passage, script 64890 + reg_t hunkId = argv[1]; // obtained from kBitmap(0) + uint16 x = argv[2].toUint16(); + uint16 y = argv[3].toUint16(); + uint16 fillWidth = argv[4].toUint16(); // width - 1 + uint16 fillHeight = argv[5].toUint16(); // height - 1 + uint16 back = argv[6].toUint16(); + + byte *memoryPtr = s->_segMan->getHunkPointer(hunkId); + // Get totalWidth, totalHeight + uint16 totalWidth = READ_LE_UINT16(memoryPtr); + uint16 totalHeight = READ_LE_UINT16(memoryPtr + 2); + uint16 width = MIN(totalWidth - x, fillWidth); + uint16 height = MIN(totalHeight - y, fillHeight); + byte *bitmap = memoryPtr + BITMAP_HEADER_SIZE; + + for (uint16 curY = 0; curY < height; curY++) { + for (uint16 curX = 0; curX < width; curX++) { + bitmap[(curY + y) * totalWidth + (curX + x)] = back; + } + } + + } + break; + default: + kStub(s, argc, argv); + break; + } + + return s->r_acc; +} + +// Used for edit boxes in save/load dialogs. It's a rewritten version of kEditControl, +// but it handles events on its own, using an internal loop, instead of using SCI +// scripts for event management like kEditControl does. Called by script 64914, +// DEdit::hilite(). +reg_t kEditText(EngineState *s, int argc, reg_t *argv) { + reg_t controlObject = argv[0]; + + if (!controlObject.isNull()) { + g_sci->_gfxControls32->kernelTexteditChange(controlObject); + } + + return s->r_acc; +} + +#endif + +} // End of namespace Sci diff --git a/engines/sci/module.mk b/engines/sci/module.mk index 90a0f33f06..2842e4724e 100644 --- a/engines/sci/module.mk +++ b/engines/sci/module.mk @@ -81,6 +81,7 @@ ifdef ENABLE_SCI32 MODULE_OBJS += \ graphics/controls32.o \ graphics/frameout.o \ + engine/kgraphics32.o \ graphics/paint32.o \ graphics/text32.o \ video/robot_decoder.o -- cgit v1.2.3 From 6fb9511c93393a73a7177ed5fb56c3776e5f3a23 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sun, 20 May 2012 20:26:45 +0300 Subject: SCI: Remove the hackish (and wrong) SCI32 fade code --- engines/sci/engine/kgraphics32.cpp | 75 +++++--------------------------------- 1 file changed, 9 insertions(+), 66 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/engine/kgraphics32.cpp b/engines/sci/engine/kgraphics32.cpp index 178c5d6e43..786a58aae9 100644 --- a/engines/sci/engine/kgraphics32.cpp +++ b/engines/sci/engine/kgraphics32.cpp @@ -25,7 +25,6 @@ #include "engines/util.h" #include "graphics/cursorman.h" #include "graphics/surface.h" -#include "graphics/palette.h" // temporary, for the fadeIn()/fadeOut() functions below #include "gui/message.h" @@ -227,46 +226,6 @@ reg_t kWinHelp(EngineState *s, int argc, reg_t *argv) { return s->r_acc; } -// Taken from the SCI16 GfxTransitions class -static void fadeOut() { - byte oldPalette[3 * 256], workPalette[3 * 256]; - int16 stepNr, colorNr; - // Sierra did not fade in/out color 255 for sci1.1, but they used it in - // several pictures (e.g. qfg3 demo/intro), so the fading looked weird - int16 tillColorNr = getSciVersion() >= SCI_VERSION_1_1 ? 255 : 254; - - g_system->getPaletteManager()->grabPalette(oldPalette, 0, 256); - - for (stepNr = 100; stepNr >= 0; stepNr -= 10) { - for (colorNr = 1; colorNr <= tillColorNr; colorNr++) { - if (g_sci->_gfxPalette->colorIsFromMacClut(colorNr)) { - workPalette[colorNr * 3 + 0] = oldPalette[colorNr * 3]; - workPalette[colorNr * 3 + 1] = oldPalette[colorNr * 3 + 1]; - workPalette[colorNr * 3 + 2] = oldPalette[colorNr * 3 + 2]; - } else { - workPalette[colorNr * 3 + 0] = oldPalette[colorNr * 3] * stepNr / 100; - workPalette[colorNr * 3 + 1] = oldPalette[colorNr * 3 + 1] * stepNr / 100; - workPalette[colorNr * 3 + 2] = oldPalette[colorNr * 3 + 2] * stepNr / 100; - } - } - g_system->getPaletteManager()->setPalette(workPalette + 3, 1, tillColorNr); - g_sci->getEngineState()->wait(2); - } -} - -// Taken from the SCI16 GfxTransitions class -static void fadeIn() { - int16 stepNr; - // Sierra did not fade in/out color 255 for sci1.1, but they used it in - // several pictures (e.g. qfg3 demo/intro), so the fading looked weird - int16 tillColorNr = getSciVersion() >= SCI_VERSION_1_1 ? 255 : 254; - - for (stepNr = 0; stepNr <= 100; stepNr += 10) { - g_sci->_gfxPalette->kernelSetIntensity(1, tillColorNr + 1, stepNr, true); - g_sci->getEngineState()->wait(2); - } -} - /** * Used for scene transitions, replacing (but reusing parts of) the old * transition code. @@ -299,38 +258,22 @@ reg_t kSetShowStyle(EngineState *s, int argc, reg_t *argv) { return s->r_acc; } - // TODO: Proper implementation. This is a very basic version. I'm not even - // sure if the rest of the styles will work with this mechanism. - - // Check if the passed parameters are the ones we expect - if (showStyle == 13 || showStyle == 14) { // fade out / fade in - if (seconds != 1) - warning("kSetShowStyle(fade): seconds isn't 1, it's %d", seconds); - if (backColor != 0 && backColor != 0xFFFF) - warning("kSetShowStyle(fade): backColor isn't 0 or 0xFFFF, it's %d", backColor); - if (priority != 200) - warning("kSetShowStyle(fade): priority isn't 200, it's %d", priority); - if (animate != 0) - warning("kSetShowStyle(fade): animate isn't 0, it's %d", animate); - if (refFrame != 0) - warning("kSetShowStyle(fade): refFrame isn't 0, it's %d", refFrame); - if (divisions >= 0 && divisions != 20) - warning("kSetShowStyle(fade): divisions isn't 20, it's %d", divisions); - } + // GK1 calls fadeout (13) / fadein (14) with the following parameters: + // seconds: 1 + // backColor: 0 / -1 + // fade: 200 + // animate: 0 + // refFrame: 0 + // divisions: 0 / 20 // TODO: Check if the plane is in the list of planes to draw switch (showStyle) { //case 0: // no transition, perhaps? (like in the previous SCI versions) case 13: // fade out - // TODO: Temporary implementation, which ignores all additional parameters - fadeOut(); - break; + // TODO case 14: // fade in - // TODO: Temporary implementation, which ignores all additional parameters - g_sci->_gfxFrameout->kernelFrameout(); // draw new scene before fading in - fadeIn(); - break; + // TODO default: // TODO: This is all a stub/skeleton, thus we're invoking kStub() for now kStub(s, argc, argv); -- cgit v1.2.3 From b5eac1b35b5982a86bbe6d7a672609de8ef717a0 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sun, 20 May 2012 21:35:27 +0300 Subject: SCI: Fix case of the SciOpcodes enum --- engines/sci/engine/vm.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines/sci') diff --git a/engines/sci/engine/vm.h b/engines/sci/engine/vm.h index 23f5a09d34..cdd9b9a06e 100644 --- a/engines/sci/engine/vm.h +++ b/engines/sci/engine/vm.h @@ -139,7 +139,7 @@ enum { GC_INTERVAL = 0x8000 }; -enum sciOpcodes { +enum SciOpcodes { op_bnot = 0x00, // 000 op_add = 0x01, // 001 op_sub = 0x02, // 002 -- cgit v1.2.3 From 6cda15ba8e57891471c53449433385f5992bce3a Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Mon, 21 May 2012 01:29:30 +0300 Subject: SCI: Added two new debug commands, plane_list and plane_items These can be used to debug drawn items in SCI32 --- engines/sci/console.cpp | 54 ++++++++++++++++++++++++++++++++++++++- engines/sci/console.h | 2 ++ engines/sci/graphics/frameout.cpp | 51 ++++++++++++++++++++++++++++++++++++ engines/sci/graphics/frameout.h | 2 ++ 4 files changed, 108 insertions(+), 1 deletion(-) (limited to 'engines/sci') diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp index 9607a8e66d..5b5301b468 100644 --- a/engines/sci/console.cpp +++ b/engines/sci/console.cpp @@ -53,6 +53,7 @@ #include "video/avi_decoder.h" #include "sci/video/seq_decoder.h" #ifdef ENABLE_SCI32 +#include "sci/graphics/frameout.h" #include "video/coktel_decoder.h" #include "sci/video/robot_decoder.h" #endif @@ -131,6 +132,10 @@ Console::Console(SciEngine *engine) : GUI::Debugger(), DCmd_Register("al", WRAP_METHOD(Console, cmdAnimateList)); // alias DCmd_Register("window_list", WRAP_METHOD(Console, cmdWindowList)); DCmd_Register("wl", WRAP_METHOD(Console, cmdWindowList)); // alias + DCmd_Register("plane_list", WRAP_METHOD(Console, cmdPlaneList)); + DCmd_Register("pl", WRAP_METHOD(Console, cmdPlaneList)); // alias + DCmd_Register("plane_items", WRAP_METHOD(Console, cmdPlaneItemList)); + DCmd_Register("pi", WRAP_METHOD(Console, cmdPlaneItemList)); // alias DCmd_Register("saved_bits", WRAP_METHOD(Console, cmdSavedBits)); DCmd_Register("show_saved_bits", WRAP_METHOD(Console, cmdShowSavedBits)); // Segments @@ -365,7 +370,9 @@ bool Console::cmdHelp(int argc, const char **argv) { DebugPrintf(" pic_visualize - Enables visualization of the drawing process of EGA pictures\n"); DebugPrintf(" undither - Enable/disable undithering\n"); DebugPrintf(" play_video - Plays a SEQ, AVI, VMD, RBT or DUK video\n"); - DebugPrintf(" animate_object_list / al - Shows the current list of objects in kAnimate's draw list\n"); + DebugPrintf(" animate_list / al - Shows the current list of objects in kAnimate's draw list (SCI0 - SCI1.1)\n"); + DebugPrintf(" window_list / wl - Shows a list of all the windows (ports) in the draw list (SCI0 - SCI1.1)\n"); + DebugPrintf(" plane_list / pl - Shows a list of all the planes in the draw list (SCI2+)\n"); DebugPrintf(" saved_bits - List saved bits on the hunk\n"); DebugPrintf(" show_saved_bits - Display saved bits\n"); DebugPrintf("\n"); @@ -1589,6 +1596,8 @@ bool Console::cmdAnimateList(int argc, const char **argv) { if (_engine->_gfxAnimate) { DebugPrintf("Animate list:\n"); _engine->_gfxAnimate->printAnimateList(this); + } else { + DebugPrintf("This SCI version does not have an animate list\n"); } return true; } @@ -1597,9 +1606,52 @@ bool Console::cmdWindowList(int argc, const char **argv) { if (_engine->_gfxPorts) { DebugPrintf("Window list:\n"); _engine->_gfxPorts->printWindowList(this); + } else { + DebugPrintf("This SCI version does not have a list of ports\n"); } return true; +} +bool Console::cmdPlaneList(int argc, const char **argv) { +#ifdef ENABLE_SCI32 + if (_engine->_gfxFrameout) { + DebugPrintf("Plane list:\n"); + _engine->_gfxFrameout->printPlaneList(this); + } else { + DebugPrintf("This SCI version does not have a list of planes\n"); + } +#else + DebugPrintf("SCI32 isn't included in this compiled executable\n"); +#endif + return true; +} + +bool Console::cmdPlaneItemList(int argc, const char **argv) { + if (argc != 2) { + DebugPrintf("Shows the list of items for a plane\n"); + DebugPrintf("Usage: %s \n", argv[0]); + return true; + } + + reg_t planeObject = NULL_REG; + + if (parse_reg_t(_engine->_gamestate, argv[1], &planeObject, false)) { + DebugPrintf("Invalid address passed.\n"); + DebugPrintf("Check the \"addresses\" command on how to use addresses\n"); + return true; + } + +#ifdef ENABLE_SCI32 + if (_engine->_gfxFrameout) { + DebugPrintf("Plane item list:\n"); + _engine->_gfxFrameout->printPlaneItemList(this, planeObject); + } else { + DebugPrintf("This SCI version does not have a list of plane items\n"); + } +#else + DebugPrintf("SCI32 isn't included in this compiled executable\n"); +#endif + return true; } bool Console::cmdSavedBits(int argc, const char **argv) { diff --git a/engines/sci/console.h b/engines/sci/console.h index d943923ba1..be17fdb728 100644 --- a/engines/sci/console.h +++ b/engines/sci/console.h @@ -94,6 +94,8 @@ private: bool cmdPlayVideo(int argc, const char **argv); bool cmdAnimateList(int argc, const char **argv); bool cmdWindowList(int argc, const char **argv); + bool cmdPlaneList(int argc, const char **argv); + bool cmdPlaneItemList(int argc, const char **argv); bool cmdSavedBits(int argc, const char **argv); bool cmdShowSavedBits(int argc, const char **argv); // Segments diff --git a/engines/sci/graphics/frameout.cpp b/engines/sci/graphics/frameout.cpp index 42b51e409d..709a708d8b 100644 --- a/engines/sci/graphics/frameout.cpp +++ b/engines/sci/graphics/frameout.cpp @@ -31,6 +31,7 @@ #include "graphics/surface.h" #include "sci/sci.h" +#include "sci/console.h" #include "sci/engine/kernel.h" #include "sci/engine/state.h" #include "sci/engine/selector.h" @@ -677,4 +678,54 @@ void GfxFrameout::kernelFrameout() { g_sci->getEngineState()->_throttleTrigger = true; } +void GfxFrameout::printPlaneList(Console *con) { + for (PlaneList::const_iterator it = _planes.begin(); it != _planes.end(); ++it) { + PlaneEntry p = *it; + Common::String curPlaneName = _segMan->getObjectName(p.object); + Common::Rect r = p.upscaledPlaneRect; + Common::Rect cr = p.upscaledPlaneClipRect; + + con->DebugPrintf("%04x:%04x (%s): prio %d, lastprio %d, offsetX %d, offsetY %d, pic %d, mirror %d, back %d\n", + PRINT_REG(p.object), curPlaneName.c_str(), + (int16)p.priority, (int16)p.lastPriority, + p.planeOffsetX, p.planeOffsetY, p.pictureId, + p.planePictureMirrored, p.planeBack); + con->DebugPrintf(" rect: (%d, %d, %d, %d), clip rect: (%d, %d, %d, %d)\n", + r.left, r.top, r.right, r.bottom, + cr.left, cr.top, cr.right, cr.bottom); + + if (p.pictureId != 0xffff && p.pictureId != 0xfffe) { + con->DebugPrintf("Pictures:\n"); + + for (PlanePictureList::iterator pictureIt = _planePictures.begin(); pictureIt != _planePictures.end(); pictureIt++) { + if (pictureIt->object == p.object) { + con->DebugPrintf(" Picture %d: x %d, y %d\n", pictureIt->pictureId, pictureIt->startX, pictureIt->startY); + } + } + } + } +} + +void GfxFrameout::printPlaneItemList(Console *con, reg_t planeObject) { + for (FrameoutList::iterator listIterator = _screenItems.begin(); listIterator != _screenItems.end(); listIterator++) { + FrameoutEntry *e = *listIterator; + reg_t itemPlane = readSelector(_segMan, e->object, SELECTOR(plane)); + + if (planeObject == itemPlane) { + Common::String curItemName = _segMan->getObjectName(e->object); + Common::Rect icr = e->celRect; + GuiResourceId picId = e->picture ? e->picture->getResourceId() : 0; + + con->DebugPrintf("%d: %04x:%04x (%s), view %d, loop %d, cel %d, x %d, y %d, z %d, " + "signal %d, scale signal %d, scaleX %d, scaleY %d, rect (%d, %d, %d, %d), " + "pic %d, picX %d, picY %d, visible %d\n", + e->givenOrderNr, PRINT_REG(e->object), curItemName.c_str(), + e->viewId, e->loopNo, e->celNo, e->x, e->y, e->z, + e->signal, e->scaleSignal, e->scaleX, e->scaleY, + icr.left, icr.top, icr.right, icr.bottom, + picId, e->picStartX, e->picStartY, e->visible); + } + } +} + } // End of namespace Sci diff --git a/engines/sci/graphics/frameout.h b/engines/sci/graphics/frameout.h index a3d686c592..ec4de62c0a 100644 --- a/engines/sci/graphics/frameout.h +++ b/engines/sci/graphics/frameout.h @@ -104,6 +104,8 @@ public: void addPlanePicture(reg_t object, GuiResourceId pictureId, uint16 startX, uint16 startY = 0); void deletePlanePictures(reg_t object); void clear(); + void printPlaneList(Console *con); + void printPlaneItemList(Console *con, reg_t planeObject); private: void showVideo(); -- cgit v1.2.3 From a07840931a638bffd9fc0e7325f87b745fc4af24 Mon Sep 17 00:00:00 2001 From: Matthew Hoops Date: Mon, 21 May 2012 00:06:42 -0400 Subject: SCI: Properly alphabetize the SCI32 objects --- engines/sci/module.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines/sci') diff --git a/engines/sci/module.mk b/engines/sci/module.mk index 2842e4724e..b6d5837b31 100644 --- a/engines/sci/module.mk +++ b/engines/sci/module.mk @@ -79,9 +79,9 @@ MODULE_OBJS := \ ifdef ENABLE_SCI32 MODULE_OBJS += \ + engine/kgraphics32.o \ graphics/controls32.o \ graphics/frameout.o \ - engine/kgraphics32.o \ graphics/paint32.o \ graphics/text32.o \ video/robot_decoder.o -- cgit v1.2.3 From 92b907e8560c689e6c61ccda9a08ae8306655db9 Mon Sep 17 00:00:00 2001 From: Matthew Hoops Date: Mon, 21 May 2012 00:07:28 -0400 Subject: SCI: Silence unused variable warnings --- engines/sci/engine/kgraphics32.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/engine/kgraphics32.cpp b/engines/sci/engine/kgraphics32.cpp index 786a58aae9..2bb8288cb7 100644 --- a/engines/sci/engine/kgraphics32.cpp +++ b/engines/sci/engine/kgraphics32.cpp @@ -236,11 +236,11 @@ reg_t kSetShowStyle(EngineState *s, int argc, reg_t *argv) { // tables inside graphics/transitions.cpp uint16 showStyle = argv[0].toUint16(); // 0 - 15 reg_t planeObj = argv[1]; // the affected plane - uint16 seconds = argv[2].toUint16(); // seconds that the transition lasts - uint16 backColor = argv[3].toUint16(); // target back color(?). When fading out, it's 0x0000. When fading in, it's 0xffff - int16 priority = argv[4].toSint16(); // always 0xc8 (200) when fading in/out - uint16 animate = argv[5].toUint16(); // boolean, animate or not while the transition lasts - uint16 refFrame = argv[6].toUint16(); // refFrame, always 0 when fading in/out + //uint16 seconds = argv[2].toUint16(); // seconds that the transition lasts + //uint16 backColor = argv[3].toUint16(); // target back color(?). When fading out, it's 0x0000. When fading in, it's 0xffff + //int16 priority = argv[4].toSint16(); // always 0xc8 (200) when fading in/out + //uint16 animate = argv[5].toUint16(); // boolean, animate or not while the transition lasts + //uint16 refFrame = argv[6].toUint16(); // refFrame, always 0 when fading in/out int16 divisions; // If the game has the pFadeArray selector, another parameter is used here, -- cgit v1.2.3 From 5a8a28bb22ac986e2f18a93fd6afd0252b5a2333 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Tue, 22 May 2012 10:45:57 +0300 Subject: SCI: Add a workaround for a hack used in the NRS script patches for QFG3 The patched script 33 in the NRS patch attempts to perform kAbs() on an object. Return a dummy value instead. Fixes bugs #3528416 and #3528542 --- engines/sci/engine/workarounds.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'engines/sci') diff --git a/engines/sci/engine/workarounds.cpp b/engines/sci/engine/workarounds.cpp index 81c6fbb246..c1d4a3d9f9 100644 --- a/engines/sci/engine/workarounds.cpp +++ b/engines/sci/engine/workarounds.cpp @@ -176,6 +176,7 @@ const SciWorkaroundEntry kAbs_workarounds[] = { { GID_HOYLE1, 2, 2, 0, "room2", "doit", -1, 0, { WORKAROUND_FAKE, 0x3e9 } }, // old maid - called with objects instead of integers { GID_HOYLE1, 3, 3, 0, "room3", "doit", -1, 0, { WORKAROUND_FAKE, 0x3e9 } }, // hearts - called with objects instead of integers { GID_QFG1VGA, -1, -1, 0, NULL, "doit", -1, 0, { WORKAROUND_FAKE, 0x3e9 } }, // when the game is patched with the NRS patch + { GID_QFG3 , -1, -1, 0, NULL, "doit", -1, 0, { WORKAROUND_FAKE, 0x3e9 } }, // when the game is patched with the NRS patch (bugs #3528416, #3528542) SCI_WORKAROUNDENTRY_TERMINATOR }; -- cgit v1.2.3 From a1554b9ddd719efc97cbf344fe84d20416810b0b Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Tue, 22 May 2012 10:47:04 +0300 Subject: SCI: Fix the detection of the NRS patch for QFG3 --- engines/sci/sci.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines/sci') diff --git a/engines/sci/sci.cpp b/engines/sci/sci.cpp index 9b0ee6924b..960016764a 100644 --- a/engines/sci/sci.cpp +++ b/engines/sci/sci.cpp @@ -385,7 +385,7 @@ bool SciEngine::gameHasFanMadePatch() { { GID_PQ3, 994, 4686, 1291, 0x78 }, // English { GID_PQ3, 994, 4734, 1283, 0x78 }, // German { GID_QFG1VGA, 994, 4388, 0, 0x00 }, - { GID_QFG3, 994, 4714, 0, 0x00 }, + { GID_QFG3, 33, 260, 0, 0x00 }, // TODO: Disabled, as it fixes a whole lot of bugs which can't be tested till SCI2.1 support is finished //{ GID_QFG4, 710, 11477, 0, 0x00 }, { GID_SQ1, 994, 4740, 0, 0x00 }, -- cgit v1.2.3 From beef27fc10bb714fe37f2ee0c35cd143dc706829 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Thu, 24 May 2012 01:43:03 +0300 Subject: SCI: Map the rarely used VibrateMouse kernel function to be an empty call This is a function used to implement vibration in the floppy version of QFG4 for exotic force feedback mice, such as the Logitech Cyberman --- engines/sci/engine/kernel_tables.h | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/engine/kernel_tables.h b/engines/sci/engine/kernel_tables.h index ff06b79d72..1fa12b01fd 100644 --- a/engines/sci/engine/kernel_tables.h +++ b/engines/sci/engine/kernel_tables.h @@ -507,13 +507,20 @@ static SciKernelMapEntry s_kernelMap[] = { // SetScroll - called by script 64909, Styler::doit() // PalCycle - called by Game::newRoom. Related to RemapColors. - // VibrateMouse - used in QFG4 // SCI2 Empty functions // Debug function used to track resources { MAP_EMPTY(ResourceTrack), SIG_EVERYWHERE, "(.*)", NULL, NULL }, - + // Future TODO: This call is used in the floppy version of QFG4 to add + // vibration to exotic mice with force feedback, such as the Logitech + // Cyberman and Wingman mice. Since this is only used for very exotic + // hardware and we have no direct and cross-platform way of communicating + // with them via SDL, plus we would probably need to make changes to common + // code, this call is mapped to an empty function for now as it's a rare + // feature not worth the effort. + { MAP_EMPTY(VibrateMouse), SIG_EVERYWHERE, "(.*)", NULL, NULL }, + // Unused / debug SCI2 unused functions, always mapped to kDummy // AddMagnify/DeleteMagnify are both called by script 64979 (the Magnifier -- cgit v1.2.3 From 79926b305cada849e7881b4d10b8dc1ea8ad522a Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sat, 26 May 2012 16:23:03 +0300 Subject: SCI: Bugfix for kFileIOReadRaw Avoid overwriting the target buffer with junk when no data has been read --- engines/sci/engine/kfile.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'engines/sci') diff --git a/engines/sci/engine/kfile.cpp b/engines/sci/engine/kfile.cpp index af438bdaff..b1f85227c1 100644 --- a/engines/sci/engine/kfile.cpp +++ b/engines/sci/engine/kfile.cpp @@ -812,7 +812,8 @@ reg_t kFileIOReadRaw(EngineState *s, int argc, reg_t *argv) { FileHandle *f = getFileFromHandle(s, handle); if (f) { bytesRead = f->_in->read(buf, size); - s->_segMan->memcpy(argv[1], (const byte*)buf, size); + if (bytesRead > 0) + s->_segMan->memcpy(argv[1], (const byte*)buf, size); } delete[] buf; -- cgit v1.2.3 From b4152bd7ebe70dfff210bb74798c30012371812e Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sat, 26 May 2012 16:32:37 +0300 Subject: SCI: Add some missing game-specific options --- engines/sci/detection_tables.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/detection_tables.h b/engines/sci/detection_tables.h index ff78d4f18b..506f79b4d8 100644 --- a/engines/sci/detection_tables.h +++ b/engines/sci/detection_tables.h @@ -445,7 +445,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "a4b73d5d2b55bdb6e44345e99c8fbdd0", 4804}, {"resource.000", 0, "d908dbef56816ac6c60dd145fdeafb2b", 3536046}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformWindows, ADGF_CD, GUIO1(GUIO_MIDIGM) }, + Common::EN_ANY, Common::kPlatformWindows, ADGF_CD, GUIO4(GUIO_MIDIGM, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Eco Quest - English DOS Floppy // SCI interpreter version 1.000.510 @@ -1007,7 +1007,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "459f5b04467bc2107aec02f5c4b71b37", 4878}, {"resource.001", 0, "3876da2ce16fb7dea2f5d943d946fa84", 1652150}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformWindows, ADGF_CD, GUIO2(GUIO_MIDIGM, GAMEOPTION_JONES_CDAUDIO) }, + Common::EN_ANY, Common::kPlatformWindows, ADGF_CD, GUIO4(GUIO_MIDIGM, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_FB01_MIDI, GAMEOPTION_JONES_CDAUDIO) }, // King's Quest 1 SCI Remake - English Amiga (from www.back2roots.org) // Executable scanning reports "1.003.007" @@ -1221,7 +1221,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.000", 0, "449471bfd77be52f18a3773c7f7d843d", 571368}, {"resource.001", 0, "b45a581ff8751e052c7e364f58d3617f", 16800210}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformWindows, ADGF_CD, GUIO1(GUIO_MIDIGM) }, + Common::EN_ANY, Common::kPlatformWindows, ADGF_CD, GUIO4(GUIO_MIDIGM, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // King's Quest 5 - English DOS Floppy // SCI interpreter version 1.000.060 -- cgit v1.2.3 From 5af1ccbac66925f4521419a36a970bff4259e984 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sat, 26 May 2012 16:41:11 +0300 Subject: SCI: Implement kGetConfig and kGetSierraProfileInt This fixes the sluggish game speed in Phantasmagoria (DOS/Windows) --- engines/sci/engine/kernel.h | 1 + engines/sci/engine/kernel_tables.h | 6 +---- engines/sci/engine/kmisc.cpp | 46 ++++++++++++++++++++++++++++++++++++-- 3 files changed, 46 insertions(+), 7 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/engine/kernel.h b/engines/sci/engine/kernel.h index 42651ec4a5..664c97f7b5 100644 --- a/engines/sci/engine/kernel.h +++ b/engines/sci/engine/kernel.h @@ -475,6 +475,7 @@ reg_t kMoveToEnd(EngineState *s, int argc, reg_t *argv); reg_t kGetWindowsOption(EngineState *s, int argc, reg_t *argv); reg_t kWinHelp(EngineState *s, int argc, reg_t *argv); reg_t kGetConfig(EngineState *s, int argc, reg_t *argv); +reg_t kGetSierraProfileInt(EngineState *s, int argc, reg_t *argv); reg_t kCelInfo(EngineState *s, int argc, reg_t *argv); reg_t kSetLanguage(EngineState *s, int argc, reg_t *argv); reg_t kScrollWindow(EngineState *s, int argc, reg_t *argv); diff --git a/engines/sci/engine/kernel_tables.h b/engines/sci/engine/kernel_tables.h index 1fa12b01fd..d8414b3b4c 100644 --- a/engines/sci/engine/kernel_tables.h +++ b/engines/sci/engine/kernel_tables.h @@ -560,6 +560,7 @@ static SciKernelMapEntry s_kernelMap[] = { { MAP_CALL(GetWindowsOption), SIG_EVERYWHERE, "i", NULL, NULL }, { MAP_CALL(WinHelp), SIG_EVERYWHERE, "(.*)", NULL, NULL }, { MAP_CALL(GetConfig), SIG_EVERYWHERE, "ro", NULL, NULL }, + { MAP_CALL(GetSierraProfileInt), SIG_EVERYWHERE, "rri", NULL, NULL }, { MAP_CALL(CelInfo), SIG_EVERYWHERE, "iiiiii", NULL, NULL }, { MAP_CALL(SetLanguage), SIG_EVERYWHERE, "r", NULL, NULL }, { MAP_CALL(ScrollWindow), SIG_EVERYWHERE, "(.*)", NULL, NULL }, @@ -579,11 +580,6 @@ static SciKernelMapEntry s_kernelMap[] = { // the game window in Phantasmagoria 2. We ignore these settings completely. { MAP_EMPTY(SetWindowsOption), SIG_EVERYWHERE, "ii", NULL, NULL }, - // Used by the Windows version of Phantasmagoria 1 to get the video speed setting. This is called after - // kGetConfig and overrides the setting obtained by it. It is a dummy function in the DOS Version. We can - // just use GetConfig and mark this one as empty, like the DOS version does. - { MAP_EMPTY(GetSierraProfileInt), SIG_EVERYWHERE, "(.*)", NULL, NULL }, - // Debug function called whenever the current room changes { MAP_EMPTY(NewRoom), SIG_EVERYWHERE, "(.*)", NULL, NULL }, diff --git a/engines/sci/engine/kmisc.cpp b/engines/sci/engine/kmisc.cpp index a32480c168..2be9432521 100644 --- a/engines/sci/engine/kmisc.cpp +++ b/engines/sci/engine/kmisc.cpp @@ -356,10 +356,52 @@ reg_t kGetConfig(EngineState *s, int argc, reg_t *argv) { Common::String setting = s->_segMan->getString(argv[0]); reg_t data = readSelector(s->_segMan, argv[1], SELECTOR(data)); - warning("Get config setting %s", setting.c_str()); - s->_segMan->strcpy(data, ""); + // This function is used to get the benchmarked results stored in the + // resource.cfg configuration file in Phantasmagoria 1. Normally, + // the configuration file contains values stored by the installer + // regarding audio and video settings, which are then used by the + // executable. In Phantasmagoria, two extra executable files are used + // to perform system benchmarks: + // - CPUID for the CPU benchmarks, sets the cpu and cpuspeed settings + // - HDDTEC for the graphics and CD-ROM benchmarks, sets the videospeed setting + // + // These settings are then used by the game scripts directly to modify + // the game speed and graphics output. The result of this call is stored + // in global 178. The scripts check these values against the value 425. + // Anything below that makes Phantasmagoria awfully sluggish, so we're + // setting everything to 500, which makes the game playable. + + if (setting == "videospeed") { + s->_segMan->strcpy(data, "500"); + } else if (setting == "cpu") { + // We always return the fastest CPU setting that CPUID can detect + // (i.e. 586). + s->_segMan->strcpy(data, "586"); + } else if (setting == "cpuspeed") { + s->_segMan->strcpy(data, "500"); + } else { + error("GetConfig: Unknown configuration setting %s", setting.c_str()); + } + return argv[1]; } + +reg_t kGetSierraProfileInt(EngineState *s, int argc, reg_t *argv) { + Common::String category = s->_segMan->getString(argv[0]); // always "config" + if (category != "config") + error("GetSierraProfileInt: category isn't 'config', it's '%s'", category.c_str()); + + Common::String setting = s->_segMan->getString(argv[1]); + if (setting != "videospeed") + error("GetSierraProfileInt: setting isn't 'videospeed', it's '%s'", setting.c_str()); + + // The game scripts pass 425 as the third parameter for some unknown reason, + // as after the call they compare the result to 425 anyway... + + // We return the same fake value for videospeed as with kGetConfig + return make_reg(0, 500); +} + #endif // kIconBar is really a subop of kMacPlatform for SCI1.1 Mac -- cgit v1.2.3 From f15582b190baeae3ab1ddf2b6fc9dc305810f5f0 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sat, 26 May 2012 16:42:38 +0300 Subject: SCI: Map another missing kFileIO call This is used to change directories in the save/load dialog (unused by us) --- engines/sci/engine/kernel_tables.h | 1 + 1 file changed, 1 insertion(+) (limited to 'engines/sci') diff --git a/engines/sci/engine/kernel_tables.h b/engines/sci/engine/kernel_tables.h index d8414b3b4c..4ddf0534ea 100644 --- a/engines/sci/engine/kernel_tables.h +++ b/engines/sci/engine/kernel_tables.h @@ -239,6 +239,7 @@ static const SciKernelMapSubEntry kFileIO_subops[] = { { SIG_SCI32, 15, MAP_CALL(FileIOReadWord), "i", NULL }, { SIG_SCI32, 16, MAP_CALL(FileIOWriteWord), "ii", NULL }, { SIG_SCI32, 17, MAP_CALL(FileIOCreateSaveSlot), "ir", NULL }, + { SIG_SCI32, 18, MAP_EMPTY(FileIOChangeDirectory), "r", NULL }, // for SQ6, when changing the savegame directory in the save/load dialog { SIG_SCI32, 19, MAP_CALL(Stub), "r", NULL }, // for Torin / Torin demo #endif SCI_SUBOPENTRY_TERMINATOR -- cgit v1.2.3 From e77fc29101dfec7e5e35559783dd4e729df8a0c7 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sat, 26 May 2012 19:06:54 +0300 Subject: SCI: Add a TODO in kFileIOReadRaw --- engines/sci/engine/kfile.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'engines/sci') diff --git a/engines/sci/engine/kfile.cpp b/engines/sci/engine/kfile.cpp index b1f85227c1..8d1b078697 100644 --- a/engines/sci/engine/kfile.cpp +++ b/engines/sci/engine/kfile.cpp @@ -812,6 +812,9 @@ reg_t kFileIOReadRaw(EngineState *s, int argc, reg_t *argv) { FileHandle *f = getFileFromHandle(s, handle); if (f) { bytesRead = f->_in->read(buf, size); + // TODO: What happens if less bytes are read than what has + // been requested? (i.e. if bytesRead is non-zero, but still + // less than size) if (bytesRead > 0) s->_segMan->memcpy(argv[1], (const byte*)buf, size); } -- cgit v1.2.3 From 10f7e805c20c164a7b3a20832237341136165e28 Mon Sep 17 00:00:00 2001 From: Matthew Hoops Date: Sun, 27 May 2012 21:18:32 -0400 Subject: VIDEO: Add volume/balance control to VideoDecoder --- engines/sci/video/robot_decoder.cpp | 12 +++++++++++- engines/sci/video/robot_decoder.h | 5 +++++ 2 files changed, 16 insertions(+), 1 deletion(-) (limited to 'engines/sci') diff --git a/engines/sci/video/robot_decoder.cpp b/engines/sci/video/robot_decoder.cpp index 77f45e0788..95b3c2abc1 100644 --- a/engines/sci/video/robot_decoder.cpp +++ b/engines/sci/video/robot_decoder.cpp @@ -116,7 +116,7 @@ bool RobotDecoder::loadStream(Common::SeekableReadStream *stream) { if (_header.hasSound) { _audioStream = Audio::makeQueuingAudioStream(11025, false); - _mixer->playStream(Audio::Mixer::kMusicSoundType, &_audioHandle, _audioStream); + _mixer->playStream(Audio::Mixer::kMusicSoundType, &_audioHandle, _audioStream, -1, getVolume(), getBalance()); } readPaletteChunk(_header.paletteDataSize); @@ -361,6 +361,16 @@ void RobotDecoder::close() { reset(); } +void RobotDecoder::updateVolume() { + if (g_system->getMixer()->isSoundHandleActive(_audioHandle)) + g_system->getMixer()->setChannelVolume(_audioHandle, getVolume()); +} + +void RobotDecoder::updateBalance() { + if (g_system->getMixer()->isSoundHandleActive(_audioHandle)) + g_system->getMixer()->setChannelBalance(_audioHandle, getBalance()); +} + #endif } // End of namespace Sci diff --git a/engines/sci/video/robot_decoder.h b/engines/sci/video/robot_decoder.h index 3f93582418..e9cefe7d91 100644 --- a/engines/sci/video/robot_decoder.h +++ b/engines/sci/video/robot_decoder.h @@ -71,6 +71,11 @@ public: Common::Point getPos() const { return _pos; } protected: + // VideoDecoder API + void updateVolume(); + void updateBalance(); + + // FixedRateVideoDecoder API Common::Rational getFrameRate() const { return Common::Rational(60, 10); } private: -- cgit v1.2.3 From 403b646c13f0729a32c21f89a2e9284d84df34cf Mon Sep 17 00:00:00 2001 From: Lars Skovlund Date: Wed, 30 May 2012 18:43:39 +0200 Subject: SCI32: Case-insensitive configuration getters --- engines/sci/engine/kmisc.cpp | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'engines/sci') diff --git a/engines/sci/engine/kmisc.cpp b/engines/sci/engine/kmisc.cpp index 2be9432521..2911af97df 100644 --- a/engines/sci/engine/kmisc.cpp +++ b/engines/sci/engine/kmisc.cpp @@ -371,6 +371,8 @@ reg_t kGetConfig(EngineState *s, int argc, reg_t *argv) { // Anything below that makes Phantasmagoria awfully sluggish, so we're // setting everything to 500, which makes the game playable. + setting.toLowercase(); + if (setting == "videospeed") { s->_segMan->strcpy(data, "500"); } else if (setting == "cpu") { @@ -388,10 +390,12 @@ reg_t kGetConfig(EngineState *s, int argc, reg_t *argv) { reg_t kGetSierraProfileInt(EngineState *s, int argc, reg_t *argv) { Common::String category = s->_segMan->getString(argv[0]); // always "config" + category.toLowercase(); if (category != "config") error("GetSierraProfileInt: category isn't 'config', it's '%s'", category.c_str()); Common::String setting = s->_segMan->getString(argv[1]); + setting.toLowercase(); if (setting != "videospeed") error("GetSierraProfileInt: setting isn't 'videospeed', it's '%s'", setting.c_str()); -- cgit v1.2.3 From c1dd3d5c2986f6c688eaf5ea80034658840b2828 Mon Sep 17 00:00:00 2001 From: Lars Skovlund Date: Sat, 2 Jun 2012 18:50:46 +0200 Subject: SCI32: Implement GetConfig("language") --- engines/sci/engine/kmisc.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'engines/sci') diff --git a/engines/sci/engine/kmisc.cpp b/engines/sci/engine/kmisc.cpp index 2911af97df..9a113bc5f9 100644 --- a/engines/sci/engine/kmisc.cpp +++ b/engines/sci/engine/kmisc.cpp @@ -381,6 +381,9 @@ reg_t kGetConfig(EngineState *s, int argc, reg_t *argv) { s->_segMan->strcpy(data, "586"); } else if (setting == "cpuspeed") { s->_segMan->strcpy(data, "500"); + } else if (setting == "language") { + Common::String languageId = Common::String::format("%d", g_sci->getSciLanguage()); + s->_segMan->strcpy(data, languageId.c_str()); } else { error("GetConfig: Unknown configuration setting %s", setting.c_str()); } -- cgit v1.2.3 From de3f6a19ed6ca98ad152f5038c1db1f70f2c72ed Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Thu, 7 Jun 2012 11:26:32 +0300 Subject: SCI: Initial implementation of kScrollWindow, used in some SCI21 games This is used in LSL6 hires and SQ6. This initial implementation is hackish and only works in SQ6 (nothing is shown in LSL6) --- engines/sci/engine/kernel_tables.h | 2 +- engines/sci/engine/kgraphics32.cpp | 128 +++++++++++++++++-------------------- engines/sci/graphics/frameout.cpp | 45 +++++++++++++ engines/sci/graphics/frameout.h | 25 ++++++++ engines/sci/graphics/text32.cpp | 39 +++++++++-- engines/sci/graphics/text32.h | 6 +- 6 files changed, 169 insertions(+), 76 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/engine/kernel_tables.h b/engines/sci/engine/kernel_tables.h index 4ddf0534ea..254a479e65 100644 --- a/engines/sci/engine/kernel_tables.h +++ b/engines/sci/engine/kernel_tables.h @@ -564,7 +564,7 @@ static SciKernelMapEntry s_kernelMap[] = { { MAP_CALL(GetSierraProfileInt), SIG_EVERYWHERE, "rri", NULL, NULL }, { MAP_CALL(CelInfo), SIG_EVERYWHERE, "iiiiii", NULL, NULL }, { MAP_CALL(SetLanguage), SIG_EVERYWHERE, "r", NULL, NULL }, - { MAP_CALL(ScrollWindow), SIG_EVERYWHERE, "(.*)", NULL, NULL }, + { MAP_CALL(ScrollWindow), SIG_EVERYWHERE, "io(.*)", NULL, NULL }, { MAP_CALL(SetFontRes), SIG_EVERYWHERE, "ii", NULL, NULL }, { MAP_CALL(Font), SIG_EVERYWHERE, "i(.*)", NULL, NULL }, { MAP_CALL(Bitmap), SIG_EVERYWHERE, "(.*)", NULL, NULL }, diff --git a/engines/sci/engine/kgraphics32.cpp b/engines/sci/engine/kgraphics32.cpp index 2bb8288cb7..71c4949d65 100644 --- a/engines/sci/engine/kgraphics32.cpp +++ b/engines/sci/engine/kgraphics32.cpp @@ -308,103 +308,91 @@ reg_t kCelInfo(EngineState *s, int argc, reg_t *argv) { } reg_t kScrollWindow(EngineState *s, int argc, reg_t *argv) { - // Used by Phantasmagoria 1 and SQ6. In SQ6, it is used for the messages - // shown in the scroll window at the bottom of the screen. - - // TODO: This is all a stub/skeleton, thus we're invoking kStub() for now - kStub(s, argc, argv); - - switch (argv[0].toUint16()) { + // Used by SQ6 and LSL6 hires for the text area in the bottom of the + // screen. The relevant scripts also exist in Phantasmagoria 1, but they're + // unused. This is always called by scripts 64906 (ScrollerWindow) and + // 64907 (ScrollableWindow). + + reg_t kWindow = argv[1]; + uint16 op = argv[0].toUint16(); + switch (op) { case 0: // Init - // 2 parameters - // argv[1] points to the scroll object (e.g. textScroller in SQ6) - // argv[2] is an integer (e.g. 0x32) - break; - case 1: // Show message + g_sci->_gfxFrameout->initScrollText(argv[2].toUint16()); // maxItems + g_sci->_gfxFrameout->clearScrollTexts(); + return argv[1]; // kWindow + case 1: // Show message, called by ScrollableWindow::addString + case 14: // Modify message, called by ScrollableWindow::modifyString // 5 or 6 parameters // Seems to be called with 5 parameters when the narrator speaks, and // with 6 when Roger speaks - // argv[1] unknown (usually 0) - // argv[2] the text to show - // argv[3] a small integer (e.g. 0x32) - // argv[4] a small integer (e.g. 0x54) - // argv[5] optional, unknown (usually 0) - warning("kScrollWindow: '%s'", s->_segMan->getString(argv[2]).c_str()); - break; - case 2: // Clear - // 2 parameters - // TODO - break; - case 3: // Page up - // 2 parameters - // TODO - break; - case 4: // Page down - // 2 parameters - // TODO + { + Common::String text = s->_segMan->getString(argv[2]); + uint16 x = 0;//argv[3].toUint16(); // TODO: can't be x (values are all wrong) + uint16 y = 0;//argv[4].toUint16(); // TODO: can't be y (values are all wrong) + // TODO: argv[5] is an optional unknown parameter (an integer set to 0) + g_sci->_gfxFrameout->addScrollTextEntry(text, kWindow, x, y, (op == 14)); + } break; - case 5: // Up arrow - // 2 parameters - // TODO + case 2: // Clear, called by ScrollableWindow::erase + g_sci->_gfxFrameout->clearScrollTexts(); break; - case 6: // Down arrow - // 2 parameters + case 3: // Page up, called by ScrollableWindow::scrollTo // TODO + kStub(s, argc, argv); break; - case 7: // Home - // 2 parameters + case 4: // Page down, called by ScrollableWindow::scrollTo // TODO + kStub(s, argc, argv); break; - case 8: // End - // 2 parameters - // TODO + case 5: // Up arrow, called by ScrollableWindow::scrollTo + g_sci->_gfxFrameout->prevScrollText(); break; - case 9: // Resize - // 3 parameters - // TODO + case 6: // Down arrow, called by ScrollableWindow::scrollTo + g_sci->_gfxFrameout->nextScrollText(); break; - case 10: // Where - // 3 parameters - // TODO + case 7: // Home, called by ScrollableWindow::scrollTo + g_sci->_gfxFrameout->firstScrollText(); break; - case 11: // Go - // 4 parameters - // TODO + case 8: // End, called by ScrollableWindow::scrollTo + g_sci->_gfxFrameout->lastScrollText(); break; - case 12: // Insert - // 7 parameters + case 9: // Resize, called by ScrollableWindow::resize and ScrollerWindow::resize // TODO + kStub(s, argc, argv); break; - case 13: // Delete - // 3 parameters + case 10: // Where, called by ScrollableWindow::where // TODO + // argv[2] is an unknown integer + kStub(s, argc, argv); break; - case 14: // Modify - // 7 or 8 parameters + case 11: // Go, called by ScrollableWindow::scrollTo + // 2 extra parameters here // TODO + kStub(s, argc, argv); break; - case 15: // Hide - // 2 parameters + case 12: // Insert, called by ScrollableWindow::insertString + // 3 extra parameters here // TODO + kStub(s, argc, argv); break; - case 16: // Show - // 2 parameters - // TODO + // case 13 (Delete) is handled below + // case 14 (Modify) is handled above + case 15: // Hide, called by ScrollableWindow::hide + g_sci->_gfxFrameout->toggleScrollText(false); break; - case 17: // Destroy - // 2 parameters - // TODO + case 16: // Show, called by ScrollableWindow::show + g_sci->_gfxFrameout->toggleScrollText(true); break; - case 18: // Text - // 2 parameters - // TODO + case 17: // Destroy, called by ScrollableWindow::dispose + g_sci->_gfxFrameout->clearScrollTexts(); break; - case 19: // Reconstruct - // 3 parameters - // TODO + case 13: // Delete, unused + case 18: // Text, unused + case 19: // Reconstruct, unused + error("kScrollWindow: Unused subop %d invoked", op); break; default: - error("kScrollWindow: unknown subop %d", argv[0].toUint16()); + error("kScrollWindow: unknown subop %d", op); break; } diff --git a/engines/sci/graphics/frameout.cpp b/engines/sci/graphics/frameout.cpp index 709a708d8b..450581000b 100644 --- a/engines/sci/graphics/frameout.cpp +++ b/engines/sci/graphics/frameout.cpp @@ -59,6 +59,9 @@ GfxFrameout::GfxFrameout(SegManager *segMan, ResourceManager *resMan, GfxCoordAd _coordAdjuster = (GfxCoordAdjuster32 *)coordAdjuster; _scriptsRunningWidth = 320; _scriptsRunningHeight = 200; + _curScrollText = -1; + _showScrollText = false; + _maxScrollTexts = 0; } GfxFrameout::~GfxFrameout() { @@ -69,6 +72,46 @@ void GfxFrameout::clear() { deletePlaneItems(NULL_REG); _planes.clear(); deletePlanePictures(NULL_REG); + clearScrollTexts(); +} + +void GfxFrameout::clearScrollTexts() { + _scrollTexts.clear(); + _curScrollText = -1; +} + +void GfxFrameout::addScrollTextEntry(Common::String &text, reg_t kWindow, uint16 x, uint16 y, bool replace) { + //reg_t bitmapHandle = g_sci->_gfxText32->createScrollTextBitmap(text, kWindow); + // HACK: We set the container dimensions manually + reg_t bitmapHandle = g_sci->_gfxText32->createScrollTextBitmap(text, kWindow, 480, 70); + ScrollTextEntry textEntry; + textEntry.bitmapHandle = bitmapHandle; + textEntry.kWindow = kWindow; + textEntry.x = x; + textEntry.y = y; + if (!replace || _scrollTexts.size() == 0) { + if (_scrollTexts.size() > _maxScrollTexts) { + _scrollTexts.remove_at(0); + _curScrollText--; + } + _scrollTexts.push_back(textEntry); + _curScrollText++; + } else { + _scrollTexts.pop_back(); + _scrollTexts.push_back(textEntry); + } +} + +void GfxFrameout::showCurrentScrollText() { + if (!_showScrollText || _curScrollText < 0) + return; + + uint16 size = (uint16)_scrollTexts.size(); + if (size > 0) { + assert(_curScrollText < size); + ScrollTextEntry textEntry = _scrollTexts[_curScrollText]; + g_sci->_gfxText32->drawScrollTextBitmap(textEntry.kWindow, textEntry.bitmapHandle, textEntry.x, textEntry.y); + } } void GfxFrameout::kernelAddPlane(reg_t object) { @@ -673,6 +716,8 @@ void GfxFrameout::kernelFrameout() { } } + showCurrentScrollText(); + _screen->copyToScreen(); g_sci->getEngineState()->_throttleTrigger = true; diff --git a/engines/sci/graphics/frameout.h b/engines/sci/graphics/frameout.h index ec4de62c0a..2d2ca6546c 100644 --- a/engines/sci/graphics/frameout.h +++ b/engines/sci/graphics/frameout.h @@ -76,6 +76,15 @@ struct PlanePictureEntry { typedef Common::List PlanePictureList; +struct ScrollTextEntry { + reg_t bitmapHandle; + reg_t kWindow; + uint16 x; + uint16 y; +}; + +typedef Common::Array ScrollTextList; + class GfxCache; class GfxCoordAdjuster32; class GfxPaint32; @@ -104,6 +113,18 @@ public: void addPlanePicture(reg_t object, GuiResourceId pictureId, uint16 startX, uint16 startY = 0); void deletePlanePictures(reg_t object); void clear(); + + // Scroll text functions + void addScrollTextEntry(Common::String &text, reg_t kWindow, uint16 x, uint16 y, bool replace); + void showCurrentScrollText(); + void initScrollText(uint16 maxItems) { _maxScrollTexts = maxItems; } + void clearScrollTexts(); + void firstScrollText() { if (_scrollTexts.size() > 0) _curScrollText = 0; } + void lastScrollText() { if (_scrollTexts.size() > 0) _curScrollText = _scrollTexts.size() - 1; } + void prevScrollText() { if (_curScrollText > 0) _curScrollText--; } + void nextScrollText() { if (_curScrollText + 1 < (uint16)_scrollTexts.size()) _curScrollText++; } + void toggleScrollText(bool show) { _showScrollText = show; } + void printPlaneList(Console *con); void printPlaneItemList(Console *con, reg_t planeObject); @@ -127,6 +148,10 @@ private: FrameoutList _screenItems; PlaneList _planes; PlanePictureList _planePictures; + ScrollTextList _scrollTexts; + int16 _curScrollText; + bool _showScrollText; + uint16 _maxScrollTexts; void sortPlanes(); diff --git a/engines/sci/graphics/text32.cpp b/engines/sci/graphics/text32.cpp index cd24ca5a99..8ac9582535 100644 --- a/engines/sci/graphics/text32.cpp +++ b/engines/sci/graphics/text32.cpp @@ -49,9 +49,12 @@ GfxText32::GfxText32(SegManager *segMan, GfxCache *fonts, GfxScreen *screen) GfxText32::~GfxText32() { } +reg_t GfxText32::createScrollTextBitmap(Common::String text, reg_t textObject, uint16 maxWidth, uint16 maxHeight, reg_t prevHunk) { + return createTextBitmapInternal(text, textObject, maxWidth, maxHeight, prevHunk); + +} reg_t GfxText32::createTextBitmap(reg_t textObject, uint16 maxWidth, uint16 maxHeight, reg_t prevHunk) { reg_t stringObject = readSelector(_segMan, textObject, SELECTOR(text)); - // The object in the text selector of the item can be either a raw string // or a Str object. In the latter case, we need to access the object's data // selector to get the raw string. @@ -59,6 +62,11 @@ reg_t GfxText32::createTextBitmap(reg_t textObject, uint16 maxWidth, uint16 maxH stringObject = readSelector(_segMan, stringObject, SELECTOR(data)); Common::String text = _segMan->getString(stringObject); + + return createTextBitmapInternal(text, textObject, maxWidth, maxHeight, prevHunk); +} + +reg_t GfxText32::createTextBitmapInternal(Common::String &text, reg_t textObject, uint16 maxWidth, uint16 maxHeight, reg_t prevHunk) { // HACK: The character offsets of the up and down arrow buttons are off by one // in GK1, for some unknown reason. Fix them here. if (text.size() == 1 && (text[0] == 29 || text[0] == 30)) { @@ -91,7 +99,11 @@ reg_t GfxText32::createTextBitmap(reg_t textObject, uint16 maxWidth, uint16 maxH reg_t memoryId = NULL_REG; if (prevHunk.isNull()) { memoryId = _segMan->allocateHunkEntry("TextBitmap()", entrySize); - writeSelector(_segMan, textObject, SELECTOR(bitmap), memoryId); + + // Scroll text objects have no bitmap selector! + ObjVarRef varp; + if (lookupSelector(_segMan, textObject, SELECTOR(bitmap), &varp, NULL) == kSelectorVariable) + writeSelector(_segMan, textObject, SELECTOR(bitmap), memoryId); } else { memoryId = prevHunk; } @@ -175,6 +187,24 @@ void GfxText32::disposeTextBitmap(reg_t hunkId) { void GfxText32::drawTextBitmap(int16 x, int16 y, Common::Rect planeRect, reg_t textObject) { reg_t hunkId = readSelector(_segMan, textObject, SELECTOR(bitmap)); + drawTextBitmapInternal(x, y, planeRect, textObject, hunkId); +} + +void GfxText32::drawScrollTextBitmap(reg_t textObject, reg_t hunkId, uint16 x, uint16 y) { + /*reg_t plane = readSelector(_segMan, textObject, SELECTOR(plane)); + Common::Rect planeRect; + planeRect.top = readSelectorValue(_segMan, plane, SELECTOR(top)); + planeRect.left = readSelectorValue(_segMan, plane, SELECTOR(left)); + planeRect.bottom = readSelectorValue(_segMan, plane, SELECTOR(bottom)); + planeRect.right = readSelectorValue(_segMan, plane, SELECTOR(right)); + + drawTextBitmapInternal(x, y, planeRect, textObject, hunkId);*/ + + // HACK: we pretty much ignore the plane rect and x, y... + drawTextBitmapInternal(0, 0, Common::Rect(20, 390, 600, 460), textObject, hunkId); +} + +void GfxText32::drawTextBitmapInternal(int16 x, int16 y, Common::Rect planeRect, reg_t textObject, reg_t hunkId) { uint16 backColor = readSelectorValue(_segMan, textObject, SELECTOR(back)); // Sanity check: Check if the hunk is set. If not, either the game scripts // didn't set it, or an old saved game has been loaded, where it wasn't set. @@ -188,8 +218,9 @@ void GfxText32::drawTextBitmap(int16 x, int16 y, Common::Rect planeRect, reg_t t byte *memoryPtr = _segMan->getHunkPointer(hunkId); if (!memoryPtr) { - // Happens when restoring in some SCI32 games - warning("Attempt to draw an invalid text bitmap"); + // Happens when restoring in some SCI32 games (e.g. SQ6). + // Commented out to reduce console spam + //warning("Attempt to draw an invalid text bitmap"); return; } diff --git a/engines/sci/graphics/text32.h b/engines/sci/graphics/text32.h index 3505de85eb..ce78003fdf 100644 --- a/engines/sci/graphics/text32.h +++ b/engines/sci/graphics/text32.h @@ -33,13 +33,17 @@ public: GfxText32(SegManager *segMan, GfxCache *fonts, GfxScreen *screen); ~GfxText32(); reg_t createTextBitmap(reg_t textObject, uint16 maxWidth = 0, uint16 maxHeight = 0, reg_t prevHunk = NULL_REG); - void disposeTextBitmap(reg_t hunkId); + reg_t createScrollTextBitmap(Common::String text, reg_t textObject, uint16 maxWidth = 0, uint16 maxHeight = 0, reg_t prevHunk = NULL_REG); void drawTextBitmap(int16 x, int16 y, Common::Rect planeRect, reg_t textObject); + void drawScrollTextBitmap(reg_t textObject, reg_t hunkId, uint16 x, uint16 y); + void disposeTextBitmap(reg_t hunkId); int16 GetLongest(const char *text, int16 maxWidth, GfxFont *font); void kernelTextSize(const char *text, int16 font, int16 maxWidth, int16 *textWidth, int16 *textHeight); private: + reg_t createTextBitmapInternal(Common::String &text, reg_t textObject, uint16 maxWidth, uint16 maxHeight, reg_t hunkId); + void drawTextBitmapInternal(int16 x, int16 y, Common::Rect planeRect, reg_t textObject, reg_t hunkId); int16 Size(Common::Rect &rect, const char *text, GuiResourceId fontId, int16 maxWidth); void Width(const char *text, int16 from, int16 len, GuiResourceId orgFontId, int16 &textWidth, int16 &textHeight, bool restoreFont); void StringWidth(const char *str, GuiResourceId orgFontId, int16 &textWidth, int16 &textHeight); -- cgit v1.2.3 From 18dd5e5128dcff623830ed43916828bc5cde1969 Mon Sep 17 00:00:00 2001 From: Willem Jan Palenstijn Date: Fri, 8 Jun 2012 08:30:32 +0200 Subject: SCI: Fix mouse up events Regression from 906f0248317e1a4167190a666fe308a09334bfac. Fixes bug #3533069. --- engines/sci/event.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/event.cpp b/engines/sci/event.cpp index 378e88b7df..14443db1e2 100644 --- a/engines/sci/event.cpp +++ b/engines/sci/event.cpp @@ -102,8 +102,8 @@ const MouseEventConversion mouseEventMappings[] = { { Common::EVENT_RBUTTONDOWN, SCI_EVENT_MOUSE_PRESS, 2 }, { Common::EVENT_MBUTTONDOWN, SCI_EVENT_MOUSE_PRESS, 3 }, { Common::EVENT_LBUTTONUP, SCI_EVENT_MOUSE_RELEASE, 1 }, - { Common::EVENT_LBUTTONUP, SCI_EVENT_MOUSE_RELEASE, 2 }, - { Common::EVENT_LBUTTONUP, SCI_EVENT_MOUSE_RELEASE, 3 } + { Common::EVENT_RBUTTONUP, SCI_EVENT_MOUSE_RELEASE, 2 }, + { Common::EVENT_MBUTTONUP, SCI_EVENT_MOUSE_RELEASE, 3 } }; EventManager::EventManager(bool fontIsExtended) : _fontIsExtended(fontIsExtended) { -- cgit v1.2.3 From a643981a385b20ef71a4d1987965f5d1b73fdadc Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Fri, 8 Jun 2012 11:57:43 +0300 Subject: SCI: Handle resource ID -1 when setting the palVary resource Fixes several wrong colors in SQ6 --- engines/sci/graphics/palette.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines/sci') diff --git a/engines/sci/graphics/palette.cpp b/engines/sci/graphics/palette.cpp index 47d1647c6c..ea154c5037 100644 --- a/engines/sci/graphics/palette.cpp +++ b/engines/sci/graphics/palette.cpp @@ -698,7 +698,7 @@ void GfxPalette::palVaryInit() { } bool GfxPalette::palVaryLoadTargetPalette(GuiResourceId resourceId) { - _palVaryResourceId = resourceId; + _palVaryResourceId = (resourceId != 65535) ? resourceId : -1; Resource *palResource = _resMan->findResource(ResourceId(kResourceTypePalette, resourceId), false); if (palResource) { // Load and initialize destination palette -- cgit v1.2.3 From 66af2cf1d729e5944641ab203f3d36761fdff132 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sat, 9 Jun 2012 12:12:44 +0300 Subject: SCI: Handle translucent text planes Fixes the incorrect flood fill in the Rada Drums screen in GK1 --- engines/sci/graphics/frameout.cpp | 23 ++++++++++++++--------- engines/sci/graphics/text32.cpp | 9 ++++++--- 2 files changed, 20 insertions(+), 12 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/graphics/frameout.cpp b/engines/sci/graphics/frameout.cpp index 450581000b..a5bd8ba48e 100644 --- a/engines/sci/graphics/frameout.cpp +++ b/engines/sci/graphics/frameout.cpp @@ -53,6 +53,11 @@ namespace Sci { // TODO/FIXME: This is all guesswork +enum SciSpeciaPlanelPictureCodes { + kPlaneTranslucent = 0xfffe, // -2 + kPlanePlainColored = 0xffff // -1 +}; + GfxFrameout::GfxFrameout(SegManager *segMan, ResourceManager *resMan, GfxCoordAdjuster *coordAdjuster, GfxCache *cache, GfxScreen *screen, GfxPalette *palette, GfxPaint32 *paint32) : _segMan(segMan), _resMan(resMan), _cache(cache), _screen(screen), _palette(palette), _paint32(paint32) { @@ -137,7 +142,7 @@ void GfxFrameout::kernelAddPlane(reg_t object) { newPlane.lastPriority = 0xFFFF; // hidden newPlane.planeOffsetX = 0; newPlane.planeOffsetY = 0; - newPlane.pictureId = 0xFFFF; + newPlane.pictureId = kPlanePlainColored; newPlane.planePictureMirrored = false; newPlane.planeBack = 0; _planes.push_back(newPlane); @@ -155,7 +160,8 @@ void GfxFrameout::kernelUpdatePlane(reg_t object) { if (lastPictureId != it->pictureId) { // picture got changed, load new picture deletePlanePictures(object); - if ((it->pictureId != 0xFFFF) && (it->pictureId != 0xFFFE)) { + // Draw the plane's picture if it's not a translucent/plane colored frame + if ((it->pictureId != kPlanePlainColored) && (it->pictureId != kPlaneTranslucent)) { // SQ6 gives us a bad picture number for the control menu if (_resMan->testResource(ResourceId(kResourceTypePic, it->pictureId))) addPlanePicture(object, it->pictureId, 0); @@ -248,6 +254,9 @@ void GfxFrameout::kernelDeletePlane(reg_t object) { } void GfxFrameout::addPlanePicture(reg_t object, GuiResourceId pictureId, uint16 startX, uint16 startY) { + if (pictureId == kPlanePlainColored || pictureId == kPlaneTranslucent) // sanity check + return; + PlanePictureEntry newPicture; newPicture.object = object; newPicture.pictureId = pictureId; @@ -574,21 +583,17 @@ void GfxFrameout::kernelFrameout() { // There is a race condition lurking in SQ6, which causes the game to hang in the intro, when teleporting to Polysorbate LX. // Since I first wrote the patch, the race has stopped occurring for me though. // I'll leave this for investigation later, when someone can reproduce. - //if (it->pictureId == 0xffff) // FIXME: This is what SSCI does, and fixes the intro of LSL7, but breaks the dialogs in GK1 (adds black boxes) - if (it->planeBack) + //if (it->pictureId == kPlanePlainColored) // FIXME: This is what SSCI does, and fixes the intro of LSL7, but breaks the dialogs in GK1 (adds black boxes) + if (it->pictureId == kPlanePlainColored && it->planeBack) _paint32->fillRect(it->planeRect, it->planeBack); - GuiResourceId planeMainPictureId = it->pictureId; - _coordAdjuster->pictureSetDisplayArea(it->planeRect); - _palette->drewPicture(planeMainPictureId); + _palette->drewPicture(it->pictureId); FrameoutList itemList; createPlaneItemList(planeObject, itemList); -// warning("Plane %s", _segMan->getObjectName(planeObject)); - for (FrameoutList::iterator listIterator = itemList.begin(); listIterator != itemList.end(); listIterator++) { FrameoutEntry *itemEntry = *listIterator; diff --git a/engines/sci/graphics/text32.cpp b/engines/sci/graphics/text32.cpp index 8ac9582535..7907809c91 100644 --- a/engines/sci/graphics/text32.cpp +++ b/engines/sci/graphics/text32.cpp @@ -205,7 +205,7 @@ void GfxText32::drawScrollTextBitmap(reg_t textObject, reg_t hunkId, uint16 x, u } void GfxText32::drawTextBitmapInternal(int16 x, int16 y, Common::Rect planeRect, reg_t textObject, reg_t hunkId) { - uint16 backColor = readSelectorValue(_segMan, textObject, SELECTOR(back)); + int16 backColor = (int16)readSelectorValue(_segMan, textObject, SELECTOR(back)); // Sanity check: Check if the hunk is set. If not, either the game scripts // didn't set it, or an old saved game has been loaded, where it wasn't set. if (hunkId.isNull()) @@ -227,7 +227,7 @@ void GfxText32::drawTextBitmapInternal(int16 x, int16 y, Common::Rect planeRect, byte *surface = memoryPtr + BITMAP_HEADER_SIZE; int curByte = 0; - uint16 skipColor = readSelectorValue(_segMan, textObject, SELECTOR(skip)); + int16 skipColor = (int16)readSelectorValue(_segMan, textObject, SELECTOR(skip)); uint16 textX = planeRect.left + x; uint16 textY = planeRect.top + y; // Get totalWidth, totalHeight @@ -240,10 +240,13 @@ void GfxText32::drawTextBitmapInternal(int16 x, int16 y, Common::Rect planeRect, textY = textY * _screen->getDisplayHeight() / _screen->getHeight(); } + bool translucent = (skipColor == -1 && backColor == -1); + for (int curY = 0; curY < height; curY++) { for (int curX = 0; curX < width; curX++) { byte pixel = surface[curByte++]; - if (pixel != skipColor && pixel != backColor) + if ((!translucent && pixel != skipColor && pixel != backColor) || + (translucent && pixel != 0xFF)) _screen->putFontPixel(textY, curX + textX, curY, pixel); } } -- cgit v1.2.3 From dc11d223cdb156dd71300a8535cb5ab0940180c1 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sat, 9 Jun 2012 15:36:36 +0300 Subject: SCI: Initial implementation of AddLine, UpdateLine, DeleteLine --- engines/sci/engine/kernel.h | 3 ++ engines/sci/engine/kernel_tables.h | 6 ++-- engines/sci/engine/kgraphics32.cpp | 32 +++++++++++++++++++ engines/sci/graphics/frameout.cpp | 63 ++++++++++++++++++++++++++++++++++++++ engines/sci/graphics/frameout.h | 15 +++++++++ 5 files changed, 116 insertions(+), 3 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/engine/kernel.h b/engines/sci/engine/kernel.h index 664c97f7b5..d9fdbefbc2 100644 --- a/engines/sci/engine/kernel.h +++ b/engines/sci/engine/kernel.h @@ -482,6 +482,9 @@ reg_t kScrollWindow(EngineState *s, int argc, reg_t *argv); reg_t kSetFontRes(EngineState *s, int argc, reg_t *argv); reg_t kFont(EngineState *s, int argc, reg_t *argv); reg_t kBitmap(EngineState *s, int argc, reg_t *argv); +reg_t kAddLine(EngineState *s, int argc, reg_t *argv); +reg_t kUpdateLine(EngineState *s, int argc, reg_t *argv); +reg_t kDeleteLine(EngineState *s, int argc, reg_t *argv); // SCI3 Kernel functions reg_t kPlayDuck(EngineState *s, int argc, reg_t *argv); diff --git a/engines/sci/engine/kernel_tables.h b/engines/sci/engine/kernel_tables.h index 254a479e65..9b765283ec 100644 --- a/engines/sci/engine/kernel_tables.h +++ b/engines/sci/engine/kernel_tables.h @@ -568,6 +568,9 @@ static SciKernelMapEntry s_kernelMap[] = { { MAP_CALL(SetFontRes), SIG_EVERYWHERE, "ii", NULL, NULL }, { MAP_CALL(Font), SIG_EVERYWHERE, "i(.*)", NULL, NULL }, { MAP_CALL(Bitmap), SIG_EVERYWHERE, "(.*)", NULL, NULL }, + { MAP_CALL(AddLine), SIG_EVERYWHERE, "oiiiiiiiii", NULL, NULL }, + { MAP_CALL(UpdateLine), SIG_EVERYWHERE, "roiiiiiiiii", NULL, NULL }, + { MAP_CALL(DeleteLine), SIG_EVERYWHERE, "ro", NULL, NULL }, // SCI2.1 Empty Functions @@ -613,9 +616,6 @@ static SciKernelMapEntry s_kernelMap[] = { // SCI2.1 unmapped functions - TODO! // MovePlaneItems - used by SQ6 to scroll through the inventory via the up/down buttons - // AddLine - used by Torin's Passage to highlight the chapter buttons - // DeleteLine - used by Torin's Passage to delete the highlight from the chapter buttons - // UpdateLine - used by LSL6 // SetPalStyleRange - 2 integer parameters, start and end. All styles from start-end // (inclusive) are set to 0 // MorphOn - used by SQ6, script 900, the datacorder reprogramming puzzle (from room 270) diff --git a/engines/sci/engine/kgraphics32.cpp b/engines/sci/engine/kgraphics32.cpp index 71c4949d65..53cf8ada75 100644 --- a/engines/sci/engine/kgraphics32.cpp +++ b/engines/sci/engine/kgraphics32.cpp @@ -605,6 +605,38 @@ reg_t kEditText(EngineState *s, int argc, reg_t *argv) { return s->r_acc; } +reg_t kAddLine(EngineState *s, int argc, reg_t *argv) { + reg_t plane = argv[0]; + Common::Point startPoint(argv[1].toUint16(), argv[2].toUint16()); + Common::Point endPoint(argv[3].toUint16(), argv[4].toUint16()); + // argv[5] is unknown (a number, usually 200) + byte color = (byte)argv[6].toUint16(); + byte priority = (byte)argv[7].toUint16(); + byte control = (byte)argv[8].toUint16(); + // argv[9] is unknown (usually a small number, 1 or 2). Thickness, perhaps? + return g_sci->_gfxFrameout->addPlaneLine(plane, startPoint, endPoint, color, priority, control); +} + +reg_t kUpdateLine(EngineState *s, int argc, reg_t *argv) { + reg_t hunkId = argv[0]; + reg_t plane = argv[1]; + Common::Point startPoint(argv[2].toUint16(), argv[3].toUint16()); + Common::Point endPoint(argv[4].toUint16(), argv[5].toUint16()); + // argv[6] is unknown (a number, usually 200) + byte color = (byte)argv[7].toUint16(); + byte priority = (byte)argv[8].toUint16(); + byte control = (byte)argv[9].toUint16(); + // argv[10] is unknown (usually a small number, 1 or 2). Thickness, perhaps? + g_sci->_gfxFrameout->updatePlaneLine(plane, hunkId, startPoint, endPoint, color, priority, control); + return s->r_acc; +} +reg_t kDeleteLine(EngineState *s, int argc, reg_t *argv) { + reg_t hunkId = argv[0]; + reg_t plane = argv[1]; + g_sci->_gfxFrameout->deletePlaneLine(plane, hunkId); + return s->r_acc; +} + #endif } // End of namespace Sci diff --git a/engines/sci/graphics/frameout.cpp b/engines/sci/graphics/frameout.cpp index a5bd8ba48e..db49497b6b 100644 --- a/engines/sci/graphics/frameout.cpp +++ b/engines/sci/graphics/frameout.cpp @@ -281,6 +281,56 @@ void GfxFrameout::deletePlanePictures(reg_t object) { } } +// Provides the same functionality as kGraph(DrawLine) +reg_t GfxFrameout::addPlaneLine(reg_t object, Common::Point startPoint, Common::Point endPoint, byte color, byte priority, byte control) { + for (PlaneList::iterator it = _planes.begin(); it != _planes.end(); ++it) { + if (it->object == object) { + PlaneLineEntry line; + line.hunkId = _segMan->allocateHunkEntry("PlaneLine()", 1); // we basically use this for a unique ID + line.startPoint = startPoint; + line.endPoint = endPoint; + line.color = color; + line.priority = priority; + line.control = control; + it->lines.push_back(line); + return line.hunkId; + } + } + + return NULL_REG; +} + +void GfxFrameout::updatePlaneLine(reg_t object, reg_t hunkId, Common::Point startPoint, Common::Point endPoint, byte color, byte priority, byte control) { + for (PlaneList::iterator it = _planes.begin(); it != _planes.end(); ++it) { + if (it->object == object) { + for (PlaneLineList::iterator it2 = it->lines.begin(); it2 != it->lines.end(); ++it2) { + if (it2->hunkId == hunkId) { + it2->startPoint = startPoint; + it2->endPoint = endPoint; + it2->color = color; + it2->priority = priority; + it2->control = control; + return; + } + } + } + } +} + +void GfxFrameout::deletePlaneLine(reg_t object, reg_t hunkId) { + for (PlaneList::iterator it = _planes.begin(); it != _planes.end(); ++it) { + if (it->object == object) { + for (PlaneLineList::iterator it2 = it->lines.begin(); it2 != it->lines.end(); ++it2) { + if (it2->hunkId == hunkId) { + _segMan->freeHunkEntry(hunkId); + it2 = it->lines.erase(it2); + return; + } + } + } + } +} + void GfxFrameout::kernelAddScreenItem(reg_t object) { // Ignore invalid items if (!_segMan->isObject(object)) @@ -567,6 +617,19 @@ void GfxFrameout::kernelFrameout() { for (PlaneList::iterator it = _planes.begin(); it != _planes.end(); it++) { reg_t planeObject = it->object; + + // Draw any plane lines, if they exist + // These are drawn on invisible planes as well. (e.g. "invisiblePlane" in LSL6 hires) + // FIXME: Lines aren't always drawn (e.g. when the narrator speaks in LSL6 hires). + // Perhaps something is painted over them? + for (PlaneLineList::iterator it2 = it->lines.begin(); it2 != it->lines.end(); ++it2) { + Common::Point startPoint = it2->startPoint; + Common::Point endPoint = it2->endPoint; + _coordAdjuster->kernelLocalToGlobal(startPoint.x, startPoint.y, it->object); + _coordAdjuster->kernelLocalToGlobal(endPoint.x, endPoint.y, it->object); + _screen->drawLine(startPoint, endPoint, it2->color, it2->priority, it2->control); + } + uint16 planeLastPriority = it->lastPriority; // Update priority here, sq6 sets it w/o UpdatePlane diff --git a/engines/sci/graphics/frameout.h b/engines/sci/graphics/frameout.h index 2d2ca6546c..0d80a68f1d 100644 --- a/engines/sci/graphics/frameout.h +++ b/engines/sci/graphics/frameout.h @@ -27,6 +27,17 @@ namespace Sci { class GfxPicture; +struct PlaneLineEntry { + reg_t hunkId; + Common::Point startPoint; + Common::Point endPoint; + byte color; + byte priority; + byte control; +}; + +typedef Common::List PlaneLineList; + struct PlaneEntry { reg_t object; uint16 priority; @@ -40,6 +51,7 @@ struct PlaneEntry { Common::Rect upscaledPlaneClipRect; bool planePictureMirrored; byte planeBack; + PlaneLineList lines; }; typedef Common::List PlaneList; @@ -112,6 +124,9 @@ public: void addPlanePicture(reg_t object, GuiResourceId pictureId, uint16 startX, uint16 startY = 0); void deletePlanePictures(reg_t object); + reg_t addPlaneLine(reg_t object, Common::Point startPoint, Common::Point endPoint, byte color, byte priority, byte control); + void updatePlaneLine(reg_t object, reg_t hunkId, Common::Point startPoint, Common::Point endPoint, byte color, byte priority, byte control); + void deletePlaneLine(reg_t object, reg_t hunkId); void clear(); // Scroll text functions -- cgit v1.2.3 From ca3ea849d808b7f184cb05c42c317ed19edb73fc Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sat, 9 Jun 2012 16:29:14 +0300 Subject: SCI: Update information on kGetSierraProfileInt Thanks to LePhilousophe for his feedback and observations on this --- engines/sci/engine/kmisc.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/engine/kmisc.cpp b/engines/sci/engine/kmisc.cpp index 9a113bc5f9..f243cf2ffe 100644 --- a/engines/sci/engine/kmisc.cpp +++ b/engines/sci/engine/kmisc.cpp @@ -391,6 +391,8 @@ reg_t kGetConfig(EngineState *s, int argc, reg_t *argv) { return argv[1]; } +// Likely modelled after the Windows 3.1 function GetPrivateProfileInt: +// http://msdn.microsoft.com/en-us/library/windows/desktop/ms724345%28v=vs.85%29.aspx reg_t kGetSierraProfileInt(EngineState *s, int argc, reg_t *argv) { Common::String category = s->_segMan->getString(argv[0]); // always "config" category.toLowercase(); @@ -402,8 +404,7 @@ reg_t kGetSierraProfileInt(EngineState *s, int argc, reg_t *argv) { if (setting != "videospeed") error("GetSierraProfileInt: setting isn't 'videospeed', it's '%s'", setting.c_str()); - // The game scripts pass 425 as the third parameter for some unknown reason, - // as after the call they compare the result to 425 anyway... + // The third parameter is 425 (the default if the configuration key is missing) // We return the same fake value for videospeed as with kGetConfig return make_reg(0, 500); -- cgit v1.2.3 From 15046a7529e3c755de1f00b4a2666786eb2bd4f8 Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Sun, 10 Jun 2012 04:14:17 +0200 Subject: GUI: Get rid of SaveLoadChooser::setSaveMode. We already pass the title and process button name to the constructor of SaveLoadChooser and then do not offer any way of changing it, thus changing the edit mode of the chooser is kind of pointless and was never actually used. Instead we pass the mode on SaveLoadChooser construction now. --- engines/sci/engine/kfile.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/engine/kfile.cpp b/engines/sci/engine/kfile.cpp index 8d1b078697..6c40be87e2 100644 --- a/engines/sci/engine/kfile.cpp +++ b/engines/sci/engine/kfile.cpp @@ -564,8 +564,7 @@ reg_t kSaveGame(EngineState *s, int argc, reg_t *argv) { g_sci->_soundCmd->pauseAll(true); // pause music const EnginePlugin *plugin = NULL; EngineMan.findGame(g_sci->getGameIdStr(), &plugin); - GUI::SaveLoadChooser *dialog = new GUI::SaveLoadChooser(_("Save game:"), _("Save")); - dialog->setSaveMode(true); + GUI::SaveLoadChooser *dialog = new GUI::SaveLoadChooser(_("Save game:"), _("Save"), true); savegameId = dialog->runModalWithPluginAndTarget(plugin, ConfMan.getActiveDomainName()); game_description = dialog->getResultString(); if (game_description.empty()) { @@ -671,8 +670,7 @@ reg_t kRestoreGame(EngineState *s, int argc, reg_t *argv) { g_sci->_soundCmd->pauseAll(true); // pause music const EnginePlugin *plugin = NULL; EngineMan.findGame(g_sci->getGameIdStr(), &plugin); - GUI::SaveLoadChooser *dialog = new GUI::SaveLoadChooser(_("Restore game:"), _("Restore")); - dialog->setSaveMode(false); + GUI::SaveLoadChooser *dialog = new GUI::SaveLoadChooser(_("Restore game:"), _("Restore"), false); savegameId = dialog->runModalWithPluginAndTarget(plugin, ConfMan.getActiveDomainName()); delete dialog; if (savegameId < 0) { -- cgit v1.2.3 From 7c5cf1b400808865a5f601f70d624ad6704a0c8c Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Sun, 10 Jun 2012 04:49:42 +0200 Subject: GUI: Add helper to SaveLoadChooser, which uses the currently active target. This reduces the code duplication in all client code, which formerly duplicated the querying of the plugin, game id etc. and now simply calls the newly added method runModalWithCurrentTarget() on a SaveLoadChooser object. --- engines/sci/engine/kfile.cpp | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/engine/kfile.cpp b/engines/sci/engine/kfile.cpp index 6c40be87e2..4af71f41af 100644 --- a/engines/sci/engine/kfile.cpp +++ b/engines/sci/engine/kfile.cpp @@ -562,10 +562,8 @@ reg_t kSaveGame(EngineState *s, int argc, reg_t *argv) { // we are supposed to show a dialog for the user and let him choose where to save g_sci->_soundCmd->pauseAll(true); // pause music - const EnginePlugin *plugin = NULL; - EngineMan.findGame(g_sci->getGameIdStr(), &plugin); GUI::SaveLoadChooser *dialog = new GUI::SaveLoadChooser(_("Save game:"), _("Save"), true); - savegameId = dialog->runModalWithPluginAndTarget(plugin, ConfMan.getActiveDomainName()); + savegameId = dialog->runModalWithCurrentTarget(); game_description = dialog->getResultString(); if (game_description.empty()) { // create our own description for the saved game, the user didnt enter it @@ -668,10 +666,8 @@ reg_t kRestoreGame(EngineState *s, int argc, reg_t *argv) { if (savegameId == -1) { // we are supposed to show a dialog for the user and let him choose a saved game g_sci->_soundCmd->pauseAll(true); // pause music - const EnginePlugin *plugin = NULL; - EngineMan.findGame(g_sci->getGameIdStr(), &plugin); GUI::SaveLoadChooser *dialog = new GUI::SaveLoadChooser(_("Restore game:"), _("Restore"), false); - savegameId = dialog->runModalWithPluginAndTarget(plugin, ConfMan.getActiveDomainName()); + savegameId = dialog->runModalWithCurrentTarget(); delete dialog; if (savegameId < 0) { g_sci->_soundCmd->pauseAll(false); // unpause music -- cgit v1.2.3 From 49fafb48a7f089c97ed3baa9aefe65ec56dce682 Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Sun, 10 Jun 2012 05:04:59 +0200 Subject: GUI: Refactor default savegame description creation. Formerly the GMM, AGI and SCI duplicated the logic for USE_SAVEGAME_TIMESTAMP. Now I added a method to SaveLoadChooser instead, which takes care of this. This might not be the best placement of such a functionality, thus I added a TODO which talks about moving it to a better place. --- engines/sci/engine/kfile.cpp | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/engine/kfile.cpp b/engines/sci/engine/kfile.cpp index 4af71f41af..42f8b8832c 100644 --- a/engines/sci/engine/kfile.cpp +++ b/engines/sci/engine/kfile.cpp @@ -567,15 +567,7 @@ reg_t kSaveGame(EngineState *s, int argc, reg_t *argv) { game_description = dialog->getResultString(); if (game_description.empty()) { // create our own description for the saved game, the user didnt enter it - #if defined(USE_SAVEGAME_TIMESTAMP) - TimeDate curTime; - g_system->getTimeAndDate(curTime); - curTime.tm_year += 1900; // fixup year - curTime.tm_mon++; // fixup month - game_description = Common::String::format("%04d.%02d.%02d / %02d:%02d:%02d", curTime.tm_year, curTime.tm_mon, curTime.tm_mday, curTime.tm_hour, curTime.tm_min, curTime.tm_sec); - #else - game_description = Common::String::format("Save %d", savegameId + 1); - #endif + game_description = dialog->createDefaultSaveDescription(savegameId); } delete dialog; g_sci->_soundCmd->pauseAll(false); // unpause music ( we can't have it paused during save) -- cgit v1.2.3 From 0ccfd614aa935ed38a4fce7888c91ff1429691f1 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Mon, 11 Jun 2012 11:48:49 +0300 Subject: SCI: Add more verbose debug output for DoAudio in SCI2.1 --- engines/sci/engine/ksound.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/engine/ksound.cpp b/engines/sci/engine/ksound.cpp index c469f775f9..b378b4d58b 100644 --- a/engines/sci/engine/ksound.cpp +++ b/engines/sci/engine/ksound.cpp @@ -140,8 +140,12 @@ reg_t kDoAudio(EngineState *s, int argc, reg_t *argv) { ((argv[3].toUint16() & 0xff) << 16) | ((argv[4].toUint16() & 0xff) << 8) | (argv[5].toUint16() & 0xff); - if (argc == 8) - warning("kDoAudio: Play called with SQ6 extra parameters"); + if (argc == 8) { + // argv[6] is always 1 + // argv[7] is the contents of global 229 (0xE5) + warning("kDoAudio: Play called with SCI2.1 extra parameters: %04x:%04x and %04x:%04x", + PRINT_REG(argv[6]), PRINT_REG(argv[7])); + } } else { warning("kDoAudio: Play called with an unknown number of parameters (%d)", argc); return NULL_REG; -- cgit v1.2.3 From b812ed50c8f6d9a24b607831a88a398730458d9a Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Mon, 11 Jun 2012 11:51:54 +0300 Subject: SCI: Bugfix for negative numbers in kString(at) Fixes one of the bugs in the savegame selection screen in Phantasmagoria --- engines/sci/engine/kstring.cpp | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/engine/kstring.cpp b/engines/sci/engine/kstring.cpp index fe8d631497..0877e37a65 100644 --- a/engines/sci/engine/kstring.cpp +++ b/engines/sci/engine/kstring.cpp @@ -653,10 +653,18 @@ reg_t kString(EngineState *s, int argc, reg_t *argv) { case 1: // Size return make_reg(0, s->_segMan->getString(argv[1]).size()); case 2: { // At (return value at an index) - if (argv[1].segment == s->_segMan->getStringSegmentId()) - return make_reg(0, s->_segMan->lookupString(argv[1])->getRawData()[argv[2].toUint16()]); - - return make_reg(0, s->_segMan->getString(argv[1])[argv[2].toUint16()]); + // Note that values need to be truncated to bytes, otherwise + // 0xff (negative char -1) will incorrectly be changed to + // 0xffff (negative int16 -1) + if (argv[1].segment == s->_segMan->getStringSegmentId()) { + SciString *string = s->_segMan->lookupString(argv[1]); + byte val = string->getRawData()[argv[2].toUint16()]; + return make_reg(0, val); + } else { + Common::String string = s->_segMan->getString(argv[1]); + byte val = string[argv[2].toUint16()]; + return make_reg(0, val); + } } case 3: { // Atput (put value at an index) SciString *string = s->_segMan->lookupString(argv[1]); -- cgit v1.2.3 From 3fde390e006963f354c0678640c70f49753907ef Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Mon, 11 Jun 2012 20:21:47 +0300 Subject: SCI: Added another French version of Torin's Passage Thanks to LePhilousophe for providing the file details. Also fixed all of the detection entries for Torin's Passage --- engines/sci/detection_tables.h | 38 +++++++++++++++++++++++--------------- 1 file changed, 23 insertions(+), 15 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/detection_tables.h b/engines/sci/detection_tables.h index 506f79b4d8..6e66c48ff1 100644 --- a/engines/sci/detection_tables.h +++ b/engines/sci/detection_tables.h @@ -3744,53 +3744,61 @@ static const struct ADGameDescription SciGameDescriptions[] = { #ifdef ENABLE_SCI32 // Torin's Passage - English Windows Interactive Demo - // SCI interpreter version 2.100.002 (just a guess) + // SCI interpreter version 2.100.002 {"torin", "Demo", { {"resmap.000", 0, "9a3e172cde9963d0a969f26469318cec", 3403}, {"ressci.000", 0, "db3e290481c35c3224e9602e71e4a1f1", 5073868}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformWindows, ADGF_DEMO | ADGF_UNSTABLE, GUIO5(GUIO_NOSPEECH, GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + Common::EN_ANY, Common::kPlatformWindows, ADGF_DEMO | ADGF_UNSTABLE, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, - // Torin's Passage - English Windows - // SCI interpreter version 2.100.002 (just a guess) + // Torin's Passage (Multilingual) - English Windows CD + // SCI interpreter version 2.100.002 {"torin", "", { {"resmap.000", 0, "bb3b0b22ff08df54fbe2d06263409be6", 9799}, {"ressci.000", 0, "693a259d346c9360f4a0c11fdaae430a", 55973887}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformWindows, ADGF_UNSTABLE, GUIO5(GUIO_NOSPEECH, GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + Common::EN_ANY, Common::kPlatformWindows, ADGF_UNSTABLE, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, - // Torin's Passage - Spanish Windows (from jvprat) + // Torin's Passage (Multilingual) - Spanish Windows CD (from jvprat) // Executable scanning reports "2.100.002", VERSION file reports "1.0" {"torin", "", { {"resmap.000", 0, "bb3b0b22ff08df54fbe2d06263409be6", 9799}, {"ressci.000", 0, "693a259d346c9360f4a0c11fdaae430a", 55973887}, // TODO: depend on one of the patches? AD_LISTEND}, - Common::ES_ESP, Common::kPlatformWindows, ADGF_UNSTABLE, GUIO5(GUIO_NOSPEECH, GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + Common::ES_ESP, Common::kPlatformWindows, ADGF_UNSTABLE, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, - // Torin's Passage - French Windows - // SCI interpreter version 2.100.002 (just a guess) + // Torin's Passage (Multilingual) - French Windows CD + // SCI interpreter version 2.100.002 {"torin", "", { {"resmap.000", 0, "bb3b0b22ff08df54fbe2d06263409be6", 9799}, {"ressci.000", 0, "693a259d346c9360f4a0c11fdaae430a", 55973887}, AD_LISTEND}, - Common::FR_FRA, Common::kPlatformWindows, ADGF_UNSTABLE, GUIO5(GUIO_NOSPEECH, GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + Common::FR_FRA, Common::kPlatformWindows, ADGF_UNSTABLE, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, - // Torin's Passage - German Windows - // SCI interpreter version 2.100.002 (just a guess) + // Torin's Passage (Multilingual) - German Windows CD + // SCI interpreter version 2.100.002 {"torin", "", { {"resmap.000", 0, "bb3b0b22ff08df54fbe2d06263409be6", 9799}, {"ressci.000", 0, "693a259d346c9360f4a0c11fdaae430a", 55973887}, AD_LISTEND}, - Common::DE_DEU, Common::kPlatformWindows, ADGF_UNSTABLE, GUIO5(GUIO_NOSPEECH, GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + Common::DE_DEU, Common::kPlatformWindows, ADGF_UNSTABLE, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, - // Torin's Passage - Italian Windows CD (from glorifindel) - // SCI interpreter version 2.100.002 (just a guess) + // Torin's Passage (Multilingual) - Italian Windows CD (from glorifindel) + // SCI interpreter version 2.100.002 {"torin", "", { {"resmap.000", 0, "bb3b0b22ff08df54fbe2d06263409be6", 9799}, {"ressci.000", 0, "693a259d346c9360f4a0c11fdaae430a", 55973887}, AD_LISTEND}, Common::IT_ITA, Common::kPlatformWindows, ADGF_UNSTABLE, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + + // Torin's Passage - French Windows (from LePhilousophe) + // SCI interpreter version 2.100.002 + {"torin", "", { + {"resmap.000", 0, "66ed46e3e56f487e688d52f05b33d0ba", 9787}, + {"ressci.000", 0, "118f9bec04bfe17c4f87bbb5ddb43c18", 56126981}, + AD_LISTEND}, + Common::FR_FRA, Common::kPlatformWindows, ADGF_UNSTABLE, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, #endif // ENABLE_SCI32 // SCI Fanmade Games -- cgit v1.2.3 From 15306bc554b926e7d50f6a443766065e684557f3 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Mon, 11 Jun 2012 20:28:28 +0300 Subject: SCI: Return the default value for unknown configuration settings Based on a patch by LePhilousophe --- engines/sci/engine/kmisc.cpp | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/engine/kmisc.cpp b/engines/sci/engine/kmisc.cpp index f243cf2ffe..1cbaf0708d 100644 --- a/engines/sci/engine/kmisc.cpp +++ b/engines/sci/engine/kmisc.cpp @@ -396,18 +396,17 @@ reg_t kGetConfig(EngineState *s, int argc, reg_t *argv) { reg_t kGetSierraProfileInt(EngineState *s, int argc, reg_t *argv) { Common::String category = s->_segMan->getString(argv[0]); // always "config" category.toLowercase(); - if (category != "config") - error("GetSierraProfileInt: category isn't 'config', it's '%s'", category.c_str()); - Common::String setting = s->_segMan->getString(argv[1]); setting.toLowercase(); - if (setting != "videospeed") - error("GetSierraProfileInt: setting isn't 'videospeed', it's '%s'", setting.c_str()); + // The third parameter is the default value returned if the configuration key is missing - // The third parameter is 425 (the default if the configuration key is missing) + if (category == "config" && setting == "videospeed") { + // We return the same fake value for videospeed as with kGetConfig + return make_reg(0, 500); + } - // We return the same fake value for videospeed as with kGetConfig - return make_reg(0, 500); + warning("kGetSierraProfileInt: Returning default value %d for unknown setting %s.%s", argv[2].toSint16(), category.c_str(), setting.c_str()); + return argv[2]; } #endif -- cgit v1.2.3 From ea06210b92a45f8fca6b9be19057bcd607988ee7 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Mon, 11 Jun 2012 21:14:08 +0300 Subject: SCI: Add support for variable selectors in kListFirstTrue / kListAllTrue This is used by Torin's Passage (e.g. when trying to open the menu). Based on a slightly modified patch by LePhilousophe --- engines/sci/engine/klists.cpp | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/engine/klists.cpp b/engines/sci/engine/klists.cpp index 2a33df26bc..5a608af034 100644 --- a/engines/sci/engine/klists.cpp +++ b/engines/sci/engine/klists.cpp @@ -575,8 +575,11 @@ reg_t kListFirstTrue(EngineState *s, int argc, reg_t *argv) { // First, check if the target selector is a variable if (lookupSelector(s->_segMan, curObject, slc, &address, NULL) == kSelectorVariable) { - // Can this happen with variable selectors? - error("kListFirstTrue: Attempted to access a variable selector"); + // If it's a variable selector, check its value. + // Example: script 64893 in Torin, MenuHandler::isHilited checks + // all children for variable selector 0x03ba (bHilited). + if (!readSelector(s->_segMan, curObject, slc).isNull()) + return curObject; } else { invokeSelector(s, curObject, slc, argc, argv, argc - 2, argv + 2); @@ -609,16 +612,16 @@ reg_t kListAllTrue(EngineState *s, int argc, reg_t *argv) { // First, check if the target selector is a variable if (lookupSelector(s->_segMan, curObject, slc, &address, NULL) == kSelectorVariable) { - // Can this happen with variable selectors? - error("kListAllTrue: Attempted to access a variable selector"); + // If it's a variable selector, check its value + s->r_acc = readSelector(s->_segMan, curObject, slc); } else { invokeSelector(s, curObject, slc, argc, argv, argc - 2, argv + 2); - - // Check if the result isn't true - if (s->r_acc.isNull()) - break; } + // Check if the result isn't true + if (s->r_acc.isNull()) + break; + curNode = s->_segMan->lookupNode(nextNode); } -- cgit v1.2.3 From ef8239df4877772762876ca1a98ad48676af8d5c Mon Sep 17 00:00:00 2001 From: Matthew Hoops Date: Mon, 11 Jun 2012 20:10:49 -0400 Subject: SCI: Fix comment in kString(at) --- engines/sci/engine/kstring.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/engine/kstring.cpp b/engines/sci/engine/kstring.cpp index 0877e37a65..33b8c15e9f 100644 --- a/engines/sci/engine/kstring.cpp +++ b/engines/sci/engine/kstring.cpp @@ -653,9 +653,7 @@ reg_t kString(EngineState *s, int argc, reg_t *argv) { case 1: // Size return make_reg(0, s->_segMan->getString(argv[1]).size()); case 2: { // At (return value at an index) - // Note that values need to be truncated to bytes, otherwise - // 0xff (negative char -1) will incorrectly be changed to - // 0xffff (negative int16 -1) + // Note that values are put in bytes to avoid sign extension if (argv[1].segment == s->_segMan->getStringSegmentId()) { SciString *string = s->_segMan->lookupString(argv[1]); byte val = string->getRawData()[argv[2].toUint16()]; -- cgit v1.2.3 From f76c71d9682e193af3c852e27c3923950137445d Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Wed, 13 Jun 2012 03:48:39 +0300 Subject: SCI: Add debug code to automatically skip robot videos --- engines/sci/engine/kvideo.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'engines/sci') diff --git a/engines/sci/engine/kvideo.cpp b/engines/sci/engine/kvideo.cpp index c9cf652013..f176a13721 100644 --- a/engines/sci/engine/kvideo.cpp +++ b/engines/sci/engine/kvideo.cpp @@ -259,6 +259,7 @@ reg_t kRobot(EngineState *s, int argc, reg_t *argv) { warning("kRobot(%d)", subop); break; case 8: // sync + //if (false) { // debug: automatically skip all robot videos if ((uint32)g_sci->_robotDecoder->getCurFrame() != g_sci->_robotDecoder->getFrameCount() - 1) { writeSelector(s->_segMan, argv[1], SELECTOR(signal), NULL_REG); } else { -- cgit v1.2.3 From aeac51d7263bf5233f3fb1f24d8a0789a9f8ca18 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Wed, 13 Jun 2012 11:00:58 +0300 Subject: SCI: Implement the file operations needed for the save dialog in Phantasmagoria Phantasmagoria's scripts keep polling for the existence of the savegame index file and request to read and write it using the same parameters when opening it. The index file is closed and reopened for every save slot, which is slow and can be much slower on non-desktop devices. Also, the game scripts request seeking in writable streams and request to expand the existing index file. To provide this functionality and to reduce constant slow file opening and closing, this virtual class has been introduced --- engines/sci/engine/file.cpp | 139 ++++++++++++++++++++++++++++++++++++++ engines/sci/engine/file.h | 75 +++++++++++++++++++++ engines/sci/engine/kfile.cpp | 156 +++++++++++++++++++++++++++++++++---------- engines/sci/engine/state.cpp | 12 +++- engines/sci/engine/state.h | 5 ++ engines/sci/module.mk | 1 + 6 files changed, 351 insertions(+), 37 deletions(-) create mode 100644 engines/sci/engine/file.cpp create mode 100644 engines/sci/engine/file.h (limited to 'engines/sci') diff --git a/engines/sci/engine/file.cpp b/engines/sci/engine/file.cpp new file mode 100644 index 0000000000..8876f3c46c --- /dev/null +++ b/engines/sci/engine/file.cpp @@ -0,0 +1,139 @@ +/* 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. + * + */ + +#include "common/savefile.h" +#include "common/stream.h" + +#include "sci/sci.h" +#include "sci/engine/file.h" + +namespace Sci { + +#ifdef ENABLE_SCI32 + +VirtualIndexFile::VirtualIndexFile(Common::String fileName) : _fileName(fileName), _changed(false) { + Common::SeekableReadStream *inFile = g_sci->getSaveFileManager()->openForLoading(fileName); + + _bufferSize = inFile->size(); + _buffer = new char[_bufferSize]; + inFile->read(_buffer, _bufferSize); + _ptr = _buffer; + delete inFile; +} + +VirtualIndexFile::~VirtualIndexFile() { + close(); + + _bufferSize = 0; + delete[] _buffer; + _buffer = 0; +} + +uint32 VirtualIndexFile::read(char *buffer, uint32 size) { + uint32 curPos = _ptr - _buffer; + uint32 finalSize = MIN(size, _bufferSize - curPos); + char *localPtr = buffer; + + for (uint32 i = 0; i < finalSize; i++) + *localPtr++ = *_ptr++; + + return finalSize; +} + +uint32 VirtualIndexFile::write(const char *buffer, uint32 size) { + _changed = true; + uint32 curPos = _ptr - _buffer; + + // Check if the buffer needs to be resized + if (curPos + size >= _bufferSize) { + _bufferSize = curPos + size + 1; + char *tmp = _buffer; + _buffer = new char[_bufferSize]; + _ptr = _buffer + curPos; + memcpy(_buffer, tmp, _bufferSize); + delete[] tmp; + } + + for (uint32 i = 0; i < size; i++) + *_ptr++ = *buffer++; + + return size; +} + +uint32 VirtualIndexFile::readLine(char *buffer, uint32 size) { + uint32 startPos = _ptr - _buffer; + uint32 bytesRead = 0; + char *localPtr = buffer; + + // This is not a full-blown implementation of readLine, but it + // suffices for Phantasmagoria + while (startPos + bytesRead < size) { + bytesRead++; + + if (*_ptr == 0 || *_ptr == 0x0A) { + _ptr++; + *localPtr = 0; + return bytesRead; + } else { + *localPtr++ = *_ptr++; + } + } + + return bytesRead; +} + +bool VirtualIndexFile::seek(int32 offset, int whence) { + uint32 startPos = _ptr - _buffer; + assert(offset >= 0); + + switch (whence) { + case SEEK_CUR: + assert(startPos + offset < _bufferSize); + _ptr += offset; + break; + case SEEK_SET: + assert(offset < _bufferSize); + _ptr = _buffer + offset; + break; + case SEEK_END: + assert(_bufferSize - offset >= 0); + _ptr = _buffer + (_bufferSize - offset); + break; + } + + return true; +} + +void VirtualIndexFile::close() { + if (_changed) { + Common::WriteStream *outFile = g_sci->getSaveFileManager()->openForSaving(_fileName); + outFile->write(_buffer, _bufferSize); + delete outFile; + } + + // Maintain the buffer, and seek to the beginning of it + _ptr = _buffer; +} + +#endif + +} // End of namespace Sci diff --git a/engines/sci/engine/file.h b/engines/sci/engine/file.h new file mode 100644 index 0000000000..e7b1090c91 --- /dev/null +++ b/engines/sci/engine/file.h @@ -0,0 +1,75 @@ +/* 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. + * + */ + +#ifndef SCI_ENGINE_FILE_H +#define SCI_ENGINE_FILE_H + +#include "common/scummsys.h" + +namespace Sci { + +#ifdef ENABLE_SCI32 + +/** + * An implementation of a virtual file that supports basic read and write + * operations simultaneously. + * + * This class has been initially implemented for Phantasmagoria, which has its + * own custom save/load code. The load code keeps checking for the existence + * of the save index file and keeps closing and reopening it for each save + * slot. This is notoriously slow and clumsy, and introduces noticeable delays, + * especially for non-desktop systems. Also, its game scripts request to open + * the index file for reading and writing with the same parameters + * (SaveManager::setCurrentSave and SaveManager::getCurrentSave). Moreover, + * the game scripts reopen the index file for writing in order to update it + * and seek within it. We do not support seeking in writeable streams, and the + * fact that our saved games are ZIP files makes this operation even more + * expensive. Finally, the savegame index file is supposed to be expanded when + * a new save slot is added. + * For the aforementioned reasons, this class has been implemented, which offers + * the basic functionality needed by the game scripts in Phantasmagoria. + */ +class VirtualIndexFile { +public: + VirtualIndexFile(Common::String fileName); + ~VirtualIndexFile(); + + uint32 read(char *buffer, uint32 size); + uint32 readLine(char *buffer, uint32 size); + uint32 write(const char *buffer, uint32 size); + bool seek(int32 offset, int whence); + void close(); + +private: + char *_buffer; + uint32 _bufferSize; + char *_ptr; + + Common::String _fileName; + bool _changed; +}; + +#endif + +} // End of namespace Sci + +#endif // SCI_ENGINE_FILE_H diff --git a/engines/sci/engine/kfile.cpp b/engines/sci/engine/kfile.cpp index 42f8b8832c..0dd2296f41 100644 --- a/engines/sci/engine/kfile.cpp +++ b/engines/sci/engine/kfile.cpp @@ -33,6 +33,7 @@ #include "gui/saveload.h" #include "sci/sci.h" +#include "sci/engine/file.h" #include "sci/engine/state.h" #include "sci/engine/kernel.h" #include "sci/engine/savegame.h" @@ -72,8 +73,6 @@ struct SavegameDesc { * for reading only. */ - - FileHandle::FileHandle() : _in(0), _out(0) { } @@ -93,15 +92,14 @@ bool FileHandle::isOpen() const { return _in || _out; } - - enum { _K_FILE_MODE_OPEN_OR_CREATE = 0, _K_FILE_MODE_OPEN_OR_FAIL = 1, _K_FILE_MODE_CREATE = 2 }; - +#define VIRTUALFILE_HANDLE 200 +#define PHANTASMAGORIA_SAVEGAME_INDEX "phantsg.dir" reg_t file_open(EngineState *s, const Common::String &filename, int mode, bool unwrapFilename) { Common::String englishName = g_sci->getSciLanguageString(filename, K_LANG_ENGLISH); @@ -130,6 +128,7 @@ reg_t file_open(EngineState *s, const Common::String &filename, int mode, bool u outFile = saveFileMan->openForSaving(wrappedName); if (!outFile) debugC(kDebugLevelFile, " -> file_open(_K_FILE_MODE_CREATE): failed to create file '%s'", englishName.c_str()); + // QfG1 opens the character export file with _K_FILE_MODE_CREATE first, // closes it immediately and opens it again with this here. Perhaps // other games use this for read access as well. I guess changing this @@ -171,8 +170,8 @@ reg_t kFOpen(EngineState *s, int argc, reg_t *argv) { } static FileHandle *getFileFromHandle(EngineState *s, uint handle) { - if (handle == 0) { - error("Attempt to use file handle 0"); + if (handle == 0 || handle == VIRTUALFILE_HANDLE) { + error("Attempt to use invalid file handle (%d)", handle); return 0; } @@ -738,6 +737,21 @@ reg_t kFileIO(EngineState *s, int argc, reg_t *argv) { reg_t kFileIOOpen(EngineState *s, int argc, reg_t *argv) { Common::String name = s->_segMan->getString(argv[0]); +#ifdef ENABLE_SCI32 + if (name == PHANTASMAGORIA_SAVEGAME_INDEX) { + if (s->_virtualIndexFile) { + return make_reg(0, VIRTUALFILE_HANDLE); + } else { + Common::String englishName = g_sci->getSciLanguageString(name, K_LANG_ENGLISH); + Common::String wrappedName = g_sci->wrapFilename(englishName); + if (!g_sci->getSaveFileManager()->listSavefiles(wrappedName).empty()) { + s->_virtualIndexFile = new VirtualIndexFile(wrappedName); + return make_reg(0, VIRTUALFILE_HANDLE); + } + } + } +#endif + // SCI32 can call K_FILEIO_OPEN with only one argument. It seems to // just be checking if it exists. int mode = (argc < 2) ? (int)_K_FILE_MODE_OPEN_OR_FAIL : argv[1].toUint16(); @@ -780,7 +794,16 @@ reg_t kFileIOOpen(EngineState *s, int argc, reg_t *argv) { reg_t kFileIOClose(EngineState *s, int argc, reg_t *argv) { debugC(kDebugLevelFile, "kFileIO(close): %d", argv[0].toUint16()); - FileHandle *f = getFileFromHandle(s, argv[0].toUint16()); + uint16 handle = argv[0].toUint16(); + +#ifdef ENABLE_SCI32 + if (handle == VIRTUALFILE_HANDLE) { + s->_virtualIndexFile->close(); + return SIGNAL_REG; + } +#endif + + FileHandle *f = getFileFromHandle(s, handle); if (f) { f->close(); return SIGNAL_REG; @@ -789,39 +812,56 @@ reg_t kFileIOClose(EngineState *s, int argc, reg_t *argv) { } reg_t kFileIOReadRaw(EngineState *s, int argc, reg_t *argv) { - int handle = argv[0].toUint16(); - int size = argv[2].toUint16(); + uint16 handle = argv[0].toUint16(); + uint16 size = argv[2].toUint16(); int bytesRead = 0; char *buf = new char[size]; debugC(kDebugLevelFile, "kFileIO(readRaw): %d, %d", handle, size); - FileHandle *f = getFileFromHandle(s, handle); - if (f) { - bytesRead = f->_in->read(buf, size); - // TODO: What happens if less bytes are read than what has - // been requested? (i.e. if bytesRead is non-zero, but still - // less than size) - if (bytesRead > 0) - s->_segMan->memcpy(argv[1], (const byte*)buf, size); +#ifdef ENABLE_SCI32 + if (handle == VIRTUALFILE_HANDLE) { + bytesRead = s->_virtualIndexFile->read(buf, size); + } else { +#endif + FileHandle *f = getFileFromHandle(s, handle); + if (f) + bytesRead = f->_in->read(buf, size); +#ifdef ENABLE_SCI32 } +#endif + + // TODO: What happens if less bytes are read than what has + // been requested? (i.e. if bytesRead is non-zero, but still + // less than size) + if (bytesRead > 0) + s->_segMan->memcpy(argv[1], (const byte*)buf, size); delete[] buf; return make_reg(0, bytesRead); } reg_t kFileIOWriteRaw(EngineState *s, int argc, reg_t *argv) { - int handle = argv[0].toUint16(); - int size = argv[2].toUint16(); + uint16 handle = argv[0].toUint16(); + uint16 size = argv[2].toUint16(); char *buf = new char[size]; bool success = false; s->_segMan->memcpy((byte *)buf, argv[1], size); debugC(kDebugLevelFile, "kFileIO(writeRaw): %d, %d", handle, size); - FileHandle *f = getFileFromHandle(s, handle); - if (f) { - f->_out->write(buf, size); +#ifdef ENABLE_SCI32 + if (handle == VIRTUALFILE_HANDLE) { + s->_virtualIndexFile->write(buf, size); success = true; + } else { +#endif + FileHandle *f = getFileFromHandle(s, handle); + if (f) { + f->_out->write(buf, size); + success = true; + } +#ifdef ENABLE_SCI32 } +#endif delete[] buf; if (success) @@ -854,9 +894,19 @@ reg_t kFileIOUnlink(EngineState *s, int argc, reg_t *argv) { name = g_sci->getSavegameName(savedir_nr); result = saveFileMan->removeSavefile(name); } else if (getSciVersion() >= SCI_VERSION_2) { - // We don't need to wrap the filename in SCI32 games, as it's already - // constructed here + // The file name may be already wrapped, so check both cases result = saveFileMan->removeSavefile(name); + if (!result) { + const Common::String wrappedName = g_sci->wrapFilename(name); + result = saveFileMan->removeSavefile(wrappedName); + } + +#ifdef ENABLE_SCI32 + if (name == PHANTASMAGORIA_SAVEGAME_INDEX) { + delete s->_virtualIndexFile; + s->_virtualIndexFile = 0; + } +#endif } else { const Common::String wrappedName = g_sci->wrapFilename(name); result = saveFileMan->removeSavefile(wrappedName); @@ -869,15 +919,22 @@ reg_t kFileIOUnlink(EngineState *s, int argc, reg_t *argv) { } reg_t kFileIOReadString(EngineState *s, int argc, reg_t *argv) { - int size = argv[1].toUint16(); + uint16 size = argv[1].toUint16(); char *buf = new char[size]; - int handle = argv[2].toUint16(); + uint16 handle = argv[2].toUint16(); debugC(kDebugLevelFile, "kFileIO(readString): %d, %d", handle, size); + uint32 bytesRead; + +#ifdef ENABLE_SCI32 + if (handle == VIRTUALFILE_HANDLE) + bytesRead = s->_virtualIndexFile->readLine(buf, size); + else +#endif + bytesRead = fgets_wrapper(s, buf, size, handle); - int readBytes = fgets_wrapper(s, buf, size, handle); s->_segMan->memcpy(argv[0], (const byte*)buf, size); delete[] buf; - return readBytes ? argv[0] : NULL_REG; + return bytesRead ? argv[0] : NULL_REG; } reg_t kFileIOWriteString(EngineState *s, int argc, reg_t *argv) { @@ -885,6 +942,13 @@ reg_t kFileIOWriteString(EngineState *s, int argc, reg_t *argv) { Common::String str = s->_segMan->getString(argv[1]); debugC(kDebugLevelFile, "kFileIO(writeString): %d", handle); +#ifdef ENABLE_SCI32 + if (handle == VIRTUALFILE_HANDLE) { + s->_virtualIndexFile->write(str.c_str(), str.size()); + return NULL_REG; + } +#endif + FileHandle *f = getFileFromHandle(s, handle); if (f) { @@ -896,15 +960,31 @@ reg_t kFileIOWriteString(EngineState *s, int argc, reg_t *argv) { } reg_t kFileIOSeek(EngineState *s, int argc, reg_t *argv) { - int handle = argv[0].toUint16(); - int offset = argv[1].toUint16(); - int whence = argv[2].toUint16(); + uint16 handle = argv[0].toUint16(); + uint16 offset = ABS(argv[1].toSint16()); // can be negative + uint16 whence = argv[2].toUint16(); debugC(kDebugLevelFile, "kFileIO(seek): %d, %d, %d", handle, offset, whence); +#ifdef ENABLE_SCI32 + if (handle == VIRTUALFILE_HANDLE) + return make_reg(0, s->_virtualIndexFile->seek(offset, whence)); +#endif + FileHandle *f = getFileFromHandle(s, handle); - if (f) - s->r_acc = make_reg(0, f->_in->seek(offset, whence)); + if (f && f->_in) { + // Backward seeking isn't supported in zip file streams, thus adapt the + // parameters accordingly if games ask for such a seek mode. A known + // case where this is requested is the save file manager in Phantasmagoria + if (whence == SEEK_END) { + whence = SEEK_SET; + offset = f->_in->size() - offset; + } + + return make_reg(0, f->_in->seek(offset, whence)); + } else if (f && f->_out) { + error("kFileIOSeek: Unsupported seek operation on a writeable stream (offset: %d, whence: %d)", offset, whence); + } return SIGNAL_REG; } @@ -1027,6 +1107,14 @@ reg_t kFileIOFindNext(EngineState *s, int argc, reg_t *argv) { reg_t kFileIOExists(EngineState *s, int argc, reg_t *argv) { Common::String name = s->_segMan->getString(argv[0]); +#ifdef ENABLE_SCI32 + // Cache the file existence result for the Phantasmagoria + // save index file, as the game scripts keep checking for + // its existence. + if (name == PHANTASMAGORIA_SAVEGAME_INDEX && s->_virtualIndexFile) + return TRUE_REG; +#endif + bool exists = false; // Check for regular file diff --git a/engines/sci/engine/state.cpp b/engines/sci/engine/state.cpp index 28818cddef..237c6b54a6 100644 --- a/engines/sci/engine/state.cpp +++ b/engines/sci/engine/state.cpp @@ -26,6 +26,7 @@ #include "sci/debug.h" // for g_debug_sleeptime_factor #include "sci/event.h" +#include "sci/engine/file.h" #include "sci/engine/kernel.h" #include "sci/engine/state.h" #include "sci/engine/selector.h" @@ -68,21 +69,26 @@ static const uint16 s_halfWidthSJISMap[256] = { }; EngineState::EngineState(SegManager *segMan) -: _segMan(segMan), _dirseeker() { +: _segMan(segMan), +#ifdef ENABLE_SCI32 + _virtualIndexFile(0), +#endif + _dirseeker() { reset(false); } EngineState::~EngineState() { delete _msgState; +#ifdef ENABLE_SCI32 + delete _virtualIndexFile; +#endif } void EngineState::reset(bool isRestoring) { if (!isRestoring) { _memorySegmentSize = 0; - _fileHandles.resize(5); - abortScriptProcessing = kAbortNone; } diff --git a/engines/sci/engine/state.h b/engines/sci/engine/state.h index dcffe6dbb3..6f1f6a6bda 100644 --- a/engines/sci/engine/state.h +++ b/engines/sci/engine/state.h @@ -45,6 +45,7 @@ namespace Sci { class EventManager; class MessageState; class SoundCommandParser; +class VirtualIndexFile; enum AbortGameState { kAbortNone = 0, @@ -163,6 +164,10 @@ public: int16 _lastSaveVirtualId; // last virtual id fed to kSaveGame, if no kGetSaveFiles was called inbetween int16 _lastSaveNewId; // last newly created filename-id by kSaveGame +#ifdef ENABLE_SCI32 + VirtualIndexFile *_virtualIndexFile; +#endif + uint _chosenQfGImportItem; // Remembers the item selected in QfG import rooms bool _cursorWorkaroundActive; // ffs. GfxCursor::setPosition() diff --git a/engines/sci/module.mk b/engines/sci/module.mk index b6d5837b31..6b6058c819 100644 --- a/engines/sci/module.mk +++ b/engines/sci/module.mk @@ -10,6 +10,7 @@ MODULE_OBJS := \ sci.o \ util.o \ engine/features.o \ + engine/file.o \ engine/gc.o \ engine/kernel.o \ engine/kevent.o \ -- cgit v1.2.3 From a209359a678ea19935c875da96fbdb1015bcee74 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Wed, 13 Jun 2012 11:02:00 +0300 Subject: SCI: Reorder the file kernel functions a bit --- engines/sci/engine/kfile.cpp | 82 ++++++++++++++++++++++---------------------- 1 file changed, 41 insertions(+), 41 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/engine/kfile.cpp b/engines/sci/engine/kfile.cpp index 0dd2296f41..dddbc2710e 100644 --- a/engines/sci/engine/kfile.cpp +++ b/engines/sci/engine/kfile.cpp @@ -869,6 +869,47 @@ reg_t kFileIOWriteRaw(EngineState *s, int argc, reg_t *argv) { return make_reg(0, 6); // DOS - invalid handle } +reg_t kFileIOReadString(EngineState *s, int argc, reg_t *argv) { + uint16 size = argv[1].toUint16(); + char *buf = new char[size]; + uint16 handle = argv[2].toUint16(); + debugC(kDebugLevelFile, "kFileIO(readString): %d, %d", handle, size); + uint32 bytesRead; + +#ifdef ENABLE_SCI32 + if (handle == VIRTUALFILE_HANDLE) + bytesRead = s->_virtualIndexFile->readLine(buf, size); + else +#endif + bytesRead = fgets_wrapper(s, buf, size, handle); + + s->_segMan->memcpy(argv[0], (const byte*)buf, size); + delete[] buf; + return bytesRead ? argv[0] : NULL_REG; +} + +reg_t kFileIOWriteString(EngineState *s, int argc, reg_t *argv) { + int handle = argv[0].toUint16(); + Common::String str = s->_segMan->getString(argv[1]); + debugC(kDebugLevelFile, "kFileIO(writeString): %d", handle); + +#ifdef ENABLE_SCI32 + if (handle == VIRTUALFILE_HANDLE) { + s->_virtualIndexFile->write(str.c_str(), str.size()); + return NULL_REG; + } +#endif + + FileHandle *f = getFileFromHandle(s, handle); + + if (f) { + f->_out->write(str.c_str(), str.size()); + return NULL_REG; + } + + return make_reg(0, 6); // DOS - invalid handle +} + reg_t kFileIOUnlink(EngineState *s, int argc, reg_t *argv) { Common::String name = s->_segMan->getString(argv[0]); Common::SaveFileManager *saveFileMan = g_sci->getSaveFileManager(); @@ -918,47 +959,6 @@ reg_t kFileIOUnlink(EngineState *s, int argc, reg_t *argv) { return make_reg(0, 2); // DOS - file not found error code } -reg_t kFileIOReadString(EngineState *s, int argc, reg_t *argv) { - uint16 size = argv[1].toUint16(); - char *buf = new char[size]; - uint16 handle = argv[2].toUint16(); - debugC(kDebugLevelFile, "kFileIO(readString): %d, %d", handle, size); - uint32 bytesRead; - -#ifdef ENABLE_SCI32 - if (handle == VIRTUALFILE_HANDLE) - bytesRead = s->_virtualIndexFile->readLine(buf, size); - else -#endif - bytesRead = fgets_wrapper(s, buf, size, handle); - - s->_segMan->memcpy(argv[0], (const byte*)buf, size); - delete[] buf; - return bytesRead ? argv[0] : NULL_REG; -} - -reg_t kFileIOWriteString(EngineState *s, int argc, reg_t *argv) { - int handle = argv[0].toUint16(); - Common::String str = s->_segMan->getString(argv[1]); - debugC(kDebugLevelFile, "kFileIO(writeString): %d", handle); - -#ifdef ENABLE_SCI32 - if (handle == VIRTUALFILE_HANDLE) { - s->_virtualIndexFile->write(str.c_str(), str.size()); - return NULL_REG; - } -#endif - - FileHandle *f = getFileFromHandle(s, handle); - - if (f) { - f->_out->write(str.c_str(), str.size()); - return NULL_REG; - } - - return make_reg(0, 6); // DOS - invalid handle -} - reg_t kFileIOSeek(EngineState *s, int argc, reg_t *argv) { uint16 handle = argv[0].toUint16(); uint16 offset = ABS(argv[1].toSint16()); // can be negative -- cgit v1.2.3 From 5a17ea058583fb0a3d00392b8e07b2a1f414fded Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Wed, 13 Jun 2012 11:29:14 +0300 Subject: SCI: Move all file-related functions in file.* This way, there is a clear separation of the actual SCI kernel file functions and the file classes and wrappers of ScummVM --- engines/sci/console.cpp | 21 +++ engines/sci/engine/file.cpp | 308 +++++++++++++++++++++++++++++++++++++- engines/sci/engine/file.h | 66 ++++++++- engines/sci/engine/kernel.h | 3 - engines/sci/engine/kfile.cpp | 343 +------------------------------------------ engines/sci/engine/state.h | 43 +----- 6 files changed, 401 insertions(+), 383 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp index 5b5301b468..6a44972a4b 100644 --- a/engines/sci/console.cpp +++ b/engines/sci/console.cpp @@ -1216,6 +1216,27 @@ bool Console::cmdRestartGame(int argc, const char **argv) { return Cmd_Exit(0, 0); } +// The scripts get IDs ranging from 100->199, because the scripts require us to assign unique ids THAT EVEN STAY BETWEEN +// SAVES and the scripts also use "saves-count + 1" to create a new savedgame slot. +// SCI1.1 actually recycles ids, in that case we will currently get "0". +// This behavior is required especially for LSL6. In this game, it's possible to quick save. The scripts will use +// the last-used id for that feature. If we don't assign sticky ids, the feature will overwrite different saves all the +// time. And sadly we can't just use the actual filename ids directly, because of the creation method for new slots. + +extern void listSavegames(Common::Array &saves); + +bool Console::cmdListSaves(int argc, const char **argv) { + Common::Array saves; + listSavegames(saves); + + for (uint i = 0; i < saves.size(); i++) { + Common::String filename = g_sci->getSavegameName(saves[i].id); + DebugPrintf("%s: '%s'\n", filename.c_str(), saves[i].name); + } + + return true; +} + bool Console::cmdClassTable(int argc, const char **argv) { DebugPrintf("Available classes (parse a parameter to filter the table by a specific class):\n"); diff --git a/engines/sci/engine/file.cpp b/engines/sci/engine/file.cpp index 8876f3c46c..66f54d67df 100644 --- a/engines/sci/engine/file.cpp +++ b/engines/sci/engine/file.cpp @@ -25,9 +25,315 @@ #include "sci/sci.h" #include "sci/engine/file.h" +#include "sci/engine/kernel.h" +#include "sci/engine/savegame.h" +#include "sci/engine/selector.h" +#include "sci/engine/state.h" namespace Sci { +/* + * Note on how file I/O is implemented: In ScummVM, one can not create/write + * arbitrary data files, simply because many of our target platforms do not + * support this. The only files one can create are savestates. But SCI has an + * opcode to create and write to seemingly 'arbitrary' files. This is mainly + * used in LSL3 for LARRY3.DRV (which is a game data file, not a driver, used + * for persisting the results of the "age quiz" across restarts) and in LSL5 + * for MEMORY.DRV (which is again a game data file and contains the game's + * password, XOR encrypted). + * To implement that opcode, we combine the SaveFileManager with regular file + * code, similarly to how the SCUMM HE engine does it. + * + * To handle opening a file called "foobar", what we do is this: First, we + * create an 'augmented file name', by prepending the game target and a dash, + * so if we running game target sq1sci, the name becomes "sq1sci-foobar". + * Next, we check if such a file is known to the SaveFileManager. If so, we + * we use that for reading/writing, delete it, whatever. + * + * If no such file is present but we were only asked to *read* the file, + * we fallback to looking for a regular file called "foobar", and open that + * for reading only. + */ + +reg_t file_open(EngineState *s, const Common::String &filename, int mode, bool unwrapFilename) { + Common::String englishName = g_sci->getSciLanguageString(filename, K_LANG_ENGLISH); + Common::String wrappedName = unwrapFilename ? g_sci->wrapFilename(englishName) : englishName; + Common::SeekableReadStream *inFile = 0; + Common::WriteStream *outFile = 0; + Common::SaveFileManager *saveFileMan = g_sci->getSaveFileManager(); + + if (mode == _K_FILE_MODE_OPEN_OR_FAIL) { + // Try to open file, abort if not possible + inFile = saveFileMan->openForLoading(wrappedName); + // If no matching savestate exists: fall back to reading from a regular + // file + if (!inFile) + inFile = SearchMan.createReadStreamForMember(englishName); + + if (!inFile) + debugC(kDebugLevelFile, " -> file_open(_K_FILE_MODE_OPEN_OR_FAIL): failed to open file '%s'", englishName.c_str()); + } else if (mode == _K_FILE_MODE_CREATE) { + // Create the file, destroying any content it might have had + outFile = saveFileMan->openForSaving(wrappedName); + if (!outFile) + debugC(kDebugLevelFile, " -> file_open(_K_FILE_MODE_CREATE): failed to create file '%s'", englishName.c_str()); + } else if (mode == _K_FILE_MODE_OPEN_OR_CREATE) { + // Try to open file, create it if it doesn't exist + outFile = saveFileMan->openForSaving(wrappedName); + if (!outFile) + debugC(kDebugLevelFile, " -> file_open(_K_FILE_MODE_CREATE): failed to create file '%s'", englishName.c_str()); + + // QfG1 opens the character export file with _K_FILE_MODE_CREATE first, + // closes it immediately and opens it again with this here. Perhaps + // other games use this for read access as well. I guess changing this + // whole code into using virtual files and writing them after close + // would be more appropriate. + } else { + error("file_open: unsupported mode %d (filename '%s')", mode, englishName.c_str()); + } + + if (!inFile && !outFile) { // Failed + debugC(kDebugLevelFile, " -> file_open() failed"); + return SIGNAL_REG; + } + + // Find a free file handle + uint handle = 1; // Ignore _fileHandles[0] + while ((handle < s->_fileHandles.size()) && s->_fileHandles[handle].isOpen()) + handle++; + + if (handle == s->_fileHandles.size()) { + // Hit size limit => Allocate more space + s->_fileHandles.resize(s->_fileHandles.size() + 1); + } + + s->_fileHandles[handle]._in = inFile; + s->_fileHandles[handle]._out = outFile; + s->_fileHandles[handle]._name = englishName; + + debugC(kDebugLevelFile, " -> opened file '%s' with handle %d", englishName.c_str(), handle); + return make_reg(0, handle); +} + +FileHandle *getFileFromHandle(EngineState *s, uint handle) { + if (handle == 0 || handle == VIRTUALFILE_HANDLE) { + error("Attempt to use invalid file handle (%d)", handle); + return 0; + } + + if ((handle >= s->_fileHandles.size()) || !s->_fileHandles[handle].isOpen()) { + warning("Attempt to use invalid/unused file handle %d", handle); + return 0; + } + + return &s->_fileHandles[handle]; +} + +int fgets_wrapper(EngineState *s, char *dest, int maxsize, int handle) { + FileHandle *f = getFileFromHandle(s, handle); + if (!f) + return 0; + + if (!f->_in) { + error("fgets_wrapper: Trying to read from file '%s' opened for writing", f->_name.c_str()); + return 0; + } + int readBytes = 0; + if (maxsize > 1) { + memset(dest, 0, maxsize); + f->_in->readLine(dest, maxsize); + readBytes = strlen(dest); // FIXME: sierra sci returned byte count and didn't react on NUL characters + // The returned string must not have an ending LF + if (readBytes > 0) { + if (dest[readBytes - 1] == 0x0A) + dest[readBytes - 1] = 0; + } + } else { + *dest = 0; + } + + debugC(kDebugLevelFile, " -> FGets'ed \"%s\"", dest); + return readBytes; +} + +static bool _savegame_sort_byDate(const SavegameDesc &l, const SavegameDesc &r) { + if (l.date != r.date) + return (l.date > r.date); + return (l.time > r.time); +} + +// Create a sorted array containing all found savedgames +void listSavegames(Common::Array &saves) { + Common::SaveFileManager *saveFileMan = g_sci->getSaveFileManager(); + + // Load all saves + Common::StringArray saveNames = saveFileMan->listSavefiles(g_sci->getSavegamePattern()); + + for (Common::StringArray::const_iterator iter = saveNames.begin(); iter != saveNames.end(); ++iter) { + Common::String filename = *iter; + Common::SeekableReadStream *in; + if ((in = saveFileMan->openForLoading(filename))) { + SavegameMetadata meta; + if (!get_savegame_metadata(in, &meta) || meta.name.empty()) { + // invalid + delete in; + continue; + } + delete in; + + SavegameDesc desc; + desc.id = strtol(filename.end() - 3, NULL, 10); + desc.date = meta.saveDate; + // We need to fix date in here, because we save DDMMYYYY instead of + // YYYYMMDD, so sorting wouldn't work + desc.date = ((desc.date & 0xFFFF) << 16) | ((desc.date & 0xFF0000) >> 8) | ((desc.date & 0xFF000000) >> 24); + desc.time = meta.saveTime; + desc.version = meta.version; + + if (meta.name.lastChar() == '\n') + meta.name.deleteLastChar(); + + Common::strlcpy(desc.name, meta.name.c_str(), SCI_MAX_SAVENAME_LENGTH); + + debug(3, "Savegame in file %s ok, id %d", filename.c_str(), desc.id); + + saves.push_back(desc); + } + } + + // Sort the list by creation date of the saves + Common::sort(saves.begin(), saves.end(), _savegame_sort_byDate); +} + +// Find a savedgame according to virtualId and return the position within our array +int findSavegame(Common::Array &saves, int16 savegameId) { + for (uint saveNr = 0; saveNr < saves.size(); saveNr++) { + if (saves[saveNr].id == savegameId) + return saveNr; + } + return -1; +} + + +FileHandle::FileHandle() : _in(0), _out(0) { +} + +FileHandle::~FileHandle() { + close(); +} + +void FileHandle::close() { + delete _in; + delete _out; + _in = 0; + _out = 0; + _name.clear(); +} + +bool FileHandle::isOpen() const { + return _in || _out; +} + + +void DirSeeker::addAsVirtualFiles(Common::String title, Common::String fileMask) { + Common::SaveFileManager *saveFileMan = g_sci->getSaveFileManager(); + Common::StringArray foundFiles = saveFileMan->listSavefiles(fileMask); + if (!foundFiles.empty()) { + _files.push_back(title); + _virtualFiles.push_back(""); + Common::StringArray::iterator it; + Common::StringArray::iterator it_end = foundFiles.end(); + + for (it = foundFiles.begin(); it != it_end; it++) { + Common::String regularFilename = *it; + Common::String wrappedFilename = Common::String(regularFilename.c_str() + fileMask.size() - 1); + + Common::SeekableReadStream *testfile = saveFileMan->openForLoading(regularFilename); + int32 testfileSize = testfile->size(); + delete testfile; + if (testfileSize > 1024) // check, if larger than 1k. in that case its a saved game. + continue; // and we dont want to have those in the list + // We need to remove the prefix for display purposes + _files.push_back(wrappedFilename); + // but remember the actual name as well + _virtualFiles.push_back(regularFilename); + } + } +} + +Common::String DirSeeker::getVirtualFilename(uint fileNumber) { + if (fileNumber >= _virtualFiles.size()) + error("invalid virtual filename access"); + return _virtualFiles[fileNumber]; +} + +reg_t DirSeeker::firstFile(const Common::String &mask, reg_t buffer, SegManager *segMan) { + // Verify that we are given a valid buffer + if (!buffer.segment) { + error("DirSeeker::firstFile('%s') invoked with invalid buffer", mask.c_str()); + return NULL_REG; + } + _outbuffer = buffer; + _files.clear(); + _virtualFiles.clear(); + + int QfGImport = g_sci->inQfGImportRoom(); + if (QfGImport) { + _files.clear(); + addAsVirtualFiles("-QfG1-", "qfg1-*"); + addAsVirtualFiles("-QfG1VGA-", "qfg1vga-*"); + if (QfGImport > 2) + addAsVirtualFiles("-QfG2-", "qfg2-*"); + if (QfGImport > 3) + addAsVirtualFiles("-QfG3-", "qfg3-*"); + + if (QfGImport == 3) { + // QfG3 sorts the filelisting itself, we can't let that happen otherwise our + // virtual list would go out-of-sync + reg_t savedHeros = segMan->findObjectByName("savedHeros"); + if (!savedHeros.isNull()) + writeSelectorValue(segMan, savedHeros, SELECTOR(sort), 0); + } + + } else { + // Prefix the mask + const Common::String wrappedMask = g_sci->wrapFilename(mask); + + // Obtain a list of all files matching the given mask + Common::SaveFileManager *saveFileMan = g_sci->getSaveFileManager(); + _files = saveFileMan->listSavefiles(wrappedMask); + } + + // Reset the list iterator and write the first match to the output buffer, + // if any. + _iter = _files.begin(); + return nextFile(segMan); +} + +reg_t DirSeeker::nextFile(SegManager *segMan) { + if (_iter == _files.end()) { + return NULL_REG; + } + + Common::String string; + + if (_virtualFiles.empty()) { + // Strip the prefix, if we don't got a virtual filelisting + const Common::String wrappedString = *_iter; + string = g_sci->unwrapFilename(wrappedString); + } else { + string = *_iter; + } + if (string.size() > 12) + string = Common::String(string.c_str(), 12); + segMan->strcpy(_outbuffer, string.c_str()); + + // Return the result and advance the list iterator :) + ++_iter; + return _outbuffer; +} + + #ifdef ENABLE_SCI32 VirtualIndexFile::VirtualIndexFile(Common::String fileName) : _fileName(fileName), _changed(false) { @@ -111,7 +417,7 @@ bool VirtualIndexFile::seek(int32 offset, int whence) { _ptr += offset; break; case SEEK_SET: - assert(offset < _bufferSize); + assert(offset < (int32)_bufferSize); _ptr = _buffer + offset; break; case SEEK_END: diff --git a/engines/sci/engine/file.h b/engines/sci/engine/file.h index e7b1090c91..896dcd2a42 100644 --- a/engines/sci/engine/file.h +++ b/engines/sci/engine/file.h @@ -23,10 +23,74 @@ #ifndef SCI_ENGINE_FILE_H #define SCI_ENGINE_FILE_H -#include "common/scummsys.h" +#include "common/str-array.h" +#include "common/stream.h" namespace Sci { +enum { + _K_FILE_MODE_OPEN_OR_CREATE = 0, + _K_FILE_MODE_OPEN_OR_FAIL = 1, + _K_FILE_MODE_CREATE = 2 +}; + +/* Maximum length of a savegame name (including terminator character). */ +#define SCI_MAX_SAVENAME_LENGTH 0x24 + +enum { + MAX_SAVEGAME_NR = 20 /**< Maximum number of savegames */ +}; + +#define VIRTUALFILE_HANDLE 200 +#define PHANTASMAGORIA_SAVEGAME_INDEX "phantsg.dir" + +struct SavegameDesc { + int16 id; + int virtualId; // straight numbered, according to id but w/o gaps + int date; + int time; + int version; + char name[SCI_MAX_SAVENAME_LENGTH]; +}; + +class FileHandle { +public: + Common::String _name; + Common::SeekableReadStream *_in; + Common::WriteStream *_out; + +public: + FileHandle(); + ~FileHandle(); + + void close(); + bool isOpen() const; +}; + + +class DirSeeker { +protected: + reg_t _outbuffer; + Common::StringArray _files; + Common::StringArray _virtualFiles; + Common::StringArray::const_iterator _iter; + +public: + DirSeeker() { + _outbuffer = NULL_REG; + _iter = _files.begin(); + } + + reg_t firstFile(const Common::String &mask, reg_t buffer, SegManager *segMan); + reg_t nextFile(SegManager *segMan); + + Common::String getVirtualFilename(uint fileNumber); + +private: + void addAsVirtualFiles(Common::String title, Common::String fileMask); +}; + + #ifdef ENABLE_SCI32 /** diff --git a/engines/sci/engine/kernel.h b/engines/sci/engine/kernel.h index d9fdbefbc2..25ca082a9a 100644 --- a/engines/sci/engine/kernel.h +++ b/engines/sci/engine/kernel.h @@ -276,9 +276,6 @@ private: const Common::String _invalid; }; -/* Maximum length of a savegame name (including terminator character). */ -#define SCI_MAX_SAVENAME_LENGTH 0x24 - /******************** Kernel functions ********************/ reg_t kStrLen(EngineState *s, int argc, reg_t *argv); diff --git a/engines/sci/engine/kfile.cpp b/engines/sci/engine/kfile.cpp index dddbc2710e..36e5273b06 100644 --- a/engines/sci/engine/kfile.cpp +++ b/engines/sci/engine/kfile.cpp @@ -41,125 +41,11 @@ namespace Sci { -struct SavegameDesc { - int16 id; - int virtualId; // straight numbered, according to id but w/o gaps - int date; - int time; - int version; - char name[SCI_MAX_SAVENAME_LENGTH]; -}; - -/* - * Note on how file I/O is implemented: In ScummVM, one can not create/write - * arbitrary data files, simply because many of our target platforms do not - * support this. The only files one can create are savestates. But SCI has an - * opcode to create and write to seemingly 'arbitrary' files. This is mainly - * used in LSL3 for LARRY3.DRV (which is a game data file, not a driver, used - * for persisting the results of the "age quiz" across restarts) and in LSL5 - * for MEMORY.DRV (which is again a game data file and contains the game's - * password, XOR encrypted). - * To implement that opcode, we combine the SaveFileManager with regular file - * code, similarly to how the SCUMM HE engine does it. - * - * To handle opening a file called "foobar", what we do is this: First, we - * create an 'augmented file name', by prepending the game target and a dash, - * so if we running game target sq1sci, the name becomes "sq1sci-foobar". - * Next, we check if such a file is known to the SaveFileManager. If so, we - * we use that for reading/writing, delete it, whatever. - * - * If no such file is present but we were only asked to *read* the file, - * we fallback to looking for a regular file called "foobar", and open that - * for reading only. - */ - -FileHandle::FileHandle() : _in(0), _out(0) { -} - -FileHandle::~FileHandle() { - close(); -} - -void FileHandle::close() { - delete _in; - delete _out; - _in = 0; - _out = 0; - _name.clear(); -} - -bool FileHandle::isOpen() const { - return _in || _out; -} - -enum { - _K_FILE_MODE_OPEN_OR_CREATE = 0, - _K_FILE_MODE_OPEN_OR_FAIL = 1, - _K_FILE_MODE_CREATE = 2 -}; - -#define VIRTUALFILE_HANDLE 200 -#define PHANTASMAGORIA_SAVEGAME_INDEX "phantsg.dir" - -reg_t file_open(EngineState *s, const Common::String &filename, int mode, bool unwrapFilename) { - Common::String englishName = g_sci->getSciLanguageString(filename, K_LANG_ENGLISH); - Common::String wrappedName = unwrapFilename ? g_sci->wrapFilename(englishName) : englishName; - Common::SeekableReadStream *inFile = 0; - Common::WriteStream *outFile = 0; - Common::SaveFileManager *saveFileMan = g_sci->getSaveFileManager(); - - if (mode == _K_FILE_MODE_OPEN_OR_FAIL) { - // Try to open file, abort if not possible - inFile = saveFileMan->openForLoading(wrappedName); - // If no matching savestate exists: fall back to reading from a regular - // file - if (!inFile) - inFile = SearchMan.createReadStreamForMember(englishName); - - if (!inFile) - debugC(kDebugLevelFile, " -> file_open(_K_FILE_MODE_OPEN_OR_FAIL): failed to open file '%s'", englishName.c_str()); - } else if (mode == _K_FILE_MODE_CREATE) { - // Create the file, destroying any content it might have had - outFile = saveFileMan->openForSaving(wrappedName); - if (!outFile) - debugC(kDebugLevelFile, " -> file_open(_K_FILE_MODE_CREATE): failed to create file '%s'", englishName.c_str()); - } else if (mode == _K_FILE_MODE_OPEN_OR_CREATE) { - // Try to open file, create it if it doesn't exist - outFile = saveFileMan->openForSaving(wrappedName); - if (!outFile) - debugC(kDebugLevelFile, " -> file_open(_K_FILE_MODE_CREATE): failed to create file '%s'", englishName.c_str()); - - // QfG1 opens the character export file with _K_FILE_MODE_CREATE first, - // closes it immediately and opens it again with this here. Perhaps - // other games use this for read access as well. I guess changing this - // whole code into using virtual files and writing them after close - // would be more appropriate. - } else { - error("file_open: unsupported mode %d (filename '%s')", mode, englishName.c_str()); - } - - if (!inFile && !outFile) { // Failed - debugC(kDebugLevelFile, " -> file_open() failed"); - return SIGNAL_REG; - } - - // Find a free file handle - uint handle = 1; // Ignore _fileHandles[0] - while ((handle < s->_fileHandles.size()) && s->_fileHandles[handle].isOpen()) - handle++; - - if (handle == s->_fileHandles.size()) { - // Hit size limit => Allocate more space - s->_fileHandles.resize(s->_fileHandles.size() + 1); - } - - s->_fileHandles[handle]._in = inFile; - s->_fileHandles[handle]._out = outFile; - s->_fileHandles[handle]._name = englishName; - - debugC(kDebugLevelFile, " -> opened file '%s' with handle %d", englishName.c_str(), handle); - return make_reg(0, handle); -} +extern reg_t file_open(EngineState *s, const Common::String &filename, int mode, bool unwrapFilename); +extern FileHandle *getFileFromHandle(EngineState *s, uint handle); +extern int fgets_wrapper(EngineState *s, char *dest, int maxsize, int handle); +extern void listSavegames(Common::Array &saves); +extern int findSavegame(Common::Array &saves, int16 savegameId); reg_t kFOpen(EngineState *s, int argc, reg_t *argv) { Common::String name = s->_segMan->getString(argv[0]); @@ -169,20 +55,6 @@ reg_t kFOpen(EngineState *s, int argc, reg_t *argv) { return file_open(s, name, mode, true); } -static FileHandle *getFileFromHandle(EngineState *s, uint handle) { - if (handle == 0 || handle == VIRTUALFILE_HANDLE) { - error("Attempt to use invalid file handle (%d)", handle); - return 0; - } - - if ((handle >= s->_fileHandles.size()) || !s->_fileHandles[handle].isOpen()) { - warning("Attempt to use invalid/unused file handle %d", handle); - return 0; - } - - return &s->_fileHandles[handle]; -} - reg_t kFClose(EngineState *s, int argc, reg_t *argv) { debugC(kDebugLevelFile, "kFClose(%d)", argv[0].toUint16()); if (argv[0] != SIGNAL_REG) { @@ -204,33 +76,6 @@ reg_t kFPuts(EngineState *s, int argc, reg_t *argv) { return s->r_acc; } -static int fgets_wrapper(EngineState *s, char *dest, int maxsize, int handle) { - FileHandle *f = getFileFromHandle(s, handle); - if (!f) - return 0; - - if (!f->_in) { - error("fgets_wrapper: Trying to read from file '%s' opened for writing", f->_name.c_str()); - return 0; - } - int readBytes = 0; - if (maxsize > 1) { - memset(dest, 0, maxsize); - f->_in->readLine(dest, maxsize); - readBytes = strlen(dest); // FIXME: sierra sci returned byte count and didn't react on NUL characters - // The returned string must not have an ending LF - if (readBytes > 0) { - if (dest[readBytes - 1] == 0x0A) - dest[readBytes - 1] = 0; - } - } else { - *dest = 0; - } - - debugC(kDebugLevelFile, " -> FGets'ed \"%s\"", dest); - return readBytes; -} - reg_t kFGets(EngineState *s, int argc, reg_t *argv) { int maxsize = argv[1].toUint16(); char *buf = new char[maxsize]; @@ -257,9 +102,6 @@ reg_t kGetCWD(EngineState *s, int argc, reg_t *argv) { return argv[0]; } -static void listSavegames(Common::Array &saves); -static int findSavegame(Common::Array &saves, int16 saveId); - enum { K_DEVICE_INFO_GET_DEVICE = 0, K_DEVICE_INFO_GET_CURRENT_DEVICE = 1, @@ -393,83 +235,6 @@ reg_t kCheckFreeSpace(EngineState *s, int argc, reg_t *argv) { return make_reg(0, 1); } -static bool _savegame_sort_byDate(const SavegameDesc &l, const SavegameDesc &r) { - if (l.date != r.date) - return (l.date > r.date); - return (l.time > r.time); -} - -// Create a sorted array containing all found savedgames -static void listSavegames(Common::Array &saves) { - Common::SaveFileManager *saveFileMan = g_sci->getSaveFileManager(); - - // Load all saves - Common::StringArray saveNames = saveFileMan->listSavefiles(g_sci->getSavegamePattern()); - - for (Common::StringArray::const_iterator iter = saveNames.begin(); iter != saveNames.end(); ++iter) { - Common::String filename = *iter; - Common::SeekableReadStream *in; - if ((in = saveFileMan->openForLoading(filename))) { - SavegameMetadata meta; - if (!get_savegame_metadata(in, &meta) || meta.name.empty()) { - // invalid - delete in; - continue; - } - delete in; - - SavegameDesc desc; - desc.id = strtol(filename.end() - 3, NULL, 10); - desc.date = meta.saveDate; - // We need to fix date in here, because we save DDMMYYYY instead of - // YYYYMMDD, so sorting wouldn't work - desc.date = ((desc.date & 0xFFFF) << 16) | ((desc.date & 0xFF0000) >> 8) | ((desc.date & 0xFF000000) >> 24); - desc.time = meta.saveTime; - desc.version = meta.version; - - if (meta.name.lastChar() == '\n') - meta.name.deleteLastChar(); - - Common::strlcpy(desc.name, meta.name.c_str(), SCI_MAX_SAVENAME_LENGTH); - - debug(3, "Savegame in file %s ok, id %d", filename.c_str(), desc.id); - - saves.push_back(desc); - } - } - - // Sort the list by creation date of the saves - Common::sort(saves.begin(), saves.end(), _savegame_sort_byDate); -} - -// Find a savedgame according to virtualId and return the position within our array -static int findSavegame(Common::Array &saves, int16 savegameId) { - for (uint saveNr = 0; saveNr < saves.size(); saveNr++) { - if (saves[saveNr].id == savegameId) - return saveNr; - } - return -1; -} - -// The scripts get IDs ranging from 100->199, because the scripts require us to assign unique ids THAT EVEN STAY BETWEEN -// SAVES and the scripts also use "saves-count + 1" to create a new savedgame slot. -// SCI1.1 actually recycles ids, in that case we will currently get "0". -// This behavior is required especially for LSL6. In this game, it's possible to quick save. The scripts will use -// the last-used id for that feature. If we don't assign sticky ids, the feature will overwrite different saves all the -// time. And sadly we can't just use the actual filename ids directly, because of the creation method for new slots. - -bool Console::cmdListSaves(int argc, const char **argv) { - Common::Array saves; - listSavegames(saves); - - for (uint i = 0; i < saves.size(); i++) { - Common::String filename = g_sci->getSavegameName(saves[i].id); - DebugPrintf("%s: '%s'\n", filename.c_str(), saves[i].name); - } - - return true; -} - reg_t kCheckSaveGame(EngineState *s, int argc, reg_t *argv) { Common::String game_id = s->_segMan->getString(argv[0]); uint16 virtualId = argv[1].toUint16(); @@ -989,104 +754,6 @@ reg_t kFileIOSeek(EngineState *s, int argc, reg_t *argv) { return SIGNAL_REG; } -void DirSeeker::addAsVirtualFiles(Common::String title, Common::String fileMask) { - Common::SaveFileManager *saveFileMan = g_sci->getSaveFileManager(); - Common::StringArray foundFiles = saveFileMan->listSavefiles(fileMask); - if (!foundFiles.empty()) { - _files.push_back(title); - _virtualFiles.push_back(""); - Common::StringArray::iterator it; - Common::StringArray::iterator it_end = foundFiles.end(); - - for (it = foundFiles.begin(); it != it_end; it++) { - Common::String regularFilename = *it; - Common::String wrappedFilename = Common::String(regularFilename.c_str() + fileMask.size() - 1); - - Common::SeekableReadStream *testfile = saveFileMan->openForLoading(regularFilename); - int32 testfileSize = testfile->size(); - delete testfile; - if (testfileSize > 1024) // check, if larger than 1k. in that case its a saved game. - continue; // and we dont want to have those in the list - // We need to remove the prefix for display purposes - _files.push_back(wrappedFilename); - // but remember the actual name as well - _virtualFiles.push_back(regularFilename); - } - } -} - -Common::String DirSeeker::getVirtualFilename(uint fileNumber) { - if (fileNumber >= _virtualFiles.size()) - error("invalid virtual filename access"); - return _virtualFiles[fileNumber]; -} - -reg_t DirSeeker::firstFile(const Common::String &mask, reg_t buffer, SegManager *segMan) { - // Verify that we are given a valid buffer - if (!buffer.segment) { - error("DirSeeker::firstFile('%s') invoked with invalid buffer", mask.c_str()); - return NULL_REG; - } - _outbuffer = buffer; - _files.clear(); - _virtualFiles.clear(); - - int QfGImport = g_sci->inQfGImportRoom(); - if (QfGImport) { - _files.clear(); - addAsVirtualFiles("-QfG1-", "qfg1-*"); - addAsVirtualFiles("-QfG1VGA-", "qfg1vga-*"); - if (QfGImport > 2) - addAsVirtualFiles("-QfG2-", "qfg2-*"); - if (QfGImport > 3) - addAsVirtualFiles("-QfG3-", "qfg3-*"); - - if (QfGImport == 3) { - // QfG3 sorts the filelisting itself, we can't let that happen otherwise our - // virtual list would go out-of-sync - reg_t savedHeros = segMan->findObjectByName("savedHeros"); - if (!savedHeros.isNull()) - writeSelectorValue(segMan, savedHeros, SELECTOR(sort), 0); - } - - } else { - // Prefix the mask - const Common::String wrappedMask = g_sci->wrapFilename(mask); - - // Obtain a list of all files matching the given mask - Common::SaveFileManager *saveFileMan = g_sci->getSaveFileManager(); - _files = saveFileMan->listSavefiles(wrappedMask); - } - - // Reset the list iterator and write the first match to the output buffer, - // if any. - _iter = _files.begin(); - return nextFile(segMan); -} - -reg_t DirSeeker::nextFile(SegManager *segMan) { - if (_iter == _files.end()) { - return NULL_REG; - } - - Common::String string; - - if (_virtualFiles.empty()) { - // Strip the prefix, if we don't got a virtual filelisting - const Common::String wrappedString = *_iter; - string = g_sci->unwrapFilename(wrappedString); - } else { - string = *_iter; - } - if (string.size() > 12) - string = Common::String(string.c_str(), 12); - segMan->strcpy(_outbuffer, string.c_str()); - - // Return the result and advance the list iterator :) - ++_iter; - return _outbuffer; -} - reg_t kFileIOFindFirst(EngineState *s, int argc, reg_t *argv) { Common::String mask = s->_segMan->getString(argv[0]); reg_t buf = argv[1]; diff --git a/engines/sci/engine/state.h b/engines/sci/engine/state.h index 6f1f6a6bda..78a8a5b0a2 100644 --- a/engines/sci/engine/state.h +++ b/engines/sci/engine/state.h @@ -34,6 +34,7 @@ class WriteStream; } #include "sci/sci.h" +#include "sci/engine/file.h" #include "sci/engine/seg_manager.h" #include "sci/parser/vocabulary.h" @@ -42,6 +43,8 @@ class WriteStream; namespace Sci { +class FileHandle; +class DirSeeker; class EventManager; class MessageState; class SoundCommandParser; @@ -54,32 +57,6 @@ enum AbortGameState { kAbortQuitGame = 3 }; -class DirSeeker { -protected: - reg_t _outbuffer; - Common::StringArray _files; - Common::StringArray _virtualFiles; - Common::StringArray::const_iterator _iter; - -public: - DirSeeker() { - _outbuffer = NULL_REG; - _iter = _files.begin(); - } - - reg_t firstFile(const Common::String &mask, reg_t buffer, SegManager *segMan); - reg_t nextFile(SegManager *segMan); - - Common::String getVirtualFilename(uint fileNumber); - -private: - void addAsVirtualFiles(Common::String title, Common::String fileMask); -}; - -enum { - MAX_SAVEGAME_NR = 20 /**< Maximum number of savegames */ -}; - // We assume that scripts give us savegameId 0->99 for creating a new save slot // and savegameId 100->199 for existing save slots ffs. kfile.cpp enum { @@ -93,20 +70,6 @@ enum { GAMEISRESTARTING_RESTORE = 2 }; -class FileHandle { -public: - Common::String _name; - Common::SeekableReadStream *_in; - Common::WriteStream *_out; - -public: - FileHandle(); - ~FileHandle(); - - void close(); - bool isOpen() const; -}; - enum VideoFlags { kNone = 0, kDoubled = 1 << 0, -- cgit v1.2.3 From 944a774e6a7fd604b0754569007e5e34d1be915f Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Wed, 13 Jun 2012 11:56:13 +0300 Subject: SCI: Change kSave() to be a kernel function with subops --- engines/sci/engine/kernel.h | 1 + engines/sci/engine/kernel_tables.h | 14 ++++++++++++- engines/sci/engine/kfile.cpp | 42 +++++++++++++------------------------- 3 files changed, 28 insertions(+), 29 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/engine/kernel.h b/engines/sci/engine/kernel.h index 25ca082a9a..d64bc42841 100644 --- a/engines/sci/engine/kernel.h +++ b/engines/sci/engine/kernel.h @@ -461,6 +461,7 @@ reg_t kMakeSaveFileName(EngineState *s, int argc, reg_t *argv); // SCI2.1 Kernel Functions reg_t kText(EngineState *s, int argc, reg_t *argv); reg_t kSave(EngineState *s, int argc, reg_t *argv); +reg_t kAutoSave(EngineState *s, int argc, reg_t *argv); reg_t kList(EngineState *s, int argc, reg_t *argv); reg_t kRobot(EngineState *s, int argc, reg_t *argv); reg_t kPlayVMD(EngineState *s, int argc, reg_t *argv); diff --git a/engines/sci/engine/kernel_tables.h b/engines/sci/engine/kernel_tables.h index 9b765283ec..cdc810eef0 100644 --- a/engines/sci/engine/kernel_tables.h +++ b/engines/sci/engine/kernel_tables.h @@ -245,6 +245,18 @@ static const SciKernelMapSubEntry kFileIO_subops[] = { SCI_SUBOPENTRY_TERMINATOR }; +static const SciKernelMapSubEntry kSave_subops[] = { + { SIG_SCI32, 0, MAP_CALL(SaveGame), "[r0]i[r0](r)", NULL }, + { SIG_SCI32, 1, MAP_CALL(RestoreGame), "[r0]i[r0]", NULL }, + { SIG_SCI32, 2, MAP_CALL(GetSaveDir), "(r*)", NULL }, + { SIG_SCI32, 3, MAP_CALL(CheckSaveGame), ".*", NULL }, + // Subop 4 hasn't been encountered yet + { SIG_SCI32, 5, MAP_CALL(GetSaveFiles), "rrr", NULL }, + { SIG_SCI32, 6, MAP_CALL(MakeSaveCatName), "rr", NULL }, + { SIG_SCI32, 7, MAP_CALL(MakeSaveFileName), "rri", NULL }, + { SIG_SCI32, 8, MAP_CALL(AutoSave), "[o0]", NULL }, +}; + #ifdef ENABLE_SCI32 // version, subId, function-mapping, signature, workarounds static const SciKernelMapSubEntry kList_subops[] = { @@ -555,7 +567,7 @@ static SciKernelMapEntry s_kernelMap[] = { { MAP_CALL(MulDiv), SIG_EVERYWHERE, "iii", NULL, NULL }, { MAP_CALL(PlayVMD), SIG_EVERYWHERE, "(.*)", NULL, NULL }, { MAP_CALL(Robot), SIG_EVERYWHERE, "(.*)", NULL, NULL }, - { MAP_CALL(Save), SIG_EVERYWHERE, "(.*)", NULL, NULL }, + { MAP_CALL(Save), SIG_EVERYWHERE, "i(.*)", kSave_subops, NULL }, { MAP_CALL(Text), SIG_EVERYWHERE, "(.*)", NULL, NULL }, { MAP_CALL(AddPicAt), SIG_EVERYWHERE, "oiii", NULL, NULL }, { MAP_CALL(GetWindowsOption), SIG_EVERYWHERE, "i", NULL, NULL }, diff --git a/engines/sci/engine/kfile.cpp b/engines/sci/engine/kfile.cpp index 36e5273b06..fe54987e47 100644 --- a/engines/sci/engine/kfile.cpp +++ b/engines/sci/engine/kfile.cpp @@ -946,35 +946,21 @@ reg_t kMakeSaveFileName(EngineState *s, int argc, reg_t *argv) { return argv[0]; } +reg_t kAutoSave(EngineState *s, int argc, reg_t *argv) { + // TODO + // This is a timer callback, with 1 parameter: the timer object + // (e.g. "timers"). + // It's used for auto-saving (i.e. save every X minutes, by checking + // the elapsed time from the timer object) + + // This function has to return something other than 0 to proceed + return s->r_acc; +} + reg_t kSave(EngineState *s, int argc, reg_t *argv) { - switch (argv[0].toUint16()) { - case 0: - return kSaveGame(s, argc - 1,argv + 1); - case 1: - return kRestoreGame(s, argc - 1,argv + 1); - case 2: - return kGetSaveDir(s, argc - 1, argv + 1); - case 3: - return kCheckSaveGame(s, argc - 1, argv + 1); - case 5: - return kGetSaveFiles(s, argc - 1, argv + 1); - case 6: - return kMakeSaveCatName(s, argc - 1, argv + 1); - case 7: - return kMakeSaveFileName(s, argc - 1, argv + 1); - case 8: - // TODO - // This is a timer callback, with 1 parameter: the timer object - // (e.g. "timers"). - // It's used for auto-saving (i.e. save every X minutes, by checking - // the elapsed time from the timer object) - - // This function has to return something other than 0 to proceed - return s->r_acc; - default: - kStub(s, argc, argv); - return NULL_REG; - } + if (!s) + return make_reg(0, getSciVersion()); + error("not supposed to call this"); } #endif -- cgit v1.2.3 From 098f162ecc4951873909e9815506d4053178b6f9 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Wed, 13 Jun 2012 12:19:18 +0300 Subject: SCI: Use the later SCI file functions for the SCI0 ones They are essentially the same (with the exception of the return values), so unifying them reduces code duplication --- engines/sci/engine/kernel.h | 4 --- engines/sci/engine/kernel_tables.h | 8 ++--- engines/sci/engine/kfile.cpp | 65 +++++++++++--------------------------- 3 files changed, 22 insertions(+), 55 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/engine/kernel.h b/engines/sci/engine/kernel.h index d64bc42841..677b790f93 100644 --- a/engines/sci/engine/kernel.h +++ b/engines/sci/engine/kernel.h @@ -323,10 +323,6 @@ reg_t kTimesCot(EngineState *s, int argc, reg_t *argv); reg_t kCosDiv(EngineState *s, int argc, reg_t *argv); reg_t kSinDiv(EngineState *s, int argc, reg_t *argv); reg_t kValidPath(EngineState *s, int argc, reg_t *argv); -reg_t kFOpen(EngineState *s, int argc, reg_t *argv); -reg_t kFPuts(EngineState *s, int argc, reg_t *argv); -reg_t kFGets(EngineState *s, int argc, reg_t *argv); -reg_t kFClose(EngineState *s, int argc, reg_t *argv); reg_t kMapKeyToDir(EngineState *s, int argc, reg_t *argv); reg_t kGlobalToLocal(EngineState *s, int argc, reg_t *argv); reg_t kLocalToGlobal(EngineState *s, int argc, reg_t *argv); diff --git a/engines/sci/engine/kernel_tables.h b/engines/sci/engine/kernel_tables.h index cdc810eef0..d093310139 100644 --- a/engines/sci/engine/kernel_tables.h +++ b/engines/sci/engine/kernel_tables.h @@ -350,10 +350,10 @@ static SciKernelMapEntry s_kernelMap[] = { { MAP_CALL(EditControl), SIG_EVERYWHERE, "[o0][o0]", NULL, NULL }, { MAP_CALL(Empty), SIG_EVERYWHERE, "(.*)", NULL, NULL }, { MAP_CALL(EmptyList), SIG_EVERYWHERE, "l", NULL, NULL }, - { MAP_CALL(FClose), SIG_EVERYWHERE, "i", NULL, NULL }, - { MAP_CALL(FGets), SIG_EVERYWHERE, "rii", NULL, NULL }, - { MAP_CALL(FOpen), SIG_EVERYWHERE, "ri", NULL, NULL }, - { MAP_CALL(FPuts), SIG_EVERYWHERE, "ir", NULL, NULL }, + { "FClose", kFileIOClose, SIG_EVERYWHERE, "i", NULL, NULL }, + { "FGets", kFileIOReadString, SIG_EVERYWHERE, "rii", NULL, NULL }, + { "FOpen", kFileIOOpen, SIG_EVERYWHERE, "ri", NULL, NULL }, + { "FPuts", kFileIOWriteString, SIG_EVERYWHERE, "ir", NULL, NULL }, { MAP_CALL(FileIO), SIG_EVERYWHERE, "i(.*)", kFileIO_subops, NULL }, { MAP_CALL(FindKey), SIG_EVERYWHERE, "l.", NULL, kFindKey_workarounds }, { MAP_CALL(FirstNode), SIG_EVERYWHERE, "[l0]", NULL, NULL }, diff --git a/engines/sci/engine/kfile.cpp b/engines/sci/engine/kfile.cpp index fe54987e47..052332957b 100644 --- a/engines/sci/engine/kfile.cpp +++ b/engines/sci/engine/kfile.cpp @@ -47,47 +47,6 @@ extern int fgets_wrapper(EngineState *s, char *dest, int maxsize, int handle); extern void listSavegames(Common::Array &saves); extern int findSavegame(Common::Array &saves, int16 savegameId); -reg_t kFOpen(EngineState *s, int argc, reg_t *argv) { - Common::String name = s->_segMan->getString(argv[0]); - int mode = argv[1].toUint16(); - - debugC(kDebugLevelFile, "kFOpen(%s,0x%x)", name.c_str(), mode); - return file_open(s, name, mode, true); -} - -reg_t kFClose(EngineState *s, int argc, reg_t *argv) { - debugC(kDebugLevelFile, "kFClose(%d)", argv[0].toUint16()); - if (argv[0] != SIGNAL_REG) { - FileHandle *f = getFileFromHandle(s, argv[0].toUint16()); - if (f) - f->close(); - } - return s->r_acc; -} - -reg_t kFPuts(EngineState *s, int argc, reg_t *argv) { - int handle = argv[0].toUint16(); - Common::String data = s->_segMan->getString(argv[1]); - - FileHandle *f = getFileFromHandle(s, handle); - if (f) - f->_out->write(data.c_str(), data.size()); - - return s->r_acc; -} - -reg_t kFGets(EngineState *s, int argc, reg_t *argv) { - int maxsize = argv[1].toUint16(); - char *buf = new char[maxsize]; - int handle = argv[2].toUint16(); - - debugC(kDebugLevelFile, "kFGets(%d, %d)", handle, maxsize); - int readBytes = fgets_wrapper(s, buf, maxsize, handle); - s->_segMan->memcpy(argv[0], (const byte*)buf, maxsize); - delete[] buf; - return readBytes ? argv[0] : NULL_REG; -} - /** * Writes the cwd to the supplied address and returns the address in acc. */ @@ -559,6 +518,9 @@ reg_t kFileIOOpen(EngineState *s, int argc, reg_t *argv) { reg_t kFileIOClose(EngineState *s, int argc, reg_t *argv) { debugC(kDebugLevelFile, "kFileIO(close): %d", argv[0].toUint16()); + if (argv[0] == SIGNAL_REG) + return s->r_acc; + uint16 handle = argv[0].toUint16(); #ifdef ENABLE_SCI32 @@ -571,8 +533,13 @@ reg_t kFileIOClose(EngineState *s, int argc, reg_t *argv) { FileHandle *f = getFileFromHandle(s, handle); if (f) { f->close(); + if (getSciVersion() <= SCI_VERSION_0_LATE) + return s->r_acc; // SCI0 semantics: no value returned return SIGNAL_REG; } + + if (getSciVersion() <= SCI_VERSION_0_LATE) + return s->r_acc; // SCI0 semantics: no value returned return NULL_REG; } @@ -635,20 +602,20 @@ reg_t kFileIOWriteRaw(EngineState *s, int argc, reg_t *argv) { } reg_t kFileIOReadString(EngineState *s, int argc, reg_t *argv) { - uint16 size = argv[1].toUint16(); - char *buf = new char[size]; + uint16 maxsize = argv[1].toUint16(); + char *buf = new char[maxsize]; uint16 handle = argv[2].toUint16(); - debugC(kDebugLevelFile, "kFileIO(readString): %d, %d", handle, size); + debugC(kDebugLevelFile, "kFileIO(readString): %d, %d", handle, maxsize); uint32 bytesRead; #ifdef ENABLE_SCI32 if (handle == VIRTUALFILE_HANDLE) - bytesRead = s->_virtualIndexFile->readLine(buf, size); + bytesRead = s->_virtualIndexFile->readLine(buf, maxsize); else #endif - bytesRead = fgets_wrapper(s, buf, size, handle); + bytesRead = fgets_wrapper(s, buf, maxsize, handle); - s->_segMan->memcpy(argv[0], (const byte*)buf, size); + s->_segMan->memcpy(argv[0], (const byte*)buf, maxsize); delete[] buf; return bytesRead ? argv[0] : NULL_REG; } @@ -669,9 +636,13 @@ reg_t kFileIOWriteString(EngineState *s, int argc, reg_t *argv) { if (f) { f->_out->write(str.c_str(), str.size()); + if (getSciVersion() <= SCI_VERSION_0_LATE) + return s->r_acc; // SCI0 semantics: no value returned return NULL_REG; } + if (getSciVersion() <= SCI_VERSION_0_LATE) + return s->r_acc; // SCI0 semantics: no value returned return make_reg(0, 6); // DOS - invalid handle } -- cgit v1.2.3 From 694f0f534a548061c3fecec3c8b0be0e0e5310dd Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Wed, 13 Jun 2012 12:22:51 +0300 Subject: SCI: Only include kSave_subops if ENABLE_SCI32 is defined --- engines/sci/engine/kernel_tables.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'engines/sci') diff --git a/engines/sci/engine/kernel_tables.h b/engines/sci/engine/kernel_tables.h index d093310139..6965a5da45 100644 --- a/engines/sci/engine/kernel_tables.h +++ b/engines/sci/engine/kernel_tables.h @@ -245,6 +245,8 @@ static const SciKernelMapSubEntry kFileIO_subops[] = { SCI_SUBOPENTRY_TERMINATOR }; +#ifdef ENABLE_SCI32 + static const SciKernelMapSubEntry kSave_subops[] = { { SIG_SCI32, 0, MAP_CALL(SaveGame), "[r0]i[r0](r)", NULL }, { SIG_SCI32, 1, MAP_CALL(RestoreGame), "[r0]i[r0]", NULL }, @@ -255,9 +257,9 @@ static const SciKernelMapSubEntry kSave_subops[] = { { SIG_SCI32, 6, MAP_CALL(MakeSaveCatName), "rr", NULL }, { SIG_SCI32, 7, MAP_CALL(MakeSaveFileName), "rri", NULL }, { SIG_SCI32, 8, MAP_CALL(AutoSave), "[o0]", NULL }, + SCI_SUBOPENTRY_TERMINATOR }; -#ifdef ENABLE_SCI32 // version, subId, function-mapping, signature, workarounds static const SciKernelMapSubEntry kList_subops[] = { { SIG_SCI21, 0, MAP_CALL(NewList), "", NULL }, -- cgit v1.2.3 From e2613d22423fe2108e13909279b2f336a8a3209d Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Wed, 13 Jun 2012 12:23:43 +0300 Subject: SCI: Add a workaround for the French version of Torin's Passage Thanks to LePhilousophe for playing and providing the workaround --- engines/sci/engine/workarounds.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'engines/sci') diff --git a/engines/sci/engine/workarounds.cpp b/engines/sci/engine/workarounds.cpp index c1d4a3d9f9..ecb1e4c2d5 100644 --- a/engines/sci/engine/workarounds.cpp +++ b/engines/sci/engine/workarounds.cpp @@ -167,6 +167,7 @@ const SciWorkaroundEntry uninitializedReadWorkarounds[] = { { GID_SQ6, -1, 0, 0, "SQ6", "init", -1, 2, { WORKAROUND_FAKE, 0 } }, // Demo and full version: called when the game starts (demo: room 0, full: room 100) { GID_SQ6, 100, 64950, 0, "View", "handleEvent", -1, 0, { WORKAROUND_FAKE, 0 } }, // called when pressing "Start game" in the main menu { GID_SQ6, -1, 64964, 0, "DPath", "init", -1, 1, { WORKAROUND_FAKE, 0 } }, // during the game + { GID_TORIN, -1, 64017, 0, "oFlags", "clear", -1, 0, { WORKAROUND_FAKE, 0 } }, // entering Torin's home in the French version SCI_WORKAROUNDENTRY_TERMINATOR }; -- cgit v1.2.3 From 93024c073be6d93c9369a83e4b4468bb0aaeeadd Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Wed, 13 Jun 2012 12:26:13 +0300 Subject: SCI: Handle the torindebug config setting for Torin's Passage French Thanks to LePhilousophe for testing and providing a patch --- engines/sci/engine/kmisc.cpp | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'engines/sci') diff --git a/engines/sci/engine/kmisc.cpp b/engines/sci/engine/kmisc.cpp index 1cbaf0708d..47c891eefd 100644 --- a/engines/sci/engine/kmisc.cpp +++ b/engines/sci/engine/kmisc.cpp @@ -384,6 +384,10 @@ reg_t kGetConfig(EngineState *s, int argc, reg_t *argv) { } else if (setting == "language") { Common::String languageId = Common::String::format("%d", g_sci->getSciLanguage()); s->_segMan->strcpy(data, languageId.c_str()); + } else if (setting == "torindebug") { + // Used to enable the debug mode in Torin's Passage (French). + // If true, the debug mode is enabled. + s->_segMan->strcpy(data, ""); } else { error("GetConfig: Unknown configuration setting %s", setting.c_str()); } -- cgit v1.2.3 From 045613af95b84b6a57526125da35b949d0f431ea Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Wed, 13 Jun 2012 12:54:40 +0300 Subject: SCI: Shuffle the kernel functions inside kfile.cpp This puts them in the order that they are defined in the kernel tables --- engines/sci/engine/kfile.cpp | 1144 +++++++++++++++++++++--------------------- 1 file changed, 580 insertions(+), 564 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/engine/kfile.cpp b/engines/sci/engine/kfile.cpp index 052332957b..445a019368 100644 --- a/engines/sci/engine/kfile.cpp +++ b/engines/sci/engine/kfile.cpp @@ -152,18 +152,6 @@ reg_t kDeviceInfo(EngineState *s, int argc, reg_t *argv) { return s->r_acc; } -reg_t kGetSaveDir(EngineState *s, int argc, reg_t *argv) { -#ifdef ENABLE_SCI32 - // SCI32 uses a parameter here. It is used to modify a string, stored in a - // global variable, so that game scripts store the save directory. We - // don't really set a save game directory, thus not setting the string to - // anything is the correct thing to do here. - //if (argc > 0) - // warning("kGetSaveDir called with %d parameter(s): %04x:%04x", argc, PRINT_REG(argv[0])); -#endif - return s->_segMan->getSaveDirPtr(); -} - reg_t kCheckFreeSpace(EngineState *s, int argc, reg_t *argv) { if (argc > 1) { // SCI1.1/SCI32 @@ -194,292 +182,187 @@ reg_t kCheckFreeSpace(EngineState *s, int argc, reg_t *argv) { return make_reg(0, 1); } -reg_t kCheckSaveGame(EngineState *s, int argc, reg_t *argv) { - Common::String game_id = s->_segMan->getString(argv[0]); - uint16 virtualId = argv[1].toUint16(); - - debug(3, "kCheckSaveGame(%s, %d)", game_id.c_str(), virtualId); +reg_t kValidPath(EngineState *s, int argc, reg_t *argv) { + Common::String path = s->_segMan->getString(argv[0]); - Common::Array saves; - listSavegames(saves); + debug(3, "kValidPath(%s) -> %d", path.c_str(), s->r_acc.offset); - // we allow 0 (happens in QfG2 when trying to restore from an empty saved game list) and return false in that case - if (virtualId == 0) - return NULL_REG; + // Always return true + return make_reg(0, 1); +} - // Find saved-game - if ((virtualId < SAVEGAMEID_OFFICIALRANGE_START) || (virtualId > SAVEGAMEID_OFFICIALRANGE_END)) - error("kCheckSaveGame: called with invalid savegameId"); - uint savegameId = virtualId - SAVEGAMEID_OFFICIALRANGE_START; - int savegameNr = findSavegame(saves, savegameId); - if (savegameNr == -1) - return NULL_REG; +#ifdef ENABLE_SCI32 - // Check for compatible savegame version - int ver = saves[savegameNr].version; - if (ver < MINIMUM_SAVEGAME_VERSION || ver > CURRENT_SAVEGAME_VERSION) - return NULL_REG; +reg_t kCD(EngineState *s, int argc, reg_t *argv) { + // TODO: Stub + switch (argv[0].toUint16()) { + case 0: + // Return whether the contents of disc argv[1] is available. + return TRUE_REG; + default: + warning("CD(%d)", argv[0].toUint16()); + } - // Otherwise we assume the savegame is OK - return TRUE_REG; + return NULL_REG; } -reg_t kGetSaveFiles(EngineState *s, int argc, reg_t *argv) { - Common::String game_id = s->_segMan->getString(argv[0]); - - debug(3, "kGetSaveFiles(%s)", game_id.c_str()); +#endif - // Scripts ask for current save files, we can assume that if afterwards they ask us to create a new slot they really - // mean new slot instead of overwriting the old one - s->_lastSaveVirtualId = SAVEGAMEID_OFFICIALRANGE_START; +// ---- FileIO operations ----------------------------------------------------- - Common::Array saves; - listSavegames(saves); - uint totalSaves = MIN(saves.size(), MAX_SAVEGAME_NR); +reg_t kFileIO(EngineState *s, int argc, reg_t *argv) { + if (!s) + return make_reg(0, getSciVersion()); + error("not supposed to call this"); +} - reg_t *slot = s->_segMan->derefRegPtr(argv[2], totalSaves); +reg_t kFileIOOpen(EngineState *s, int argc, reg_t *argv) { + Common::String name = s->_segMan->getString(argv[0]); - if (!slot) { - warning("kGetSaveFiles: %04X:%04X invalid or too small to hold slot data", PRINT_REG(argv[2])); - totalSaves = 0; +#ifdef ENABLE_SCI32 + if (name == PHANTASMAGORIA_SAVEGAME_INDEX) { + if (s->_virtualIndexFile) { + return make_reg(0, VIRTUALFILE_HANDLE); + } else { + Common::String englishName = g_sci->getSciLanguageString(name, K_LANG_ENGLISH); + Common::String wrappedName = g_sci->wrapFilename(englishName); + if (!g_sci->getSaveFileManager()->listSavefiles(wrappedName).empty()) { + s->_virtualIndexFile = new VirtualIndexFile(wrappedName); + return make_reg(0, VIRTUALFILE_HANDLE); + } + } } +#endif - const uint bufSize = (totalSaves * SCI_MAX_SAVENAME_LENGTH) + 1; - char *saveNames = new char[bufSize]; - char *saveNamePtr = saveNames; + // SCI32 can call K_FILEIO_OPEN with only one argument. It seems to + // just be checking if it exists. + int mode = (argc < 2) ? (int)_K_FILE_MODE_OPEN_OR_FAIL : argv[1].toUint16(); + bool unwrapFilename = true; - for (uint i = 0; i < totalSaves; i++) { - *slot++ = make_reg(0, saves[i].id + SAVEGAMEID_OFFICIALRANGE_START); // Store the virtual savegame ID ffs. see above - strcpy(saveNamePtr, saves[i].name); - saveNamePtr += SCI_MAX_SAVENAME_LENGTH; + // SQ4 floppy prepends /\ to the filenames + if (name.hasPrefix("/\\")) { + name.deleteChar(0); + name.deleteChar(0); } - *saveNamePtr = 0; // Terminate list + // SQ4 floppy attempts to update the savegame index file sq4sg.dir when + // deleting saved games. We don't use an index file for saving or loading, + // so just stop the game from modifying the file here in order to avoid + // having it saved in the ScummVM save directory. + if (name == "sq4sg.dir") { + debugC(kDebugLevelFile, "Not opening unused file sq4sg.dir"); + return SIGNAL_REG; + } - s->_segMan->memcpy(argv[1], (byte *)saveNames, bufSize); - delete[] saveNames; + if (name.empty()) { + // Happens many times during KQ1 (e.g. when typing something) + debugC(kDebugLevelFile, "Attempted to open a file with an empty filename"); + return SIGNAL_REG; + } + debugC(kDebugLevelFile, "kFileIO(open): %s, 0x%x", name.c_str(), mode); - return make_reg(0, totalSaves); + // QFG import rooms get a virtual filelisting instead of an actual one + if (g_sci->inQfGImportRoom()) { + // We need to find out what the user actually selected, "savedHeroes" is + // already destroyed when we get here. That's why we need to remember + // selection via kDrawControl. + name = s->_dirseeker.getVirtualFilename(s->_chosenQfGImportItem); + unwrapFilename = false; + } + + return file_open(s, name, mode, unwrapFilename); } -reg_t kSaveGame(EngineState *s, int argc, reg_t *argv) { - Common::String game_id; - int16 virtualId = argv[1].toSint16(); - int16 savegameId = -1; - Common::String game_description; - Common::String version; +reg_t kFileIOClose(EngineState *s, int argc, reg_t *argv) { + debugC(kDebugLevelFile, "kFileIO(close): %d", argv[0].toUint16()); - if (argc > 3) - version = s->_segMan->getString(argv[3]); + if (argv[0] == SIGNAL_REG) + return s->r_acc; + + uint16 handle = argv[0].toUint16(); - // We check here, we don't want to delete a users save in case we are within a kernel function - if (s->executionStackBase) { - warning("kSaveGame - won't save from within kernel function"); - return NULL_REG; +#ifdef ENABLE_SCI32 + if (handle == VIRTUALFILE_HANDLE) { + s->_virtualIndexFile->close(); + return SIGNAL_REG; } +#endif - if (argv[0].isNull()) { - // Direct call, from a patched Game::save - if ((argv[1] != SIGNAL_REG) || (!argv[2].isNull())) - error("kSaveGame: assumed patched call isn't accurate"); - - // we are supposed to show a dialog for the user and let him choose where to save - g_sci->_soundCmd->pauseAll(true); // pause music - GUI::SaveLoadChooser *dialog = new GUI::SaveLoadChooser(_("Save game:"), _("Save"), true); - savegameId = dialog->runModalWithCurrentTarget(); - game_description = dialog->getResultString(); - if (game_description.empty()) { - // create our own description for the saved game, the user didnt enter it - game_description = dialog->createDefaultSaveDescription(savegameId); - } - delete dialog; - g_sci->_soundCmd->pauseAll(false); // unpause music ( we can't have it paused during save) - if (savegameId < 0) - return NULL_REG; - - } else { - // Real call from script - game_id = s->_segMan->getString(argv[0]); - if (argv[2].isNull()) - error("kSaveGame: called with description being NULL"); - game_description = s->_segMan->getString(argv[2]); - - debug(3, "kSaveGame(%s,%d,%s,%s)", game_id.c_str(), virtualId, game_description.c_str(), version.c_str()); + FileHandle *f = getFileFromHandle(s, handle); + if (f) { + f->close(); + if (getSciVersion() <= SCI_VERSION_0_LATE) + return s->r_acc; // SCI0 semantics: no value returned + return SIGNAL_REG; + } - Common::Array saves; - listSavegames(saves); + if (getSciVersion() <= SCI_VERSION_0_LATE) + return s->r_acc; // SCI0 semantics: no value returned + return NULL_REG; +} - if ((virtualId >= SAVEGAMEID_OFFICIALRANGE_START) && (virtualId <= SAVEGAMEID_OFFICIALRANGE_END)) { - // savegameId is an actual Id, so search for it just to make sure - savegameId = virtualId - SAVEGAMEID_OFFICIALRANGE_START; - if (findSavegame(saves, savegameId) == -1) - return NULL_REG; - } else if (virtualId < SAVEGAMEID_OFFICIALRANGE_START) { - // virtualId is low, we assume that scripts expect us to create new slot - if (virtualId == s->_lastSaveVirtualId) { - // if last virtual id is the same as this one, we assume that caller wants to overwrite last save - savegameId = s->_lastSaveNewId; - } else { - uint savegameNr; - // savegameId is in lower range, scripts expect us to create a new slot - for (savegameId = 0; savegameId < SAVEGAMEID_OFFICIALRANGE_START; savegameId++) { - for (savegameNr = 0; savegameNr < saves.size(); savegameNr++) { - if (savegameId == saves[savegameNr].id) - break; - } - if (savegameNr == saves.size()) - break; - } - if (savegameId == SAVEGAMEID_OFFICIALRANGE_START) - error("kSavegame: no more savegame slots available"); - } - } else { - error("kSaveGame: invalid savegameId used"); - } +reg_t kFileIOReadRaw(EngineState *s, int argc, reg_t *argv) { + uint16 handle = argv[0].toUint16(); + uint16 size = argv[2].toUint16(); + int bytesRead = 0; + char *buf = new char[size]; + debugC(kDebugLevelFile, "kFileIO(readRaw): %d, %d", handle, size); - // Save in case caller wants to overwrite last newly created save - s->_lastSaveVirtualId = virtualId; - s->_lastSaveNewId = savegameId; +#ifdef ENABLE_SCI32 + if (handle == VIRTUALFILE_HANDLE) { + bytesRead = s->_virtualIndexFile->read(buf, size); + } else { +#endif + FileHandle *f = getFileFromHandle(s, handle); + if (f) + bytesRead = f->_in->read(buf, size); +#ifdef ENABLE_SCI32 } +#endif - s->r_acc = NULL_REG; + // TODO: What happens if less bytes are read than what has + // been requested? (i.e. if bytesRead is non-zero, but still + // less than size) + if (bytesRead > 0) + s->_segMan->memcpy(argv[1], (const byte*)buf, size); - Common::String filename = g_sci->getSavegameName(savegameId); - Common::SaveFileManager *saveFileMan = g_sci->getSaveFileManager(); - Common::OutSaveFile *out; + delete[] buf; + return make_reg(0, bytesRead); +} - out = saveFileMan->openForSaving(filename); - if (!out) { - warning("Error opening savegame \"%s\" for writing", filename.c_str()); - } else { - if (!gamestate_save(s, out, game_description, version)) { - warning("Saving the game failed"); - } else { - s->r_acc = TRUE_REG; // save successful - } - - out->finalize(); - if (out->err()) { - warning("Writing the savegame failed"); - s->r_acc = NULL_REG; // write failure - } - delete out; - } - - return s->r_acc; -} - -reg_t kRestoreGame(EngineState *s, int argc, reg_t *argv) { - Common::String game_id = !argv[0].isNull() ? s->_segMan->getString(argv[0]) : ""; - int16 savegameId = argv[1].toSint16(); - bool pausedMusic = false; - - debug(3, "kRestoreGame(%s,%d)", game_id.c_str(), savegameId); - - if (argv[0].isNull()) { - // Direct call, either from launcher or from a patched Game::restore - if (savegameId == -1) { - // we are supposed to show a dialog for the user and let him choose a saved game - g_sci->_soundCmd->pauseAll(true); // pause music - GUI::SaveLoadChooser *dialog = new GUI::SaveLoadChooser(_("Restore game:"), _("Restore"), false); - savegameId = dialog->runModalWithCurrentTarget(); - delete dialog; - if (savegameId < 0) { - g_sci->_soundCmd->pauseAll(false); // unpause music - return s->r_acc; - } - pausedMusic = true; - } - // don't adjust ID of the saved game, it's already correct - } else { - if (argv[2].isNull()) - error("kRestoreGame: called with parameter 2 being NULL"); - // Real call from script, we need to adjust ID - if ((savegameId < SAVEGAMEID_OFFICIALRANGE_START) || (savegameId > SAVEGAMEID_OFFICIALRANGE_END)) { - warning("Savegame ID %d is not allowed", savegameId); - return TRUE_REG; - } - savegameId -= SAVEGAMEID_OFFICIALRANGE_START; - } - - s->r_acc = NULL_REG; // signals success +reg_t kFileIOWriteRaw(EngineState *s, int argc, reg_t *argv) { + uint16 handle = argv[0].toUint16(); + uint16 size = argv[2].toUint16(); + char *buf = new char[size]; + bool success = false; + s->_segMan->memcpy((byte *)buf, argv[1], size); + debugC(kDebugLevelFile, "kFileIO(writeRaw): %d, %d", handle, size); - Common::Array saves; - listSavegames(saves); - if (findSavegame(saves, savegameId) == -1) { - s->r_acc = TRUE_REG; - warning("Savegame ID %d not found", savegameId); +#ifdef ENABLE_SCI32 + if (handle == VIRTUALFILE_HANDLE) { + s->_virtualIndexFile->write(buf, size); + success = true; } else { - Common::SaveFileManager *saveFileMan = g_sci->getSaveFileManager(); - Common::String filename = g_sci->getSavegameName(savegameId); - Common::SeekableReadStream *in; - - in = saveFileMan->openForLoading(filename); - if (in) { - // found a savegame file - - gamestate_restore(s, in); - delete in; - - if (g_sci->getGameId() == GID_MOTHERGOOSE256) { - // WORKAROUND: Mother Goose SCI1/SCI1.1 does some weird things for - // saving a previously restored game. - // We set the current savedgame-id directly and remove the script - // code concerning this via script patch. - s->variables[VAR_GLOBAL][0xB3].offset = SAVEGAMEID_OFFICIALRANGE_START + savegameId; - } - } else { - s->r_acc = TRUE_REG; - warning("Savegame #%d not found", savegameId); +#endif + FileHandle *f = getFileFromHandle(s, handle); + if (f) { + f->_out->write(buf, size); + success = true; } +#ifdef ENABLE_SCI32 } +#endif - if (!s->r_acc.isNull()) { - // no success? - if (pausedMusic) - g_sci->_soundCmd->pauseAll(false); // unpause music - } - - return s->r_acc; -} - -reg_t kValidPath(EngineState *s, int argc, reg_t *argv) { - Common::String path = s->_segMan->getString(argv[0]); - - debug(3, "kValidPath(%s) -> %d", path.c_str(), s->r_acc.offset); - - // Always return true - return make_reg(0, 1); -} - -reg_t kFileIO(EngineState *s, int argc, reg_t *argv) { - if (!s) - return make_reg(0, getSciVersion()); - error("not supposed to call this"); + delete[] buf; + if (success) + return NULL_REG; + return make_reg(0, 6); // DOS - invalid handle } -reg_t kFileIOOpen(EngineState *s, int argc, reg_t *argv) { +reg_t kFileIOUnlink(EngineState *s, int argc, reg_t *argv) { Common::String name = s->_segMan->getString(argv[0]); - -#ifdef ENABLE_SCI32 - if (name == PHANTASMAGORIA_SAVEGAME_INDEX) { - if (s->_virtualIndexFile) { - return make_reg(0, VIRTUALFILE_HANDLE); - } else { - Common::String englishName = g_sci->getSciLanguageString(name, K_LANG_ENGLISH); - Common::String wrappedName = g_sci->wrapFilename(englishName); - if (!g_sci->getSaveFileManager()->listSavefiles(wrappedName).empty()) { - s->_virtualIndexFile = new VirtualIndexFile(wrappedName); - return make_reg(0, VIRTUALFILE_HANDLE); - } - } - } -#endif - - // SCI32 can call K_FILEIO_OPEN with only one argument. It seems to - // just be checking if it exists. - int mode = (argc < 2) ? (int)_K_FILE_MODE_OPEN_OR_FAIL : argv[1].toUint16(); - bool unwrapFilename = true; + Common::SaveFileManager *saveFileMan = g_sci->getSaveFileManager(); + bool result; // SQ4 floppy prepends /\ to the filenames if (name.hasPrefix("/\\")) { @@ -487,407 +370,546 @@ reg_t kFileIOOpen(EngineState *s, int argc, reg_t *argv) { name.deleteChar(0); } - // SQ4 floppy attempts to update the savegame index file sq4sg.dir when - // deleting saved games. We don't use an index file for saving or loading, - // so just stop the game from modifying the file here in order to avoid - // having it saved in the ScummVM save directory. - if (name == "sq4sg.dir") { - debugC(kDebugLevelFile, "Not opening unused file sq4sg.dir"); - return SIGNAL_REG; - } - - if (name.empty()) { - // Happens many times during KQ1 (e.g. when typing something) - debugC(kDebugLevelFile, "Attempted to open a file with an empty filename"); - return SIGNAL_REG; - } - debugC(kDebugLevelFile, "kFileIO(open): %s, 0x%x", name.c_str(), mode); + // Special case for SQ4 floppy: This game has hardcoded names for all of + // its savegames, and they are all named "sq4sg.xxx", where xxx is the + // slot. We just take the slot number here, and delete the appropriate + // save game. + if (name.hasPrefix("sq4sg.")) { + // Special handling for SQ4... get the slot number and construct the + // save game name. + int slotNum = atoi(name.c_str() + name.size() - 3); + Common::Array saves; + listSavegames(saves); + int savedir_nr = saves[slotNum].id; + name = g_sci->getSavegameName(savedir_nr); + result = saveFileMan->removeSavefile(name); + } else if (getSciVersion() >= SCI_VERSION_2) { + // The file name may be already wrapped, so check both cases + result = saveFileMan->removeSavefile(name); + if (!result) { + const Common::String wrappedName = g_sci->wrapFilename(name); + result = saveFileMan->removeSavefile(wrappedName); + } - // QFG import rooms get a virtual filelisting instead of an actual one - if (g_sci->inQfGImportRoom()) { - // We need to find out what the user actually selected, "savedHeroes" is - // already destroyed when we get here. That's why we need to remember - // selection via kDrawControl. - name = s->_dirseeker.getVirtualFilename(s->_chosenQfGImportItem); - unwrapFilename = false; +#ifdef ENABLE_SCI32 + if (name == PHANTASMAGORIA_SAVEGAME_INDEX) { + delete s->_virtualIndexFile; + s->_virtualIndexFile = 0; + } +#endif + } else { + const Common::String wrappedName = g_sci->wrapFilename(name); + result = saveFileMan->removeSavefile(wrappedName); } - return file_open(s, name, mode, unwrapFilename); + debugC(kDebugLevelFile, "kFileIO(unlink): %s", name.c_str()); + if (result) + return NULL_REG; + return make_reg(0, 2); // DOS - file not found error code } -reg_t kFileIOClose(EngineState *s, int argc, reg_t *argv) { - debugC(kDebugLevelFile, "kFileIO(close): %d", argv[0].toUint16()); +reg_t kFileIOReadString(EngineState *s, int argc, reg_t *argv) { + uint16 maxsize = argv[1].toUint16(); + char *buf = new char[maxsize]; + uint16 handle = argv[2].toUint16(); + debugC(kDebugLevelFile, "kFileIO(readString): %d, %d", handle, maxsize); + uint32 bytesRead; - if (argv[0] == SIGNAL_REG) - return s->r_acc; - - uint16 handle = argv[0].toUint16(); +#ifdef ENABLE_SCI32 + if (handle == VIRTUALFILE_HANDLE) + bytesRead = s->_virtualIndexFile->readLine(buf, maxsize); + else +#endif + bytesRead = fgets_wrapper(s, buf, maxsize, handle); + + s->_segMan->memcpy(argv[0], (const byte*)buf, maxsize); + delete[] buf; + return bytesRead ? argv[0] : NULL_REG; +} + +reg_t kFileIOWriteString(EngineState *s, int argc, reg_t *argv) { + int handle = argv[0].toUint16(); + Common::String str = s->_segMan->getString(argv[1]); + debugC(kDebugLevelFile, "kFileIO(writeString): %d", handle); #ifdef ENABLE_SCI32 if (handle == VIRTUALFILE_HANDLE) { - s->_virtualIndexFile->close(); - return SIGNAL_REG; + s->_virtualIndexFile->write(str.c_str(), str.size()); + return NULL_REG; } #endif FileHandle *f = getFileFromHandle(s, handle); + if (f) { - f->close(); + f->_out->write(str.c_str(), str.size()); if (getSciVersion() <= SCI_VERSION_0_LATE) return s->r_acc; // SCI0 semantics: no value returned - return SIGNAL_REG; + return NULL_REG; } if (getSciVersion() <= SCI_VERSION_0_LATE) return s->r_acc; // SCI0 semantics: no value returned - return NULL_REG; + return make_reg(0, 6); // DOS - invalid handle } -reg_t kFileIOReadRaw(EngineState *s, int argc, reg_t *argv) { +reg_t kFileIOSeek(EngineState *s, int argc, reg_t *argv) { uint16 handle = argv[0].toUint16(); - uint16 size = argv[2].toUint16(); - int bytesRead = 0; - char *buf = new char[size]; - debugC(kDebugLevelFile, "kFileIO(readRaw): %d, %d", handle, size); + uint16 offset = ABS(argv[1].toSint16()); // can be negative + uint16 whence = argv[2].toUint16(); + debugC(kDebugLevelFile, "kFileIO(seek): %d, %d, %d", handle, offset, whence); #ifdef ENABLE_SCI32 - if (handle == VIRTUALFILE_HANDLE) { - bytesRead = s->_virtualIndexFile->read(buf, size); - } else { + if (handle == VIRTUALFILE_HANDLE) + return make_reg(0, s->_virtualIndexFile->seek(offset, whence)); #endif - FileHandle *f = getFileFromHandle(s, handle); - if (f) - bytesRead = f->_in->read(buf, size); -#ifdef ENABLE_SCI32 + + FileHandle *f = getFileFromHandle(s, handle); + + if (f && f->_in) { + // Backward seeking isn't supported in zip file streams, thus adapt the + // parameters accordingly if games ask for such a seek mode. A known + // case where this is requested is the save file manager in Phantasmagoria + if (whence == SEEK_END) { + whence = SEEK_SET; + offset = f->_in->size() - offset; + } + + return make_reg(0, f->_in->seek(offset, whence)); + } else if (f && f->_out) { + error("kFileIOSeek: Unsupported seek operation on a writeable stream (offset: %d, whence: %d)", offset, whence); } -#endif - // TODO: What happens if less bytes are read than what has - // been requested? (i.e. if bytesRead is non-zero, but still - // less than size) - if (bytesRead > 0) - s->_segMan->memcpy(argv[1], (const byte*)buf, size); + return SIGNAL_REG; +} - delete[] buf; - return make_reg(0, bytesRead); +reg_t kFileIOFindFirst(EngineState *s, int argc, reg_t *argv) { + Common::String mask = s->_segMan->getString(argv[0]); + reg_t buf = argv[1]; + int attr = argv[2].toUint16(); // We won't use this, Win32 might, though... + debugC(kDebugLevelFile, "kFileIO(findFirst): %s, 0x%x", mask.c_str(), attr); + + // We remove ".*". mask will get prefixed, so we will return all additional files for that gameid + if (mask == "*.*") + mask = "*"; + return s->_dirseeker.firstFile(mask, buf, s->_segMan); } -reg_t kFileIOWriteRaw(EngineState *s, int argc, reg_t *argv) { - uint16 handle = argv[0].toUint16(); - uint16 size = argv[2].toUint16(); - char *buf = new char[size]; - bool success = false; - s->_segMan->memcpy((byte *)buf, argv[1], size); - debugC(kDebugLevelFile, "kFileIO(writeRaw): %d, %d", handle, size); +reg_t kFileIOFindNext(EngineState *s, int argc, reg_t *argv) { + debugC(kDebugLevelFile, "kFileIO(findNext)"); + return s->_dirseeker.nextFile(s->_segMan); +} + +reg_t kFileIOExists(EngineState *s, int argc, reg_t *argv) { + Common::String name = s->_segMan->getString(argv[0]); #ifdef ENABLE_SCI32 - if (handle == VIRTUALFILE_HANDLE) { - s->_virtualIndexFile->write(buf, size); - success = true; - } else { + // Cache the file existence result for the Phantasmagoria + // save index file, as the game scripts keep checking for + // its existence. + if (name == PHANTASMAGORIA_SAVEGAME_INDEX && s->_virtualIndexFile) + return TRUE_REG; #endif - FileHandle *f = getFileFromHandle(s, handle); - if (f) { - f->_out->write(buf, size); - success = true; - } -#ifdef ENABLE_SCI32 + + bool exists = false; + + // Check for regular file + exists = Common::File::exists(name); + + // Check for a savegame with the name + Common::SaveFileManager *saveFileMan = g_sci->getSaveFileManager(); + if (!exists) + exists = !saveFileMan->listSavefiles(name).empty(); + + // Try searching for the file prepending "target-" + const Common::String wrappedName = g_sci->wrapFilename(name); + if (!exists) { + exists = !saveFileMan->listSavefiles(wrappedName).empty(); } -#endif - delete[] buf; - if (success) - return NULL_REG; - return make_reg(0, 6); // DOS - invalid handle -} + // SCI2+ debug mode + if (DebugMan.isDebugChannelEnabled(kDebugLevelDebugMode)) { + if (!exists && name == "1.scr") // PQ4 + exists = true; + if (!exists && name == "18.scr") // QFG4 + exists = true; + if (!exists && name == "99.scr") // GK1, KQ7 + exists = true; + if (!exists && name == "classes") // GK2, SQ6, LSL7 + exists = true; + } -reg_t kFileIOReadString(EngineState *s, int argc, reg_t *argv) { - uint16 maxsize = argv[1].toUint16(); - char *buf = new char[maxsize]; - uint16 handle = argv[2].toUint16(); - debugC(kDebugLevelFile, "kFileIO(readString): %d, %d", handle, maxsize); - uint32 bytesRead; + // Special case for non-English versions of LSL5: The English version of + // LSL5 calls kFileIO(), case K_FILEIO_OPEN for reading to check if + // memory.drv exists (which is where the game's password is stored). If + // it's not found, it calls kFileIO() again, case K_FILEIO_OPEN for + // writing and creates a new file. Non-English versions call kFileIO(), + // case K_FILEIO_FILE_EXISTS instead, and fail if memory.drv can't be + // found. We create a default memory.drv file with no password, so that + // the game can continue. + if (!exists && name == "memory.drv") { + // Create a new file, and write the bytes for the empty password + // string inside + byte defaultContent[] = { 0xE9, 0xE9, 0xEB, 0xE1, 0x0D, 0x0A, 0x31, 0x30, 0x30, 0x30 }; + Common::WriteStream *outFile = saveFileMan->openForSaving(wrappedName); + for (int i = 0; i < 10; i++) + outFile->writeByte(defaultContent[i]); + outFile->finalize(); + exists = !outFile->err(); // check whether we managed to create the file. + delete outFile; + } -#ifdef ENABLE_SCI32 - if (handle == VIRTUALFILE_HANDLE) - bytesRead = s->_virtualIndexFile->readLine(buf, maxsize); - else -#endif - bytesRead = fgets_wrapper(s, buf, maxsize, handle); + // Special case for KQ6 Mac: The game checks for two video files to see + // if they exist before it plays them. Since we support multiple naming + // schemes for resource fork files, we also need to support that here in + // case someone has a "HalfDome.bin" file, etc. + if (!exists && g_sci->getGameId() == GID_KQ6 && g_sci->getPlatform() == Common::kPlatformMacintosh && + (name == "HalfDome" || name == "Kq6Movie")) + exists = Common::MacResManager::exists(name); - s->_segMan->memcpy(argv[0], (const byte*)buf, maxsize); - delete[] buf; - return bytesRead ? argv[0] : NULL_REG; + debugC(kDebugLevelFile, "kFileIO(fileExists) %s -> %d", name.c_str(), exists); + return make_reg(0, exists); } -reg_t kFileIOWriteString(EngineState *s, int argc, reg_t *argv) { - int handle = argv[0].toUint16(); - Common::String str = s->_segMan->getString(argv[1]); - debugC(kDebugLevelFile, "kFileIO(writeString): %d", handle); +reg_t kFileIORename(EngineState *s, int argc, reg_t *argv) { + Common::String oldName = s->_segMan->getString(argv[0]); + Common::String newName = s->_segMan->getString(argv[1]); + + // SCI1.1 returns 0 on success and a DOS error code on fail. SCI32 + // returns -1 on fail. We just return -1 for all versions. + if (g_sci->getSaveFileManager()->renameSavefile(oldName, newName)) + return NULL_REG; + else + return SIGNAL_REG; +} #ifdef ENABLE_SCI32 - if (handle == VIRTUALFILE_HANDLE) { - s->_virtualIndexFile->write(str.c_str(), str.size()); +reg_t kFileIOReadByte(EngineState *s, int argc, reg_t *argv) { + // Read the byte into the low byte of the accumulator + FileHandle *f = getFileFromHandle(s, argv[0].toUint16()); + if (!f) return NULL_REG; - } -#endif + return make_reg(0, (s->r_acc.toUint16() & 0xff00) | f->_in->readByte()); +} - FileHandle *f = getFileFromHandle(s, handle); +reg_t kFileIOWriteByte(EngineState *s, int argc, reg_t *argv) { + FileHandle *f = getFileFromHandle(s, argv[0].toUint16()); + if (f) + f->_out->writeByte(argv[1].toUint16() & 0xff); + return s->r_acc; // FIXME: does this really not return anything? +} - if (f) { - f->_out->write(str.c_str(), str.size()); - if (getSciVersion() <= SCI_VERSION_0_LATE) - return s->r_acc; // SCI0 semantics: no value returned +reg_t kFileIOReadWord(EngineState *s, int argc, reg_t *argv) { + FileHandle *f = getFileFromHandle(s, argv[0].toUint16()); + if (!f) return NULL_REG; - } + return make_reg(0, f->_in->readUint16LE()); +} - if (getSciVersion() <= SCI_VERSION_0_LATE) - return s->r_acc; // SCI0 semantics: no value returned - return make_reg(0, 6); // DOS - invalid handle +reg_t kFileIOWriteWord(EngineState *s, int argc, reg_t *argv) { + FileHandle *f = getFileFromHandle(s, argv[0].toUint16()); + if (f) + f->_out->writeUint16LE(argv[1].toUint16()); + return s->r_acc; // FIXME: does this really not return anything? } -reg_t kFileIOUnlink(EngineState *s, int argc, reg_t *argv) { - Common::String name = s->_segMan->getString(argv[0]); - Common::SaveFileManager *saveFileMan = g_sci->getSaveFileManager(); - bool result; +reg_t kFileIOCreateSaveSlot(EngineState *s, int argc, reg_t *argv) { + // Used in Shivers when the user enters his name on the guest book + // in the beginning to start the game. - // SQ4 floppy prepends /\ to the filenames - if (name.hasPrefix("/\\")) { - name.deleteChar(0); - name.deleteChar(0); - } + // Creates a new save slot, and returns if the operation was successful - // Special case for SQ4 floppy: This game has hardcoded names for all of - // its savegames, and they are all named "sq4sg.xxx", where xxx is the - // slot. We just take the slot number here, and delete the appropriate - // save game. - if (name.hasPrefix("sq4sg.")) { - // Special handling for SQ4... get the slot number and construct the - // save game name. - int slotNum = atoi(name.c_str() + name.size() - 3); - Common::Array saves; - listSavegames(saves); - int savedir_nr = saves[slotNum].id; - name = g_sci->getSavegameName(savedir_nr); - result = saveFileMan->removeSavefile(name); - } else if (getSciVersion() >= SCI_VERSION_2) { - // The file name may be already wrapped, so check both cases - result = saveFileMan->removeSavefile(name); - if (!result) { - const Common::String wrappedName = g_sci->wrapFilename(name); - result = saveFileMan->removeSavefile(wrappedName); - } + // Argument 0 denotes the save slot as a negative integer, 2 means "0" + // Argument 1 is a string, with the file name, obtained from kSave(5). + // The interpreter checks if it can be written to (by checking for free + // disk space and write permissions) -#ifdef ENABLE_SCI32 - if (name == PHANTASMAGORIA_SAVEGAME_INDEX) { - delete s->_virtualIndexFile; - s->_virtualIndexFile = 0; - } -#endif - } else { - const Common::String wrappedName = g_sci->wrapFilename(name); - result = saveFileMan->removeSavefile(wrappedName); - } + // We don't really use or need any of this... - debugC(kDebugLevelFile, "kFileIO(unlink): %s", name.c_str()); - if (result) - return NULL_REG; - return make_reg(0, 2); // DOS - file not found error code + uint16 saveSlot = argv[0].toUint16(); + char* fileName = s->_segMan->lookupString(argv[1])->getRawData(); + warning("kFileIOCreateSaveSlot(%d, '%s')", saveSlot, fileName); + + return TRUE_REG; // slot creation was successful } -reg_t kFileIOSeek(EngineState *s, int argc, reg_t *argv) { - uint16 handle = argv[0].toUint16(); - uint16 offset = ABS(argv[1].toSint16()); // can be negative - uint16 whence = argv[2].toUint16(); - debugC(kDebugLevelFile, "kFileIO(seek): %d, %d, %d", handle, offset, whence); +#endif + +// ---- Save operations ------------------------------------------------------- #ifdef ENABLE_SCI32 - if (handle == VIRTUALFILE_HANDLE) - return make_reg(0, s->_virtualIndexFile->seek(offset, whence)); + +reg_t kSave(EngineState *s, int argc, reg_t *argv) { + if (!s) + return make_reg(0, getSciVersion()); + error("not supposed to call this"); +} + #endif - FileHandle *f = getFileFromHandle(s, handle); +reg_t kSaveGame(EngineState *s, int argc, reg_t *argv) { + Common::String game_id; + int16 virtualId = argv[1].toSint16(); + int16 savegameId = -1; + Common::String game_description; + Common::String version; - if (f && f->_in) { - // Backward seeking isn't supported in zip file streams, thus adapt the - // parameters accordingly if games ask for such a seek mode. A known - // case where this is requested is the save file manager in Phantasmagoria - if (whence == SEEK_END) { - whence = SEEK_SET; - offset = f->_in->size() - offset; + if (argc > 3) + version = s->_segMan->getString(argv[3]); + + // We check here, we don't want to delete a users save in case we are within a kernel function + if (s->executionStackBase) { + warning("kSaveGame - won't save from within kernel function"); + return NULL_REG; + } + + if (argv[0].isNull()) { + // Direct call, from a patched Game::save + if ((argv[1] != SIGNAL_REG) || (!argv[2].isNull())) + error("kSaveGame: assumed patched call isn't accurate"); + + // we are supposed to show a dialog for the user and let him choose where to save + g_sci->_soundCmd->pauseAll(true); // pause music + GUI::SaveLoadChooser *dialog = new GUI::SaveLoadChooser(_("Save game:"), _("Save"), true); + savegameId = dialog->runModalWithCurrentTarget(); + game_description = dialog->getResultString(); + if (game_description.empty()) { + // create our own description for the saved game, the user didnt enter it + game_description = dialog->createDefaultSaveDescription(savegameId); } + delete dialog; + g_sci->_soundCmd->pauseAll(false); // unpause music ( we can't have it paused during save) + if (savegameId < 0) + return NULL_REG; - return make_reg(0, f->_in->seek(offset, whence)); - } else if (f && f->_out) { - error("kFileIOSeek: Unsupported seek operation on a writeable stream (offset: %d, whence: %d)", offset, whence); + } else { + // Real call from script + game_id = s->_segMan->getString(argv[0]); + if (argv[2].isNull()) + error("kSaveGame: called with description being NULL"); + game_description = s->_segMan->getString(argv[2]); + + debug(3, "kSaveGame(%s,%d,%s,%s)", game_id.c_str(), virtualId, game_description.c_str(), version.c_str()); + + Common::Array saves; + listSavegames(saves); + + if ((virtualId >= SAVEGAMEID_OFFICIALRANGE_START) && (virtualId <= SAVEGAMEID_OFFICIALRANGE_END)) { + // savegameId is an actual Id, so search for it just to make sure + savegameId = virtualId - SAVEGAMEID_OFFICIALRANGE_START; + if (findSavegame(saves, savegameId) == -1) + return NULL_REG; + } else if (virtualId < SAVEGAMEID_OFFICIALRANGE_START) { + // virtualId is low, we assume that scripts expect us to create new slot + if (virtualId == s->_lastSaveVirtualId) { + // if last virtual id is the same as this one, we assume that caller wants to overwrite last save + savegameId = s->_lastSaveNewId; + } else { + uint savegameNr; + // savegameId is in lower range, scripts expect us to create a new slot + for (savegameId = 0; savegameId < SAVEGAMEID_OFFICIALRANGE_START; savegameId++) { + for (savegameNr = 0; savegameNr < saves.size(); savegameNr++) { + if (savegameId == saves[savegameNr].id) + break; + } + if (savegameNr == saves.size()) + break; + } + if (savegameId == SAVEGAMEID_OFFICIALRANGE_START) + error("kSavegame: no more savegame slots available"); + } + } else { + error("kSaveGame: invalid savegameId used"); + } + + // Save in case caller wants to overwrite last newly created save + s->_lastSaveVirtualId = virtualId; + s->_lastSaveNewId = savegameId; } - return SIGNAL_REG; -} + s->r_acc = NULL_REG; -reg_t kFileIOFindFirst(EngineState *s, int argc, reg_t *argv) { - Common::String mask = s->_segMan->getString(argv[0]); - reg_t buf = argv[1]; - int attr = argv[2].toUint16(); // We won't use this, Win32 might, though... - debugC(kDebugLevelFile, "kFileIO(findFirst): %s, 0x%x", mask.c_str(), attr); + Common::String filename = g_sci->getSavegameName(savegameId); + Common::SaveFileManager *saveFileMan = g_sci->getSaveFileManager(); + Common::OutSaveFile *out; + + out = saveFileMan->openForSaving(filename); + if (!out) { + warning("Error opening savegame \"%s\" for writing", filename.c_str()); + } else { + if (!gamestate_save(s, out, game_description, version)) { + warning("Saving the game failed"); + } else { + s->r_acc = TRUE_REG; // save successful + } + + out->finalize(); + if (out->err()) { + warning("Writing the savegame failed"); + s->r_acc = NULL_REG; // write failure + } + delete out; + } - // We remove ".*". mask will get prefixed, so we will return all additional files for that gameid - if (mask == "*.*") - mask = "*"; - return s->_dirseeker.firstFile(mask, buf, s->_segMan); + return s->r_acc; } -reg_t kFileIOFindNext(EngineState *s, int argc, reg_t *argv) { - debugC(kDebugLevelFile, "kFileIO(findNext)"); - return s->_dirseeker.nextFile(s->_segMan); -} +reg_t kRestoreGame(EngineState *s, int argc, reg_t *argv) { + Common::String game_id = !argv[0].isNull() ? s->_segMan->getString(argv[0]) : ""; + int16 savegameId = argv[1].toSint16(); + bool pausedMusic = false; -reg_t kFileIOExists(EngineState *s, int argc, reg_t *argv) { - Common::String name = s->_segMan->getString(argv[0]); + debug(3, "kRestoreGame(%s,%d)", game_id.c_str(), savegameId); -#ifdef ENABLE_SCI32 - // Cache the file existence result for the Phantasmagoria - // save index file, as the game scripts keep checking for - // its existence. - if (name == PHANTASMAGORIA_SAVEGAME_INDEX && s->_virtualIndexFile) - return TRUE_REG; -#endif + if (argv[0].isNull()) { + // Direct call, either from launcher or from a patched Game::restore + if (savegameId == -1) { + // we are supposed to show a dialog for the user and let him choose a saved game + g_sci->_soundCmd->pauseAll(true); // pause music + GUI::SaveLoadChooser *dialog = new GUI::SaveLoadChooser(_("Restore game:"), _("Restore"), false); + savegameId = dialog->runModalWithCurrentTarget(); + delete dialog; + if (savegameId < 0) { + g_sci->_soundCmd->pauseAll(false); // unpause music + return s->r_acc; + } + pausedMusic = true; + } + // don't adjust ID of the saved game, it's already correct + } else { + if (argv[2].isNull()) + error("kRestoreGame: called with parameter 2 being NULL"); + // Real call from script, we need to adjust ID + if ((savegameId < SAVEGAMEID_OFFICIALRANGE_START) || (savegameId > SAVEGAMEID_OFFICIALRANGE_END)) { + warning("Savegame ID %d is not allowed", savegameId); + return TRUE_REG; + } + savegameId -= SAVEGAMEID_OFFICIALRANGE_START; + } - bool exists = false; + s->r_acc = NULL_REG; // signals success - // Check for regular file - exists = Common::File::exists(name); + Common::Array saves; + listSavegames(saves); + if (findSavegame(saves, savegameId) == -1) { + s->r_acc = TRUE_REG; + warning("Savegame ID %d not found", savegameId); + } else { + Common::SaveFileManager *saveFileMan = g_sci->getSaveFileManager(); + Common::String filename = g_sci->getSavegameName(savegameId); + Common::SeekableReadStream *in; - // Check for a savegame with the name - Common::SaveFileManager *saveFileMan = g_sci->getSaveFileManager(); - if (!exists) - exists = !saveFileMan->listSavefiles(name).empty(); + in = saveFileMan->openForLoading(filename); + if (in) { + // found a savegame file - // Try searching for the file prepending "target-" - const Common::String wrappedName = g_sci->wrapFilename(name); - if (!exists) { - exists = !saveFileMan->listSavefiles(wrappedName).empty(); - } + gamestate_restore(s, in); + delete in; - // SCI2+ debug mode - if (DebugMan.isDebugChannelEnabled(kDebugLevelDebugMode)) { - if (!exists && name == "1.scr") // PQ4 - exists = true; - if (!exists && name == "18.scr") // QFG4 - exists = true; - if (!exists && name == "99.scr") // GK1, KQ7 - exists = true; - if (!exists && name == "classes") // GK2, SQ6, LSL7 - exists = true; + if (g_sci->getGameId() == GID_MOTHERGOOSE256) { + // WORKAROUND: Mother Goose SCI1/SCI1.1 does some weird things for + // saving a previously restored game. + // We set the current savedgame-id directly and remove the script + // code concerning this via script patch. + s->variables[VAR_GLOBAL][0xB3].offset = SAVEGAMEID_OFFICIALRANGE_START + savegameId; + } + } else { + s->r_acc = TRUE_REG; + warning("Savegame #%d not found", savegameId); + } } - // Special case for non-English versions of LSL5: The English version of - // LSL5 calls kFileIO(), case K_FILEIO_OPEN for reading to check if - // memory.drv exists (which is where the game's password is stored). If - // it's not found, it calls kFileIO() again, case K_FILEIO_OPEN for - // writing and creates a new file. Non-English versions call kFileIO(), - // case K_FILEIO_FILE_EXISTS instead, and fail if memory.drv can't be - // found. We create a default memory.drv file with no password, so that - // the game can continue. - if (!exists && name == "memory.drv") { - // Create a new file, and write the bytes for the empty password - // string inside - byte defaultContent[] = { 0xE9, 0xE9, 0xEB, 0xE1, 0x0D, 0x0A, 0x31, 0x30, 0x30, 0x30 }; - Common::WriteStream *outFile = saveFileMan->openForSaving(wrappedName); - for (int i = 0; i < 10; i++) - outFile->writeByte(defaultContent[i]); - outFile->finalize(); - exists = !outFile->err(); // check whether we managed to create the file. - delete outFile; + if (!s->r_acc.isNull()) { + // no success? + if (pausedMusic) + g_sci->_soundCmd->pauseAll(false); // unpause music } - // Special case for KQ6 Mac: The game checks for two video files to see - // if they exist before it plays them. Since we support multiple naming - // schemes for resource fork files, we also need to support that here in - // case someone has a "HalfDome.bin" file, etc. - if (!exists && g_sci->getGameId() == GID_KQ6 && g_sci->getPlatform() == Common::kPlatformMacintosh && - (name == "HalfDome" || name == "Kq6Movie")) - exists = Common::MacResManager::exists(name); + return s->r_acc; +} - debugC(kDebugLevelFile, "kFileIO(fileExists) %s -> %d", name.c_str(), exists); - return make_reg(0, exists); +reg_t kGetSaveDir(EngineState *s, int argc, reg_t *argv) { +#ifdef ENABLE_SCI32 + // SCI32 uses a parameter here. It is used to modify a string, stored in a + // global variable, so that game scripts store the save directory. We + // don't really set a save game directory, thus not setting the string to + // anything is the correct thing to do here. + //if (argc > 0) + // warning("kGetSaveDir called with %d parameter(s): %04x:%04x", argc, PRINT_REG(argv[0])); +#endif + return s->_segMan->getSaveDirPtr(); } -reg_t kFileIORename(EngineState *s, int argc, reg_t *argv) { - Common::String oldName = s->_segMan->getString(argv[0]); - Common::String newName = s->_segMan->getString(argv[1]); +reg_t kCheckSaveGame(EngineState *s, int argc, reg_t *argv) { + Common::String game_id = s->_segMan->getString(argv[0]); + uint16 virtualId = argv[1].toUint16(); - // SCI1.1 returns 0 on success and a DOS error code on fail. SCI32 - // returns -1 on fail. We just return -1 for all versions. - if (g_sci->getSaveFileManager()->renameSavefile(oldName, newName)) - return NULL_REG; - else - return SIGNAL_REG; -} + debug(3, "kCheckSaveGame(%s, %d)", game_id.c_str(), virtualId); -#ifdef ENABLE_SCI32 -reg_t kFileIOReadByte(EngineState *s, int argc, reg_t *argv) { - // Read the byte into the low byte of the accumulator - FileHandle *f = getFileFromHandle(s, argv[0].toUint16()); - if (!f) + Common::Array saves; + listSavegames(saves); + + // we allow 0 (happens in QfG2 when trying to restore from an empty saved game list) and return false in that case + if (virtualId == 0) return NULL_REG; - return make_reg(0, (s->r_acc.toUint16() & 0xff00) | f->_in->readByte()); -} -reg_t kFileIOWriteByte(EngineState *s, int argc, reg_t *argv) { - FileHandle *f = getFileFromHandle(s, argv[0].toUint16()); - if (f) - f->_out->writeByte(argv[1].toUint16() & 0xff); - return s->r_acc; // FIXME: does this really not return anything? -} + // Find saved-game + if ((virtualId < SAVEGAMEID_OFFICIALRANGE_START) || (virtualId > SAVEGAMEID_OFFICIALRANGE_END)) + error("kCheckSaveGame: called with invalid savegameId"); + uint savegameId = virtualId - SAVEGAMEID_OFFICIALRANGE_START; + int savegameNr = findSavegame(saves, savegameId); + if (savegameNr == -1) + return NULL_REG; -reg_t kFileIOReadWord(EngineState *s, int argc, reg_t *argv) { - FileHandle *f = getFileFromHandle(s, argv[0].toUint16()); - if (!f) + // Check for compatible savegame version + int ver = saves[savegameNr].version; + if (ver < MINIMUM_SAVEGAME_VERSION || ver > CURRENT_SAVEGAME_VERSION) return NULL_REG; - return make_reg(0, f->_in->readUint16LE()); -} -reg_t kFileIOWriteWord(EngineState *s, int argc, reg_t *argv) { - FileHandle *f = getFileFromHandle(s, argv[0].toUint16()); - if (f) - f->_out->writeUint16LE(argv[1].toUint16()); - return s->r_acc; // FIXME: does this really not return anything? + // Otherwise we assume the savegame is OK + return TRUE_REG; } -reg_t kFileIOCreateSaveSlot(EngineState *s, int argc, reg_t *argv) { - // Used in Shivers when the user enters his name on the guest book - // in the beginning to start the game. +reg_t kGetSaveFiles(EngineState *s, int argc, reg_t *argv) { + Common::String game_id = s->_segMan->getString(argv[0]); - // Creates a new save slot, and returns if the operation was successful + debug(3, "kGetSaveFiles(%s)", game_id.c_str()); - // Argument 0 denotes the save slot as a negative integer, 2 means "0" - // Argument 1 is a string, with the file name, obtained from kSave(5). - // The interpreter checks if it can be written to (by checking for free - // disk space and write permissions) + // Scripts ask for current save files, we can assume that if afterwards they ask us to create a new slot they really + // mean new slot instead of overwriting the old one + s->_lastSaveVirtualId = SAVEGAMEID_OFFICIALRANGE_START; - // We don't really use or need any of this... + Common::Array saves; + listSavegames(saves); + uint totalSaves = MIN(saves.size(), MAX_SAVEGAME_NR); - uint16 saveSlot = argv[0].toUint16(); - char* fileName = s->_segMan->lookupString(argv[1])->getRawData(); - warning("kFileIOCreateSaveSlot(%d, '%s')", saveSlot, fileName); + reg_t *slot = s->_segMan->derefRegPtr(argv[2], totalSaves); - return TRUE_REG; // slot creation was successful -} + if (!slot) { + warning("kGetSaveFiles: %04X:%04X invalid or too small to hold slot data", PRINT_REG(argv[2])); + totalSaves = 0; + } -reg_t kCD(EngineState *s, int argc, reg_t *argv) { - // TODO: Stub - switch (argv[0].toUint16()) { - case 0: - // Return whether the contents of disc argv[1] is available. - return TRUE_REG; - default: - warning("CD(%d)", argv[0].toUint16()); + const uint bufSize = (totalSaves * SCI_MAX_SAVENAME_LENGTH) + 1; + char *saveNames = new char[bufSize]; + char *saveNamePtr = saveNames; + + for (uint i = 0; i < totalSaves; i++) { + *slot++ = make_reg(0, saves[i].id + SAVEGAMEID_OFFICIALRANGE_START); // Store the virtual savegame ID ffs. see above + strcpy(saveNamePtr, saves[i].name); + saveNamePtr += SCI_MAX_SAVENAME_LENGTH; } - return NULL_REG; + *saveNamePtr = 0; // Terminate list + + s->_segMan->memcpy(argv[1], (byte *)saveNames, bufSize); + delete[] saveNames; + + return make_reg(0, totalSaves); } +#ifdef ENABLE_SCI32 + reg_t kMakeSaveCatName(EngineState *s, int argc, reg_t *argv) { // Normally, this creates the name of the save catalogue/directory to save into. // First parameter is the string to save the result into. Second is a string @@ -928,12 +950,6 @@ reg_t kAutoSave(EngineState *s, int argc, reg_t *argv) { return s->r_acc; } -reg_t kSave(EngineState *s, int argc, reg_t *argv) { - if (!s) - return make_reg(0, getSciVersion()); - error("not supposed to call this"); -} - #endif } // End of namespace Sci -- cgit v1.2.3 From e4f08a4644c5a59b8e02b3702eef436e52e2d994 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Wed, 13 Jun 2012 22:55:27 +0300 Subject: SCI: Fix the loading screen and the loading functionality in Shivers Shivers uses extra special hardcoded save files together with the normal ones that are used to store slot names and spot descriptions. The scheme is a bit odd, and since the names of the extra save files are hardcoded, this scheme is problematic to use. We skip the creation of these files altogether and use virtual files instead, which means that the (broken) spot descriptions won't be visible next to each save description. This isn't a major issue for now, and it's left as a future TODO to implement this feature in a cleaner way, and not with extra save files. This scheme fixes the slot descriptions in the loading screen. Also, kCD(1) has been implemented, which fixes loading of the save states themselves --- engines/sci/engine/file.cpp | 8 ++++- engines/sci/engine/file.h | 1 + engines/sci/engine/kfile.cpp | 85 ++++++++++++++++++++++++++++++++++++-------- 3 files changed, 78 insertions(+), 16 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/engine/file.cpp b/engines/sci/engine/file.cpp index 66f54d67df..3470d23fe2 100644 --- a/engines/sci/engine/file.cpp +++ b/engines/sci/engine/file.cpp @@ -346,6 +346,12 @@ VirtualIndexFile::VirtualIndexFile(Common::String fileName) : _fileName(fileName delete inFile; } +VirtualIndexFile::VirtualIndexFile(uint32 initialSize) : _changed(false) { + _bufferSize = initialSize; + _buffer = new char[_bufferSize]; + _ptr = _buffer; +} + VirtualIndexFile::~VirtualIndexFile() { close(); @@ -430,7 +436,7 @@ bool VirtualIndexFile::seek(int32 offset, int whence) { } void VirtualIndexFile::close() { - if (_changed) { + if (_changed && !_fileName.empty()) { Common::WriteStream *outFile = g_sci->getSaveFileManager()->openForSaving(_fileName); outFile->write(_buffer, _bufferSize); delete outFile; diff --git a/engines/sci/engine/file.h b/engines/sci/engine/file.h index 896dcd2a42..1c8e302d15 100644 --- a/engines/sci/engine/file.h +++ b/engines/sci/engine/file.h @@ -115,6 +115,7 @@ private: class VirtualIndexFile { public: VirtualIndexFile(Common::String fileName); + VirtualIndexFile(uint32 initialSize); ~VirtualIndexFile(); uint32 read(char *buffer, uint32 size); diff --git a/engines/sci/engine/kfile.cpp b/engines/sci/engine/kfile.cpp index 445a019368..7a2f161829 100644 --- a/engines/sci/engine/kfile.cpp +++ b/engines/sci/engine/kfile.cpp @@ -199,6 +199,9 @@ reg_t kCD(EngineState *s, int argc, reg_t *argv) { case 0: // Return whether the contents of disc argv[1] is available. return TRUE_REG; + case 1: + // Return the current CD number + return make_reg(0, 1); default: warning("CD(%d)", argv[0].toUint16()); } @@ -219,21 +222,6 @@ reg_t kFileIO(EngineState *s, int argc, reg_t *argv) { reg_t kFileIOOpen(EngineState *s, int argc, reg_t *argv) { Common::String name = s->_segMan->getString(argv[0]); -#ifdef ENABLE_SCI32 - if (name == PHANTASMAGORIA_SAVEGAME_INDEX) { - if (s->_virtualIndexFile) { - return make_reg(0, VIRTUALFILE_HANDLE); - } else { - Common::String englishName = g_sci->getSciLanguageString(name, K_LANG_ENGLISH); - Common::String wrappedName = g_sci->wrapFilename(englishName); - if (!g_sci->getSaveFileManager()->listSavefiles(wrappedName).empty()) { - s->_virtualIndexFile = new VirtualIndexFile(wrappedName); - return make_reg(0, VIRTUALFILE_HANDLE); - } - } - } -#endif - // SCI32 can call K_FILEIO_OPEN with only one argument. It seems to // just be checking if it exists. int mode = (argc < 2) ? (int)_K_FILE_MODE_OPEN_OR_FAIL : argv[1].toUint16(); @@ -261,6 +249,73 @@ reg_t kFileIOOpen(EngineState *s, int argc, reg_t *argv) { } debugC(kDebugLevelFile, "kFileIO(open): %s, 0x%x", name.c_str(), mode); +#ifdef ENABLE_SCI32 + if (name == PHANTASMAGORIA_SAVEGAME_INDEX) { + if (s->_virtualIndexFile) { + return make_reg(0, VIRTUALFILE_HANDLE); + } else { + Common::String englishName = g_sci->getSciLanguageString(name, K_LANG_ENGLISH); + Common::String wrappedName = g_sci->wrapFilename(englishName); + if (!g_sci->getSaveFileManager()->listSavefiles(wrappedName).empty()) { + s->_virtualIndexFile = new VirtualIndexFile(wrappedName); + return make_reg(0, VIRTUALFILE_HANDLE); + } + } + } + + // Shivers is trying to store savegame descriptions and current spots in + // separate .SG files, which are hardcoded in the scripts. + // Essentially, there is a normal save file, created by the executable + // and an extra hardcoded save file, created by the game scripts, probably + // because they didn't want to modify the save/load code to add the extra + // information. + // Each slot in the book then has two strings, the save description and a + // description of the current spot that the player is at. Currently, the + // spot strings are always empty (probably related to the unimplemented + // kString subop 14, which gets called right before this call). + // For now, we don't allow the creation of these files, which means that + // all the spot descriptions next to each slot description will be empty + // (they are empty anyway). Until a viable solution is found to handle these + // extra files and until the spot description strings are initialized + // correctly, we resort to virtual files in order to make the load screen + // useable. Without this code it is unusable, as the extra information is + // always saved to 0.SG for some reason, but on restore the correct file is + // used. Perhaps the virtual ID is not taken into account when saving. + // + // Future TODO: maintain spot descriptions and show them too, ideally without + // having to return to this logic of extra hardcoded files. + if (g_sci->getGameId() == GID_SHIVERS && name.hasSuffix(".SG")) { + if (mode == _K_FILE_MODE_OPEN_OR_CREATE || mode == _K_FILE_MODE_CREATE) { + // Game scripts are trying to create a file with the save + // description, stop them here + debugC(kDebugLevelFile, "Not creating unused file %s", name.c_str()); + return SIGNAL_REG; + } else if (mode == _K_FILE_MODE_OPEN_OR_FAIL) { + // Create a virtual file containing the save game description + // and slot number, as the game scripts expect. + int slotNumber; + sscanf(name.c_str(), "%d.SG", &slotNumber); + + Common::Array saves; + listSavegames(saves); + int savegameNr = findSavegame(saves, slotNumber - SAVEGAMEID_OFFICIALRANGE_START); + + if (!s->_virtualIndexFile) { + // Make the virtual file buffer big enough to avoid having it grow dynamically. + // 50 bytes should be more than enough. + s->_virtualIndexFile = new VirtualIndexFile(50); + } + + s->_virtualIndexFile->seek(0, SEEK_SET); + s->_virtualIndexFile->write(saves[savegameNr].name, strlen(saves[savegameNr].name)); + s->_virtualIndexFile->write("\0", 1); + s->_virtualIndexFile->write("\0", 1); // Spot description (empty) + s->_virtualIndexFile->seek(0, SEEK_SET); + return make_reg(0, VIRTUALFILE_HANDLE); + } + } +#endif + // QFG import rooms get a virtual filelisting instead of an actual one if (g_sci->inQfGImportRoom()) { // We need to find out what the user actually selected, "savedHeroes" is -- cgit v1.2.3 From b9057761df4de1b314aaec9eb7b14653863bb031 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Thu, 14 Jun 2012 02:36:45 +0300 Subject: SCI: Add missing documentation for the plane_items / pi console command --- engines/sci/console.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'engines/sci') diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp index 6a44972a4b..94ac437a15 100644 --- a/engines/sci/console.cpp +++ b/engines/sci/console.cpp @@ -373,6 +373,7 @@ bool Console::cmdHelp(int argc, const char **argv) { DebugPrintf(" animate_list / al - Shows the current list of objects in kAnimate's draw list (SCI0 - SCI1.1)\n"); DebugPrintf(" window_list / wl - Shows a list of all the windows (ports) in the draw list (SCI0 - SCI1.1)\n"); DebugPrintf(" plane_list / pl - Shows a list of all the planes in the draw list (SCI2+)\n"); + DebugPrintf(" plane_items / pi - Shows a list of all items for a plane (SCI2+)\n"); DebugPrintf(" saved_bits - List saved bits on the hunk\n"); DebugPrintf(" show_saved_bits - Display saved bits\n"); DebugPrintf("\n"); -- cgit v1.2.3 From 0a3fb38bc728c11654810d426819853d86ae609c Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Thu, 14 Jun 2012 12:10:39 +0300 Subject: SCI: Add handling of two more configuration settings for LSL7 --- engines/sci/engine/kmisc.cpp | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'engines/sci') diff --git a/engines/sci/engine/kmisc.cpp b/engines/sci/engine/kmisc.cpp index 47c891eefd..2e80764d01 100644 --- a/engines/sci/engine/kmisc.cpp +++ b/engines/sci/engine/kmisc.cpp @@ -388,6 +388,12 @@ reg_t kGetConfig(EngineState *s, int argc, reg_t *argv) { // Used to enable the debug mode in Torin's Passage (French). // If true, the debug mode is enabled. s->_segMan->strcpy(data, ""); + } else if (setting == "leakdump") { + // An unknown setting in LSL7. Likely used for debugging. + s->_segMan->strcpy(data, ""); + } else if (setting == "startroom") { + // Debug setting in LSL7, specifies the room to start from. + s->_segMan->strcpy(data, ""); } else { error("GetConfig: Unknown configuration setting %s", setting.c_str()); } -- cgit v1.2.3 From 21b6b81f16abc4af90a7e21974d51ad7a984f1ed Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Thu, 14 Jun 2012 12:12:30 +0300 Subject: SCI: A separate implementation is needed for syncStringHeap() for SCI3 --- engines/sci/engine/savegame.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'engines/sci') diff --git a/engines/sci/engine/savegame.cpp b/engines/sci/engine/savegame.cpp index 404bea799d..7c41e18bec 100644 --- a/engines/sci/engine/savegame.cpp +++ b/engines/sci/engine/savegame.cpp @@ -467,7 +467,7 @@ void Script::syncStringHeap(Common::Serializer &s) { break; } while (1); - } else { + } else if (getSciVersion() >= SCI_VERSION_1_1 && getSciVersion() <= SCI_VERSION_2_1){ // Strings in SCI1.1 come after the object instances byte *buf = _heapStart + 4 + READ_SCI11ENDIAN_UINT16(_heapStart + 2) * 2; @@ -477,6 +477,8 @@ void Script::syncStringHeap(Common::Serializer &s) { // Now, sync everything till the end of the buffer s.syncBytes(buf, _heapSize - (buf - _heapStart)); + } else if (getSciVersion() == SCI_VERSION_3) { + warning("TODO: syncStringHeap(): Implement SCI3 variant"); } } -- cgit v1.2.3 From 9c8ff41181955048abd602f1d58639e2082182c7 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Thu, 14 Jun 2012 12:14:04 +0300 Subject: SCI: Add known large SCI3 scripts --- engines/sci/engine/script.cpp | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'engines/sci') diff --git a/engines/sci/engine/script.cpp b/engines/sci/engine/script.cpp index 8b26969f4a..5f0118b5b6 100644 --- a/engines/sci/engine/script.cpp +++ b/engines/sci/engine/script.cpp @@ -115,6 +115,13 @@ void Script::init(int script_nr, ResourceManager *resMan) { // scheme. We need an overlaying mechanism, or a mechanism to split script parts // in different segments to handle these. For now, simply stop when such a script // is found. + // + // Known large SCI 3 scripts are: + // Lighthouse: 9, 220, 270, 351, 360, 490, 760, 765, 800 + // LSL7: 240, 511, 550 + // Phantasmagoria 2: none (hooray!) + // RAMA: 70 + // // TODO: Remove this once such a mechanism is in place if (script->size > 65535) error("TODO: SCI script %d is over 64KB - it's %d bytes long. This can't " -- cgit v1.2.3 From 27f2b6e4dd829663f771fec0651b8a1e31514a90 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Thu, 14 Jun 2012 12:15:57 +0300 Subject: SCI: Change the script buffer size to be a size_t as well This will be needed in the future to load large SCI3 scripts --- engines/sci/engine/script.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines/sci') diff --git a/engines/sci/engine/script.h b/engines/sci/engine/script.h index 1ebae3b7a8..a180579d2f 100644 --- a/engines/sci/engine/script.h +++ b/engines/sci/engine/script.h @@ -57,7 +57,7 @@ private: int _lockers; /**< Number of classes and objects that require this script */ size_t _scriptSize; size_t _heapSize; - uint16 _bufSize; + size_t _bufSize; const uint16 *_exportTable; /**< Abs. offset of the export table or 0 if not present */ uint16 _numExports; /**< Number of entries in the exports table */ -- cgit v1.2.3 From 425926ed7ebde1fa77f3874498a6f285af75ac08 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Fri, 15 Jun 2012 11:33:28 +0300 Subject: SCI: Limit floodfill hack to GK1 Fixes the intro of LSL7 and the inventory screen in PQ4 --- engines/sci/graphics/frameout.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines/sci') diff --git a/engines/sci/graphics/frameout.cpp b/engines/sci/graphics/frameout.cpp index db49497b6b..dff332458a 100644 --- a/engines/sci/graphics/frameout.cpp +++ b/engines/sci/graphics/frameout.cpp @@ -647,7 +647,7 @@ void GfxFrameout::kernelFrameout() { // Since I first wrote the patch, the race has stopped occurring for me though. // I'll leave this for investigation later, when someone can reproduce. //if (it->pictureId == kPlanePlainColored) // FIXME: This is what SSCI does, and fixes the intro of LSL7, but breaks the dialogs in GK1 (adds black boxes) - if (it->pictureId == kPlanePlainColored && it->planeBack) + if (it->pictureId == kPlanePlainColored && (it->planeBack || g_sci->getGameId() != GID_GK1)) _paint32->fillRect(it->planeRect, it->planeBack); _coordAdjuster->pictureSetDisplayArea(it->planeRect); -- cgit v1.2.3 From 577d7e41c9ca2c498dc85e41c373fbdca8d2ed41 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Fri, 15 Jun 2012 11:44:54 +0300 Subject: SCI: Change Script::getObject() to accept a reg_t This is needed for upcoming changes to the Script class --- engines/sci/engine/kernel.cpp | 2 +- engines/sci/engine/script.cpp | 14 +++++++------- engines/sci/engine/script.h | 4 ++-- engines/sci/engine/seg_manager.cpp | 2 +- 4 files changed, 11 insertions(+), 11 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/engine/kernel.cpp b/engines/sci/engine/kernel.cpp index c99bc4fe47..0266414b26 100644 --- a/engines/sci/engine/kernel.cpp +++ b/engines/sci/engine/kernel.cpp @@ -377,7 +377,7 @@ uint16 Kernel::findRegType(reg_t reg) { if (reg.offset <= (*(Script *)mobj).getBufSize() && reg.offset >= -SCRIPT_OBJECT_MAGIC_OFFSET && RAW_IS_OBJECT((*(Script *)mobj).getBuf(reg.offset)) ) { - result |= ((Script *)mobj)->getObject(reg.offset) ? SIG_TYPE_OBJECT : SIG_TYPE_REFERENCE; + result |= ((Script *)mobj)->getObject(reg) ? SIG_TYPE_OBJECT : SIG_TYPE_REFERENCE; } else result |= SIG_TYPE_REFERENCE; break; diff --git a/engines/sci/engine/script.cpp b/engines/sci/engine/script.cpp index 5f0118b5b6..08f7922b1e 100644 --- a/engines/sci/engine/script.cpp +++ b/engines/sci/engine/script.cpp @@ -243,16 +243,16 @@ const byte *Script::getSci3ObjectsPointer() { return ptr; } -Object *Script::getObject(uint16 offset) { - if (_objects.contains(offset)) - return &_objects[offset]; +Object *Script::getObject(reg_t pos) { + if (_objects.contains(pos.offset)) + return &_objects[pos.offset]; else return 0; } -const Object *Script::getObject(uint16 offset) const { - if (_objects.contains(offset)) - return &_objects[offset]; +const Object *Script::getObject(reg_t pos) const { + if (_objects.contains(pos.offset)) + return &_objects[pos.offset]; else return 0; } @@ -746,7 +746,7 @@ Common::Array Script::listAllDeallocatable(SegmentId segId) const { Common::Array Script::listAllOutgoingReferences(reg_t addr) const { Common::Array tmp; if (addr.offset <= _bufSize && addr.offset >= -SCRIPT_OBJECT_MAGIC_OFFSET && RAW_IS_OBJECT(_buf + addr.offset)) { - const Object *obj = getObject(addr.offset); + const Object *obj = getObject(addr); if (obj) { // Note all local variables, if we have a local variable environment if (_localsSegment) diff --git a/engines/sci/engine/script.h b/engines/sci/engine/script.h index a180579d2f..06a7f089ba 100644 --- a/engines/sci/engine/script.h +++ b/engines/sci/engine/script.h @@ -119,8 +119,8 @@ public: virtual void saveLoadWithSerializer(Common::Serializer &ser); - Object *getObject(uint16 offset); - const Object *getObject(uint16 offset) const; + Object *getObject(reg_t pos); + const Object *getObject(reg_t pos) const; /** * Initializes an object within the segment manager diff --git a/engines/sci/engine/seg_manager.cpp b/engines/sci/engine/seg_manager.cpp index cc127c8dbc..cfa83a7697 100644 --- a/engines/sci/engine/seg_manager.cpp +++ b/engines/sci/engine/seg_manager.cpp @@ -228,7 +228,7 @@ Object *SegManager::getObject(reg_t pos) const { Script *scr = (Script *)mobj; if (pos.offset <= scr->getBufSize() && pos.offset >= -SCRIPT_OBJECT_MAGIC_OFFSET && RAW_IS_OBJECT(scr->getBuf(pos.offset))) { - obj = scr->getObject(pos.offset); + obj = scr->getObject(pos); } } } -- cgit v1.2.3 From e1ae1108601cce0ad7aeab5f3e017f630f02e7ea Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Fri, 15 Jun 2012 11:48:56 +0300 Subject: SCI: Clean up the script initialization code --- engines/sci/engine/script.cpp | 30 ++++++++---------------------- 1 file changed, 8 insertions(+), 22 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/engine/script.cpp b/engines/sci/engine/script.cpp index 08f7922b1e..f8c5539325 100644 --- a/engines/sci/engine/script.cpp +++ b/engines/sci/engine/script.cpp @@ -37,17 +37,22 @@ Script::Script() : SegmentObj(SEG_TYPE_SCRIPT) { _buf = NULL; _bufSize = 0; _scriptSize = 0; - _heapSize = 0; - _synonyms = NULL; _heapStart = NULL; + _heapSize = 0; + _exportTable = NULL; + _numExports = 0; + _synonyms = NULL; + _numSynonyms = 0; _localsOffset = 0; _localsSegment = 0; _localsBlock = NULL; _localsCount = 0; + _lockers = 1; + _markedAsDeleted = false; } @@ -65,25 +70,11 @@ void Script::freeScript() { void Script::init(int script_nr, ResourceManager *resMan) { Resource *script = resMan->findResource(ResourceId(kResourceTypeScript, script_nr), 0); - if (!script) error("Script %d not found", script_nr); - _localsOffset = 0; - _localsBlock = NULL; - _localsCount = 0; - - _markedAsDeleted = false; - _nr = script_nr; - _buf = 0; - _heapStart = 0; - - _scriptSize = script->size; - _bufSize = script->size; - _heapSize = 0; - - _lockers = 1; + _bufSize = _scriptSize = script->size; if (getSciVersion() == SCI_VERSION_0_EARLY) { _bufSize += READ_LE_UINT16(script->data) * 2; @@ -163,11 +154,6 @@ void Script::load(ResourceManager *resMan) { memcpy(_heapStart, heap->data, heap->size); } - _exportTable = 0; - _numExports = 0; - _synonyms = 0; - _numSynonyms = 0; - if (getSciVersion() <= SCI_VERSION_1_LATE) { _exportTable = (const uint16 *)findBlockSCI0(SCI_OBJ_EXPORTS); if (_exportTable) { -- cgit v1.2.3 From 9aaefbd53665cd03359ad692d64e3fc437f97202 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Fri, 15 Jun 2012 11:53:19 +0300 Subject: SCI: _propertyOffsetsSci3 and classpos should be 32-bit integers These are needed for future handling of large SCI3 script files --- engines/sci/engine/object.cpp | 7 ++++--- engines/sci/engine/object.h | 4 ++-- engines/sci/engine/script.cpp | 2 +- 3 files changed, 7 insertions(+), 6 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/engine/object.cpp b/engines/sci/engine/object.cpp index 78e216cdb5..2a0ed38e61 100644 --- a/engines/sci/engine/object.cpp +++ b/engines/sci/engine/object.cpp @@ -112,7 +112,7 @@ bool Object::relocateSci0Sci21(SegmentId segment, int location, size_t scriptSiz return relocateBlock(_variables, getPos().offset, segment, location, scriptSize); } -bool Object::relocateSci3(SegmentId segment, int location, int offset, size_t scriptSize) { +bool Object::relocateSci3(SegmentId segment, uint32 location, int offset, size_t scriptSize) { assert(_propertyOffsetsSci3); for (uint i = 0; i < _variables.size(); ++i) { @@ -286,7 +286,7 @@ void Object::initSelectorsSci3(const byte *buf) { _variables.resize(properties); uint16 *propertyIds = (uint16 *)malloc(sizeof(uint16) * properties); // uint16 *methodOffsets = (uint16 *)malloc(sizeof(uint16) * 2 * methods); - uint16 *propertyOffsets = (uint16 *)malloc(sizeof(uint16) * properties); + uint32 *propertyOffsets = (uint32 *)malloc(sizeof(uint32) * properties); int propertyCounter = 0; int methodCounter = 0; @@ -314,7 +314,8 @@ void Object::initSelectorsSci3(const byte *buf) { WRITE_SCI11ENDIAN_UINT16(&propertyIds[propertyCounter], groupBaseId + bit); _variables[propertyCounter] = make_reg(0, value); - propertyOffsets[propertyCounter] = (seeker + bit * 2) - buf; + uint32 propertyOffset = (seeker + bit * 2) - buf; + propertyOffsets[propertyCounter] = propertyOffset; ++propertyCounter; } else if (value != 0xffff) { // Method _baseMethod.push_back(groupBaseId + bit); diff --git a/engines/sci/engine/object.h b/engines/sci/engine/object.h index 0ca16b48a2..e8deafa8bd 100644 --- a/engines/sci/engine/object.h +++ b/engines/sci/engine/object.h @@ -223,7 +223,7 @@ public: } bool relocateSci0Sci21(SegmentId segment, int location, size_t scriptSize); - bool relocateSci3(SegmentId segment, int location, int offset, size_t scriptSize); + bool relocateSci3(SegmentId segment, uint32 location, int offset, size_t scriptSize); int propertyOffsetToId(SegManager *segMan, int propertyOffset) const; @@ -238,7 +238,7 @@ private: const byte *_baseObj; /**< base + object offset within base */ const uint16 *_baseVars; /**< Pointer to the varselector area for this object */ Common::Array _baseMethod; /**< Pointer to the method selector area for this object */ - uint16 *_propertyOffsetsSci3; /**< This is used to enable relocation of property valuesa in SCI3 */ + uint32 *_propertyOffsetsSci3; /**< This is used to enable relocation of property valuesa in SCI3 */ Common::Array _variables; uint16 _methodCount; diff --git a/engines/sci/engine/script.cpp b/engines/sci/engine/script.cpp index f8c5539325..18e23f36b5 100644 --- a/engines/sci/engine/script.cpp +++ b/engines/sci/engine/script.cpp @@ -546,7 +546,7 @@ void Script::initializeClasses(SegManager *segMan) { uint16 marker; bool isClass = false; - uint16 classpos; + uint32 classpos; int16 species = 0; while (true) { -- cgit v1.2.3 From 23ed0f1dc89a8557692928785bf3da355e36bc8e Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Fri, 15 Jun 2012 12:04:28 +0300 Subject: SCI: Skip playing of the unsupported robot video 1003 in RAMA --- engines/sci/video/robot_decoder.cpp | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'engines/sci') diff --git a/engines/sci/video/robot_decoder.cpp b/engines/sci/video/robot_decoder.cpp index 95b3c2abc1..8ffcecc339 100644 --- a/engines/sci/video/robot_decoder.cpp +++ b/engines/sci/video/robot_decoder.cpp @@ -87,6 +87,13 @@ RobotDecoder::~RobotDecoder() { } bool RobotDecoder::load(GuiResourceId id) { + // TODO: RAMA's robot 1003 cannot be played (shown at the menu screen) - + // its drawn at odd coordinates. SV can't play it either (along with some + // others), so it must be some new functionality added in RAMA's robot + // videos. Skip it for now. + if (g_sci->getGameId() == GID_RAMA && id == 1003) + return false; + Common::String fileName = Common::String::format("%d.rbt", id); Common::SeekableReadStream *stream = SearchMan.createReadStreamForMember(fileName); -- cgit v1.2.3 From 562a8a980c22eab85144558050e5fa5e425612c4 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Fri, 15 Jun 2012 12:53:17 +0300 Subject: SCI: Further cleanup of the script code Merge the init() and load() Script methods and reset the script when necessary --- engines/sci/engine/savegame.cpp | 7 ++----- engines/sci/engine/script.cpp | 32 +++++++++++++------------------- engines/sci/engine/script.h | 3 +-- engines/sci/engine/seg_manager.cpp | 3 +-- 4 files changed, 17 insertions(+), 28 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/engine/savegame.cpp b/engines/sci/engine/savegame.cpp index 7c41e18bec..cabe5f468a 100644 --- a/engines/sci/engine/savegame.cpp +++ b/engines/sci/engine/savegame.cpp @@ -189,7 +189,7 @@ void SegManager::saveLoadWithSerializer(Common::Serializer &s) { assert(mobj); - // Let the object sync custom data + // Let the object sync custom data. Scripts are loaded at this point. mobj->saveLoadWithSerializer(s); if (type == SEG_TYPE_SCRIPT) { @@ -200,9 +200,6 @@ void SegManager::saveLoadWithSerializer(Common::Serializer &s) { // Hook the script up in the script->segment map _scriptSegMap[scr->getScriptNumber()] = i; - // Now, load the script itself - scr->load(g_sci->getResMan()); - ObjMap objects = scr->getObjectMap(); for (ObjMap::iterator it = objects.begin(); it != objects.end(); ++it) it->_value.syncBaseObject(scr->getBuf(it->_value.getPos().offset)); @@ -486,7 +483,7 @@ void Script::saveLoadWithSerializer(Common::Serializer &s) { s.syncAsSint32LE(_nr); if (s.isLoading()) - init(_nr, g_sci->getResMan()); + load(_nr, g_sci->getResMan()); s.skip(4, VER(14), VER(22)); // OBSOLETE: Used to be _bufSize s.skip(4, VER(14), VER(22)); // OBSOLETE: Used to be _scriptSize s.skip(4, VER(14), VER(22)); // OBSOLETE: Used to be _heapSize diff --git a/engines/sci/engine/script.cpp b/engines/sci/engine/script.cpp index 18e23f36b5..7714983120 100644 --- a/engines/sci/engine/script.cpp +++ b/engines/sci/engine/script.cpp @@ -32,12 +32,21 @@ namespace Sci { -Script::Script() : SegmentObj(SEG_TYPE_SCRIPT) { +Script::Script() : SegmentObj(SEG_TYPE_SCRIPT), _buf(NULL) { + freeScript(); +} + +Script::~Script() { + freeScript(); +} + +void Script::freeScript() { _nr = 0; + + free(_buf); _buf = NULL; _bufSize = 0; _scriptSize = 0; - _heapStart = NULL; _heapSize = 0; @@ -52,23 +61,13 @@ Script::Script() : SegmentObj(SEG_TYPE_SCRIPT) { _localsCount = 0; _lockers = 1; - _markedAsDeleted = false; + _objects.clear(); } -Script::~Script() { +void Script::load(int script_nr, ResourceManager *resMan) { freeScript(); -} - -void Script::freeScript() { - free(_buf); - _buf = NULL; - _bufSize = 0; - - _objects.clear(); -} -void Script::init(int script_nr, ResourceManager *resMan) { Resource *script = resMan->findResource(ResourceId(kResourceTypeScript, script_nr), 0); if (!script) error("Script %d not found", script_nr); @@ -118,11 +117,6 @@ void Script::init(int script_nr, ResourceManager *resMan) { error("TODO: SCI script %d is over 64KB - it's %d bytes long. This can't " "be handled at the moment, thus stopping", script_nr, script->size); } -} - -void Script::load(ResourceManager *resMan) { - Resource *script = resMan->findResource(ResourceId(kResourceTypeScript, _nr), 0); - assert(script != 0); uint extraLocalsWorkaround = 0; if (g_sci->getGameId() == GID_FANMADE && _nr == 1 && script->size == 11140) { diff --git a/engines/sci/engine/script.h b/engines/sci/engine/script.h index 06a7f089ba..4d23ffbba8 100644 --- a/engines/sci/engine/script.h +++ b/engines/sci/engine/script.h @@ -95,8 +95,7 @@ public: ~Script(); void freeScript(); - void init(int script_nr, ResourceManager *resMan); - void load(ResourceManager *resMan); + void load(int script_nr, ResourceManager *resMan); void matchSignatureAndPatch(uint16 scriptNr, byte *scriptData, const uint32 scriptSize); int32 findSignature(const SciScriptSignature *signature, const byte *scriptData, const uint32 scriptSize); diff --git a/engines/sci/engine/seg_manager.cpp b/engines/sci/engine/seg_manager.cpp index cfa83a7697..8f85577fb8 100644 --- a/engines/sci/engine/seg_manager.cpp +++ b/engines/sci/engine/seg_manager.cpp @@ -977,8 +977,7 @@ int SegManager::instantiateScript(int scriptNum) { scr = allocateScript(scriptNum, &segmentId); } - scr->init(scriptNum, _resMan); - scr->load(_resMan); + scr->load(scriptNum, _resMan); scr->initializeLocals(this); scr->initializeClasses(this); scr->initializeObjects(this, segmentId); -- cgit v1.2.3 From 160732b2f73a5df173c1fa867f82fa2913ec2236 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Fri, 15 Jun 2012 21:47:22 +0300 Subject: Revert "SCI: Change Script::getObject() to accept a reg_t" This reverts commit 577d7e41c9ca2c498dc85e41c373fbdca8d2ed41. --- engines/sci/engine/kernel.cpp | 2 +- engines/sci/engine/script.cpp | 14 +++++++------- engines/sci/engine/script.h | 4 ++-- engines/sci/engine/seg_manager.cpp | 2 +- 4 files changed, 11 insertions(+), 11 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/engine/kernel.cpp b/engines/sci/engine/kernel.cpp index 0266414b26..c99bc4fe47 100644 --- a/engines/sci/engine/kernel.cpp +++ b/engines/sci/engine/kernel.cpp @@ -377,7 +377,7 @@ uint16 Kernel::findRegType(reg_t reg) { if (reg.offset <= (*(Script *)mobj).getBufSize() && reg.offset >= -SCRIPT_OBJECT_MAGIC_OFFSET && RAW_IS_OBJECT((*(Script *)mobj).getBuf(reg.offset)) ) { - result |= ((Script *)mobj)->getObject(reg) ? SIG_TYPE_OBJECT : SIG_TYPE_REFERENCE; + result |= ((Script *)mobj)->getObject(reg.offset) ? SIG_TYPE_OBJECT : SIG_TYPE_REFERENCE; } else result |= SIG_TYPE_REFERENCE; break; diff --git a/engines/sci/engine/script.cpp b/engines/sci/engine/script.cpp index 7714983120..0ed9598b41 100644 --- a/engines/sci/engine/script.cpp +++ b/engines/sci/engine/script.cpp @@ -223,16 +223,16 @@ const byte *Script::getSci3ObjectsPointer() { return ptr; } -Object *Script::getObject(reg_t pos) { - if (_objects.contains(pos.offset)) - return &_objects[pos.offset]; +Object *Script::getObject(uint16 offset) { + if (_objects.contains(offset)) + return &_objects[offset]; else return 0; } -const Object *Script::getObject(reg_t pos) const { - if (_objects.contains(pos.offset)) - return &_objects[pos.offset]; +const Object *Script::getObject(uint16 offset) const { + if (_objects.contains(offset)) + return &_objects[offset]; else return 0; } @@ -726,7 +726,7 @@ Common::Array Script::listAllDeallocatable(SegmentId segId) const { Common::Array Script::listAllOutgoingReferences(reg_t addr) const { Common::Array tmp; if (addr.offset <= _bufSize && addr.offset >= -SCRIPT_OBJECT_MAGIC_OFFSET && RAW_IS_OBJECT(_buf + addr.offset)) { - const Object *obj = getObject(addr); + const Object *obj = getObject(addr.offset); if (obj) { // Note all local variables, if we have a local variable environment if (_localsSegment) diff --git a/engines/sci/engine/script.h b/engines/sci/engine/script.h index 4d23ffbba8..df7f42cc0d 100644 --- a/engines/sci/engine/script.h +++ b/engines/sci/engine/script.h @@ -118,8 +118,8 @@ public: virtual void saveLoadWithSerializer(Common::Serializer &ser); - Object *getObject(reg_t pos); - const Object *getObject(reg_t pos) const; + Object *getObject(uint16 offset); + const Object *getObject(uint16 offset) const; /** * Initializes an object within the segment manager diff --git a/engines/sci/engine/seg_manager.cpp b/engines/sci/engine/seg_manager.cpp index 8f85577fb8..20a8240641 100644 --- a/engines/sci/engine/seg_manager.cpp +++ b/engines/sci/engine/seg_manager.cpp @@ -228,7 +228,7 @@ Object *SegManager::getObject(reg_t pos) const { Script *scr = (Script *)mobj; if (pos.offset <= scr->getBufSize() && pos.offset >= -SCRIPT_OBJECT_MAGIC_OFFSET && RAW_IS_OBJECT(scr->getBuf(pos.offset))) { - obj = scr->getObject(pos); + obj = scr->getObject(pos.offset); } } } -- cgit v1.2.3 From 5ca22a1104d2e1ca0a7b7f5ac159b5c721e13ead Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Fri, 15 Jun 2012 21:52:03 +0300 Subject: SCI: Fix warnings Thanks to DrMcCoy for reporting them --- engines/sci/engine/file.cpp | 2 +- engines/sci/engine/kgraphics32.cpp | 3 ++- engines/sci/engine/script.cpp | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/engine/file.cpp b/engines/sci/engine/file.cpp index 3470d23fe2..c44963f457 100644 --- a/engines/sci/engine/file.cpp +++ b/engines/sci/engine/file.cpp @@ -427,7 +427,7 @@ bool VirtualIndexFile::seek(int32 offset, int whence) { _ptr = _buffer + offset; break; case SEEK_END: - assert(_bufferSize - offset >= 0); + assert((int32)_bufferSize - offset >= 0); _ptr = _buffer + (_bufferSize - offset); break; } diff --git a/engines/sci/engine/kgraphics32.cpp b/engines/sci/engine/kgraphics32.cpp index 53cf8ada75..377c05935a 100644 --- a/engines/sci/engine/kgraphics32.cpp +++ b/engines/sci/engine/kgraphics32.cpp @@ -241,6 +241,7 @@ reg_t kSetShowStyle(EngineState *s, int argc, reg_t *argv) { //int16 priority = argv[4].toSint16(); // always 0xc8 (200) when fading in/out //uint16 animate = argv[5].toUint16(); // boolean, animate or not while the transition lasts //uint16 refFrame = argv[6].toUint16(); // refFrame, always 0 when fading in/out +#if 0 int16 divisions; // If the game has the pFadeArray selector, another parameter is used here, @@ -252,7 +253,7 @@ reg_t kSetShowStyle(EngineState *s, int argc, reg_t *argv) { } else { divisions = (argc >= 8) ? argv[7].toSint16() : -1; // divisions (transition steps?) } - +#endif if (showStyle > 15) { warning("kSetShowStyle: Illegal style %d for plane %04x:%04x", showStyle, PRINT_REG(planeObj)); return s->r_acc; diff --git a/engines/sci/engine/script.cpp b/engines/sci/engine/script.cpp index 0ed9598b41..ca7eaad383 100644 --- a/engines/sci/engine/script.cpp +++ b/engines/sci/engine/script.cpp @@ -199,7 +199,7 @@ void Script::load(int script_nr, ResourceManager *resMan) { _localsOffset = 0; if (_localsOffset + _localsCount * 2 + 1 >= (int)_bufSize) { - error("Locals extend beyond end of script: offset %04x, count %d vs size %d", _localsOffset, _localsCount, _bufSize); + error("Locals extend beyond end of script: offset %04x, count %d vs size %d", _localsOffset, _localsCount, (int)_bufSize); //_localsCount = (_bufSize - _localsOffset) >> 1; } } -- cgit v1.2.3 From 041b1447c02616c0f285556bb453e79268da7dce Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Fri, 15 Jun 2012 22:02:13 +0300 Subject: SCI: Replace RAW_IS_OBJECT with a method --- engines/sci/engine/kernel.cpp | 2 +- engines/sci/engine/script.cpp | 6 +++++- engines/sci/engine/script.h | 1 + engines/sci/engine/seg_manager.cpp | 2 +- engines/sci/engine/vm.h | 2 -- 5 files changed, 8 insertions(+), 5 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/engine/kernel.cpp b/engines/sci/engine/kernel.cpp index c99bc4fe47..3a33c928e7 100644 --- a/engines/sci/engine/kernel.cpp +++ b/engines/sci/engine/kernel.cpp @@ -376,7 +376,7 @@ uint16 Kernel::findRegType(reg_t reg) { case SEG_TYPE_SCRIPT: if (reg.offset <= (*(Script *)mobj).getBufSize() && reg.offset >= -SCRIPT_OBJECT_MAGIC_OFFSET && - RAW_IS_OBJECT((*(Script *)mobj).getBuf(reg.offset)) ) { + (*(Script *)mobj).offsetIsObject(reg.offset)) { result |= ((Script *)mobj)->getObject(reg.offset) ? SIG_TYPE_OBJECT : SIG_TYPE_REFERENCE; } else result |= SIG_TYPE_REFERENCE; diff --git a/engines/sci/engine/script.cpp b/engines/sci/engine/script.cpp index ca7eaad383..d09b5ace80 100644 --- a/engines/sci/engine/script.cpp +++ b/engines/sci/engine/script.cpp @@ -725,7 +725,7 @@ Common::Array Script::listAllDeallocatable(SegmentId segId) const { Common::Array Script::listAllOutgoingReferences(reg_t addr) const { Common::Array tmp; - if (addr.offset <= _bufSize && addr.offset >= -SCRIPT_OBJECT_MAGIC_OFFSET && RAW_IS_OBJECT(_buf + addr.offset)) { + if (addr.offset <= _bufSize && addr.offset >= -SCRIPT_OBJECT_MAGIC_OFFSET && offsetIsObject(addr.offset)) { const Object *obj = getObject(addr.offset); if (obj) { // Note all local variables, if we have a local variable environment @@ -761,4 +761,8 @@ Common::Array Script::listObjectReferences() const { return tmp; } +bool Script::offsetIsObject(uint16 offset) const { + return (READ_SCI11ENDIAN_UINT16((const byte *)_buf + offset + SCRIPT_OBJECT_MAGIC_OFFSET) == SCRIPT_OBJECT_MAGIC_NUMBER); +} + } // End of namespace Sci diff --git a/engines/sci/engine/script.h b/engines/sci/engine/script.h index df7f42cc0d..0c99f13235 100644 --- a/engines/sci/engine/script.h +++ b/engines/sci/engine/script.h @@ -89,6 +89,7 @@ public: void syncLocalsBlock(SegManager *segMan); ObjMap &getObjectMap() { return _objects; } const ObjMap &getObjectMap() const { return _objects; } + bool offsetIsObject(uint16 offset) const; public: Script(); diff --git a/engines/sci/engine/seg_manager.cpp b/engines/sci/engine/seg_manager.cpp index 20a8240641..eaa587e3f9 100644 --- a/engines/sci/engine/seg_manager.cpp +++ b/engines/sci/engine/seg_manager.cpp @@ -227,7 +227,7 @@ Object *SegManager::getObject(reg_t pos) const { } else if (mobj->getType() == SEG_TYPE_SCRIPT) { Script *scr = (Script *)mobj; if (pos.offset <= scr->getBufSize() && pos.offset >= -SCRIPT_OBJECT_MAGIC_OFFSET - && RAW_IS_OBJECT(scr->getBuf(pos.offset))) { + && scr->offsetIsObject(pos.offset)) { obj = scr->getObject(pos.offset); } } diff --git a/engines/sci/engine/vm.h b/engines/sci/engine/vm.h index cdd9b9a06e..67b9dd44eb 100644 --- a/engines/sci/engine/vm.h +++ b/engines/sci/engine/vm.h @@ -61,8 +61,6 @@ struct Class { reg_t reg; ///< offset; script-relative offset, segment: 0 if not instantiated }; -#define RAW_IS_OBJECT(datablock) (READ_SCI11ENDIAN_UINT16(((const byte *) datablock) + SCRIPT_OBJECT_MAGIC_OFFSET) == SCRIPT_OBJECT_MAGIC_NUMBER) - // A reference to an object's variable. // The object is stored as a reg_t, the variable as an index into _variables struct ObjVarRef { -- cgit v1.2.3 From 8666a0528ff7f01acff97355df1bddf6136869b1 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Fri, 15 Jun 2012 22:03:42 +0300 Subject: SCI: Also skip a robot video in the Lighthouse demo --- engines/sci/video/robot_decoder.cpp | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'engines/sci') diff --git a/engines/sci/video/robot_decoder.cpp b/engines/sci/video/robot_decoder.cpp index 8ffcecc339..ebcfac6054 100644 --- a/engines/sci/video/robot_decoder.cpp +++ b/engines/sci/video/robot_decoder.cpp @@ -93,6 +93,10 @@ bool RobotDecoder::load(GuiResourceId id) { // videos. Skip it for now. if (g_sci->getGameId() == GID_RAMA && id == 1003) return false; + + // TODO: The robot video in the Lighthouse demo gets stuck + if (g_sci->getGameId() == GID_LIGHTHOUSE && id == 16) + return false; Common::String fileName = Common::String::format("%d.rbt", id); Common::SeekableReadStream *stream = SearchMan.createReadStreamForMember(fileName); -- cgit v1.2.3 From a0add53c6003a8ed42324d4bacc7f4745ee25543 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Fri, 15 Jun 2012 22:24:35 +0300 Subject: SCI: Change getClassAddress() to only require the caller segment The caller offset is never actually used inside the function --- engines/sci/engine/object.cpp | 4 ++-- engines/sci/engine/script.cpp | 4 ++-- engines/sci/engine/seg_manager.cpp | 4 ++-- engines/sci/engine/seg_manager.h | 2 +- engines/sci/engine/vm.cpp | 4 ++-- 5 files changed, 9 insertions(+), 9 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/engine/object.cpp b/engines/sci/engine/object.cpp index 2a0ed38e61..de028392ea 100644 --- a/engines/sci/engine/object.cpp +++ b/engines/sci/engine/object.cpp @@ -153,7 +153,7 @@ void Object::initSpecies(SegManager *segMan, reg_t addr) { if (speciesOffset == 0xffff) // -1 setSpeciesSelector(NULL_REG); // no species else - setSpeciesSelector(segMan->getClassAddress(speciesOffset, SCRIPT_GET_LOCK, addr)); + setSpeciesSelector(segMan->getClassAddress(speciesOffset, SCRIPT_GET_LOCK, addr.segment)); } void Object::initSuperClass(SegManager *segMan, reg_t addr) { @@ -162,7 +162,7 @@ void Object::initSuperClass(SegManager *segMan, reg_t addr) { if (superClassOffset == 0xffff) // -1 setSuperClassSelector(NULL_REG); // no superclass else - setSuperClassSelector(segMan->getClassAddress(superClassOffset, SCRIPT_GET_LOCK, addr)); + setSuperClassSelector(segMan->getClassAddress(superClassOffset, SCRIPT_GET_LOCK, addr.segment)); } bool Object::initBaseObject(SegManager *segMan, reg_t addr, bool doInitSuperClass) { diff --git a/engines/sci/engine/script.cpp b/engines/sci/engine/script.cpp index d09b5ace80..d018872b43 100644 --- a/engines/sci/engine/script.cpp +++ b/engines/sci/engine/script.cpp @@ -653,7 +653,7 @@ void Script::initializeObjectsSci11(SegManager *segMan, SegmentId segmentId) { // Copy base from species class, as we need its selector IDs obj->setSuperClassSelector( - segMan->getClassAddress(obj->getSuperClassSelector().offset, SCRIPT_GET_LOCK, NULL_REG)); + segMan->getClassAddress(obj->getSuperClassSelector().offset, SCRIPT_GET_LOCK, 0)); // If object is instance, get -propDict- from class and set it for this // object. This is needed for ::isMemberOf() to work. @@ -686,7 +686,7 @@ void Script::initializeObjectsSci3(SegManager *segMan, SegmentId segmentId) { reg_t reg = make_reg(segmentId, seeker - _buf); Object *obj = scriptObjInit(reg); - obj->setSuperClassSelector(segMan->getClassAddress(obj->getSuperClassSelector().offset, SCRIPT_GET_LOCK, NULL_REG)); + obj->setSuperClassSelector(segMan->getClassAddress(obj->getSuperClassSelector().offset, SCRIPT_GET_LOCK, 0)); seeker += READ_SCI11ENDIAN_UINT16(seeker + 2); } diff --git a/engines/sci/engine/seg_manager.cpp b/engines/sci/engine/seg_manager.cpp index eaa587e3f9..ac02022ee7 100644 --- a/engines/sci/engine/seg_manager.cpp +++ b/engines/sci/engine/seg_manager.cpp @@ -939,7 +939,7 @@ void SegManager::createClassTable() { _resMan->unlockResource(vocab996); } -reg_t SegManager::getClassAddress(int classnr, ScriptLoadType lock, reg_t caller) { +reg_t SegManager::getClassAddress(int classnr, ScriptLoadType lock, uint16 callerSegment) { if (classnr == 0xffff) return NULL_REG; @@ -956,7 +956,7 @@ reg_t SegManager::getClassAddress(int classnr, ScriptLoadType lock, reg_t caller return NULL_REG; } } else - if (caller.segment != the_class->reg.segment) + if (callerSegment != the_class->reg.segment) getScript(the_class->reg.segment)->incrementLockers(); return the_class->reg; diff --git a/engines/sci/engine/seg_manager.h b/engines/sci/engine/seg_manager.h index 62e711e686..356a1b04a7 100644 --- a/engines/sci/engine/seg_manager.h +++ b/engines/sci/engine/seg_manager.h @@ -125,7 +125,7 @@ private: public: // TODO: document this - reg_t getClassAddress(int classnr, ScriptLoadType lock, reg_t caller); + reg_t getClassAddress(int classnr, ScriptLoadType lock, uint16 callerSegment); /** * Return a pointer to the specified script. diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index 162dce9fcc..7dc397c11e 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -996,7 +996,7 @@ void run_vm(EngineState *s) { case op_class: // 0x28 (40) // Get class address s->r_acc = s->_segMan->getClassAddress((unsigned)opparams[0], SCRIPT_GET_LOCK, - s->xs->addr.pc); + s->xs->addr.pc.segment); break; case 0x29: // (41) @@ -1021,7 +1021,7 @@ void run_vm(EngineState *s) { case op_super: // 0x2b (43) // Send to any class - r_temp = s->_segMan->getClassAddress(opparams[0], SCRIPT_GET_LOAD, s->xs->addr.pc); + r_temp = s->_segMan->getClassAddress(opparams[0], SCRIPT_GET_LOAD, s->xs->addr.pc.segment); if (!r_temp.isPointer()) error("[VM]: Invalid superclass in object"); -- cgit v1.2.3 From 084c1259fc5c185ec66001708f623d03675bf6f5 Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Sat, 16 Jun 2012 02:36:17 +0200 Subject: SCI: Get rid of casts on OSystem::copyRectToScreen calls. --- engines/sci/engine/kvideo.cpp | 2 +- engines/sci/graphics/frameout.cpp | 2 +- engines/sci/graphics/maciconbar.cpp | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/engine/kvideo.cpp b/engines/sci/engine/kvideo.cpp index f176a13721..fa9cc91aed 100644 --- a/engines/sci/engine/kvideo.cpp +++ b/engines/sci/engine/kvideo.cpp @@ -100,7 +100,7 @@ void playVideo(Video::VideoDecoder *videoDecoder, VideoState videoState) { g_sci->_gfxScreen->scale2x((byte *)frame->pixels, scaleBuffer, videoDecoder->getWidth(), videoDecoder->getHeight(), bytesPerPixel); g_system->copyRectToScreen(scaleBuffer, pitch, x, y, width, height); } else { - g_system->copyRectToScreen((byte *)frame->pixels, frame->pitch, x, y, width, height); + g_system->copyRectToScreen(frame->pixels, frame->pitch, x, y, width, height); } if (videoDecoder->hasDirtyPalette()) diff --git a/engines/sci/graphics/frameout.cpp b/engines/sci/graphics/frameout.cpp index dff332458a..7a9c7ba281 100644 --- a/engines/sci/graphics/frameout.cpp +++ b/engines/sci/graphics/frameout.cpp @@ -496,7 +496,7 @@ void GfxFrameout::showVideo() { if (videoDecoder->needsUpdate()) { const Graphics::Surface *frame = videoDecoder->decodeNextFrame(); if (frame) { - g_system->copyRectToScreen((byte *)frame->pixels, frame->pitch, x, y, frame->w, frame->h); + g_system->copyRectToScreen(frame->pixels, frame->pitch, x, y, frame->w, frame->h); if (videoDecoder->hasDirtyPalette()) videoDecoder->setSystemPalette(); diff --git a/engines/sci/graphics/maciconbar.cpp b/engines/sci/graphics/maciconbar.cpp index 7ecba5a24d..dfb50b0edb 100644 --- a/engines/sci/graphics/maciconbar.cpp +++ b/engines/sci/graphics/maciconbar.cpp @@ -129,7 +129,7 @@ void GfxMacIconBar::drawIcon(uint16 iconIndex, bool selected) { void GfxMacIconBar::drawEnabledImage(Graphics::Surface *surface, const Common::Rect &rect) { if (surface) - g_system->copyRectToScreen((byte *)surface->pixels, surface->pitch, rect.left, rect.top, rect.width(), rect.height()); + g_system->copyRectToScreen(surface->pixels, surface->pitch, rect.left, rect.top, rect.width(), rect.height()); } void GfxMacIconBar::drawDisabledImage(Graphics::Surface *surface, const Common::Rect &rect) { @@ -153,7 +153,7 @@ void GfxMacIconBar::drawDisabledImage(Graphics::Surface *surface, const Common:: *((byte *)newSurf.getBasePtr(j, i)) = 0; } - g_system->copyRectToScreen((byte *)newSurf.pixels, newSurf.pitch, rect.left, rect.top, rect.width(), rect.height()); + g_system->copyRectToScreen(newSurf.pixels, newSurf.pitch, rect.left, rect.top, rect.width(), rect.height()); newSurf.free(); } -- cgit v1.2.3 From 7b646e5c62c37b5a593994d1e27a79c62fecd501 Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Sat, 16 Jun 2012 03:19:34 +0200 Subject: SCI: Get rid of casts on CursorManager::replaceCursor calls. --- engines/sci/graphics/cursor.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines/sci') diff --git a/engines/sci/graphics/cursor.cpp b/engines/sci/graphics/cursor.cpp index 14ffa69f91..ce77cf6ed3 100644 --- a/engines/sci/graphics/cursor.cpp +++ b/engines/sci/graphics/cursor.cpp @@ -411,7 +411,7 @@ void GfxCursor::refreshPosition() { } } - CursorMan.replaceCursor((const byte *)_cursorSurface, cursorCelInfo->width, cursorCelInfo->height, cursorHotspot.x, cursorHotspot.y, cursorCelInfo->clearKey); + CursorMan.replaceCursor(_cursorSurface, cursorCelInfo->width, cursorCelInfo->height, cursorHotspot.x, cursorHotspot.y, cursorCelInfo->clearKey); } } -- cgit v1.2.3 From 3c04d333f2f6a423a67a8d0202ffca29d22da9db Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sat, 16 Jun 2012 02:58:26 +0300 Subject: SCI: Add a check for empty VMD file names --- engines/sci/engine/kvideo.cpp | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'engines/sci') diff --git a/engines/sci/engine/kvideo.cpp b/engines/sci/engine/kvideo.cpp index f176a13721..fa44a7dc19 100644 --- a/engines/sci/engine/kvideo.cpp +++ b/engines/sci/engine/kvideo.cpp @@ -342,6 +342,12 @@ reg_t kPlayVMD(EngineState *s, int argc, reg_t *argv) { case 6: // Play videoDecoder = new Video::VMDDecoder(g_system->getMixer()); + if (s->_videoState.fileName.empty()) { + // Happens in Lighthouse + warning("kPlayVMD: Empty filename passed"); + return s->r_acc; + } + if (!videoDecoder->loadFile(s->_videoState.fileName)) { warning("Could not open VMD %s", s->_videoState.fileName.c_str()); break; -- cgit v1.2.3 From 2b50824133ced47f1d8fb6407a1e0212a7eeb41c Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Mon, 18 Jun 2012 05:21:59 +0300 Subject: SCI: Add setter/getter methods to reg_t's No functionality change has been made with this commit. This avoids setting and getting the reg_t members directly, and is the basis of any future work on large SCI3 scripts (larger than 64KB) --- engines/sci/console.cpp | 105 +++++++++++++++-------------- engines/sci/engine/features.cpp | 36 +++++----- engines/sci/engine/file.cpp | 2 +- engines/sci/engine/gc.cpp | 10 +-- engines/sci/engine/gc.h | 2 +- engines/sci/engine/kernel.cpp | 28 ++++---- engines/sci/engine/kevent.cpp | 6 +- engines/sci/engine/kfile.cpp | 4 +- engines/sci/engine/kgraphics.cpp | 16 ++--- engines/sci/engine/kgraphics32.cpp | 2 +- engines/sci/engine/klists.cpp | 18 +++-- engines/sci/engine/kmisc.cpp | 10 +-- engines/sci/engine/kparse.cpp | 2 +- engines/sci/engine/kpathing.cpp | 8 +-- engines/sci/engine/kscripts.cpp | 16 ++--- engines/sci/engine/kstring.cpp | 32 +++++---- engines/sci/engine/kvideo.cpp | 12 ++-- engines/sci/engine/object.cpp | 24 +++---- engines/sci/engine/object.h | 4 +- engines/sci/engine/savegame.cpp | 13 ++-- engines/sci/engine/script.cpp | 42 ++++++------ engines/sci/engine/scriptdebug.cpp | 101 ++++++++++++++-------------- engines/sci/engine/seg_manager.cpp | 133 +++++++++++++++++++------------------ engines/sci/engine/segment.cpp | 50 +++++++------- engines/sci/engine/segment.h | 14 ++-- engines/sci/engine/selector.h | 2 +- engines/sci/engine/vm.cpp | 89 ++++++++++++------------- engines/sci/engine/vm.h | 2 +- engines/sci/engine/vm_types.cpp | 14 ++-- engines/sci/engine/vm_types.h | 47 +++++++++---- engines/sci/graphics/animate.cpp | 2 +- engines/sci/graphics/menu.cpp | 8 +-- engines/sci/graphics/paint16.cpp | 10 +-- engines/sci/resource.cpp | 2 +- engines/sci/sci.cpp | 10 +-- engines/sci/sound/soundcmd.cpp | 6 +- 36 files changed, 457 insertions(+), 425 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp index 94ac437a15..7e9f9b1c38 100644 --- a/engines/sci/console.cpp +++ b/engines/sci/console.cpp @@ -1243,7 +1243,7 @@ bool Console::cmdClassTable(int argc, const char **argv) { for (uint i = 0; i < _engine->_gamestate->_segMan->classTableSize(); i++) { Class temp = _engine->_gamestate->_segMan->_classTable[i]; - if (temp.reg.segment) { + if (temp.reg.getSegment()) { const char *className = _engine->_gamestate->_segMan->getObjectName(temp.reg); if (argc == 1 || (argc == 2 && !strcmp(className, argv[1]))) { DebugPrintf(" Class 0x%x (%s) at %04x:%04x (script %d)\n", i, @@ -1688,7 +1688,7 @@ bool Console::cmdSavedBits(int argc, const char **argv) { Common::Array entries = hunks->listAllDeallocatable(id); for (uint i = 0; i < entries.size(); ++i) { - uint16 offset = entries[i].offset; + uint16 offset = entries[i].getOffset(); const Hunk& h = hunks->_table[offset]; if (strcmp(h.type, "SaveBits()") == 0) { byte* memoryPtr = (byte *)h.mem; @@ -1751,12 +1751,12 @@ bool Console::cmdShowSavedBits(int argc, const char **argv) { return true; } - if (memoryHandle.segment != id || !hunks->isValidOffset(memoryHandle.offset)) { + if (memoryHandle.getSegment() != id || !hunks->isValidOffset(memoryHandle.getOffset())) { DebugPrintf("Invalid address.\n"); return true; } - const Hunk& h = hunks->_table[memoryHandle.offset]; + const Hunk& h = hunks->_table[memoryHandle.getOffset()]; if (strcmp(h.type, "SaveBits()") != 0) { DebugPrintf("Invalid address.\n"); @@ -2266,16 +2266,16 @@ bool Console::cmdGCShowReachable(int argc, const char **argv) { return true; } - SegmentObj *mobj = _engine->_gamestate->_segMan->getSegmentObj(addr.segment); + SegmentObj *mobj = _engine->_gamestate->_segMan->getSegmentObj(addr.getSegment()); if (!mobj) { - DebugPrintf("Unknown segment : %x\n", addr.segment); + DebugPrintf("Unknown segment : %x\n", addr.getSegment()); return 1; } DebugPrintf("Reachable from %04x:%04x:\n", PRINT_REG(addr)); const Common::Array tmp = mobj->listAllOutgoingReferences(addr); for (Common::Array::const_iterator it = tmp.begin(); it != tmp.end(); ++it) - if (it->segment) + if (it->getSegment()) g_sci->getSciDebugger()->DebugPrintf(" %04x:%04x\n", PRINT_REG(*it)); return true; @@ -2298,16 +2298,16 @@ bool Console::cmdGCShowFreeable(int argc, const char **argv) { return true; } - SegmentObj *mobj = _engine->_gamestate->_segMan->getSegmentObj(addr.segment); + SegmentObj *mobj = _engine->_gamestate->_segMan->getSegmentObj(addr.getSegment()); if (!mobj) { - DebugPrintf("Unknown segment : %x\n", addr.segment); + DebugPrintf("Unknown segment : %x\n", addr.getSegment()); return true; } - DebugPrintf("Freeable in segment %04x:\n", addr.segment); - const Common::Array tmp = mobj->listAllDeallocatable(addr.segment); + DebugPrintf("Freeable in segment %04x:\n", addr.getSegment()); + const Common::Array tmp = mobj->listAllDeallocatable(addr.getSegment()); for (Common::Array::const_iterator it = tmp.begin(); it != tmp.end(); ++it) - if (it->segment) + if (it->getSegment()) g_sci->getSciDebugger()->DebugPrintf(" %04x:%04x\n", PRINT_REG(*it)); return true; @@ -2331,9 +2331,9 @@ bool Console::cmdGCNormalize(int argc, const char **argv) { return true; } - SegmentObj *mobj = _engine->_gamestate->_segMan->getSegmentObj(addr.segment); + SegmentObj *mobj = _engine->_gamestate->_segMan->getSegmentObj(addr.getSegment()); if (!mobj) { - DebugPrintf("Unknown segment : %x\n", addr.segment); + DebugPrintf("Unknown segment : %x\n", addr.getSegment()); return true; } @@ -2572,12 +2572,12 @@ bool Console::cmdViewReference(int argc, const char **argv) { DebugPrintf("%04x:%04x is of type 0x%x: ", PRINT_REG(reg), type_mask); - if (reg.segment == 0 && reg.offset == 0) { + if (reg.getSegment() == 0 && reg.getOffset() == 0) { DebugPrintf("Null.\n"); return true; } - if (reg_end.segment != reg.segment && reg_end != NULL_REG) { + if (reg_end.getSegment() != reg.getSegment() && reg_end != NULL_REG) { DebugPrintf("Ending segment different from starting segment. Assuming no bound on dump.\n"); reg_end = NULL_REG; } @@ -2613,7 +2613,7 @@ bool Console::cmdViewReference(int argc, const char **argv) { printObject(reg); break; case SIG_TYPE_REFERENCE: { - switch (_engine->_gamestate->_segMan->getSegmentType(reg.segment)) { + switch (_engine->_gamestate->_segMan->getSegmentType(reg.getSegment())) { #ifdef ENABLE_SCI32 case SEG_TYPE_STRING: { DebugPrintf("SCI32 string\n"); @@ -2629,21 +2629,20 @@ bool Console::cmdViewReference(int argc, const char **argv) { } #endif default: { - int size; const SegmentRef block = _engine->_gamestate->_segMan->dereference(reg); - size = block.maxSize; + uint16 size = block.maxSize; DebugPrintf("raw data\n"); - if (reg_end.segment != 0 && size < reg_end.offset - reg.offset) { + if (reg_end.getSegment() != 0 && size < reg_end.getOffset() - reg.getOffset()) { DebugPrintf("Block end out of bounds (size %d). Resetting.\n", size); reg_end = NULL_REG; } - if (reg_end.segment != 0 && (size >= reg_end.offset - reg.offset)) - size = reg_end.offset - reg.offset; + if (reg_end.getSegment() != 0 && (size >= reg_end.getOffset() - reg.getOffset())) + size = reg_end.getOffset() - reg.getOffset(); - if (reg_end.segment != 0) + if (reg_end.getSegment() != 0) DebugPrintf("Block size less than or equal to %d\n", size); if (block.isRaw) @@ -2655,7 +2654,7 @@ bool Console::cmdViewReference(int argc, const char **argv) { break; } case SIG_TYPE_INTEGER: - DebugPrintf("arithmetic value\n %d (%04x)\n", (int16) reg.offset, reg.offset); + DebugPrintf("arithmetic value\n %d (%04x)\n", (int16) reg.getOffset(), reg.getOffset()); break; default: DebugPrintf("unknown type %d.\n", type); @@ -2725,7 +2724,7 @@ bool Console::cmdBacktrace(int argc, const char **argv) { switch (call.type) { case EXEC_STACK_TYPE_CALL: // Normal function if (call.type == EXEC_STACK_TYPE_CALL) - DebugPrintf(" %x: script %d - ", i, (*(Script *)_engine->_gamestate->_segMan->_heap[call.addr.pc.segment]).getScriptNumber()); + DebugPrintf(" %x: script %d - ", i, (*(Script *)_engine->_gamestate->_segMan->_heap[call.addr.pc.getSegment()]).getScriptNumber()); if (call.debugSelector != -1) { DebugPrintf("%s::%s(", objname, _engine->getKernel()->getSelectorName(call.debugSelector).c_str()); } else if (call.debugExportId != -1) { @@ -2917,7 +2916,7 @@ bool Console::cmdDisassemble(int argc, const char **argv) { addr = disassemble(_engine->_gamestate, addr, printBWTag, printBytecode); if (addr.isNull() && prevAddr < farthestTarget) addr = prevAddr + 1; // skip past the ret - } while (addr.offset > 0); + } while (addr.getOffset() > 0); return true; } @@ -2934,10 +2933,10 @@ bool Console::cmdDisassembleAddress(int argc, const char **argv) { } reg_t vpc = NULL_REG; - int opCount = 1; + uint opCount = 1; bool printBWTag = false; bool printBytes = false; - int size; + uint16 size; if (parse_reg_t(_engine->_gamestate, argv[1], &vpc, false)) { DebugPrintf("Invalid address passed.\n"); @@ -2946,7 +2945,7 @@ bool Console::cmdDisassembleAddress(int argc, const char **argv) { } SegmentRef ref = _engine->_gamestate->_segMan->dereference(vpc); - size = ref.maxSize + vpc.offset; // total segment size + size = ref.maxSize + vpc.getOffset(); // total segment size for (int i = 2; i < argc; i++) { if (!scumm_stricmp(argv[i], "bwt")) @@ -2968,7 +2967,7 @@ bool Console::cmdDisassembleAddress(int argc, const char **argv) { do { vpc = disassemble(_engine->_gamestate, vpc, printBWTag, printBytes); - } while ((vpc.offset > 0) && (vpc.offset + 6 < size) && (--opCount)); + } while ((vpc.getOffset() > 0) && (vpc.getOffset() + 6 < size) && (--opCount)); return true; } @@ -3011,7 +3010,7 @@ void Console::printKernelCallsFound(int kernelFuncNum, bool showFoundScripts) { // Now dissassemble each method of the script object for (uint16 i = 0; i < obj->getMethodCount(); i++) { reg_t fptr = obj->getFunction(i); - uint16 offset = fptr.offset; + uint16 offset = fptr.getOffset(); int16 opparams[4]; byte extOpcode; byte opcode; @@ -3699,8 +3698,8 @@ static int parse_reg_t(EngineState *s, const char *str, reg_t *dest, bool mayBeV return 1; // Now lookup the script's segment - dest->segment = s->_segMan->getScriptSegment(script_nr); - if (!dest->segment) { + dest->setSegment(s->_segMan->getScriptSegment(script_nr)); + if (!dest->getSegment()) { return 1; } @@ -3782,19 +3781,19 @@ static int parse_reg_t(EngineState *s, const char *str, reg_t *dest, bool mayBeV offsetStr = colon + 1; Common::String segmentStr(str, colon); - dest->segment = strtol(segmentStr.c_str(), &endptr, 16); + dest->setSegment(strtol(segmentStr.c_str(), &endptr, 16)); if (*endptr) return 1; } else { int val = 0; - dest->segment = 0; + dest->setSegment(0); if (charsCountNumber == charsCount) { // Only numbers in input, assume decimal value val = strtol(str, &endptr, 10); if (*endptr) return 1; // strtol failed? - dest->offset = val; + dest->setOffset(val); return 0; } else { // We also got letters, check if there were only hexadecimal letters and '0x' at the start or 'h' at the end @@ -3802,7 +3801,7 @@ static int parse_reg_t(EngineState *s, const char *str, reg_t *dest, bool mayBeV val = strtol(str, &endptr, 16); if ((*endptr != 'h') && (*endptr != 0)) return 1; - dest->offset = val; + dest->setOffset(val); return 0; } else { // Something else was in input, assume object name @@ -3851,9 +3850,9 @@ static int parse_reg_t(EngineState *s, const char *str, reg_t *dest, bool mayBeV int val = strtol(offsetStr, &endptr, 16); if (relativeOffset) - dest->offset += val; + dest->incOffset(val); else - dest->offset = val; + dest->setOffset(val); if (*endptr) return 1; @@ -3933,15 +3932,15 @@ void Console::printList(List *list) { while (!pos.isNull()) { Node *node; - NodeTable *nt = (NodeTable *)_engine->_gamestate->_segMan->getSegment(pos.segment, SEG_TYPE_NODES); + NodeTable *nt = (NodeTable *)_engine->_gamestate->_segMan->getSegment(pos.getSegment(), SEG_TYPE_NODES); - if (!nt || !nt->isValidEntry(pos.offset)) { + if (!nt || !nt->isValidEntry(pos.getOffset())) { DebugPrintf(" WARNING: %04x:%04x: Doesn't contain list node!\n", PRINT_REG(pos)); return; } - node = &(nt->_table[pos.offset]); + node = &(nt->_table[pos.getOffset()]); DebugPrintf("\t%04x:%04x : %04x:%04x -> %04x:%04x\n", PRINT_REG(pos), PRINT_REG(node->key), PRINT_REG(node->value)); @@ -3960,37 +3959,37 @@ void Console::printList(List *list) { } int Console::printNode(reg_t addr) { - SegmentObj *mobj = _engine->_gamestate->_segMan->getSegment(addr.segment, SEG_TYPE_LISTS); + SegmentObj *mobj = _engine->_gamestate->_segMan->getSegment(addr.getSegment(), SEG_TYPE_LISTS); if (mobj) { ListTable *lt = (ListTable *)mobj; List *list; - if (!lt->isValidEntry(addr.offset)) { + if (!lt->isValidEntry(addr.getOffset())) { DebugPrintf("Address does not contain a list\n"); return 1; } - list = &(lt->_table[addr.offset]); + list = &(lt->_table[addr.getOffset()]); DebugPrintf("%04x:%04x : first x last = (%04x:%04x, %04x:%04x)\n", PRINT_REG(addr), PRINT_REG(list->first), PRINT_REG(list->last)); } else { NodeTable *nt; Node *node; - mobj = _engine->_gamestate->_segMan->getSegment(addr.segment, SEG_TYPE_NODES); + mobj = _engine->_gamestate->_segMan->getSegment(addr.getSegment(), SEG_TYPE_NODES); if (!mobj) { - DebugPrintf("Segment #%04x is not a list or node segment\n", addr.segment); + DebugPrintf("Segment #%04x is not a list or node segment\n", addr.getSegment()); return 1; } nt = (NodeTable *)mobj; - if (!nt->isValidEntry(addr.offset)) { + if (!nt->isValidEntry(addr.getOffset())) { DebugPrintf("Address does not contain a node\n"); return 1; } - node = &(nt->_table[addr.offset]); + node = &(nt->_table[addr.getOffset()]); DebugPrintf("%04x:%04x : prev x next = (%04x:%04x, %04x:%04x); maps %04x:%04x -> %04x:%04x\n", PRINT_REG(addr), PRINT_REG(node->pred), PRINT_REG(node->succ), PRINT_REG(node->key), PRINT_REG(node->value)); @@ -4028,8 +4027,8 @@ int Console::printObject(reg_t pos) { reg_t val = obj->getVariable(i); DebugPrintf("%04x:%04x", PRINT_REG(val)); - if (!val.segment) - DebugPrintf(" (%d)", val.offset); + if (!val.getSegment()) + DebugPrintf(" (%d)", val.getOffset()); const Object *ref = s->_segMan->getObject(val); if (ref) @@ -4042,8 +4041,8 @@ int Console::printObject(reg_t pos) { reg_t fptr = obj->getFunction(i); DebugPrintf(" [%03x] %s = %04x:%04x\n", obj->getFuncSelector(i), _engine->getKernel()->getSelectorName(obj->getFuncSelector(i)).c_str(), PRINT_REG(fptr)); } - if (s->_segMan->_heap[pos.segment]->getType() == SEG_TYPE_SCRIPT) - DebugPrintf("\nOwner script: %d\n", s->_segMan->getScript(pos.segment)->getScriptNumber()); + if (s->_segMan->_heap[pos.getSegment()]->getType() == SEG_TYPE_SCRIPT) + DebugPrintf("\nOwner script: %d\n", s->_segMan->getScript(pos.getSegment())->getScriptNumber()); return 0; } diff --git a/engines/sci/engine/features.cpp b/engines/sci/engine/features.cpp index 8a932232f8..22c0a1479d 100644 --- a/engines/sci/engine/features.cpp +++ b/engines/sci/engine/features.cpp @@ -74,11 +74,11 @@ bool GameFeatures::autoDetectSoundType() { // Look up the script address reg_t addr = getDetectionAddr("Sound", SELECTOR(play)); - if (!addr.segment) + if (!addr.getSegment()) return false; - uint16 offset = addr.offset; - Script *script = _segMan->getScript(addr.segment); + uint16 offset = addr.getOffset(); + Script *script = _segMan->getScript(addr.getSegment()); uint16 intParam = 0xFFFF; bool foundTarget = false; @@ -221,11 +221,11 @@ bool GameFeatures::autoDetectLofsType(Common::String gameSuperClassName, int met // Look up the script address reg_t addr = getDetectionAddr(gameSuperClassName.c_str(), -1, methodNum); - if (!addr.segment) + if (!addr.getSegment()) return false; - uint16 offset = addr.offset; - Script *script = _segMan->getScript(addr.segment); + uint16 offset = addr.getOffset(); + Script *script = _segMan->getScript(addr.getSegment()); while (true) { int16 opparams[4]; @@ -320,11 +320,11 @@ bool GameFeatures::autoDetectGfxFunctionsType(int methodNum) { // Look up the script address reg_t addr = getDetectionAddr("Rm", SELECTOR(overlay), methodNum); - if (!addr.segment) + if (!addr.getSegment()) return false; - uint16 offset = addr.offset; - Script *script = _segMan->getScript(addr.segment); + uint16 offset = addr.getOffset(); + Script *script = _segMan->getScript(addr.getSegment()); while (true) { int16 opparams[4]; @@ -474,11 +474,11 @@ bool GameFeatures::autoDetectSci21KernelType() { // Look up the script address reg_t addr = getDetectionAddr("Sound", SELECTOR(play)); - if (!addr.segment) + if (!addr.getSegment()) return false; - uint16 offset = addr.offset; - Script *script = _segMan->getScript(addr.segment); + uint16 offset = addr.getOffset(); + Script *script = _segMan->getScript(addr.getSegment()); while (true) { int16 opparams[4]; @@ -550,11 +550,11 @@ bool GameFeatures::autoDetectSci21StringFunctionType() { // Look up the script address reg_t addr = getDetectionAddr("Str", SELECTOR(size)); - if (!addr.segment) + if (!addr.getSegment()) return false; - uint16 offset = addr.offset; - Script *script = _segMan->getScript(addr.segment); + uint16 offset = addr.getOffset(); + Script *script = _segMan->getScript(addr.getSegment()); while (true) { int16 opparams[4]; @@ -587,11 +587,11 @@ bool GameFeatures::autoDetectMoveCountType() { // Look up the script address reg_t addr = getDetectionAddr("Motion", SELECTOR(doit)); - if (!addr.segment) + if (!addr.getSegment()) return false; - uint16 offset = addr.offset; - Script *script = _segMan->getScript(addr.segment); + uint16 offset = addr.getOffset(); + Script *script = _segMan->getScript(addr.getSegment()); bool foundTarget = false; while (true) { diff --git a/engines/sci/engine/file.cpp b/engines/sci/engine/file.cpp index c44963f457..0d575f97dd 100644 --- a/engines/sci/engine/file.cpp +++ b/engines/sci/engine/file.cpp @@ -269,7 +269,7 @@ Common::String DirSeeker::getVirtualFilename(uint fileNumber) { reg_t DirSeeker::firstFile(const Common::String &mask, reg_t buffer, SegManager *segMan) { // Verify that we are given a valid buffer - if (!buffer.segment) { + if (!buffer.getSegment()) { error("DirSeeker::firstFile('%s') invoked with invalid buffer", mask.c_str()); return NULL_REG; } diff --git a/engines/sci/engine/gc.cpp b/engines/sci/engine/gc.cpp index 2d71878bda..9a30ff3e17 100644 --- a/engines/sci/engine/gc.cpp +++ b/engines/sci/engine/gc.cpp @@ -47,7 +47,7 @@ const char *segmentTypeNames[] = { #endif void WorklistManager::push(reg_t reg) { - if (!reg.segment) // No numbers + if (!reg.getSegment()) // No numbers return; debugC(kDebugLevelGC, "[GC] Adding %04x:%04x", PRINT_REG(reg)); @@ -69,7 +69,7 @@ static AddrSet *normalizeAddresses(SegManager *segMan, const AddrSet &nonnormal_ for (AddrSet::const_iterator i = nonnormal_map.begin(); i != nonnormal_map.end(); ++i) { reg_t reg = i->_key; - SegmentObj *mobj = segMan->getSegmentObj(reg.segment); + SegmentObj *mobj = segMan->getSegmentObj(reg.getSegment()); if (mobj) { reg = mobj->findCanonicAddress(segMan, reg); @@ -85,11 +85,11 @@ static void processWorkList(SegManager *segMan, WorklistManager &wm, const Commo while (!wm._worklist.empty()) { reg_t reg = wm._worklist.back(); wm._worklist.pop_back(); - if (reg.segment != stackSegment) { // No need to repeat this one + if (reg.getSegment() != stackSegment) { // No need to repeat this one debugC(kDebugLevelGC, "[GC] Checking %04x:%04x", PRINT_REG(reg)); - if (reg.segment < heap.size() && heap[reg.segment]) { + if (reg.getSegment() < heap.size() && heap[reg.getSegment()]) { // Valid heap object? Find its outgoing references! - wm.pushArray(heap[reg.segment]->listAllOutgoingReferences(reg)); + wm.pushArray(heap[reg.getSegment()]->listAllOutgoingReferences(reg)); } } } diff --git a/engines/sci/engine/gc.h b/engines/sci/engine/gc.h index 97aa6513b6..9e02bbd0bd 100644 --- a/engines/sci/engine/gc.h +++ b/engines/sci/engine/gc.h @@ -32,7 +32,7 @@ namespace Sci { struct reg_t_Hash { uint operator()(const reg_t& x) const { - return (x.segment << 3) ^ x.offset ^ (x.offset << 16); + return (x.getSegment() << 3) ^ x.getOffset() ^ (x.getOffset() << 16); } }; diff --git a/engines/sci/engine/kernel.cpp b/engines/sci/engine/kernel.cpp index 3a33c928e7..c8fe47d9fc 100644 --- a/engines/sci/engine/kernel.cpp +++ b/engines/sci/engine/kernel.cpp @@ -357,27 +357,27 @@ static uint16 *parseKernelSignature(const char *kernelName, const char *writtenS uint16 Kernel::findRegType(reg_t reg) { // No segment? Must be integer - if (!reg.segment) - return SIG_TYPE_INTEGER | (reg.offset ? 0 : SIG_TYPE_NULL); + if (!reg.getSegment()) + return SIG_TYPE_INTEGER | (reg.getOffset() ? 0 : SIG_TYPE_NULL); - if (reg.segment == 0xFFFF) + if (reg.getSegment() == 0xFFFF) return SIG_TYPE_UNINITIALIZED; // Otherwise it's an object - SegmentObj *mobj = _segMan->getSegmentObj(reg.segment); + SegmentObj *mobj = _segMan->getSegmentObj(reg.getSegment()); if (!mobj) return SIG_TYPE_ERROR; uint16 result = 0; - if (!mobj->isValidOffset(reg.offset)) + if (!mobj->isValidOffset(reg.getOffset())) result |= SIG_IS_INVALID; switch (mobj->getType()) { case SEG_TYPE_SCRIPT: - if (reg.offset <= (*(Script *)mobj).getBufSize() && - reg.offset >= -SCRIPT_OBJECT_MAGIC_OFFSET && - (*(Script *)mobj).offsetIsObject(reg.offset)) { - result |= ((Script *)mobj)->getObject(reg.offset) ? SIG_TYPE_OBJECT : SIG_TYPE_REFERENCE; + if (reg.getOffset() <= (*(Script *)mobj).getBufSize() && + reg.getOffset() >= (uint)-SCRIPT_OBJECT_MAGIC_OFFSET && + (*(Script *)mobj).offsetIsObject(reg.getOffset())) { + result |= ((Script *)mobj)->getObject(reg.getOffset()) ? SIG_TYPE_OBJECT : SIG_TYPE_REFERENCE; } else result |= SIG_TYPE_REFERENCE; break; @@ -608,7 +608,7 @@ void Kernel::mapFunctions() { _kernelFuncs[id].workarounds = kernelMap->workarounds; if (kernelMap->subFunctions) { // Get version for subfunction identification - SciVersion mySubVersion = (SciVersion)kernelMap->function(NULL, 0, NULL).offset; + SciVersion mySubVersion = (SciVersion)kernelMap->function(NULL, 0, NULL).getOffset(); // Now check whats the highest subfunction-id for this version const SciKernelMapSubEntry *kernelSubMap = kernelMap->subFunctions; uint16 subFunctionCount = 0; @@ -885,15 +885,15 @@ Common::String Kernel::lookupText(reg_t address, int index) { char *seeker; Resource *textres; - if (address.segment) + if (address.getSegment()) return _segMan->getString(address); int textlen; int _index = index; - textres = _resMan->findResource(ResourceId(kResourceTypeText, address.offset), 0); + textres = _resMan->findResource(ResourceId(kResourceTypeText, address.getOffset()), 0); if (!textres) { - error("text.%03d not found", address.offset); + error("text.%03d not found", address.getOffset()); return NULL; /* Will probably segfault */ } @@ -907,7 +907,7 @@ Common::String Kernel::lookupText(reg_t address, int index) { if (textlen) return seeker; - error("Index %d out of bounds in text.%03d", _index, address.offset); + error("Index %d out of bounds in text.%03d", _index, address.getOffset()); return NULL; } diff --git a/engines/sci/engine/kevent.cpp b/engines/sci/engine/kevent.cpp index df3b3efd57..34477cc23b 100644 --- a/engines/sci/engine/kevent.cpp +++ b/engines/sci/engine/kevent.cpp @@ -157,7 +157,7 @@ reg_t kGetEvent(EngineState *s, int argc, reg_t *argv) { s->r_acc = NULL_REG; } - if ((s->r_acc.offset) && (g_sci->_debugState.stopOnEvent)) { + if ((s->r_acc.getOffset()) && (g_sci->_debugState.stopOnEvent)) { g_sci->_debugState.stopOnEvent = false; // A SCI event occurred, and we have been asked to stop, so open the debug console @@ -248,7 +248,7 @@ reg_t kGlobalToLocal(EngineState *s, int argc, reg_t *argv) { reg_t planeObject = argc > 1 ? argv[1] : NULL_REG; // SCI32 SegManager *segMan = s->_segMan; - if (obj.segment) { + if (obj.getSegment()) { int16 x = readSelectorValue(segMan, obj, SELECTOR(x)); int16 y = readSelectorValue(segMan, obj, SELECTOR(y)); @@ -267,7 +267,7 @@ reg_t kLocalToGlobal(EngineState *s, int argc, reg_t *argv) { reg_t planeObject = argc > 1 ? argv[1] : NULL_REG; // SCI32 SegManager *segMan = s->_segMan; - if (obj.segment) { + if (obj.getSegment()) { int16 x = readSelectorValue(segMan, obj, SELECTOR(x)); int16 y = readSelectorValue(segMan, obj, SELECTOR(y)); diff --git a/engines/sci/engine/kfile.cpp b/engines/sci/engine/kfile.cpp index 7a2f161829..a21e19802d 100644 --- a/engines/sci/engine/kfile.cpp +++ b/engines/sci/engine/kfile.cpp @@ -185,7 +185,7 @@ reg_t kCheckFreeSpace(EngineState *s, int argc, reg_t *argv) { reg_t kValidPath(EngineState *s, int argc, reg_t *argv) { Common::String path = s->_segMan->getString(argv[0]); - debug(3, "kValidPath(%s) -> %d", path.c_str(), s->r_acc.offset); + debug(3, "kValidPath(%s) -> %d", path.c_str(), s->r_acc.getOffset()); // Always return true return make_reg(0, 1); @@ -866,7 +866,7 @@ reg_t kRestoreGame(EngineState *s, int argc, reg_t *argv) { // saving a previously restored game. // We set the current savedgame-id directly and remove the script // code concerning this via script patch. - s->variables[VAR_GLOBAL][0xB3].offset = SAVEGAMEID_OFFICIALRANGE_START + savegameId; + s->variables[VAR_GLOBAL][0xB3].setOffset(SAVEGAMEID_OFFICIALRANGE_START + savegameId); } } else { s->r_acc = TRUE_REG; diff --git a/engines/sci/engine/kgraphics.cpp b/engines/sci/engine/kgraphics.cpp index 8bf7be4ca3..8f4d99f7df 100644 --- a/engines/sci/engine/kgraphics.cpp +++ b/engines/sci/engine/kgraphics.cpp @@ -337,7 +337,7 @@ reg_t kTextSize(EngineState *s, int argc, reg_t *argv) { Common::String sep_str; const char *sep = NULL; - if ((argc > 4) && (argv[4].segment)) { + if ((argc > 4) && (argv[4].getSegment())) { sep_str = s->_segMan->getString(argv[4]); sep = sep_str.c_str(); } @@ -789,7 +789,7 @@ void _k_GenericDrawControl(EngineState *s, reg_t controlObject, bool hilite) { Common::Rect rect; TextAlignment alignment; int16 mode, maxChars, cursorPos, upperPos, listCount, i; - int16 upperOffset, cursorOffset; + uint16 upperOffset, cursorOffset; GuiResourceId viewId; int16 loopNo; int16 celNo; @@ -871,7 +871,7 @@ void _k_GenericDrawControl(EngineState *s, reg_t controlObject, bool hilite) { listCount = 0; listSeeker = textReference; while (s->_segMan->strlen(listSeeker) > 0) { listCount++; - listSeeker.offset += maxChars; + listSeeker.incOffset(maxChars); } // TODO: This is rather convoluted... It would be a lot cleaner @@ -885,11 +885,11 @@ void _k_GenericDrawControl(EngineState *s, reg_t controlObject, bool hilite) { for (i = 0; i < listCount; i++) { listStrings[i] = s->_segMan->getString(listSeeker); listEntries[i] = listStrings[i].c_str(); - if (listSeeker.offset == upperOffset) + if (listSeeker.getOffset() == upperOffset) upperPos = i; - if (listSeeker.offset == cursorOffset) + if (listSeeker.getOffset() == cursorOffset) cursorPos = i; - listSeeker.offset += maxChars; + listSeeker.incOffset(maxChars); } } @@ -1104,7 +1104,7 @@ reg_t kNewWindow(EngineState *s, int argc, reg_t *argv) { rect2 = Common::Rect (argv[5].toSint16(), argv[4].toSint16(), argv[7].toSint16(), argv[6].toSint16()); Common::String title; - if (argv[4 + argextra].segment) { + if (argv[4 + argextra].getSegment()) { title = s->_segMan->getString(argv[4 + argextra]); title = g_sci->strSplit(title.c_str(), NULL); } @@ -1143,7 +1143,7 @@ reg_t kDisplay(EngineState *s, int argc, reg_t *argv) { Common::String text; - if (textp.segment) { + if (textp.getSegment()) { argc--; argv++; text = s->_segMan->getString(textp); } else { diff --git a/engines/sci/engine/kgraphics32.cpp b/engines/sci/engine/kgraphics32.cpp index 377c05935a..413ad1ecb1 100644 --- a/engines/sci/engine/kgraphics32.cpp +++ b/engines/sci/engine/kgraphics32.cpp @@ -140,7 +140,7 @@ reg_t kIsOnMe(EngineState *s, int argc, reg_t *argv) { uint16 x = argv[0].toUint16(); uint16 y = argv[1].toUint16(); reg_t targetObject = argv[2]; - uint16 illegalBits = argv[3].offset; + uint16 illegalBits = argv[3].getOffset(); Common::Rect nsRect = g_sci->_gfxCompare->getNSRect(targetObject, true); // we assume that x, y are local coordinates diff --git a/engines/sci/engine/klists.cpp b/engines/sci/engine/klists.cpp index 5a608af034..15d18eb4bb 100644 --- a/engines/sci/engine/klists.cpp +++ b/engines/sci/engine/klists.cpp @@ -409,10 +409,14 @@ int sort_temp_cmp(const void *p1, const void *p2) { const sort_temp_t *st1 = (const sort_temp_t *)p1; const sort_temp_t *st2 = (const sort_temp_t *)p2; - if (st1->order.segment < st2->order.segment || (st1->order.segment == st2->order.segment && st1->order.offset < st2->order.offset)) + if (st1->order.getSegment() < st2->order.getSegment() || + (st1->order.getSegment() == st2->order.getSegment() && + st1->order.getOffset() < st2->order.getOffset())) return -1; - if (st1->order.segment > st2->order.segment || (st1->order.segment == st2->order.segment && st1->order.offset > st2->order.offset)) + if (st1->order.getSegment() > st2->order.getSegment() || + (st1->order.getSegment() == st2->order.getSegment() && + st1->order.getOffset() > st2->order.getOffset())) return 1; return 0; @@ -665,15 +669,15 @@ reg_t kArray(EngineState *s, int argc, reg_t *argv) { if (argv[2].toUint16() == 3) return kString(s, argc, argv); } else { - if (s->_segMan->getSegmentType(argv[1].segment) == SEG_TYPE_STRING || - s->_segMan->getSegmentType(argv[1].segment) == SEG_TYPE_SCRIPT) { + if (s->_segMan->getSegmentType(argv[1].getSegment()) == SEG_TYPE_STRING || + s->_segMan->getSegmentType(argv[1].getSegment()) == SEG_TYPE_SCRIPT) { return kString(s, argc, argv); } #if 0 if (op == 6) { - if (s->_segMan->getSegmentType(argv[3].segment) == SEG_TYPE_STRING || - s->_segMan->getSegmentType(argv[3].segment) == SEG_TYPE_SCRIPT) { + if (s->_segMan->getSegmentType(argv[3].getSegment()) == SEG_TYPE_STRING || + s->_segMan->getSegmentType(argv[3].getSegment()) == SEG_TYPE_SCRIPT) { return kString(s, argc, argv); } } @@ -792,7 +796,7 @@ reg_t kArray(EngineState *s, int argc, reg_t *argv) { #endif return NULL_REG; } - if (s->_segMan->getSegmentObj(argv[1].segment)->getType() != SEG_TYPE_ARRAY) + if (s->_segMan->getSegmentObj(argv[1].getSegment())->getType() != SEG_TYPE_ARRAY) error("kArray(Dup): Request to duplicate a segment which isn't an array"); reg_t arrayHandle; diff --git a/engines/sci/engine/kmisc.cpp b/engines/sci/engine/kmisc.cpp index 2e80764d01..12c830f622 100644 --- a/engines/sci/engine/kmisc.cpp +++ b/engines/sci/engine/kmisc.cpp @@ -128,7 +128,7 @@ reg_t kMemoryInfo(EngineState *s, int argc, reg_t *argv) { // fragmented const uint16 size = 0x7fea; - switch (argv[0].offset) { + switch (argv[0].getOffset()) { case K_MEMORYINFO_LARGEST_HEAP_BLOCK: // In order to prevent "Memory fragmented" dialogs from // popping up in some games, we must return FREE_HEAP - 2 here. @@ -140,7 +140,7 @@ reg_t kMemoryInfo(EngineState *s, int argc, reg_t *argv) { return make_reg(0, size); default: - error("Unknown MemoryInfo operation: %04x", argv[0].offset); + error("Unknown MemoryInfo operation: %04x", argv[0].getOffset()); } return NULL_REG; @@ -304,7 +304,7 @@ reg_t kMemory(EngineState *s, int argc, reg_t *argv) { break; } case K_MEMORY_PEEK : { - if (!argv[1].segment) { + if (!argv[1].getSegment()) { // This occurs in KQ5CD when interacting with certain objects warning("Attempt to peek invalid memory at %04x:%04x", PRINT_REG(argv[1])); return s->r_acc; @@ -334,11 +334,11 @@ reg_t kMemory(EngineState *s, int argc, reg_t *argv) { } if (ref.isRaw) { - if (argv[2].segment) { + if (argv[2].getSegment()) { error("Attempt to poke memory reference %04x:%04x to %04x:%04x", PRINT_REG(argv[2]), PRINT_REG(argv[1])); return s->r_acc; } - WRITE_SCIENDIAN_UINT16(ref.raw, argv[2].offset); // Amiga versions are BE + WRITE_SCIENDIAN_UINT16(ref.raw, argv[2].getOffset()); // Amiga versions are BE } else { if (ref.skipByte) error("Attempt to poke memory at odd offset %04X:%04X", PRINT_REG(argv[1])); diff --git a/engines/sci/engine/kparse.cpp b/engines/sci/engine/kparse.cpp index 59694cb6ee..5e861daaa4 100644 --- a/engines/sci/engine/kparse.cpp +++ b/engines/sci/engine/kparse.cpp @@ -48,7 +48,7 @@ reg_t kSaid(EngineState *s, int argc, reg_t *argv) { const int debug_parser = 0; #endif - if (!heap_said_block.segment) + if (!heap_said_block.getSegment()) return NULL_REG; said_block = (byte *)s->_segMan->derefBulkPtr(heap_said_block, 0); diff --git a/engines/sci/engine/kpathing.cpp b/engines/sci/engine/kpathing.cpp index 089b325a7f..002ef1ff07 100644 --- a/engines/sci/engine/kpathing.cpp +++ b/engines/sci/engine/kpathing.cpp @@ -367,7 +367,7 @@ static void draw_input(EngineState *s, reg_t poly_list, Common::Point start, Com draw_point(s, start, 1, width, height); draw_point(s, end, 0, width, height); - if (!poly_list.segment) + if (!poly_list.getSegment()) return; list = s->_segMan->lookupList(poly_list); @@ -423,7 +423,7 @@ static void print_input(EngineState *s, reg_t poly_list, Common::Point start, Co debug("End point: (%i, %i)", end.x, end.y); debug("Optimization level: %i", opt); - if (!poly_list.segment) + if (!poly_list.getSegment()) return; list = s->_segMan->lookupList(poly_list); @@ -1180,7 +1180,7 @@ static PathfindingState *convert_polygon_set(EngineState *s, reg_t poly_list, Co PathfindingState *pf_s = new PathfindingState(width, height); // Convert all polygons - if (poly_list.segment) { + if (poly_list.getSegment()) { List *list = s->_segMan->lookupList(poly_list); Node *node = s->_segMan->lookupNode(list->first); @@ -1503,7 +1503,7 @@ reg_t kAvoidPath(EngineState *s, int argc, reg_t *argv) { draw_point(s, start, 1, width, height); draw_point(s, end, 0, width, height); - if (poly_list.segment) { + if (poly_list.getSegment()) { print_input(s, poly_list, start, end, opt); draw_input(s, poly_list, start, end, opt, width, height); } diff --git a/engines/sci/engine/kscripts.cpp b/engines/sci/engine/kscripts.cpp index 9b0e490d7e..c9e94a52a4 100644 --- a/engines/sci/engine/kscripts.cpp +++ b/engines/sci/engine/kscripts.cpp @@ -140,7 +140,7 @@ reg_t kClone(EngineState *s, int argc, reg_t *argv) { debugC(kDebugLevelMemory, "Attempting to clone from %04x:%04x", PRINT_REG(parentAddr)); - uint16 infoSelector = parentObj->getInfoSelector().offset; + uint16 infoSelector = parentObj->getInfoSelector().getOffset(); cloneObj = s->_segMan->allocateClone(&cloneAddr); if (!cloneObj) { @@ -169,8 +169,8 @@ reg_t kClone(EngineState *s, int argc, reg_t *argv) { cloneObj->setSpeciesSelector(cloneObj->getPos()); if (parentObj->isClass()) cloneObj->setSuperClassSelector(parentObj->getPos()); - s->_segMan->getScript(parentObj->getPos().segment)->incrementLockers(); - s->_segMan->getScript(cloneObj->getPos().segment)->incrementLockers(); + s->_segMan->getScript(parentObj->getPos().getSegment())->incrementLockers(); + s->_segMan->getScript(cloneObj->getPos().getSegment())->incrementLockers(); return cloneAddr; } @@ -191,7 +191,7 @@ reg_t kDisposeClone(EngineState *s, int argc, reg_t *argv) { // At least kq4early relies on this behavior. The scripts clone "Sound", then set bit 1 manually // and call kDisposeClone later. In that case we may not free it, otherwise we will run into issues // later, because kIsObject would then return false and Sound object wouldn't get checked. - uint16 infoSelector = object->getInfoSelector().offset; + uint16 infoSelector = object->getInfoSelector().getOffset(); if ((infoSelector & 3) == kInfoFlagClone) object->markAsFreed(); @@ -203,7 +203,7 @@ reg_t kScriptID(EngineState *s, int argc, reg_t *argv) { int script = argv[0].toUint16(); uint16 index = (argc > 1) ? argv[1].toUint16() : 0; - if (argv[0].segment) + if (argv[0].getSegment()) return argv[0]; SegmentId scriptSeg = s->_segMan->getScriptSegment(script, SCRIPT_GET_LOAD); @@ -251,12 +251,12 @@ reg_t kScriptID(EngineState *s, int argc, reg_t *argv) { } reg_t kDisposeScript(EngineState *s, int argc, reg_t *argv) { - int script = argv[0].offset; + int script = argv[0].getOffset(); SegmentId id = s->_segMan->getScriptSegment(script); Script *scr = s->_segMan->getScriptIfLoaded(id); if (scr && !scr->isMarkedAsDeleted()) { - if (s->_executionStack.back().addr.pc.segment != id) + if (s->_executionStack.back().addr.pc.getSegment() != id) scr->setLockers(1); } @@ -273,7 +273,7 @@ reg_t kDisposeScript(EngineState *s, int argc, reg_t *argv) { } reg_t kIsObject(EngineState *s, int argc, reg_t *argv) { - if (argv[0].offset == SIGNAL_OFFSET) // Treated specially + if (argv[0].getOffset() == SIGNAL_OFFSET) // Treated specially return NULL_REG; else return make_reg(0, s->_segMan->isHeapObject(argv[0])); diff --git a/engines/sci/engine/kstring.cpp b/engines/sci/engine/kstring.cpp index 33b8c15e9f..8d627efacf 100644 --- a/engines/sci/engine/kstring.cpp +++ b/engines/sci/engine/kstring.cpp @@ -33,7 +33,7 @@ namespace Sci { reg_t kStrEnd(EngineState *s, int argc, reg_t *argv) { reg_t address = argv[0]; - address.offset += s->_segMan->strlen(address); + address.incOffset(s->_segMan->strlen(address)); return address; } @@ -123,18 +123,22 @@ reg_t kStrAt(EngineState *s, int argc, reg_t *argv) { oddOffset = !oddOffset; if (!oddOffset) { - value = tmp.offset & 0x00ff; + value = tmp.getOffset() & 0x00ff; if (argc > 2) { /* Request to modify this char */ - tmp.offset &= 0xff00; - tmp.offset |= newvalue; - tmp.segment = 0; + uint16 offset = tmp.toUint16(); + offset &= 0xff00; + offset |= newvalue; + tmp.setOffset(offset); + tmp.setSegment(0); } } else { - value = tmp.offset >> 8; + value = tmp.getOffset() >> 8; if (argc > 2) { /* Request to modify this char */ - tmp.offset &= 0x00ff; - tmp.offset |= newvalue << 8; - tmp.segment = 0; + uint16 offset = tmp.toUint16(); + offset &= 0x00ff; + offset |= newvalue << 8; + tmp.setOffset(offset); + tmp.setSegment(0); } } } @@ -204,7 +208,7 @@ reg_t kFormat(EngineState *s, int argc, reg_t *argv) { int strLength = 0; /* Used for stuff like "%13s" */ bool unsignedVar = false; - if (position.segment) + if (position.getSegment()) startarg = 2; else { // WORKAROUND: QFG1 VGA Mac calls this without the first parameter (dest). It then @@ -291,7 +295,7 @@ reg_t kFormat(EngineState *s, int argc, reg_t *argv) { if (extralen < 0) extralen = 0; - if (reg.segment) /* Heap address? */ + if (reg.getSegment()) /* Heap address? */ paramindex++; else paramindex += 2; /* No, text resource address */ @@ -654,7 +658,7 @@ reg_t kString(EngineState *s, int argc, reg_t *argv) { return make_reg(0, s->_segMan->getString(argv[1]).size()); case 2: { // At (return value at an index) // Note that values are put in bytes to avoid sign extension - if (argv[1].segment == s->_segMan->getStringSegmentId()) { + if (argv[1].getSegment() == s->_segMan->getStringSegmentId()) { SciString *string = s->_segMan->lookupString(argv[1]); byte val = string->getRawData()[argv[2].toUint16()]; return make_reg(0, val); @@ -705,7 +709,7 @@ reg_t kString(EngineState *s, int argc, reg_t *argv) { uint32 string2Size = 0; Common::String string; - if (argv[3].segment == s->_segMan->getStringSegmentId()) { + if (argv[3].getSegment() == s->_segMan->getStringSegmentId()) { SciString *sstr; sstr = s->_segMan->lookupString(argv[3]); string2 = sstr->getRawData(); @@ -755,7 +759,7 @@ reg_t kString(EngineState *s, int argc, reg_t *argv) { SciString *dupString = s->_segMan->allocateString(&stringHandle); - if (argv[1].segment == s->_segMan->getStringSegmentId()) { + if (argv[1].getSegment() == s->_segMan->getStringSegmentId()) { *dupString = *s->_segMan->lookupString(argv[1]); } else { dupString->fromString(s->_segMan->getString(argv[1])); diff --git a/engines/sci/engine/kvideo.cpp b/engines/sci/engine/kvideo.cpp index fa44a7dc19..8e4cdbcb09 100644 --- a/engines/sci/engine/kvideo.cpp +++ b/engines/sci/engine/kvideo.cpp @@ -135,7 +135,7 @@ reg_t kShowMovie(EngineState *s, int argc, reg_t *argv) { Video::VideoDecoder *videoDecoder = 0; - if (argv[0].segment != 0) { + if (argv[0].getSegment() != 0) { Common::String filename = s->_segMan->getString(argv[0]); if (g_sci->getPlatform() == Common::kPlatformMacintosh) { @@ -303,7 +303,7 @@ reg_t kPlayVMD(EngineState *s, int argc, reg_t *argv) { // with subfx 21. The subtleness has to do with creation of temporary // planes and positioning relative to such planes. - uint16 flags = argv[3].offset; + uint16 flags = argv[3].getOffset(); Common::String flagspec; if (argc > 3) { @@ -331,12 +331,12 @@ reg_t kPlayVMD(EngineState *s, int argc, reg_t *argv) { s->_videoState.flags = flags; } - warning("x, y: %d, %d", argv[1].offset, argv[2].offset); - s->_videoState.x = argv[1].offset; - s->_videoState.y = argv[2].offset; + warning("x, y: %d, %d", argv[1].getOffset(), argv[2].getOffset()); + s->_videoState.x = argv[1].getOffset(); + s->_videoState.y = argv[2].getOffset(); if (argc > 4 && flags & 16) - warning("gammaBoost: %d%% between palette entries %d and %d", argv[4].offset, argv[5].offset, argv[6].offset); + warning("gammaBoost: %d%% between palette entries %d and %d", argv[4].getOffset(), argv[5].getOffset(), argv[6].getOffset()); break; } case 6: // Play diff --git a/engines/sci/engine/object.cpp b/engines/sci/engine/object.cpp index de028392ea..b28026b71f 100644 --- a/engines/sci/engine/object.cpp +++ b/engines/sci/engine/object.cpp @@ -44,15 +44,15 @@ static bool relocateBlock(Common::Array &block, int block_location, Segme error("Attempt to relocate odd variable #%d.5e (relative to %04x)\n", idx, block_location); return false; } - block[idx].segment = segment; // Perform relocation + block[idx].setSegment(segment); // Perform relocation if (getSciVersion() >= SCI_VERSION_1_1 && getSciVersion() <= SCI_VERSION_2_1) - block[idx].offset += scriptSize; + block[idx].incOffset(scriptSize); return true; } void Object::init(byte *buf, reg_t obj_pos, bool initVariables) { - byte *data = buf + obj_pos.offset; + byte *data = buf + obj_pos.getOffset(); _baseObj = data; _pos = obj_pos; @@ -109,7 +109,7 @@ int Object::locateVarSelector(SegManager *segMan, Selector slc) const { } bool Object::relocateSci0Sci21(SegmentId segment, int location, size_t scriptSize) { - return relocateBlock(_variables, getPos().offset, segment, location, scriptSize); + return relocateBlock(_variables, getPos().getOffset(), segment, location, scriptSize); } bool Object::relocateSci3(SegmentId segment, uint32 location, int offset, size_t scriptSize) { @@ -117,8 +117,8 @@ bool Object::relocateSci3(SegmentId segment, uint32 location, int offset, size_t for (uint i = 0; i < _variables.size(); ++i) { if (location == _propertyOffsetsSci3[i]) { - _variables[i].segment = segment; - _variables[i].offset += offset; + _variables[i].setSegment(segment); + _variables[i].incOffset(offset); return true; } } @@ -148,21 +148,21 @@ int Object::propertyOffsetToId(SegManager *segMan, int propertyOffset) const { } void Object::initSpecies(SegManager *segMan, reg_t addr) { - uint16 speciesOffset = getSpeciesSelector().offset; + uint16 speciesOffset = getSpeciesSelector().getOffset(); if (speciesOffset == 0xffff) // -1 setSpeciesSelector(NULL_REG); // no species else - setSpeciesSelector(segMan->getClassAddress(speciesOffset, SCRIPT_GET_LOCK, addr.segment)); + setSpeciesSelector(segMan->getClassAddress(speciesOffset, SCRIPT_GET_LOCK, addr.getSegment())); } void Object::initSuperClass(SegManager *segMan, reg_t addr) { - uint16 superClassOffset = getSuperClassSelector().offset; + uint16 superClassOffset = getSuperClassSelector().getOffset(); if (superClassOffset == 0xffff) // -1 setSuperClassSelector(NULL_REG); // no superclass else - setSuperClassSelector(segMan->getClassAddress(superClassOffset, SCRIPT_GET_LOCK, addr.segment)); + setSuperClassSelector(segMan->getClassAddress(superClassOffset, SCRIPT_GET_LOCK, addr.getSegment())); } bool Object::initBaseObject(SegManager *segMan, reg_t addr, bool doInitSuperClass) { @@ -187,7 +187,7 @@ bool Object::initBaseObject(SegManager *segMan, reg_t addr, bool doInitSuperClas // The effect is that a number of its method selectors may be // treated as variable selectors, causing unpredictable effects. - int objScript = segMan->getScript(_pos.segment)->getScriptNumber(); + int objScript = segMan->getScript(_pos.getSegment())->getScriptNumber(); // We have to do a little bit of work to get the name of the object // before any relocations are done. @@ -196,7 +196,7 @@ bool Object::initBaseObject(SegManager *segMan, reg_t addr, bool doInitSuperClas if (nameReg.isNull()) { name = ""; } else { - nameReg.segment = _pos.segment; + nameReg.setSegment(_pos.getSegment()); name = segMan->derefString(nameReg); if (!name) name = ""; diff --git a/engines/sci/engine/object.h b/engines/sci/engine/object.h index e8deafa8bd..1ea9ae449a 100644 --- a/engines/sci/engine/object.h +++ b/engines/sci/engine/object.h @@ -168,7 +168,7 @@ public: uint16 offset = (getSciVersion() < SCI_VERSION_1_1) ? _methodCount + 1 + i : i * 2 + 2; if (getSciVersion() == SCI_VERSION_3) offset--; - return make_reg(_pos.segment, _baseMethod[offset]); + return make_reg(_pos.getSegment(), _baseMethod[offset]); } Selector getFuncSelector(uint16 i) const { @@ -198,7 +198,7 @@ public: */ int locateVarSelector(SegManager *segMan, Selector slc) const; - bool isClass() const { return (getInfoSelector().offset & kInfoFlagClass); } + bool isClass() const { return (getInfoSelector().getOffset() & kInfoFlagClass); } const Object *getClass(SegManager *segMan) const; void markAsFreed() { _flags |= OBJECT_FLAG_FREED; } diff --git a/engines/sci/engine/savegame.cpp b/engines/sci/engine/savegame.cpp index cabe5f468a..ff3f19b53d 100644 --- a/engines/sci/engine/savegame.cpp +++ b/engines/sci/engine/savegame.cpp @@ -115,8 +115,9 @@ void syncArray(Common::Serializer &s, Common::Array &arr) { template<> void syncWithSerializer(Common::Serializer &s, reg_t &obj) { - s.syncAsUint16LE(obj.segment); - s.syncAsUint16LE(obj.offset); + // Segment and offset are accessed directly here + s.syncAsUint16LE(obj._segment); + s.syncAsUint16LE(obj._offset); } template<> @@ -202,7 +203,7 @@ void SegManager::saveLoadWithSerializer(Common::Serializer &s) { ObjMap objects = scr->getObjectMap(); for (ObjMap::iterator it = objects.begin(); it != objects.end(); ++it) - it->_value.syncBaseObject(scr->getBuf(it->_value.getPos().offset)); + it->_value.syncBaseObject(scr->getBuf(it->_value.getPos().getOffset())); } @@ -507,7 +508,7 @@ void Script::saveLoadWithSerializer(Common::Serializer &s) { Object tmp; for (uint i = 0; i < numObjs; ++i) { syncWithSerializer(s, tmp); - _objects[tmp.getPos().offset] = tmp; + _objects[tmp.getPos().getOffset()] = tmp; } } else { ObjMap::iterator it; @@ -816,7 +817,7 @@ bool gamestate_save(EngineState *s, Common::WriteStream *fh, const Common::Strin Resource *script0 = g_sci->getResMan()->findResource(ResourceId(kResourceTypeScript, 0), false); meta.script0Size = script0->size; - meta.gameObjectOffset = g_sci->getGameObject().offset; + meta.gameObjectOffset = g_sci->getGameObject().getOffset(); // Checking here again if (s->executionStackBase) { @@ -867,7 +868,7 @@ void gamestate_restore(EngineState *s, Common::SeekableReadStream *fh) { if (meta.gameObjectOffset > 0 && meta.script0Size > 0) { Resource *script0 = g_sci->getResMan()->findResource(ResourceId(kResourceTypeScript, 0), false); - if (script0->size != meta.script0Size || g_sci->getGameObject().offset != meta.gameObjectOffset) { + if (script0->size != meta.script0Size || g_sci->getGameObject().getOffset() != meta.gameObjectOffset) { //warning("This saved game was created with a different version of the game, unable to load it"); showScummVMDialog("This saved game was created with a different version of the game, unable to load it"); diff --git a/engines/sci/engine/script.cpp b/engines/sci/engine/script.cpp index d018872b43..897ceccad3 100644 --- a/engines/sci/engine/script.cpp +++ b/engines/sci/engine/script.cpp @@ -239,14 +239,14 @@ const Object *Script::getObject(uint16 offset) const { Object *Script::scriptObjInit(reg_t obj_pos, bool fullObjectInit) { if (getSciVersion() < SCI_VERSION_1_1 && fullObjectInit) - obj_pos.offset += 8; // magic offset (SCRIPT_OBJECT_MAGIC_OFFSET) + obj_pos.incOffset(8); // magic offset (SCRIPT_OBJECT_MAGIC_OFFSET) - if (obj_pos.offset >= _bufSize) + if (obj_pos.getOffset() >= _bufSize) error("Attempt to initialize object beyond end of script"); // Get the object at the specified position and init it. This will // automatically "allocate" space for it in the _objects map if necessary. - Object *obj = &_objects[obj_pos.offset]; + Object *obj = &_objects[obj_pos.getOffset()]; obj->init(_buf, obj_pos, fullObjectInit); return obj; @@ -269,9 +269,9 @@ static bool relocateBlock(Common::Array &block, int block_location, Segme error("Attempt to relocate odd variable #%d.5e (relative to %04x)\n", idx, block_location); return false; } - block[idx].segment = segment; // Perform relocation + block[idx].setSegment(segment); // Perform relocation if (getSciVersion() >= SCI_VERSION_1_1 && getSciVersion() <= SCI_VERSION_2_1) - block[idx].offset += scriptSize; + block[idx].incOffset(scriptSize); return true; } @@ -310,23 +310,23 @@ void Script::relocateSci0Sci21(reg_t block) { heapOffset = _scriptSize; } - if (block.offset >= (uint16)heapSize || - READ_SCI11ENDIAN_UINT16(heap + block.offset) * 2 + block.offset >= (uint16)heapSize) + if (block.getOffset() >= (uint16)heapSize || + READ_SCI11ENDIAN_UINT16(heap + block.getOffset()) * 2 + block.getOffset() >= (uint16)heapSize) error("Relocation block outside of script"); - int count = READ_SCI11ENDIAN_UINT16(heap + block.offset); + int count = READ_SCI11ENDIAN_UINT16(heap + block.getOffset()); int exportIndex = 0; int pos = 0; for (int i = 0; i < count; i++) { - pos = READ_SCI11ENDIAN_UINT16(heap + block.offset + 2 + (exportIndex * 2)) + heapOffset; + pos = READ_SCI11ENDIAN_UINT16(heap + block.getOffset() + 2 + (exportIndex * 2)) + heapOffset; // This occurs in SCI01/SCI1 games where usually one export value is // zero. It seems that in this situation, we should skip the export and // move to the next one, though the total count of valid exports remains // the same if (!pos) { exportIndex++; - pos = READ_SCI11ENDIAN_UINT16(heap + block.offset + 2 + (exportIndex * 2)) + heapOffset; + pos = READ_SCI11ENDIAN_UINT16(heap + block.getOffset() + 2 + (exportIndex * 2)) + heapOffset; if (!pos) error("Script::relocate(): Consecutive zero exports found"); } @@ -335,12 +335,12 @@ void Script::relocateSci0Sci21(reg_t block) { // We only relocate locals and objects here, and ignore relocation of // code blocks. In SCI1.1 and newer versions, only locals and objects // are relocated. - if (!relocateLocal(block.segment, pos)) { + if (!relocateLocal(block.getSegment(), pos)) { // Not a local? It's probably an object or code block. If it's an // object, relocate it. const ObjMap::iterator end = _objects.end(); for (ObjMap::iterator it = _objects.begin(); it != end; ++it) - if (it->_value.relocateSci0Sci21(block.segment, pos, _scriptSize)) + if (it->_value.relocateSci0Sci21(block.getSegment(), pos, _scriptSize)) break; } @@ -357,7 +357,7 @@ void Script::relocateSci3(reg_t block) { const byte *seeker = relocStart; while (seeker < _buf + _bufSize) { // TODO: Find out what UINT16 at (seeker + 8) means - it->_value.relocateSci3(block.segment, + it->_value.relocateSci3(block.getSegment(), READ_SCI11ENDIAN_UINT32(seeker), READ_SCI11ENDIAN_UINT32(seeker + 4), _scriptSize); @@ -466,7 +466,7 @@ bool Script::isValidOffset(uint16 offset) const { } SegmentRef Script::dereference(reg_t pointer) { - if (pointer.offset > _bufSize) { + if (pointer.getOffset() > _bufSize) { error("Script::dereference(): Attempt to dereference invalid pointer %04x:%04x into script segment (script size=%d)", PRINT_REG(pointer), (uint)_bufSize); return SegmentRef(); @@ -474,8 +474,8 @@ SegmentRef Script::dereference(reg_t pointer) { SegmentRef ret; ret.isRaw = true; - ret.maxSize = _bufSize - pointer.offset; - ret.raw = _buf + pointer.offset; + ret.maxSize = _bufSize - pointer.getOffset(); + ret.raw = _buf + pointer.getOffset(); return ret; } @@ -653,7 +653,7 @@ void Script::initializeObjectsSci11(SegManager *segMan, SegmentId segmentId) { // Copy base from species class, as we need its selector IDs obj->setSuperClassSelector( - segMan->getClassAddress(obj->getSuperClassSelector().offset, SCRIPT_GET_LOCK, 0)); + segMan->getClassAddress(obj->getSuperClassSelector().getOffset(), SCRIPT_GET_LOCK, 0)); // If object is instance, get -propDict- from class and set it for this // object. This is needed for ::isMemberOf() to work. @@ -686,7 +686,7 @@ void Script::initializeObjectsSci3(SegManager *segMan, SegmentId segmentId) { reg_t reg = make_reg(segmentId, seeker - _buf); Object *obj = scriptObjInit(reg); - obj->setSuperClassSelector(segMan->getClassAddress(obj->getSuperClassSelector().offset, SCRIPT_GET_LOCK, 0)); + obj->setSuperClassSelector(segMan->getClassAddress(obj->getSuperClassSelector().getOffset(), SCRIPT_GET_LOCK, 0)); seeker += READ_SCI11ENDIAN_UINT16(seeker + 2); } @@ -703,7 +703,7 @@ void Script::initializeObjects(SegManager *segMan, SegmentId segmentId) { } reg_t Script::findCanonicAddress(SegManager *segMan, reg_t addr) const { - addr.offset = 0; + addr.setOffset(0); return addr; } @@ -725,8 +725,8 @@ Common::Array Script::listAllDeallocatable(SegmentId segId) const { Common::Array Script::listAllOutgoingReferences(reg_t addr) const { Common::Array tmp; - if (addr.offset <= _bufSize && addr.offset >= -SCRIPT_OBJECT_MAGIC_OFFSET && offsetIsObject(addr.offset)) { - const Object *obj = getObject(addr.offset); + if (addr.getOffset() <= _bufSize && addr.getOffset() >= (uint)-SCRIPT_OBJECT_MAGIC_OFFSET && offsetIsObject(addr.getOffset())) { + const Object *obj = getObject(addr.getOffset()); if (obj) { // Note all local variables, if we have a local variable environment if (_localsSegment) diff --git a/engines/sci/engine/scriptdebug.cpp b/engines/sci/engine/scriptdebug.cpp index ef61b2e28a..6242dc4c93 100644 --- a/engines/sci/engine/scriptdebug.cpp +++ b/engines/sci/engine/scriptdebug.cpp @@ -69,17 +69,17 @@ const char *opcodeNames[] = { // Disassembles one command from the heap, returns address of next command or 0 if a ret was encountered. reg_t disassemble(EngineState *s, reg_t pos, bool printBWTag, bool printBytecode) { - SegmentObj *mobj = s->_segMan->getSegment(pos.segment, SEG_TYPE_SCRIPT); + SegmentObj *mobj = s->_segMan->getSegment(pos.getSegment(), SEG_TYPE_SCRIPT); Script *script_entity = NULL; const byte *scr; - int scr_size; - reg_t retval = make_reg(pos.segment, pos.offset + 1); + uint scr_size; + reg_t retval = make_reg(pos.getSegment(), pos.getOffset() + 1); uint16 param_value = 0xffff; // Suppress GCC warning by setting default value, chose value as invalid to getKernelName etc. - int i = 0; + uint i = 0; Kernel *kernel = g_sci->getKernel(); if (!mobj) { - warning("Disassembly failed: Segment %04x non-existant or not a script", pos.segment); + warning("Disassembly failed: Segment %04x non-existant or not a script", pos.getSegment()); return retval; } else script_entity = (Script *)mobj; @@ -87,14 +87,14 @@ reg_t disassemble(EngineState *s, reg_t pos, bool printBWTag, bool printBytecode scr = script_entity->getBuf(); scr_size = script_entity->getBufSize(); - if (pos.offset >= scr_size) { + if (pos.getOffset() >= scr_size) { warning("Trying to disassemble beyond end of script"); return NULL_REG; } int16 opparams[4]; byte opsize; - int bytecount = readPMachineInstruction(scr + pos.offset, opsize, opparams); + uint bytecount = readPMachineInstruction(scr + pos.getOffset(), opsize, opparams); const byte opcode = opsize >> 1; opsize &= 1; // byte if true, word if false @@ -102,13 +102,13 @@ reg_t disassemble(EngineState *s, reg_t pos, bool printBWTag, bool printBytecode debugN("%04x:%04x: ", PRINT_REG(pos)); if (printBytecode) { - if (pos.offset + bytecount > scr_size) { + if (pos.getOffset() + bytecount > scr_size) { warning("Operation arguments extend beyond end of script"); return retval; } for (i = 0; i < bytecount; i++) - debugN("%02x ", scr[pos.offset + i]); + debugN("%02x ", scr[pos.getOffset() + i]); for (i = bytecount; i < 5; i++) debugN(" "); @@ -130,16 +130,16 @@ reg_t disassemble(EngineState *s, reg_t pos, bool printBWTag, bool printBytecode case Script_SByte: case Script_Byte: - param_value = scr[retval.offset]; - debugN(" %02x", scr[retval.offset]); - retval.offset++; + param_value = scr[retval.getOffset()]; + debugN(" %02x", scr[retval.getOffset()]); + retval.incOffset(1); break; case Script_Word: case Script_SWord: - param_value = READ_SCI11ENDIAN_UINT16(&scr[retval.offset]); - debugN(" %04x", READ_SCI11ENDIAN_UINT16(&scr[retval.offset])); - retval.offset += 2; + param_value = READ_SCI11ENDIAN_UINT16(&scr[retval.getOffset()]); + debugN(" %04x", READ_SCI11ENDIAN_UINT16(&scr[retval.getOffset()])); + retval.incOffset(2); break; case Script_SVariable: @@ -149,11 +149,12 @@ reg_t disassemble(EngineState *s, reg_t pos, bool printBWTag, bool printBytecode case Script_Local: case Script_Temp: case Script_Param: - if (opsize) - param_value = scr[retval.offset++]; - else { - param_value = READ_SCI11ENDIAN_UINT16(&scr[retval.offset]); - retval.offset += 2; + if (opsize) { + param_value = scr[retval.getOffset()]; + retval.incOffset(1); + } else { + param_value = READ_SCI11ENDIAN_UINT16(&scr[retval.getOffset()]); + retval.incOffset(2); } if (opcode == op_callk) @@ -166,24 +167,26 @@ reg_t disassemble(EngineState *s, reg_t pos, bool printBWTag, bool printBytecode break; case Script_Offset: - if (opsize) - param_value = scr[retval.offset++]; - else { - param_value = READ_SCI11ENDIAN_UINT16(&scr[retval.offset]); - retval.offset += 2; + if (opsize) { + param_value = scr[retval.getOffset()]; + retval.incOffset(1); + } else { + param_value = READ_SCI11ENDIAN_UINT16(&scr[retval.getOffset()]); + retval.incOffset(2); } debugN(opsize ? " %02x" : " %04x", param_value); break; case Script_SRelative: if (opsize) { - int8 offset = (int8)scr[retval.offset++]; - debugN(" %02x [%04x]", 0xff & offset, 0xffff & (retval.offset + offset)); + int8 offset = (int8)scr[retval.getOffset()]; + retval.incOffset(1); + debugN(" %02x [%04x]", 0xff & offset, 0xffff & (retval.getOffset() + offset)); } else { - int16 offset = (int16)READ_SCI11ENDIAN_UINT16(&scr[retval.offset]); - retval.offset += 2; - debugN(" %04x [%04x]", 0xffff & offset, 0xffff & (retval.offset + offset)); + int16 offset = (int16)READ_SCI11ENDIAN_UINT16(&scr[retval.getOffset()]); + retval.incOffset(2); + debugN(" %04x [%04x]", 0xffff & offset, 0xffff & (retval.getOffset() + offset)); } break; @@ -216,8 +219,8 @@ reg_t disassemble(EngineState *s, reg_t pos, bool printBWTag, bool printBytecode if (pos == s->xs->addr.pc) { // Extra information if debugging the current opcode if (opcode == op_callk) { - int stackframe = (scr[pos.offset + 2] >> 1) + (s->r_rest); - int argc = ((s->xs->sp)[- stackframe - 1]).offset; + int stackframe = (scr[pos.getOffset() + 2] >> 1) + (s->r_rest); + int argc = ((s->xs->sp)[- stackframe - 1]).getOffset(); bool oldScriptHeader = (getSciVersion() == SCI_VERSION_0_EARLY); if (!oldScriptHeader) @@ -233,13 +236,13 @@ reg_t disassemble(EngineState *s, reg_t pos, bool printBWTag, bool printBytecode debugN(")\n"); } else if ((opcode == op_send) || (opcode == op_self)) { int restmod = s->r_rest; - int stackframe = (scr[pos.offset + 1] >> 1) + restmod; + int stackframe = (scr[pos.getOffset() + 1] >> 1) + restmod; reg_t *sb = s->xs->sp; uint16 selector; reg_t fun_ref; while (stackframe > 0) { - int argc = sb[- stackframe + 1].offset; + int argc = sb[- stackframe + 1].getOffset(); const char *name = NULL; reg_t called_obj_addr = s->xs->objp; @@ -248,7 +251,7 @@ reg_t disassemble(EngineState *s, reg_t pos, bool printBWTag, bool printBytecode else if (opcode == op_self) called_obj_addr = s->xs->objp; - selector = sb[- stackframe].offset; + selector = sb[- stackframe].getOffset(); name = s->_segMan->getObjectName(called_obj_addr); @@ -290,20 +293,20 @@ reg_t disassemble(EngineState *s, reg_t pos, bool printBWTag, bool printBytecode } bool isJumpOpcode(EngineState *s, reg_t pos, reg_t& jumpTarget) { - SegmentObj *mobj = s->_segMan->getSegment(pos.segment, SEG_TYPE_SCRIPT); + SegmentObj *mobj = s->_segMan->getSegment(pos.getSegment(), SEG_TYPE_SCRIPT); if (!mobj) return false; Script *script_entity = (Script *)mobj; const byte *scr = script_entity->getBuf(); - int scr_size = script_entity->getScriptSize(); + uint scr_size = script_entity->getScriptSize(); - if (pos.offset >= scr_size) + if (pos.getOffset() >= scr_size) return false; int16 opparams[4]; byte opsize; - int bytecount = readPMachineInstruction(scr + pos.offset, opsize, opparams); + int bytecount = readPMachineInstruction(scr + pos.getOffset(), opsize, opparams); const byte opcode = opsize >> 1; switch (opcode) { @@ -313,7 +316,7 @@ bool isJumpOpcode(EngineState *s, reg_t pos, reg_t& jumpTarget) { { reg_t jmpTarget = pos + bytecount + opparams[0]; // QFG2 has invalid jumps outside the script buffer in script 260 - if (jmpTarget.offset >= scr_size) + if (jmpTarget.getOffset() >= scr_size) return false; jumpTarget = jmpTarget; } @@ -336,16 +339,16 @@ void SciEngine::scriptDebug() { if (_debugState.seeking != kDebugSeekNothing) { const reg_t pc = s->xs->addr.pc; - SegmentObj *mobj = s->_segMan->getSegment(pc.segment, SEG_TYPE_SCRIPT); + SegmentObj *mobj = s->_segMan->getSegment(pc.getSegment(), SEG_TYPE_SCRIPT); if (mobj) { Script *scr = (Script *)mobj; const byte *code_buf = scr->getBuf(); - int code_buf_size = scr->getBufSize(); - int opcode = pc.offset >= code_buf_size ? 0 : code_buf[pc.offset]; + uint16 code_buf_size = scr->getBufSize(); + int opcode = pc.getOffset() >= code_buf_size ? 0 : code_buf[pc.getOffset()]; int op = opcode >> 1; - int paramb1 = pc.offset + 1 >= code_buf_size ? 0 : code_buf[pc.offset + 1]; - int paramf1 = (opcode & 1) ? paramb1 : (pc.offset + 2 >= code_buf_size ? 0 : (int16)READ_SCI11ENDIAN_UINT16(code_buf + pc.offset + 1)); + int paramb1 = pc.getOffset() + 1 >= code_buf_size ? 0 : code_buf[pc.getOffset() + 1]; + int paramf1 = (opcode & 1) ? paramb1 : (pc.getOffset() + 2 >= code_buf_size ? 0 : (int16)READ_SCI11ENDIAN_UINT16(code_buf + pc.getOffset() + 1)); switch (_debugState.seeking) { case kDebugSeekSpecialCallk: @@ -714,7 +717,7 @@ void logKernelCall(const KernelFunction *kernelCall, const KernelSubFunction *ke else if (regType & SIG_IS_INVALID) debugN("INVALID"); else if (regType & SIG_TYPE_INTEGER) - debugN("%d", argv[parmNr].offset); + debugN("%d", argv[parmNr].getOffset()); else { debugN("%04x:%04x", PRINT_REG(argv[parmNr])); switch (regType) { @@ -723,12 +726,12 @@ void logKernelCall(const KernelFunction *kernelCall, const KernelSubFunction *ke break; case SIG_TYPE_REFERENCE: { - SegmentObj *mobj = s->_segMan->getSegmentObj(argv[parmNr].segment); + SegmentObj *mobj = s->_segMan->getSegmentObj(argv[parmNr].getSegment()); switch (mobj->getType()) { case SEG_TYPE_HUNK: { HunkTable *ht = (HunkTable *)mobj; - int index = argv[parmNr].offset; + int index = argv[parmNr].getOffset(); if (ht->isValidEntry(index)) { // NOTE: This ", deleted" isn't as useful as it could // be because it prints the status _after_ the kernel @@ -765,7 +768,7 @@ void logKernelCall(const KernelFunction *kernelCall, const KernelSubFunction *ke if (result.isPointer()) debugN(" = %04x:%04x\n", PRINT_REG(result)); else - debugN(" = %d\n", result.offset); + debugN(" = %d\n", result.getOffset()); } } // End of namespace Sci diff --git a/engines/sci/engine/seg_manager.cpp b/engines/sci/engine/seg_manager.cpp index ac02022ee7..a6c145979f 100644 --- a/engines/sci/engine/seg_manager.cpp +++ b/engines/sci/engine/seg_manager.cpp @@ -81,7 +81,7 @@ void SegManager::initSysStrings() { if (getSciVersion() <= SCI_VERSION_1_1) { // We need to allocate system strings in one segment, for compatibility reasons allocDynmem(512, "system strings", &_saveDirPtr); - _parserPtr = make_reg(_saveDirPtr.segment, _saveDirPtr.offset + 256); + _parserPtr = make_reg(_saveDirPtr.getSegment(), _saveDirPtr.getOffset() + 256); #ifdef ENABLE_SCI32 } else { SciString *saveDirString = allocateString(&_saveDirPtr); @@ -163,7 +163,7 @@ bool SegManager::isHeapObject(reg_t pos) const { const Object *obj = getObject(pos); if (obj == NULL || (obj && obj->isFreed())) return false; - Script *scr = getScriptIfLoaded(pos.segment); + Script *scr = getScriptIfLoaded(pos.getSegment()); return !(scr && scr->isMarkedAsDeleted()); } @@ -214,21 +214,21 @@ SegmentObj *SegManager::getSegment(SegmentId seg, SegmentType type) const { } Object *SegManager::getObject(reg_t pos) const { - SegmentObj *mobj = getSegmentObj(pos.segment); + SegmentObj *mobj = getSegmentObj(pos.getSegment()); Object *obj = NULL; if (mobj != NULL) { if (mobj->getType() == SEG_TYPE_CLONES) { CloneTable *ct = (CloneTable *)mobj; - if (ct->isValidEntry(pos.offset)) - obj = &(ct->_table[pos.offset]); + if (ct->isValidEntry(pos.getOffset())) + obj = &(ct->_table[pos.getOffset()]); else warning("getObject(): Trying to get an invalid object"); } else if (mobj->getType() == SEG_TYPE_SCRIPT) { Script *scr = (Script *)mobj; - if (pos.offset <= scr->getBufSize() && pos.offset >= -SCRIPT_OBJECT_MAGIC_OFFSET - && scr->offsetIsObject(pos.offset)) { - obj = scr->getObject(pos.offset); + if (pos.getOffset() <= scr->getBufSize() && pos.getOffset() >= (uint)-SCRIPT_OBJECT_MAGIC_OFFSET + && scr->offsetIsObject(pos.getOffset())) { + obj = scr->getObject(pos.getOffset()); } } } @@ -246,7 +246,7 @@ const char *SegManager::getObjectName(reg_t pos) { return ""; const char *name = 0; - if (nameReg.segment) + if (nameReg.getSegment()) name = derefString(nameReg); if (!name) return ""; @@ -272,7 +272,7 @@ reg_t SegManager::findObjectByName(const Common::String &name, int index) { const Script *scr = (const Script *)mobj; const ObjMap &objects = scr->getObjectMap(); for (ObjMap::const_iterator it = objects.begin(); it != objects.end(); ++it) { - objpos.offset = it->_value.getPos().offset; + objpos.setOffset(it->_value.getPos().getOffset()); if (name == getObjectName(objpos)) result.push_back(objpos); } @@ -283,7 +283,7 @@ reg_t SegManager::findObjectByName(const Common::String &name, int index) { if (!ct->isValidEntry(idx)) continue; - objpos.offset = idx; + objpos.setOffset(idx); if (name == getObjectName(objpos)) result.push_back(objpos); } @@ -364,14 +364,14 @@ void SegManager::freeHunkEntry(reg_t addr) { return; } - HunkTable *ht = (HunkTable *)getSegment(addr.segment, SEG_TYPE_HUNK); + HunkTable *ht = (HunkTable *)getSegment(addr.getSegment(), SEG_TYPE_HUNK); if (!ht) { warning("Attempt to free Hunk from address %04x:%04x: Invalid segment type", PRINT_REG(addr)); return; } - ht->freeEntryContents(addr.offset); + ht->freeEntryContents(addr.getOffset()); } reg_t SegManager::allocateHunkEntry(const char *hunk_type, int size) { @@ -398,14 +398,14 @@ reg_t SegManager::allocateHunkEntry(const char *hunk_type, int size) { } byte *SegManager::getHunkPointer(reg_t addr) { - HunkTable *ht = (HunkTable *)getSegment(addr.segment, SEG_TYPE_HUNK); + HunkTable *ht = (HunkTable *)getSegment(addr.getSegment(), SEG_TYPE_HUNK); - if (!ht || !ht->isValidEntry(addr.offset)) { + if (!ht || !ht->isValidEntry(addr.getOffset())) { // Valid SCI behavior, e.g. when loading/quitting return NULL; } - return (byte *)ht->_table[addr.offset].mem; + return (byte *)ht->_table[addr.getOffset()].mem; } Clone *SegManager::allocateClone(reg_t *addr) { @@ -462,35 +462,35 @@ reg_t SegManager::newNode(reg_t value, reg_t key) { } List *SegManager::lookupList(reg_t addr) { - if (getSegmentType(addr.segment) != SEG_TYPE_LISTS) { + if (getSegmentType(addr.getSegment()) != SEG_TYPE_LISTS) { error("Attempt to use non-list %04x:%04x as list", PRINT_REG(addr)); return NULL; } - ListTable *lt = (ListTable *)_heap[addr.segment]; + ListTable *lt = (ListTable *)_heap[addr.getSegment()]; - if (!lt->isValidEntry(addr.offset)) { + if (!lt->isValidEntry(addr.getOffset())) { error("Attempt to use non-list %04x:%04x as list", PRINT_REG(addr)); return NULL; } - return &(lt->_table[addr.offset]); + return &(lt->_table[addr.getOffset()]); } Node *SegManager::lookupNode(reg_t addr, bool stopOnDiscarded) { if (addr.isNull()) return NULL; // Non-error null - SegmentType type = getSegmentType(addr.segment); + SegmentType type = getSegmentType(addr.getSegment()); if (type != SEG_TYPE_NODES) { error("Attempt to use non-node %04x:%04x (type %d) as list node", PRINT_REG(addr), type); return NULL; } - NodeTable *nt = (NodeTable *)_heap[addr.segment]; + NodeTable *nt = (NodeTable *)_heap[addr.getSegment()]; - if (!nt->isValidEntry(addr.offset)) { + if (!nt->isValidEntry(addr.getOffset())) { if (!stopOnDiscarded) return NULL; @@ -498,19 +498,19 @@ Node *SegManager::lookupNode(reg_t addr, bool stopOnDiscarded) { return NULL; } - return &(nt->_table[addr.offset]); + return &(nt->_table[addr.getOffset()]); } SegmentRef SegManager::dereference(reg_t pointer) { SegmentRef ret; - if (!pointer.segment || (pointer.segment >= _heap.size()) || !_heap[pointer.segment]) { + if (!pointer.getSegment() || (pointer.getSegment() >= _heap.size()) || !_heap[pointer.getSegment()]) { // This occurs in KQ5CD when interacting with certain objects warning("SegManager::dereference(): Attempt to dereference invalid pointer %04x:%04x", PRINT_REG(pointer)); return ret; /* Invalid */ } - SegmentObj *mobj = _heap[pointer.segment]; + SegmentObj *mobj = _heap[pointer.getSegment()]; return mobj->dereference(pointer); } @@ -522,7 +522,7 @@ static void *derefPtr(SegManager *segMan, reg_t pointer, int entries, bool wantR if (ret.isRaw != wantRaw) { warning("Dereferencing pointer %04x:%04x (type %d) which is %s, but expected %s", PRINT_REG(pointer), - segMan->getSegmentType(pointer.segment), + segMan->getSegmentType(pointer.getSegment()), ret.isRaw ? "raw" : "not raw", wantRaw ? "raw" : "not raw"); } @@ -565,15 +565,15 @@ static inline char getChar(const SegmentRef &ref, uint offset) { // segment 0xFFFF means that the scripts are using uninitialized temp-variable space // we can safely ignore this, if it isn't one of the first 2 chars. // foreign lsl3 uses kFileIO(readraw) and then immediately uses kReadNumber right at the start - if (val.segment != 0) - if (!((val.segment == 0xFFFF) && (offset > 1))) + if (val.getSegment() != 0) + if (!((val.getSegment() == 0xFFFF) && (offset > 1))) warning("Attempt to read character from non-raw data"); bool oddOffset = offset & 1; if (g_sci->isBE()) oddOffset = !oddOffset; - return (oddOffset ? val.offset >> 8 : val.offset & 0xff); + return (oddOffset ? val.getOffset() >> 8 : val.getOffset() & 0xff); } static inline void setChar(const SegmentRef &ref, uint offset, byte value) { @@ -582,16 +582,16 @@ static inline void setChar(const SegmentRef &ref, uint offset, byte value) { reg_t *val = ref.reg + offset / 2; - val->segment = 0; + val->setSegment(0); bool oddOffset = offset & 1; if (g_sci->isBE()) oddOffset = !oddOffset; if (oddOffset) - val->offset = (val->offset & 0x00ff) | (value << 8); + val->setOffset((val->getOffset() & 0x00ff) | (value << 8)); else - val->offset = (val->offset & 0xff00) | value; + val->setOffset((val->getOffset() & 0xff00) | value); } // TODO: memcpy, strcpy and strncpy could maybe be folded into a single function @@ -829,10 +829,11 @@ byte *SegManager::allocDynmem(int size, const char *descr, reg_t *addr) { } bool SegManager::freeDynmem(reg_t addr) { - if (addr.segment < 1 || addr.segment >= _heap.size() || !_heap[addr.segment] || _heap[addr.segment]->getType() != SEG_TYPE_DYNMEM) + if (addr.getSegment() < 1 || addr.getSegment() >= _heap.size() || + !_heap[addr.getSegment()] || _heap[addr.getSegment()]->getType() != SEG_TYPE_DYNMEM) return false; // error - deallocate(addr.segment); + deallocate(addr.getSegment()); return true; // OK } @@ -854,28 +855,28 @@ SciArray *SegManager::allocateArray(reg_t *addr) { } SciArray *SegManager::lookupArray(reg_t addr) { - if (_heap[addr.segment]->getType() != SEG_TYPE_ARRAY) + if (_heap[addr.getSegment()]->getType() != SEG_TYPE_ARRAY) error("Attempt to use non-array %04x:%04x as array", PRINT_REG(addr)); - ArrayTable *arrayTable = (ArrayTable *)_heap[addr.segment]; + ArrayTable *arrayTable = (ArrayTable *)_heap[addr.getSegment()]; - if (!arrayTable->isValidEntry(addr.offset)) + if (!arrayTable->isValidEntry(addr.getOffset())) error("Attempt to use non-array %04x:%04x as array", PRINT_REG(addr)); - return &(arrayTable->_table[addr.offset]); + return &(arrayTable->_table[addr.getOffset()]); } void SegManager::freeArray(reg_t addr) { - if (_heap[addr.segment]->getType() != SEG_TYPE_ARRAY) + if (_heap[addr.getSegment()]->getType() != SEG_TYPE_ARRAY) error("Attempt to use non-array %04x:%04x as array", PRINT_REG(addr)); - ArrayTable *arrayTable = (ArrayTable *)_heap[addr.segment]; + ArrayTable *arrayTable = (ArrayTable *)_heap[addr.getSegment()]; - if (!arrayTable->isValidEntry(addr.offset)) + if (!arrayTable->isValidEntry(addr.getOffset())) error("Attempt to use non-array %04x:%04x as array", PRINT_REG(addr)); - arrayTable->_table[addr.offset].destroy(); - arrayTable->freeEntry(addr.offset); + arrayTable->_table[addr.getOffset()].destroy(); + arrayTable->freeEntry(addr.getOffset()); } SciString *SegManager::allocateString(reg_t *addr) { @@ -894,28 +895,28 @@ SciString *SegManager::allocateString(reg_t *addr) { } SciString *SegManager::lookupString(reg_t addr) { - if (_heap[addr.segment]->getType() != SEG_TYPE_STRING) + if (_heap[addr.getSegment()]->getType() != SEG_TYPE_STRING) error("lookupString: Attempt to use non-string %04x:%04x as string", PRINT_REG(addr)); - StringTable *stringTable = (StringTable *)_heap[addr.segment]; + StringTable *stringTable = (StringTable *)_heap[addr.getSegment()]; - if (!stringTable->isValidEntry(addr.offset)) + if (!stringTable->isValidEntry(addr.getOffset())) error("lookupString: Attempt to use non-string %04x:%04x as string", PRINT_REG(addr)); - return &(stringTable->_table[addr.offset]); + return &(stringTable->_table[addr.getOffset()]); } void SegManager::freeString(reg_t addr) { - if (_heap[addr.segment]->getType() != SEG_TYPE_STRING) + if (_heap[addr.getSegment()]->getType() != SEG_TYPE_STRING) error("freeString: Attempt to use non-string %04x:%04x as string", PRINT_REG(addr)); - StringTable *stringTable = (StringTable *)_heap[addr.segment]; + StringTable *stringTable = (StringTable *)_heap[addr.getSegment()]; - if (!stringTable->isValidEntry(addr.offset)) + if (!stringTable->isValidEntry(addr.getOffset())) error("freeString: Attempt to use non-string %04x:%04x as string", PRINT_REG(addr)); - stringTable->_table[addr.offset].destroy(); - stringTable->freeEntry(addr.offset); + stringTable->_table[addr.getOffset()].destroy(); + stringTable->freeEntry(addr.getOffset()); } #endif @@ -948,16 +949,16 @@ reg_t SegManager::getClassAddress(int classnr, ScriptLoadType lock, uint16 calle return NULL_REG; } else { Class *the_class = &_classTable[classnr]; - if (!the_class->reg.segment) { + if (!the_class->reg.getSegment()) { getScriptSegment(the_class->script, lock); - if (!the_class->reg.segment) { + if (!the_class->reg.getSegment()) { error("[VM] Trying to instantiate class %x by instantiating script 0x%x (%03d) failed;", classnr, the_class->script, the_class->script); return NULL_REG; } } else - if (callerSegment != the_class->reg.segment) - getScript(the_class->reg.segment)->incrementLockers(); + if (callerSegment != the_class->reg.getSegment()) + getScript(the_class->reg.getSegment())->incrementLockers(); return the_class->reg; } @@ -1002,7 +1003,7 @@ void SegManager::uninstantiateScript(int script_nr) { // Free all classtable references to this script for (uint i = 0; i < classTableSize(); i++) - if (getClass(i).reg.segment == segmentId) + if (getClass(i).reg.getSegment() == segmentId) setClassOffset(i, NULL_REG); if (getSciVersion() < SCI_VERSION_1_1) @@ -1026,18 +1027,18 @@ void SegManager::uninstantiateScriptSci0(int script_nr) { // Make a pass over the object in order to uninstantiate all superclasses do { - reg.offset += objLength; // Step over the last checked object + reg.incOffset(objLength); // Step over the last checked object - objType = READ_SCI11ENDIAN_UINT16(scr->getBuf(reg.offset)); + objType = READ_SCI11ENDIAN_UINT16(scr->getBuf(reg.getOffset())); if (!objType) break; - objLength = READ_SCI11ENDIAN_UINT16(scr->getBuf(reg.offset + 2)); + objLength = READ_SCI11ENDIAN_UINT16(scr->getBuf(reg.getOffset() + 2)); - reg.offset += 4; // Step over header + reg.incOffset(4); // Step over header if ((objType == SCI_OBJ_OBJECT) || (objType == SCI_OBJ_CLASS)) { // object or class? - reg.offset += 8; // magic offset (SCRIPT_OBJECT_MAGIC_OFFSET) - int16 superclass = READ_SCI11ENDIAN_UINT16(scr->getBuf(reg.offset + 2)); + reg.incOffset(8); // magic offset (SCRIPT_OBJECT_MAGIC_OFFSET) + int16 superclass = READ_SCI11ENDIAN_UINT16(scr->getBuf(reg.getOffset() + 2)); if (superclass >= 0) { int superclass_script = getClass(superclass).script; @@ -1051,10 +1052,10 @@ void SegManager::uninstantiateScriptSci0(int script_nr) { // Recurse to assure that the superclass lockers number gets decreased } - reg.offset += SCRIPT_OBJECT_MAGIC_OFFSET; + reg.incOffset(SCRIPT_OBJECT_MAGIC_OFFSET); } // if object or class - reg.offset -= 4; // Step back on header + reg.incOffset(-4); // Step back on header } while (objType != 0); } diff --git a/engines/sci/engine/segment.cpp b/engines/sci/engine/segment.cpp index 36b7d92c07..a7f147a15a 100644 --- a/engines/sci/engine/segment.cpp +++ b/engines/sci/engine/segment.cpp @@ -93,11 +93,11 @@ Common::Array CloneTable::listAllOutgoingReferences(reg_t addr) const { Common::Array tmp; // assert(addr.segment == _segId); - if (!isValidEntry(addr.offset)) { + if (!isValidEntry(addr.getOffset())) { error("Unexpected request for outgoing references from clone at %04x:%04x", PRINT_REG(addr)); } - const Clone *clone = &(_table[addr.offset]); + const Clone *clone = &(_table[addr.getOffset()]); // Emit all member variables (including references to the 'super' delegate) for (uint i = 0; i < clone->getVarCount(); i++) @@ -112,7 +112,7 @@ Common::Array CloneTable::listAllOutgoingReferences(reg_t addr) const { void CloneTable::freeAtAddress(SegManager *segMan, reg_t addr) { #ifdef GC_DEBUG - Object *victim_obj = &(_table[addr.offset]); + Object *victim_obj = &(_table[addr.getOffset()]); if (!(victim_obj->_flags & OBJECT_FLAG_FREED)) warning("[GC] Clone %04x:%04x not reachable and not freed (freeing now)", PRINT_REG(addr)); @@ -124,7 +124,7 @@ void CloneTable::freeAtAddress(SegManager *segMan, reg_t addr) { #endif #endif - freeEntry(addr.offset); + freeEntry(addr.getOffset()); } @@ -133,15 +133,15 @@ void CloneTable::freeAtAddress(SegManager *segMan, reg_t addr) { SegmentRef LocalVariables::dereference(reg_t pointer) { SegmentRef ret; ret.isRaw = false; // reg_t based data! - ret.maxSize = (_locals.size() - pointer.offset / 2) * 2; + ret.maxSize = (_locals.size() - pointer.getOffset() / 2) * 2; - if (pointer.offset & 1) { + if (pointer.getOffset() & 1) { ret.maxSize -= 1; ret.skipByte = true; } if (ret.maxSize > 0) { - ret.reg = &_locals[pointer.offset / 2]; + ret.reg = &_locals[pointer.getOffset() / 2]; } else { if ((g_sci->getEngineState()->currentRoomNumber() == 160 || g_sci->getEngineState()->currentRoomNumber() == 220) @@ -181,14 +181,14 @@ Common::Array LocalVariables::listAllOutgoingReferences(reg_t addr) const SegmentRef DataStack::dereference(reg_t pointer) { SegmentRef ret; ret.isRaw = false; // reg_t based data! - ret.maxSize = (_capacity - pointer.offset / 2) * 2; + ret.maxSize = (_capacity - pointer.getOffset() / 2) * 2; - if (pointer.offset & 1) { + if (pointer.getOffset() & 1) { ret.maxSize -= 1; ret.skipByte = true; } - ret.reg = &_entries[pointer.offset / 2]; + ret.reg = &_entries[pointer.getOffset() / 2]; return ret; } @@ -204,11 +204,11 @@ Common::Array DataStack::listAllOutgoingReferences(reg_t object) const { Common::Array ListTable::listAllOutgoingReferences(reg_t addr) const { Common::Array tmp; - if (!isValidEntry(addr.offset)) { + if (!isValidEntry(addr.getOffset())) { error("Invalid list referenced for outgoing references: %04x:%04x", PRINT_REG(addr)); } - const List *list = &(_table[addr.offset]); + const List *list = &(_table[addr.getOffset()]); tmp.push_back(list->first); tmp.push_back(list->last); @@ -222,10 +222,10 @@ Common::Array ListTable::listAllOutgoingReferences(reg_t addr) const { Common::Array NodeTable::listAllOutgoingReferences(reg_t addr) const { Common::Array tmp; - if (!isValidEntry(addr.offset)) { + if (!isValidEntry(addr.getOffset())) { error("Invalid node referenced for outgoing references: %04x:%04x", PRINT_REG(addr)); } - const Node *node = &(_table[addr.offset]); + const Node *node = &(_table[addr.getOffset()]); // We need all four here. Can't just stick with 'pred' OR 'succ' because node operations allow us // to walk around from any given node @@ -242,8 +242,8 @@ Common::Array NodeTable::listAllOutgoingReferences(reg_t addr) const { SegmentRef DynMem::dereference(reg_t pointer) { SegmentRef ret; ret.isRaw = true; - ret.maxSize = _size - pointer.offset; - ret.raw = _buf + pointer.offset; + ret.maxSize = _size - pointer.getOffset(); + ret.raw = _buf + pointer.getOffset(); return ret; } @@ -252,27 +252,27 @@ SegmentRef DynMem::dereference(reg_t pointer) { SegmentRef ArrayTable::dereference(reg_t pointer) { SegmentRef ret; ret.isRaw = false; - ret.maxSize = _table[pointer.offset].getSize() * 2; - ret.reg = _table[pointer.offset].getRawData(); + ret.maxSize = _table[pointer.getOffset()].getSize() * 2; + ret.reg = _table[pointer.getOffset()].getRawData(); return ret; } void ArrayTable::freeAtAddress(SegManager *segMan, reg_t sub_addr) { - _table[sub_addr.offset].destroy(); - freeEntry(sub_addr.offset); + _table[sub_addr.getOffset()].destroy(); + freeEntry(sub_addr.getOffset()); } Common::Array ArrayTable::listAllOutgoingReferences(reg_t addr) const { Common::Array tmp; - if (!isValidEntry(addr.offset)) { + if (!isValidEntry(addr.getOffset())) { error("Invalid array referenced for outgoing references: %04x:%04x", PRINT_REG(addr)); } - const SciArray *array = &(_table[addr.offset]); + const SciArray *array = &(_table[addr.getOffset()]); for (uint32 i = 0; i < array->getSize(); i++) { reg_t value = array->getValue(i); - if (value.segment != 0) + if (value.getSegment() != 0) tmp.push_back(value); } @@ -305,8 +305,8 @@ void SciString::fromString(const Common::String &string) { SegmentRef StringTable::dereference(reg_t pointer) { SegmentRef ret; ret.isRaw = true; - ret.maxSize = _table[pointer.offset].getSize(); - ret.raw = (byte *)_table[pointer.offset].getRawData(); + ret.maxSize = _table[pointer.getOffset()].getSize(); + ret.raw = (byte *)_table[pointer.getOffset()].getRawData(); return ret; } diff --git a/engines/sci/engine/segment.h b/engines/sci/engine/segment.h index 54cf7b98af..0d54b651e1 100644 --- a/engines/sci/engine/segment.h +++ b/engines/sci/engine/segment.h @@ -175,7 +175,7 @@ public: } virtual SegmentRef dereference(reg_t pointer); virtual reg_t findCanonicAddress(SegManager *segMan, reg_t addr) const { - return make_reg(addr.segment, 0); + return make_reg(addr.getSegment(), 0); } virtual Common::Array listAllOutgoingReferences(reg_t object) const; @@ -291,7 +291,7 @@ struct NodeTable : public SegmentObjTable { NodeTable() : SegmentObjTable(SEG_TYPE_NODES) {} virtual void freeAtAddress(SegManager *segMan, reg_t sub_addr) { - freeEntry(sub_addr.offset); + freeEntry(sub_addr.getOffset()); } virtual Common::Array listAllOutgoingReferences(reg_t object) const; @@ -304,7 +304,7 @@ struct ListTable : public SegmentObjTable { ListTable() : SegmentObjTable(SEG_TYPE_LISTS) {} virtual void freeAtAddress(SegManager *segMan, reg_t sub_addr) { - freeEntry(sub_addr.offset); + freeEntry(sub_addr.getOffset()); } virtual Common::Array listAllOutgoingReferences(reg_t object) const; @@ -333,7 +333,7 @@ struct HunkTable : public SegmentObjTable { } virtual void freeAtAddress(SegManager *segMan, reg_t sub_addr) { - freeEntry(sub_addr.offset); + freeEntry(sub_addr.getOffset()); } virtual void saveLoadWithSerializer(Common::Serializer &ser); @@ -358,7 +358,7 @@ public: } virtual SegmentRef dereference(reg_t pointer); virtual reg_t findCanonicAddress(SegManager *segMan, reg_t addr) const { - return make_reg(addr.segment, 0); + return make_reg(addr.getSegment(), 0); } virtual Common::Array listAllDeallocatable(SegmentId segId) const { const reg_t r = make_reg(segId, 0); @@ -502,8 +502,8 @@ struct StringTable : public SegmentObjTable { StringTable() : SegmentObjTable(SEG_TYPE_STRING) {} virtual void freeAtAddress(SegManager *segMan, reg_t sub_addr) { - _table[sub_addr.offset].destroy(); - freeEntry(sub_addr.offset); + _table[sub_addr.getOffset()].destroy(); + freeEntry(sub_addr.getOffset()); } void saveLoadWithSerializer(Common::Serializer &ser); diff --git a/engines/sci/engine/selector.h b/engines/sci/engine/selector.h index 2308a6c387..5d3d0752ac 100644 --- a/engines/sci/engine/selector.h +++ b/engines/sci/engine/selector.h @@ -171,7 +171,7 @@ struct SelectorCache { * SelectorCache and mapped in script.cpp. */ reg_t readSelector(SegManager *segMan, reg_t object, Selector selectorId); -#define readSelectorValue(segMan, _obj_, _slc_) (readSelector(segMan, _obj_, _slc_).offset) +#define readSelectorValue(segMan, _obj_, _slc_) (readSelector(segMan, _obj_, _slc_).getOffset()) /** * Writes a selector value to an object. diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index 7dc397c11e..89f59eaa14 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -119,7 +119,7 @@ extern const char *opcodeNames[]; // from scriptdebug.cpp static reg_t read_var(EngineState *s, int type, int index) { if (validate_variable(s->variables[type], s->stack_base, type, s->variablesMax[type], index)) { - if (s->variables[type][index].segment == 0xffff) { + if (s->variables[type][index].getSegment() == 0xffff) { switch (type) { case VAR_TEMP: { // Uninitialized read on a temp @@ -195,8 +195,8 @@ static void write_var(EngineState *s, int type, int index, reg_t value) { // this happens at least in sq1/room 44 (slot-machine), because a send is missing parameters, then // those parameters are taken from uninitialized stack and afterwards they are copied back into temps // if we don't remove the segment, we would get false-positive uninitialized reads later - if (type == VAR_TEMP && value.segment == 0xffff) - value.segment = 0; + if (type == VAR_TEMP && value.getSegment() == 0xffff) + value.setSegment(0); s->variables[type][index] = value; @@ -578,16 +578,16 @@ void run_vm(EngineState *s) { int var_type; // See description below int var_number; - g_sci->_debugState.old_pc_offset = s->xs->addr.pc.offset; + g_sci->_debugState.old_pc_offset = s->xs->addr.pc.getOffset(); g_sci->_debugState.old_sp = s->xs->sp; if (s->abortScriptProcessing != kAbortNone) return; // Stop processing if (s->_executionStackPosChanged) { - scr = s->_segMan->getScriptIfLoaded(s->xs->addr.pc.segment); + scr = s->_segMan->getScriptIfLoaded(s->xs->addr.pc.getSegment()); if (!scr) - error("No script in segment %d", s->xs->addr.pc.segment); + error("No script in segment %d", s->xs->addr.pc.getSegment()); s->xs = &(s->_executionStack.back()); s->_executionStackPosChanged = false; @@ -624,13 +624,13 @@ void run_vm(EngineState *s) { s->variablesMax[VAR_TEMP] = s->xs->sp - s->xs->fp; - if (s->xs->addr.pc.offset >= scr->getBufSize()) + if (s->xs->addr.pc.getOffset() >= scr->getBufSize()) error("run_vm(): program counter gone astray, addr: %d, code buffer size: %d", - s->xs->addr.pc.offset, scr->getBufSize()); + s->xs->addr.pc.getOffset(), scr->getBufSize()); // Get opcode byte extOpcode; - s->xs->addr.pc.offset += readPMachineInstruction(scr->getBuf() + s->xs->addr.pc.offset, extOpcode, opparams); + s->xs->addr.pc.incOffset(readPMachineInstruction(scr->getBuf(s->xs->addr.pc.getOffset()), extOpcode, opparams)); const byte opcode = extOpcode >> 1; //debug("%s: %d, %d, %d, %d, acc = %04x:%04x, script %d, local script %d", opcodeNames[opcode], opparams[0], opparams[1], opparams[2], opparams[3], PRINT_REG(s->r_acc), scr->getScriptNumber(), local_script->getScriptNumber()); @@ -705,7 +705,7 @@ void run_vm(EngineState *s) { break; case op_not: // 0x0c (12) - s->r_acc = make_reg(0, !(s->r_acc.offset || s->r_acc.segment)); + s->r_acc = make_reg(0, !(s->r_acc.getOffset() || s->r_acc.getSegment())); // Must allow pointers to be negated, as this is used for checking whether objects exist break; @@ -765,30 +765,30 @@ void run_vm(EngineState *s) { case op_bt: // 0x17 (23) // Branch relative if true - if (s->r_acc.offset || s->r_acc.segment) - s->xs->addr.pc.offset += opparams[0]; + if (s->r_acc.getOffset() || s->r_acc.getSegment()) + s->xs->addr.pc.incOffset(opparams[0]); - if (s->xs->addr.pc.offset >= local_script->getScriptSize()) + if (s->xs->addr.pc.getOffset() >= local_script->getScriptSize()) error("[VM] op_bt: request to jump past the end of script %d (offset %d, script is %d bytes)", - local_script->getScriptNumber(), s->xs->addr.pc.offset, local_script->getScriptSize()); + local_script->getScriptNumber(), s->xs->addr.pc.getOffset(), local_script->getScriptSize()); break; case op_bnt: // 0x18 (24) // Branch relative if not true - if (!(s->r_acc.offset || s->r_acc.segment)) - s->xs->addr.pc.offset += opparams[0]; + if (!(s->r_acc.getOffset() || s->r_acc.getSegment())) + s->xs->addr.pc.incOffset(opparams[0]); - if (s->xs->addr.pc.offset >= local_script->getScriptSize()) + if (s->xs->addr.pc.getOffset() >= local_script->getScriptSize()) error("[VM] op_bnt: request to jump past the end of script %d (offset %d, script is %d bytes)", - local_script->getScriptNumber(), s->xs->addr.pc.offset, local_script->getScriptSize()); + local_script->getScriptNumber(), s->xs->addr.pc.getOffset(), local_script->getScriptSize()); break; case op_jmp: // 0x19 (25) - s->xs->addr.pc.offset += opparams[0]; + s->xs->addr.pc.incOffset(opparams[0]); - if (s->xs->addr.pc.offset >= local_script->getScriptSize()) + if (s->xs->addr.pc.getOffset() >= local_script->getScriptSize()) error("[VM] op_jmp: request to jump past the end of script %d (offset %d, script is %d bytes)", - local_script->getScriptNumber(), s->xs->addr.pc.offset, local_script->getScriptSize()); + local_script->getScriptNumber(), s->xs->addr.pc.getOffset(), local_script->getScriptSize()); break; case op_ldi: // 0x1a (26) @@ -831,13 +831,13 @@ void run_vm(EngineState *s) { int argc = (opparams[1] >> 1) // Given as offset, but we need count + 1 + s->r_rest; StackPtr call_base = s->xs->sp - argc; - s->xs->sp[1].offset += s->r_rest; + s->xs->sp[1].incOffset(s->r_rest); - uint16 localCallOffset = s->xs->addr.pc.offset + opparams[0]; + uint16 localCallOffset = s->xs->addr.pc.getOffset() + opparams[0]; ExecStack xstack(s->xs->objp, s->xs->objp, s->xs->sp, (call_base->requireUint16()) + s->r_rest, call_base, - s->xs->local_segment, make_reg(s->xs->addr.pc.segment, localCallOffset), + s->xs->local_segment, make_reg(s->xs->addr.pc.getSegment(), localCallOffset), NULL_SELECTOR, -1, localCallOffset, s->_executionStack.size() - 1, EXEC_STACK_TYPE_CALL); @@ -894,9 +894,9 @@ void run_vm(EngineState *s) { s_temp = s->xs->sp; s->xs->sp -= temp; - s->xs->sp[0].offset += s->r_rest; + s->xs->sp[0].incOffset(s->r_rest); xs_new = execute_method(s, 0, opparams[0], s_temp, s->xs->objp, - s->xs->sp[0].offset, s->xs->sp); + s->xs->sp[0].getOffset(), s->xs->sp); s->r_rest = 0; // Used up the &rest adjustment if (xs_new) // in case of error, keep old stack s->_executionStackPosChanged = true; @@ -908,11 +908,10 @@ void run_vm(EngineState *s) { s_temp = s->xs->sp; s->xs->sp -= temp; - s->xs->sp[0].offset += s->r_rest; + s->xs->sp[0].incOffset(s->r_rest); xs_new = execute_method(s, opparams[0], opparams[1], s_temp, s->xs->objp, - s->xs->sp[0].offset, s->xs->sp); + s->xs->sp[0].getOffset(), s->xs->sp); s->r_rest = 0; // Used up the &rest adjustment - if (xs_new) // in case of error, keep old stack s->_executionStackPosChanged = true; break; @@ -965,7 +964,7 @@ void run_vm(EngineState *s) { s_temp = s->xs->sp; s->xs->sp -= ((opparams[0] >> 1) + s->r_rest); // Adjust stack - s->xs->sp[1].offset += s->r_rest; + s->xs->sp[1].incOffset(s->r_rest); xs_new = send_selector(s, s->r_acc, s->r_acc, s_temp, (int)(opparams[0] >> 1) + (uint16)s->r_rest, s->xs->sp); @@ -996,7 +995,7 @@ void run_vm(EngineState *s) { case op_class: // 0x28 (40) // Get class address s->r_acc = s->_segMan->getClassAddress((unsigned)opparams[0], SCRIPT_GET_LOCK, - s->xs->addr.pc.segment); + s->xs->addr.pc.getSegment()); break; case 0x29: // (41) @@ -1008,7 +1007,7 @@ void run_vm(EngineState *s) { s_temp = s->xs->sp; s->xs->sp -= ((opparams[0] >> 1) + s->r_rest); // Adjust stack - s->xs->sp[1].offset += s->r_rest; + s->xs->sp[1].incOffset(s->r_rest); xs_new = send_selector(s, s->xs->objp, s->xs->objp, s_temp, (int)(opparams[0] >> 1) + (uint16)s->r_rest, s->xs->sp); @@ -1021,7 +1020,7 @@ void run_vm(EngineState *s) { case op_super: // 0x2b (43) // Send to any class - r_temp = s->_segMan->getClassAddress(opparams[0], SCRIPT_GET_LOAD, s->xs->addr.pc.segment); + r_temp = s->_segMan->getClassAddress(opparams[0], SCRIPT_GET_LOAD, s->xs->addr.pc.getSegment()); if (!r_temp.isPointer()) error("[VM]: Invalid superclass in object"); @@ -1029,7 +1028,7 @@ void run_vm(EngineState *s) { s_temp = s->xs->sp; s->xs->sp -= ((opparams[1] >> 1) + s->r_rest); // Adjust stack - s->xs->sp[1].offset += s->r_rest; + s->xs->sp[1].incOffset(s->r_rest); xs_new = send_selector(s, r_temp, s->xs->objp, s_temp, (int)(opparams[1] >> 1) + (uint16)s->r_rest, s->xs->sp); @@ -1058,14 +1057,14 @@ void run_vm(EngineState *s) { var_number = temp & 0x03; // Get variable type // Get variable block offset - r_temp.segment = s->variablesSegment[var_number]; - r_temp.offset = s->variables[var_number] - s->variablesBase[var_number]; + r_temp.setSegment(s->variablesSegment[var_number]); + r_temp.setOffset(s->variables[var_number] - s->variablesBase[var_number]); if (temp & 0x08) // Add accumulator offset if requested - r_temp.offset += s->r_acc.requireSint16(); + r_temp.incOffset(s->r_acc.requireSint16()); - r_temp.offset += opparams[1]; // Add index - r_temp.offset *= 2; // variables are 16 bit + r_temp.incOffset(opparams[1]); // Add index + r_temp.setOffset(r_temp.getOffset() * 2); // variables are 16 bit // That's the immediate address now s->r_acc = r_temp; break; @@ -1129,28 +1128,28 @@ void run_vm(EngineState *s) { case op_lofsa: // 0x39 (57) case op_lofss: // 0x3a (58) // Load offset to accumulator or push to stack - r_temp.segment = s->xs->addr.pc.segment; + r_temp.setSegment(s->xs->addr.pc.getSegment()); switch (g_sci->_features->detectLofsType()) { case SCI_VERSION_0_EARLY: - r_temp.offset = s->xs->addr.pc.offset + opparams[0]; + r_temp.setOffset(s->xs->addr.pc.getOffset() + opparams[0]); break; case SCI_VERSION_1_MIDDLE: - r_temp.offset = opparams[0]; + r_temp.setOffset(opparams[0]); break; case SCI_VERSION_1_1: - r_temp.offset = opparams[0] + local_script->getScriptSize(); + r_temp.setOffset(opparams[0] + local_script->getScriptSize()); break; case SCI_VERSION_3: // In theory this can break if the variant with a one-byte argument is // used. For now, assume it doesn't happen. - r_temp.offset = local_script->relocateOffsetSci3(s->xs->addr.pc.offset-2); + r_temp.setOffset(local_script->relocateOffsetSci3(s->xs->addr.pc.getOffset() - 2)); break; default: error("Unknown lofs type"); } - if (r_temp.offset >= scr->getBufSize()) + if (r_temp.getOffset() >= scr->getBufSize()) error("VM: lofsa/lofss operation overflowed: %04x:%04x beyond end" " of script (at %04x)", PRINT_REG(r_temp), scr->getBufSize()); diff --git a/engines/sci/engine/vm.h b/engines/sci/engine/vm.h index 67b9dd44eb..f2d225b1d8 100644 --- a/engines/sci/engine/vm.h +++ b/engines/sci/engine/vm.h @@ -116,7 +116,7 @@ struct ExecStack { if (localsSegment_ != 0xFFFF) local_segment = localsSegment_; else - local_segment = pc_.segment; + local_segment = pc_.getSegment(); debugSelector = debugSelector_; debugExportId = debugExportId_; debugLocalCallOffset = debugLocalCallOffset_; diff --git a/engines/sci/engine/vm_types.cpp b/engines/sci/engine/vm_types.cpp index b95fd58129..27015d9be4 100644 --- a/engines/sci/engine/vm_types.cpp +++ b/engines/sci/engine/vm_types.cpp @@ -43,17 +43,17 @@ reg_t reg_t::lookForWorkaround(const reg_t right) const { reg_t reg_t::operator+(const reg_t right) const { if (isPointer() && right.isNumber()) { // Pointer arithmetics. Only some pointer types make sense here - SegmentObj *mobj = g_sci->getEngineState()->_segMan->getSegmentObj(segment); + SegmentObj *mobj = g_sci->getEngineState()->_segMan->getSegmentObj(getSegment()); if (!mobj) - error("[VM]: Attempt to add %d to invalid pointer %04x:%04x", right.offset, PRINT_REG(*this)); + error("[VM]: Attempt to add %d to invalid pointer %04x:%04x", right.getOffset(), PRINT_REG(*this)); switch (mobj->getType()) { case SEG_TYPE_LOCALS: case SEG_TYPE_SCRIPT: case SEG_TYPE_STACK: case SEG_TYPE_DYNMEM: - return make_reg(segment, offset + right.toSint16()); + return make_reg(getSegment(), getOffset() + right.toSint16()); default: return lookForWorkaround(right); } @@ -69,12 +69,12 @@ reg_t reg_t::operator+(const reg_t right) const { } reg_t reg_t::operator-(const reg_t right) const { - if (segment == right.segment) { + if (getSegment() == right.getSegment()) { // We can subtract numbers, or pointers with the same segment, // an operation which will yield a number like in C return make_reg(0, toSint16() - right.toSint16()); } else { - return *this + make_reg(right.segment, -right.offset); + return *this + make_reg(right.getSegment(), -right.toSint16()); } } @@ -174,7 +174,7 @@ reg_t reg_t::operator^(const reg_t right) const { } int reg_t::cmp(const reg_t right, bool treatAsUnsigned) const { - if (segment == right.segment) { // can compare things in the same segment + if (getSegment() == right.getSegment()) { // can compare things in the same segment if (treatAsUnsigned || !isNumber()) return toUint16() - right.toUint16(); else @@ -218,7 +218,7 @@ bool reg_t::pointerComparisonWithInteger(const reg_t right) const { // SQ1, room 28, when throwing water at the Orat // SQ1, room 58, when giving the ID card to the robot // SQ4 CD, at the first game screen, when the narrator is about to speak - return (isPointer() && right.isNumber() && right.offset <= 2000 && getSciVersion() <= SCI_VERSION_1_1); + return (isPointer() && right.isNumber() && right.getOffset() <= 2000 && getSciVersion() <= SCI_VERSION_1_1); } } // End of namespace Sci diff --git a/engines/sci/engine/vm_types.h b/engines/sci/engine/vm_types.h index 7b155a4532..2995ba3c12 100644 --- a/engines/sci/engine/vm_types.h +++ b/engines/sci/engine/vm_types.h @@ -31,43 +31,64 @@ namespace Sci { typedef uint16 SegmentId; struct reg_t { - SegmentId segment; - uint16 offset; + // Segment and offset. These should never be accessed directly + SegmentId _segment; + uint16 _offset; + + inline SegmentId getSegment() const { + return _segment; + } + + inline void setSegment(SegmentId segment) { + _segment = segment; + } + + inline uint16 getOffset() const { + return _offset; + } + + inline void setOffset(uint16 offset) { + _offset = offset; + } + + inline void incOffset(int16 offset) { + setOffset(getOffset() + offset); + } inline bool isNull() const { - return (offset | segment) == 0; + return (_offset | getSegment()) == 0; } inline uint16 toUint16() const { - return offset; + return _offset; } inline int16 toSint16() const { - return (int16)offset; + return (int16)_offset; } bool isNumber() const { - return segment == 0; + return getSegment() == 0; } bool isPointer() const { - return segment != 0 && segment != 0xFFFF; + return getSegment() != 0 && getSegment() != 0xFFFF; } uint16 requireUint16() const; int16 requireSint16() const; inline bool isInitialized() const { - return segment != 0xFFFF; + return getSegment() != 0xFFFF; } // Comparison operators bool operator==(const reg_t &x) const { - return (offset == x.offset) && (segment == x.segment); + return (getOffset() == x.getOffset()) && (getSegment() == x.getSegment()); } bool operator!=(const reg_t &x) const { - return (offset != x.offset) || (segment != x.segment); + return (getOffset() != x.getOffset()) || (getSegment() != x.getSegment()); } bool operator>(const reg_t right) const { @@ -141,12 +162,12 @@ private: static inline reg_t make_reg(SegmentId segment, uint16 offset) { reg_t r; - r.offset = offset; - r.segment = segment; + r.setSegment(segment); + r.setOffset(offset); return r; } -#define PRINT_REG(r) (0xffff) & (unsigned) (r).segment, (unsigned) (r).offset +#define PRINT_REG(r) (0xffff) & (unsigned) (r).getSegment(), (unsigned) (r).getOffset() // Stack pointer type typedef reg_t *StackPtr; diff --git a/engines/sci/graphics/animate.cpp b/engines/sci/graphics/animate.cpp index 983e697481..ee28c5ca31 100644 --- a/engines/sci/graphics/animate.cpp +++ b/engines/sci/graphics/animate.cpp @@ -723,7 +723,7 @@ void GfxAnimate::printAnimateList(Console *con) { const AnimateList::iterator end = _list.end(); for (it = _list.begin(); it != end; ++it) { - Script *scr = _s->_segMan->getScriptIfLoaded(it->object.segment); + Script *scr = _s->_segMan->getScriptIfLoaded(it->object.getSegment()); int16 scriptNo = scr ? scr->getScriptNumber() : -1; con->DebugPrintf("%04x:%04x (%s), script %d, view %d (%d, %d), pal %d, " diff --git a/engines/sci/graphics/menu.cpp b/engines/sci/graphics/menu.cpp index 47f34cf99d..bfecc296a2 100644 --- a/engines/sci/graphics/menu.cpp +++ b/engines/sci/graphics/menu.cpp @@ -219,7 +219,7 @@ void GfxMenu::kernelAddEntry(Common::String title, Common::String content, reg_t } } itemEntry->textVmPtr = contentVmPtr; - itemEntry->textVmPtr.offset += beginPos; + itemEntry->textVmPtr.incOffset(beginPos); if (rightAlignedPos) { rightAlignedPos++; @@ -297,13 +297,13 @@ void GfxMenu::kernelSetAttribute(uint16 menuId, uint16 itemId, uint16 attributeI // We assume here that no script ever creates a separatorLine dynamically break; case SCI_MENU_ATTRIBUTE_KEYPRESS: - itemEntry->keyPress = tolower(value.offset); + itemEntry->keyPress = tolower(value.getOffset()); itemEntry->keyModifier = 0; // TODO: Find out how modifier is handled - debug("setAttr keypress %X %X", value.segment, value.offset); + debug("setAttr keypress %X %X", value.getSegment(), value.getOffset()); break; case SCI_MENU_ATTRIBUTE_TAG: - itemEntry->tag = value.offset; + itemEntry->tag = value.getOffset(); break; default: // Happens when loading a game in LSL3 - attribute 1A diff --git a/engines/sci/graphics/paint16.cpp b/engines/sci/graphics/paint16.cpp index c951f3349d..89f3625e2c 100644 --- a/engines/sci/graphics/paint16.cpp +++ b/engines/sci/graphics/paint16.cpp @@ -491,10 +491,10 @@ reg_t GfxPaint16::kernelDisplay(const char *text, int argc, reg_t *argv) { // processing codes in argv while (argc > 0) { displayArg = argv[0]; - if (displayArg.segment) - displayArg.offset = 0xFFFF; + if (displayArg.getSegment()) + displayArg.setOffset(0xFFFF); argc--; argv++; - switch (displayArg.offset) { + switch (displayArg.getOffset()) { case SCI_DISPLAY_MOVEPEN: _ports->moveTo(argv[0].toUint16(), argv[1].toUint16()); argc -= 2; argv += 2; @@ -547,9 +547,9 @@ reg_t GfxPaint16::kernelDisplay(const char *text, int argc, reg_t *argv) { if (!(g_sci->getGameId() == GID_LONGBOW && g_sci->isDemo()) && !(g_sci->getGameId() == GID_QFG1 && g_sci->isDemo()) && !(g_sci->getGameId() == GID_PQ2)) - error("Unknown kDisplay argument %d", displayArg.offset); + error("Unknown kDisplay argument %d", displayArg.getOffset()); - if (displayArg.offset == SCI_DISPLAY_DUMMY2) { + if (displayArg.getOffset() == SCI_DISPLAY_DUMMY2) { if (!argc) error("No parameter left for kDisplay(115)"); argc--; argv++; diff --git a/engines/sci/resource.cpp b/engines/sci/resource.cpp index f8ddf64551..c9c0d25bc6 100644 --- a/engines/sci/resource.cpp +++ b/engines/sci/resource.cpp @@ -2590,7 +2590,7 @@ Common::String ResourceManager::findSierraGameId() { if (!heap) return ""; - int16 gameObjectOffset = findGameObject(false).offset; + int16 gameObjectOffset = findGameObject(false).getOffset(); if (!gameObjectOffset) return ""; diff --git a/engines/sci/sci.cpp b/engines/sci/sci.cpp index 960016764a..d43a9d06fc 100644 --- a/engines/sci/sci.cpp +++ b/engines/sci/sci.cpp @@ -453,8 +453,8 @@ static byte patchGameRestoreSaveSci21[] = { }; static void patchGameSaveRestoreCode(SegManager *segMan, reg_t methodAddress, byte id) { - Script *script = segMan->getScript(methodAddress.segment); - byte *patchPtr = const_cast(script->getBuf(methodAddress.offset)); + Script *script = segMan->getScript(methodAddress.getSegment()); + byte *patchPtr = const_cast(script->getBuf(methodAddress.getOffset())); if (getSciVersion() <= SCI_VERSION_1_1) memcpy(patchPtr, patchGameRestoreSave, sizeof(patchGameRestoreSave)); else // SCI2+ @@ -463,8 +463,8 @@ static void patchGameSaveRestoreCode(SegManager *segMan, reg_t methodAddress, by } static void patchGameSaveRestoreCodeSci21(SegManager *segMan, reg_t methodAddress, byte id, bool doRestore) { - Script *script = segMan->getScript(methodAddress.segment); - byte *patchPtr = const_cast(script->getBuf(methodAddress.offset)); + Script *script = segMan->getScript(methodAddress.getSegment()); + byte *patchPtr = const_cast(script->getBuf(methodAddress.getOffset())); memcpy(patchPtr, patchGameRestoreSaveSci21, sizeof(patchGameRestoreSaveSci21)); if (doRestore) patchPtr[2] = 0x78; // push1 @@ -740,7 +740,7 @@ GUI::Debugger *SciEngine::getDebugger() { if (_gamestate) { ExecStack *xs = &(_gamestate->_executionStack.back()); if (xs) { - xs->addr.pc.offset = _debugState.old_pc_offset; + xs->addr.pc.setOffset(_debugState.old_pc_offset); xs->sp = _debugState.old_sp; } } diff --git a/engines/sci/sound/soundcmd.cpp b/engines/sci/sound/soundcmd.cpp index 05bb90332a..989df7c8a1 100644 --- a/engines/sci/sound/soundcmd.cpp +++ b/engines/sci/sound/soundcmd.cpp @@ -61,7 +61,7 @@ reg_t SoundCommandParser::kDoSoundInit(int argc, reg_t *argv, reg_t acc) { } int SoundCommandParser::getSoundResourceId(reg_t obj) { - int resourceId = obj.segment ? readSelectorValue(_segMan, obj, SELECTOR(number)) : -1; + int resourceId = obj.getSegment() ? readSelectorValue(_segMan, obj, SELECTOR(number)) : -1; // Modify the resourceId for the Windows versions that have an alternate MIDI soundtrack, like SSCI did. if (g_sci && g_sci->_features->useAltWinGMSound()) { // Check if the alternate MIDI song actually exists... @@ -291,7 +291,7 @@ reg_t SoundCommandParser::kDoSoundPause(int argc, reg_t *argv, reg_t acc) { reg_t obj = argv[0]; uint16 value = argc > 1 ? argv[1].toUint16() : 0; - if (!obj.segment) { // pause the whole playlist + if (!obj.getSegment()) { // pause the whole playlist _music->pauseAll(value); } else { // pause a playlist slot MusicEntry *musicSlot = _music->getSlot(obj); @@ -369,7 +369,7 @@ reg_t SoundCommandParser::kDoSoundFade(int argc, reg_t *argv, reg_t acc) { case 5: // SCI1+ (SCI1 late sound scheme), with fade and continue musicSlot->fadeTo = CLIP(argv[1].toUint16(), 0, MUSIC_VOLUME_MAX); // sometimes we get objects in that position, fix it up (ffs. workarounds) - if (!argv[1].segment) + if (!argv[1].getSegment()) musicSlot->fadeStep = volume > musicSlot->fadeTo ? -argv[3].toUint16() : argv[3].toUint16(); else musicSlot->fadeStep = volume > musicSlot->fadeTo ? -5 : 5; -- cgit v1.2.3 From 065e83e44fd16571b251b227c8fb5ffaccbadbed Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Mon, 18 Jun 2012 12:20:07 +0300 Subject: SCI: Store script sizes in 32-bit integers Since scripts can be larger than 64KB, and getBufSize() returns a 32-bit integer, adapt variables that store script sizes accordingly --- engines/sci/console.cpp | 4 ++-- engines/sci/engine/scriptdebug.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp index 7e9f9b1c38..91795117e3 100644 --- a/engines/sci/console.cpp +++ b/engines/sci/console.cpp @@ -2630,7 +2630,7 @@ bool Console::cmdViewReference(int argc, const char **argv) { #endif default: { const SegmentRef block = _engine->_gamestate->_segMan->dereference(reg); - uint16 size = block.maxSize; + uint32 size = block.maxSize; DebugPrintf("raw data\n"); @@ -2936,7 +2936,7 @@ bool Console::cmdDisassembleAddress(int argc, const char **argv) { uint opCount = 1; bool printBWTag = false; bool printBytes = false; - uint16 size; + uint32 size; if (parse_reg_t(_engine->_gamestate, argv[1], &vpc, false)) { DebugPrintf("Invalid address passed.\n"); diff --git a/engines/sci/engine/scriptdebug.cpp b/engines/sci/engine/scriptdebug.cpp index 6242dc4c93..f55884b1c0 100644 --- a/engines/sci/engine/scriptdebug.cpp +++ b/engines/sci/engine/scriptdebug.cpp @@ -72,7 +72,7 @@ reg_t disassemble(EngineState *s, reg_t pos, bool printBWTag, bool printBytecode SegmentObj *mobj = s->_segMan->getSegment(pos.getSegment(), SEG_TYPE_SCRIPT); Script *script_entity = NULL; const byte *scr; - uint scr_size; + uint32 scr_size; reg_t retval = make_reg(pos.getSegment(), pos.getOffset() + 1); uint16 param_value = 0xffff; // Suppress GCC warning by setting default value, chose value as invalid to getKernelName etc. uint i = 0; @@ -344,7 +344,7 @@ void SciEngine::scriptDebug() { if (mobj) { Script *scr = (Script *)mobj; const byte *code_buf = scr->getBuf(); - uint16 code_buf_size = scr->getBufSize(); + uint32 code_buf_size = scr->getBufSize(); int opcode = pc.getOffset() >= code_buf_size ? 0 : code_buf[pc.getOffset()]; int op = opcode >> 1; int paramb1 = pc.getOffset() + 1 >= code_buf_size ? 0 : code_buf[pc.getOffset() + 1]; -- cgit v1.2.3 From 221ee34926927693182f835a4404eca17bdb1943 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Wed, 20 Jun 2012 04:25:20 +0300 Subject: SCI: Don't attempt to draw line feed characters in SCI32 Fixes junk in the about dialogs in PQ4 --- engines/sci/graphics/text32.cpp | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/graphics/text32.cpp b/engines/sci/graphics/text32.cpp index 7907809c91..e0f16e7265 100644 --- a/engines/sci/graphics/text32.cpp +++ b/engines/sci/graphics/text32.cpp @@ -165,10 +165,25 @@ reg_t GfxText32::createTextBitmapInternal(Common::String &text, reg_t textObject warning("Invalid alignment %d used in TextBox()", alignment); } + unsigned char curChar; + for (int i = 0; i < charCount; i++) { - unsigned char curChar = txt[i]; - font->drawToBuffer(curChar, curY + offsetY, curX + offsetX, foreColor, dimmed, bitmap, width, height); - curX += font->getCharWidth(curChar); + curChar = txt[i]; + + switch (curChar) { + case 0x0A: + case 0x0D: + case 0: + case 0x9781: // this one is used by SQ4/japanese as line break as well + break; + case 0x7C: + warning("Code processing isn't implemented in SCI32"); + break; + default: + font->drawToBuffer(curChar, curY + offsetY, curX + offsetX, foreColor, dimmed, bitmap, width, height); + curX += font->getCharWidth(curChar); + break; + } } curX = 0; -- cgit v1.2.3 From ea4260529783f80db0abde70c6b1723cf3c6f720 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Wed, 20 Jun 2012 10:55:24 +0300 Subject: SCI: Remove multibyte character processing code from SCI32 There are no Japanese/PC-98 SCI32 games, so this code is not needed --- engines/sci/graphics/text32.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/graphics/text32.cpp b/engines/sci/graphics/text32.cpp index e0f16e7265..f14ae2ef0b 100644 --- a/engines/sci/graphics/text32.cpp +++ b/engines/sci/graphics/text32.cpp @@ -165,7 +165,7 @@ reg_t GfxText32::createTextBitmapInternal(Common::String &text, reg_t textObject warning("Invalid alignment %d used in TextBox()", alignment); } - unsigned char curChar; + byte curChar; for (int i = 0; i < charCount; i++) { curChar = txt[i]; @@ -174,7 +174,6 @@ reg_t GfxText32::createTextBitmapInternal(Common::String &text, reg_t textObject case 0x0A: case 0x0D: case 0: - case 0x9781: // this one is used by SQ4/japanese as line break as well break; case 0x7C: warning("Code processing isn't implemented in SCI32"); @@ -317,7 +316,7 @@ void GfxText32::StringWidth(const char *str, GuiResourceId fontId, int16 &textWi } void GfxText32::Width(const char *text, int16 from, int16 len, GuiResourceId fontId, int16 &textWidth, int16 &textHeight, bool restoreFont) { - uint16 curChar; + byte curChar; textWidth = 0; textHeight = 0; GfxFont *font = _cache->getFont(fontId); @@ -329,7 +328,6 @@ void GfxText32::Width(const char *text, int16 from, int16 len, GuiResourceId fon switch (curChar) { case 0x0A: case 0x0D: - case 0x9781: // this one is used by SQ4/japanese as line break as well textHeight = MAX (textHeight, font->getHeight()); break; case 0x7C: -- cgit v1.2.3 From c27741ac3bb356eecb6b3f9abd1e74cb981ffbed Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Wed, 20 Jun 2012 12:31:51 +0300 Subject: SCI: Implement kRemapColors(5 - set color intensity) It's finally nighttime in the first murder scene in PQ4 --- engines/sci/engine/kgraphics.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/engine/kgraphics.cpp b/engines/sci/engine/kgraphics.cpp index 8f4d99f7df..459766c0a1 100644 --- a/engines/sci/engine/kgraphics.cpp +++ b/engines/sci/engine/kgraphics.cpp @@ -1237,7 +1237,8 @@ reg_t kRemapColors(EngineState *s, int argc, reg_t *argv) { uint16 percent = argv[2].toUint16(); // 0 - 100 if (argc >= 4) warning("RemapByPercent called with 4 parameters, unknown parameter is %d", argv[3].toUint16()); - g_sci->_gfxPalette->kernelSetIntensity(color, 255, percent, false); + // TODO: It's not correct to set intensity here + //g_sci->_gfxPalette->kernelSetIntensity(color, 255, percent, false); } break; case 3: { // remap to gray @@ -1257,10 +1258,10 @@ reg_t kRemapColors(EngineState *s, int argc, reg_t *argv) { kStub(s, argc, argv); } break; - case 5: { // increment color - //int16 unk1 = argv[1].toSint16(); - //uint16 unk2 = argv[2].toUint16(); - kStub(s, argc, argv); + case 5: { // set color intensity + int16 color = argv[1].toSint16(); + uint16 intensity = argv[2].toUint16(); + g_sci->_gfxPalette->kernelSetIntensity(color, 255, intensity, true); } break; default: -- cgit v1.2.3 From bd3366c2086e32a569eb15522e0c42dee90d50fb Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Wed, 20 Jun 2012 12:35:59 +0300 Subject: SCI: Add a warning for kRemapColors(RemapByPercent) --- engines/sci/engine/kgraphics.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'engines/sci') diff --git a/engines/sci/engine/kgraphics.cpp b/engines/sci/engine/kgraphics.cpp index 459766c0a1..59dba994b5 100644 --- a/engines/sci/engine/kgraphics.cpp +++ b/engines/sci/engine/kgraphics.cpp @@ -1237,6 +1237,7 @@ reg_t kRemapColors(EngineState *s, int argc, reg_t *argv) { uint16 percent = argv[2].toUint16(); // 0 - 100 if (argc >= 4) warning("RemapByPercent called with 4 parameters, unknown parameter is %d", argv[3].toUint16()); + warning("kRemapColors: RemapByPercent color %d by %d percent", color, percent); // TODO: It's not correct to set intensity here //g_sci->_gfxPalette->kernelSetIntensity(color, 255, percent, false); } -- cgit v1.2.3 From 5a2e65469f3650dc9785bf27b77d25d285ded4f1 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Wed, 20 Jun 2012 13:36:29 +0300 Subject: SCI: Change kRemapColors(5) again. Fixes the colors in QFG4 --- engines/sci/engine/kgraphics.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/engine/kgraphics.cpp b/engines/sci/engine/kgraphics.cpp index 59dba994b5..0ef268f108 100644 --- a/engines/sci/engine/kgraphics.cpp +++ b/engines/sci/engine/kgraphics.cpp @@ -1260,9 +1260,16 @@ reg_t kRemapColors(EngineState *s, int argc, reg_t *argv) { } break; case 5: { // set color intensity - int16 color = argv[1].toSint16(); + // TODO: This isn't right, it should be setting a mapping table instead. + // For PQ4, we can emulate this with kernelSetIntensity(). In QFG4, this + // won't do. + //int16 mapping = argv[1].toSint16(); uint16 intensity = argv[2].toUint16(); - g_sci->_gfxPalette->kernelSetIntensity(color, 255, intensity, true); + // HACK for PQ4 + if (g_sci->getGameId() == GID_PQ4) + g_sci->_gfxPalette->kernelSetIntensity(0, 255, intensity, true); + + kStub(s, argc, argv); } break; default: -- cgit v1.2.3 From eb8230988a413ffff3458f0cfade5a94c95940b1 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Thu, 21 Jun 2012 12:15:25 +0300 Subject: SCI: Don't compress exported heroes in the Quest for Glory games This allows them to be used by other games in the series not supported by ScummVM (i.e. QFG4, QFG5 and the fanmade AGS version of QFG2) --- engines/sci/engine/file.cpp | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/engine/file.cpp b/engines/sci/engine/file.cpp index 0d575f97dd..a0f7ebf4a2 100644 --- a/engines/sci/engine/file.cpp +++ b/engines/sci/engine/file.cpp @@ -57,11 +57,24 @@ namespace Sci { reg_t file_open(EngineState *s, const Common::String &filename, int mode, bool unwrapFilename) { Common::String englishName = g_sci->getSciLanguageString(filename, K_LANG_ENGLISH); + englishName.toLowercase(); + Common::String wrappedName = unwrapFilename ? g_sci->wrapFilename(englishName) : englishName; Common::SeekableReadStream *inFile = 0; Common::WriteStream *outFile = 0; Common::SaveFileManager *saveFileMan = g_sci->getSaveFileManager(); + bool isCompressed = true; + const SciGameId gameId = g_sci->getGameId(); + if ((gameId == GID_QFG1 || gameId == GID_QFG1VGA || gameId == GID_QFG2 || gameId == GID_QFG3) + && englishName.hasSuffix(".sav")) { + // QFG Characters are saved via the CharSave object. + // We leave them uncompressed so that they can be imported in later QFG + // games. + // Rooms/Scripts: QFG1: 601, QFG2: 840, QFG3/4: 52 + isCompressed = false; + } + if (mode == _K_FILE_MODE_OPEN_OR_FAIL) { // Try to open file, abort if not possible inFile = saveFileMan->openForLoading(wrappedName); @@ -74,12 +87,12 @@ reg_t file_open(EngineState *s, const Common::String &filename, int mode, bool u debugC(kDebugLevelFile, " -> file_open(_K_FILE_MODE_OPEN_OR_FAIL): failed to open file '%s'", englishName.c_str()); } else if (mode == _K_FILE_MODE_CREATE) { // Create the file, destroying any content it might have had - outFile = saveFileMan->openForSaving(wrappedName); + outFile = saveFileMan->openForSaving(wrappedName, isCompressed); if (!outFile) debugC(kDebugLevelFile, " -> file_open(_K_FILE_MODE_CREATE): failed to create file '%s'", englishName.c_str()); } else if (mode == _K_FILE_MODE_OPEN_OR_CREATE) { // Try to open file, create it if it doesn't exist - outFile = saveFileMan->openForSaving(wrappedName); + outFile = saveFileMan->openForSaving(wrappedName, isCompressed); if (!outFile) debugC(kDebugLevelFile, " -> file_open(_K_FILE_MODE_CREATE): failed to create file '%s'", englishName.c_str()); -- cgit v1.2.3 From 105fb47c89e727e9dccd2798afcab7ce290d43fa Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Thu, 21 Jun 2012 12:24:36 +0300 Subject: SCI: Add the graphics undithering game option back for QFG2 --- engines/sci/detection_tables.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/detection_tables.h b/engines/sci/detection_tables.h index 6e66c48ff1..9872973e09 100644 --- a/engines/sci/detection_tables.h +++ b/engines/sci/detection_tables.h @@ -2925,7 +2925,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.006", 0, "ccf5dba33e5cab6d5872838c0f8db44c", 500039}, {"resource.007", 0, "4c9fc1587545879295cb9627f56a2cb8", 575056}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Quest for Glory 2 - English (supplied by ssburnout in bug report #3049193) // 1.000 5x5.25" (label: INT#10.31.90) @@ -2937,7 +2937,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.003", 0, "0790f67d87642132be515cab05026baa", 972144}, {"resource.004", 0, "2ac1e6fea9aa1f5b91a06693a67b9766", 982830}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Quest for Glory 2 - English (supplied by ssburnout in bug report #3049193) // 1.000 9x3.5" (label: INT#10.31.90) @@ -2952,7 +2952,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.006", 0, "5e9deacbdb17198ad844988e04833520", 498593}, {"resource.007", 0, "2ac1e6fea9aa1f5b91a06693a67b9766", 490151}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Quest for Glory 2 - English (from FRG) // Executable scanning reports "1.000.072" @@ -2964,7 +2964,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.003", 0, "b192607c42f6960ecdf2ad2e4f90e9bc", 972804}, {"resource.004", 0, "cd2de58e27665d5853530de93fae7cd6", 983617}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Quest for Glory 2 - English DOS // Executable scanning reports "1.000.072" @@ -2979,7 +2979,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.006", 0, "b1944bd664ddbd2859cdaa0c4a0d6281", 507489}, {"resource.007", 0, "cd2de58e27665d5853530de93fae7cd6", 490794}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Quest for Glory 2 - English DOS Non-Interactive Demo // Executable scanning reports "1.000.046" @@ -2987,7 +2987,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "e75eb86bdd517b3ef709058249986a87", 906}, {"resource.001", 0, "9b098f9e1008abe30e56c93b896494e6", 362123}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Quest for Glory 3 - English DOS Non-Interactive Demo (from FRG) // Executable scanning reports "1.001.021", VERSION file reports "1.000, 0.001.059, 6.12.92" -- cgit v1.2.3 From 76f3f1b13621b43781c4a2c505e646d9d52fdab7 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Thu, 21 Jun 2012 22:24:22 +0300 Subject: SCI: Fix warnings --- engines/sci/console.cpp | 11 +++-------- engines/sci/engine/kstring.cpp | 10 +++++----- engines/sci/engine/scriptdebug.cpp | 6 +++--- 3 files changed, 11 insertions(+), 16 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp index 91795117e3..b0ed7e6225 100644 --- a/engines/sci/console.cpp +++ b/engines/sci/console.cpp @@ -2630,11 +2630,11 @@ bool Console::cmdViewReference(int argc, const char **argv) { #endif default: { const SegmentRef block = _engine->_gamestate->_segMan->dereference(reg); - uint32 size = block.maxSize; + uint16 size = block.maxSize; DebugPrintf("raw data\n"); - if (reg_end.getSegment() != 0 && size < reg_end.getOffset() - reg.getOffset()) { + if (reg_end.getSegment() != 0 && (size < reg_end.getOffset() - reg.getOffset())) { DebugPrintf("Block end out of bounds (size %d). Resetting.\n", size); reg_end = NULL_REG; } @@ -2936,7 +2936,7 @@ bool Console::cmdDisassembleAddress(int argc, const char **argv) { uint opCount = 1; bool printBWTag = false; bool printBytes = false; - uint32 size; + uint16 size; if (parse_reg_t(_engine->_gamestate, argv[1], &vpc, false)) { DebugPrintf("Invalid address passed.\n"); @@ -2960,11 +2960,6 @@ bool Console::cmdDisassembleAddress(int argc, const char **argv) { } } - if (opCount < 0) { - DebugPrintf("Invalid op_count\n"); - return true; - } - do { vpc = disassemble(_engine->_gamestate, vpc, printBWTag, printBytes); } while ((vpc.getOffset() > 0) && (vpc.getOffset() + 6 < size) && (--opCount)); diff --git a/engines/sci/engine/kstring.cpp b/engines/sci/engine/kstring.cpp index 8d627efacf..9eebf2c88a 100644 --- a/engines/sci/engine/kstring.cpp +++ b/engines/sci/engine/kstring.cpp @@ -96,7 +96,7 @@ reg_t kStrAt(EngineState *s, int argc, reg_t *argv) { byte value; byte newvalue = 0; - unsigned int offset = argv[1].toUint16(); + uint16 offset = argv[1].toUint16(); if (argc > 2) newvalue = argv[2].toSint16(); @@ -125,19 +125,19 @@ reg_t kStrAt(EngineState *s, int argc, reg_t *argv) { if (!oddOffset) { value = tmp.getOffset() & 0x00ff; if (argc > 2) { /* Request to modify this char */ - uint16 offset = tmp.toUint16(); + uint16 tmpOffset = tmp.toUint16(); offset &= 0xff00; offset |= newvalue; - tmp.setOffset(offset); + tmp.setOffset(tmpOffset); tmp.setSegment(0); } } else { value = tmp.getOffset() >> 8; if (argc > 2) { /* Request to modify this char */ - uint16 offset = tmp.toUint16(); + uint16 tmpOffset = tmp.toUint16(); offset &= 0x00ff; offset |= newvalue << 8; - tmp.setOffset(offset); + tmp.setOffset(tmpOffset); tmp.setSegment(0); } } diff --git a/engines/sci/engine/scriptdebug.cpp b/engines/sci/engine/scriptdebug.cpp index f55884b1c0..d8c05ab04b 100644 --- a/engines/sci/engine/scriptdebug.cpp +++ b/engines/sci/engine/scriptdebug.cpp @@ -344,11 +344,11 @@ void SciEngine::scriptDebug() { if (mobj) { Script *scr = (Script *)mobj; const byte *code_buf = scr->getBuf(); - uint32 code_buf_size = scr->getBufSize(); + uint16 code_buf_size = scr->getBufSize(); // TODO: change to a 32-bit integer for large SCI3 scripts int opcode = pc.getOffset() >= code_buf_size ? 0 : code_buf[pc.getOffset()]; int op = opcode >> 1; - int paramb1 = pc.getOffset() + 1 >= code_buf_size ? 0 : code_buf[pc.getOffset() + 1]; - int paramf1 = (opcode & 1) ? paramb1 : (pc.getOffset() + 2 >= code_buf_size ? 0 : (int16)READ_SCI11ENDIAN_UINT16(code_buf + pc.getOffset() + 1)); + uint16 paramb1 = pc.getOffset() + 1 >= code_buf_size ? 0 : code_buf[pc.getOffset() + 1]; + uint16 paramf1 = (opcode & 1) ? paramb1 : (pc.getOffset() + 2 >= code_buf_size ? 0 : (int16)READ_SCI11ENDIAN_UINT16(code_buf + pc.getOffset() + 1)); switch (_debugState.seeking) { case kDebugSeekSpecialCallk: -- cgit v1.2.3 From 99b1c736396799260cd715b40a074cf32d104485 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Thu, 21 Jun 2012 22:57:00 +0300 Subject: SCI: Fix silly typo Thanks to digitall for spotting this --- engines/sci/engine/kstring.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/engine/kstring.cpp b/engines/sci/engine/kstring.cpp index 9eebf2c88a..c22d7c7b1e 100644 --- a/engines/sci/engine/kstring.cpp +++ b/engines/sci/engine/kstring.cpp @@ -126,8 +126,8 @@ reg_t kStrAt(EngineState *s, int argc, reg_t *argv) { value = tmp.getOffset() & 0x00ff; if (argc > 2) { /* Request to modify this char */ uint16 tmpOffset = tmp.toUint16(); - offset &= 0xff00; - offset |= newvalue; + tmpOffset &= 0xff00; + tmpOffset |= newvalue; tmp.setOffset(tmpOffset); tmp.setSegment(0); } @@ -135,8 +135,8 @@ reg_t kStrAt(EngineState *s, int argc, reg_t *argv) { value = tmp.getOffset() >> 8; if (argc > 2) { /* Request to modify this char */ uint16 tmpOffset = tmp.toUint16(); - offset &= 0x00ff; - offset |= newvalue << 8; + tmpOffset &= 0x00ff; + tmpOffset |= newvalue << 8; tmp.setOffset(tmpOffset); tmp.setSegment(0); } -- cgit v1.2.3 From 08124396035e8fd0996c9d347be3d606a58ecd1f Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Fri, 22 Jun 2012 09:31:51 +0300 Subject: SCI: Simplify the SCI32 coordinate adjustment code --- engines/sci/graphics/frameout.cpp | 57 +++++++++++---------------------------- engines/sci/graphics/frameout.h | 6 ----- 2 files changed, 16 insertions(+), 47 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/graphics/frameout.cpp b/engines/sci/graphics/frameout.cpp index 7a9c7ba281..0681102863 100644 --- a/engines/sci/graphics/frameout.cpp +++ b/engines/sci/graphics/frameout.cpp @@ -62,8 +62,6 @@ GfxFrameout::GfxFrameout(SegManager *segMan, ResourceManager *resMan, GfxCoordAd : _segMan(segMan), _resMan(resMan), _cache(cache), _screen(screen), _palette(palette), _paint32(paint32) { _coordAdjuster = (GfxCoordAdjuster32 *)coordAdjuster; - _scriptsRunningWidth = 320; - _scriptsRunningHeight = 200; _curScrollText = -1; _showScrollText = false; _maxScrollTexts = 0; @@ -129,12 +127,12 @@ void GfxFrameout::kernelAddPlane(reg_t object) { uint16 tmpRunningHeight = readSelectorValue(_segMan, object, SELECTOR(resY)); // The above can be 0 in SCI3 (e.g. Phantasmagoria 2) - if (tmpRunningWidth > 0 && tmpRunningHeight > 0) { - _scriptsRunningWidth = tmpRunningWidth; - _scriptsRunningHeight = tmpRunningHeight; + if (tmpRunningWidth == 0 && tmpRunningHeight == 0) { + tmpRunningWidth = 320; + tmpRunningHeight = 200; } - _coordAdjuster->setScriptsResolution(_scriptsRunningWidth, _scriptsRunningHeight); + _coordAdjuster->setScriptsResolution(tmpRunningWidth, tmpRunningHeight); } newPlane.object = object; @@ -172,11 +170,8 @@ void GfxFrameout::kernelUpdatePlane(reg_t object) { it->planeRect.bottom = readSelectorValue(_segMan, object, SELECTOR(bottom)); it->planeRect.right = readSelectorValue(_segMan, object, SELECTOR(right)); - Common::Rect screenRect(_screen->getWidth(), _screen->getHeight()); - it->planeRect.top = (it->planeRect.top * screenRect.height()) / _scriptsRunningHeight; - it->planeRect.left = (it->planeRect.left * screenRect.width()) / _scriptsRunningWidth; - it->planeRect.bottom = (it->planeRect.bottom * screenRect.height()) / _scriptsRunningHeight; - it->planeRect.right = (it->planeRect.right * screenRect.width()) / _scriptsRunningWidth; + _coordAdjuster->fromScriptToDisplay(it->planeRect.top, it->planeRect.left); + _coordAdjuster->fromScriptToDisplay(it->planeRect.bottom, it->planeRect.right); // We get negative left in kq7 in scrolling rooms if (it->planeRect.left < 0) { @@ -241,11 +236,9 @@ void GfxFrameout::kernelDeletePlane(reg_t object) { planeRect.bottom = readSelectorValue(_segMan, object, SELECTOR(bottom)); planeRect.right = readSelectorValue(_segMan, object, SELECTOR(right)); - Common::Rect screenRect(_screen->getWidth(), _screen->getHeight()); - planeRect.top = (planeRect.top * screenRect.height()) / _scriptsRunningHeight; - planeRect.left = (planeRect.left * screenRect.width()) / _scriptsRunningWidth; - planeRect.bottom = (planeRect.bottom * screenRect.height()) / _scriptsRunningHeight; - planeRect.right = (planeRect.right * screenRect.width()) / _scriptsRunningWidth; + _coordAdjuster->fromScriptToDisplay(planeRect.top, planeRect.left); + _coordAdjuster->fromScriptToDisplay(planeRect.bottom, planeRect.right); + // Blackout removed plane rect _paint32->fillRect(planeRect, 0); return; @@ -466,23 +459,6 @@ void GfxFrameout::sortPlanes() { Common::sort(_planes.begin(), _planes.end(), planeSortHelper); } -int16 GfxFrameout::upscaleHorizontalCoordinate(int16 coordinate) { - return ((coordinate * _screen->getWidth()) / _scriptsRunningWidth); -} - -int16 GfxFrameout::upscaleVerticalCoordinate(int16 coordinate) { - return ((coordinate * _screen->getHeight()) / _scriptsRunningHeight); -} - -Common::Rect GfxFrameout::upscaleRect(Common::Rect &rect) { - rect.top = (rect.top * _scriptsRunningHeight) / _screen->getHeight(); - rect.left = (rect.left * _scriptsRunningWidth) / _screen->getWidth(); - rect.bottom = (rect.bottom * _scriptsRunningHeight) / _screen->getHeight(); - rect.right = (rect.right * _scriptsRunningWidth) / _screen->getWidth(); - - return rect; -} - void GfxFrameout::showVideo() { bool skipVideo = false; RobotDecoder *videoDecoder = g_sci->_robotDecoder; @@ -665,10 +641,8 @@ void GfxFrameout::kernelFrameout() { if (itemEntry->object.isNull()) { // Picture cel data - itemEntry->x = upscaleHorizontalCoordinate(itemEntry->x); - itemEntry->y = upscaleVerticalCoordinate(itemEntry->y); - itemEntry->picStartX = upscaleHorizontalCoordinate(itemEntry->picStartX); - itemEntry->picStartY = upscaleVerticalCoordinate(itemEntry->picStartY); + _coordAdjuster->fromScriptToDisplay(itemEntry->y, itemEntry->x); + _coordAdjuster->fromScriptToDisplay(itemEntry->picStartY, itemEntry->picStartX); if (!isPictureOutOfView(itemEntry, it->planeRect, it->planeOffsetX, it->planeOffsetY)) drawPicture(itemEntry, it->planeOffsetX, it->planeOffsetY, it->planePictureMirrored); @@ -680,9 +654,9 @@ void GfxFrameout::kernelFrameout() { view->adjustToUpscaledCoordinates(itemEntry->y, itemEntry->x); view->adjustToUpscaledCoordinates(itemEntry->z, dummyX); } else if (getSciVersion() == SCI_VERSION_2_1) { - itemEntry->x = upscaleHorizontalCoordinate(itemEntry->x); - itemEntry->y = upscaleVerticalCoordinate(itemEntry->y); - itemEntry->z = upscaleVerticalCoordinate(itemEntry->z); + _coordAdjuster->fromScriptToDisplay(itemEntry->y, itemEntry->x); + int16 tmpVal = 0; + _coordAdjuster->fromScriptToDisplay(itemEntry->z, tmpVal); } // Adjust according to current scroll position @@ -719,7 +693,8 @@ void GfxFrameout::kernelFrameout() { view->adjustBackUpscaledCoordinates(nsRect.top, nsRect.left); view->adjustBackUpscaledCoordinates(nsRect.bottom, nsRect.right); } else if (getSciVersion() == SCI_VERSION_2_1) { - nsRect = upscaleRect(nsRect); + _coordAdjuster->fromDisplayToScript(nsRect.top, nsRect.left); + _coordAdjuster->fromDisplayToScript(nsRect.bottom, nsRect.right); } if (g_sci->getGameId() == GID_PHANTASMAGORIA2) { diff --git a/engines/sci/graphics/frameout.h b/engines/sci/graphics/frameout.h index 0d80a68f1d..ecaf450d89 100644 --- a/engines/sci/graphics/frameout.h +++ b/engines/sci/graphics/frameout.h @@ -148,9 +148,6 @@ private: void createPlaneItemList(reg_t planeObject, FrameoutList &itemList); bool isPictureOutOfView(FrameoutEntry *itemEntry, Common::Rect planeRect, int16 planeOffsetX, int16 planeOffsetY); void drawPicture(FrameoutEntry *itemEntry, int16 planeOffsetX, int16 planeOffsetY, bool planePictureMirrored); - int16 upscaleHorizontalCoordinate(int16 coordinate); - int16 upscaleVerticalCoordinate(int16 coordinate); - Common::Rect upscaleRect(Common::Rect &rect); SegManager *_segMan; ResourceManager *_resMan; @@ -169,9 +166,6 @@ private: uint16 _maxScrollTexts; void sortPlanes(); - - uint16 _scriptsRunningWidth; - uint16 _scriptsRunningHeight; }; } // End of namespace Sci -- cgit v1.2.3 From 547fdfe12a3b999473304925bf80ae1afda5f8d6 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Fri, 22 Jun 2012 09:43:44 +0300 Subject: SCI: Further cleanup of the frame drawing code --- engines/sci/graphics/frameout.cpp | 21 ++++++--------------- 1 file changed, 6 insertions(+), 15 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/graphics/frameout.cpp b/engines/sci/graphics/frameout.cpp index 0681102863..265a175e66 100644 --- a/engines/sci/graphics/frameout.cpp +++ b/engines/sci/graphics/frameout.cpp @@ -648,15 +648,14 @@ void GfxFrameout::kernelFrameout() { drawPicture(itemEntry, it->planeOffsetX, it->planeOffsetY, it->planePictureMirrored); } else { GfxView *view = (itemEntry->viewId != 0xFFFF) ? _cache->getView(itemEntry->viewId) : NULL; - + int16 dummyX = 0; + if (view && view->isSci2Hires()) { - int16 dummyX = 0; view->adjustToUpscaledCoordinates(itemEntry->y, itemEntry->x); view->adjustToUpscaledCoordinates(itemEntry->z, dummyX); } else if (getSciVersion() == SCI_VERSION_2_1) { _coordAdjuster->fromScriptToDisplay(itemEntry->y, itemEntry->x); - int16 tmpVal = 0; - _coordAdjuster->fromScriptToDisplay(itemEntry->z, tmpVal); + _coordAdjuster->fromScriptToDisplay(itemEntry->z, dummyX); } // Adjust according to current scroll position @@ -707,17 +706,9 @@ void GfxFrameout::kernelFrameout() { g_sci->_gfxCompare->setNSRect(itemEntry->object, nsRect); } - int16 screenHeight = _screen->getHeight(); - int16 screenWidth = _screen->getWidth(); - if (view && view->isSci2Hires()) { - screenHeight = _screen->getDisplayHeight(); - screenWidth = _screen->getDisplayWidth(); - } - - if (itemEntry->celRect.bottom < 0 || itemEntry->celRect.top >= screenHeight) - continue; - - if (itemEntry->celRect.right < 0 || itemEntry->celRect.left >= screenWidth) + // FIXME: When does this happen, and why? + if (itemEntry->celRect.bottom < 0 || itemEntry->celRect.top >= _screen->getDisplayHeight() || + itemEntry->celRect.right < 0 || itemEntry->celRect.left >= _screen->getDisplayWidth()) continue; Common::Rect clipRect, translatedClipRect; -- cgit v1.2.3 From f06eb05e8c554a3462a98d18c04d5f5695074b26 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sat, 23 Jun 2012 21:00:25 +0300 Subject: SCI: Implement kPlayVMD subop 23 (set palette range) Fixes the wrong palette during video sequences in GK2 and the demo of RAMA --- engines/sci/engine/kvideo.cpp | 18 ++++++++++++++---- engines/sci/engine/state.cpp | 2 ++ engines/sci/engine/state.h | 1 + 3 files changed, 17 insertions(+), 4 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/engine/kvideo.cpp b/engines/sci/engine/kvideo.cpp index dd2bca1922..2456ba1100 100644 --- a/engines/sci/engine/kvideo.cpp +++ b/engines/sci/engine/kvideo.cpp @@ -32,6 +32,7 @@ #include "common/str.h" #include "common/system.h" #include "common/textconsole.h" +#include "graphics/palette.h" #include "graphics/pixelformat.h" #include "graphics/surface.h" #include "video/video_decoder.h" @@ -86,9 +87,12 @@ void playVideo(Video::VideoDecoder *videoDecoder, VideoState videoState) { } bool skipVideo = false; + EngineState *s = g_sci->getEngineState(); - if (videoDecoder->hasDirtyPalette()) - videoDecoder->setSystemPalette(); + if (videoDecoder->hasDirtyPalette()) { + byte *palette = (byte *)videoDecoder->getPalette() + s->_vmdPalStart * 3; + g_system->getPaletteManager()->setPalette(palette, s->_vmdPalStart, s->_vmdPalEnd - s->_vmdPalStart); + } while (!g_engine->shouldQuit() && !videoDecoder->endOfVideo() && !skipVideo) { if (videoDecoder->needsUpdate()) { @@ -103,8 +107,10 @@ void playVideo(Video::VideoDecoder *videoDecoder, VideoState videoState) { g_system->copyRectToScreen(frame->pixels, frame->pitch, x, y, width, height); } - if (videoDecoder->hasDirtyPalette()) - videoDecoder->setSystemPalette(); + if (videoDecoder->hasDirtyPalette()) { + byte *palette = (byte *)videoDecoder->getPalette() + s->_vmdPalStart * 3; + g_system->getPaletteManager()->setPalette(palette, s->_vmdPalStart, s->_vmdPalEnd - s->_vmdPalStart); + } g_system->updateScreen(); } @@ -361,6 +367,10 @@ reg_t kPlayVMD(EngineState *s, int argc, reg_t *argv) { if (reshowCursor) g_sci->_gfxCursor->kernelShow(); break; + case 23: // set video palette range + s->_vmdPalStart = argv[1].toUint16(); + s->_vmdPalEnd = argv[2].toUint16(); + break; case 14: // Takes an additional integer parameter (e.g. 3) case 16: diff --git a/engines/sci/engine/state.cpp b/engines/sci/engine/state.cpp index 237c6b54a6..94a3fe3ae5 100644 --- a/engines/sci/engine/state.cpp +++ b/engines/sci/engine/state.cpp @@ -122,6 +122,8 @@ void EngineState::reset(bool isRestoring) { _videoState.reset(); _syncedAudioOptions = false; + _vmdPalStart = 0; + _vmdPalEnd = 256; } void EngineState::speedThrottler(uint32 neededSleep) { diff --git a/engines/sci/engine/state.h b/engines/sci/engine/state.h index 78a8a5b0a2..9ae6299d83 100644 --- a/engines/sci/engine/state.h +++ b/engines/sci/engine/state.h @@ -196,6 +196,7 @@ public: byte _memorySegment[kMemorySegmentMax]; VideoState _videoState; + uint16 _vmdPalStart, _vmdPalEnd; bool _syncedAudioOptions; /** -- cgit v1.2.3 From d78ed6f6ad2c27732f1e36759303b0fa9d310190 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sat, 23 Jun 2012 21:04:39 +0300 Subject: SCI: Remove a duplicate sanity check --- engines/sci/engine/kscripts.cpp | 5 ----- 1 file changed, 5 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/engine/kscripts.cpp b/engines/sci/engine/kscripts.cpp index c9e94a52a4..2c115be500 100644 --- a/engines/sci/engine/kscripts.cpp +++ b/engines/sci/engine/kscripts.cpp @@ -226,11 +226,6 @@ reg_t kScriptID(EngineState *s, int argc, reg_t *argv) { return NULL_REG; } - if (index > scr->getExportsNr()) { - error("Dispatch index too big: %d > %d", index, scr->getExportsNr()); - return NULL_REG; - } - uint16 address = scr->validateExportFunc(index, true); // Point to the heap for SCI1.1 - SCI2.1 games -- cgit v1.2.3 From c075aafddb0dba00878f6382a6e277dbaab45e10 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sat, 23 Jun 2012 21:09:03 +0300 Subject: SCI: Add support for the debug opcode "file" in our script dissassembler Also set the correct name for the debug opcode "line" --- engines/sci/engine/scriptdebug.cpp | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/engine/scriptdebug.cpp b/engines/sci/engine/scriptdebug.cpp index d8c05ab04b..04cbf1d97c 100644 --- a/engines/sci/engine/scriptdebug.cpp +++ b/engines/sci/engine/scriptdebug.cpp @@ -50,7 +50,7 @@ const char *opcodeNames[] = { "lea", "selfID", "dummy", "pprev", "pToa", "aTop", "pTos", "sTop", "ipToa", "dpToa", "ipTos", "dpTos", "lofsa", "lofss", "push0", - "push1", "push2", "pushSelf", "dummy", "lag", + "push1", "push2", "pushSelf", "line", "lag", "lal", "lat", "lap", "lsg", "lsl", "lst", "lsp", "lagi", "lali", "lati", "lapi", "lsgi", "lsli", "lsti", "lspi", @@ -97,10 +97,19 @@ reg_t disassemble(EngineState *s, reg_t pos, bool printBWTag, bool printBytecode uint bytecount = readPMachineInstruction(scr + pos.getOffset(), opsize, opparams); const byte opcode = opsize >> 1; - opsize &= 1; // byte if true, word if false - debugN("%04x:%04x: ", PRINT_REG(pos)); + if (opcode == op_pushSelf) { // 0x3e (62) + if ((opsize & 1) && g_sci->getGameId() != GID_FANMADE) { + // Debug opcode op_file + debugN("file \"%s\"\n", scr + pos.getOffset() + 1); // +1: op_pushSelf size + retval.incOffset(bytecount - 1); + return retval; + } + } + + opsize &= 1; // byte if true, word if false + if (printBytecode) { if (pos.getOffset() + bytecount > scr_size) { warning("Operation arguments extend beyond end of script"); -- cgit v1.2.3 From c1eb93bc5a9866787f27add5ca1d821e1470a4be Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sat, 23 Jun 2012 21:20:43 +0300 Subject: SCI: Clean up validateExportFunc() and related functions Also renamed some SCI3 related code to indicate when it's SCI3 specific --- engines/sci/engine/script.cpp | 30 +++++++++++++++++++++--------- engines/sci/engine/script.h | 6 +++--- engines/sci/engine/vm.cpp | 23 ++++------------------- 3 files changed, 28 insertions(+), 31 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/engine/script.cpp b/engines/sci/engine/script.cpp index 897ceccad3..80aaedfece 100644 --- a/engines/sci/engine/script.cpp +++ b/engines/sci/engine/script.cpp @@ -385,7 +385,7 @@ void Script::setLockers(int lockers) { _lockers = lockers; } -uint16 Script::validateExportFunc(int pubfunct, bool relocate) { +uint16 Script::validateExportFunc(int pubfunct, bool relocateSci3) { bool exportsAreWide = (g_sci->_features->detectLofsType() == SCI_VERSION_1_MIDDLE); if (_numExports <= pubfunct) { @@ -398,15 +398,15 @@ uint16 Script::validateExportFunc(int pubfunct, bool relocate) { uint16 offset; - if (getSciVersion() != SCI_VERSION_3 || !relocate) { + if (getSciVersion() != SCI_VERSION_3) { offset = READ_SCI11ENDIAN_UINT16(_exportTable + pubfunct); } else { - offset = relocateOffsetSci3(pubfunct * 2 + 22); + if (!relocateSci3) + offset = READ_SCI11ENDIAN_UINT16(_exportTable + pubfunct) + getCodeBlockOffsetSci3(); + else + offset = relocateOffsetSci3(pubfunct * 2 + 22); } - if (offset >= _bufSize) - error("Invalid export function pointer"); - // Check if the offset found points to a second export table (e.g. script 912 // in Camelot and script 306 in KQ4). Such offsets are usually small (i.e. < 10), // thus easily distinguished from actual code offsets. @@ -419,11 +419,23 @@ uint16 Script::validateExportFunc(int pubfunct, bool relocate) { if (secondExportTable) { secondExportTable += 3; // skip header plus 2 bytes (secondExportTable is a uint16 pointer) offset = READ_SCI11ENDIAN_UINT16(secondExportTable + pubfunct); - if (offset >= _bufSize) - error("Invalid export function pointer"); } } + if (!offset) { +#ifdef ENABLE_SCI32 + // WORKAROUNDS for invalid (empty) exports + if (g_sci->getGameId() == GID_TORIN && _nr == 64036) { + } else if (g_sci->getGameId() == GID_RAMA && _nr == 64908) { + } else +#endif + error("Request for invalid exported function 0x%x of script %d", pubfunct, _nr); + return NULL; + } + + if (offset >= _bufSize) + error("Invalid export function pointer"); + return offset; } @@ -551,7 +563,7 @@ void Script::initializeClasses(SegManager *segMan) { if (getSciVersion() <= SCI_VERSION_1_LATE && !marker) break; - if (getSciVersion() >= SCI_VERSION_1_1 && marker != 0x1234) + if (getSciVersion() >= SCI_VERSION_1_1 && marker != SCRIPT_OBJECT_MAGIC_NUMBER) break; if (getSciVersion() <= SCI_VERSION_1_LATE) { diff --git a/engines/sci/engine/script.h b/engines/sci/engine/script.h index 0c99f13235..9747f072c5 100644 --- a/engines/sci/engine/script.h +++ b/engines/sci/engine/script.h @@ -197,11 +197,11 @@ public: * Validate whether the specified public function is exported by * the script in the specified segment. * @param pubfunct Index of the function to validate - * @param relocate Decide whether to relocate this public function or not + * @param relocateSci3 Decide whether to relocate this SCI3 public function or not * @return NULL if the public function is invalid, its * offset into the script's segment otherwise */ - uint16 validateExportFunc(int pubfunct, bool relocate); + uint16 validateExportFunc(int pubfunct, bool relocateSci3); /** * Marks the script as deleted. @@ -249,7 +249,7 @@ public: /** * Gets an offset to the beginning of the code block in a SCI3 script */ - int getCodeBlockOffset() { return READ_SCI11ENDIAN_UINT32(_buf); } + int getCodeBlockOffsetSci3() { return READ_SCI11ENDIAN_UINT32(_buf); } private: /** diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index 89f59eaa14..a42606a6a6 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -225,30 +225,15 @@ ExecStack *execute_method(EngineState *s, uint16 script, uint16 pubfunct, StackP scr = s->_segMan->getScript(seg); } - int temp = scr->validateExportFunc(pubfunct, false); - - if (getSciVersion() == SCI_VERSION_3) - temp += scr->getCodeBlockOffset(); - - if (!temp) { -#ifdef ENABLE_SCI32 - if (g_sci->getGameId() == GID_TORIN && script == 64036) { - // Script 64036 in Torin's Passage is empty and contains an invalid - // (empty) export - } else if (g_sci->getGameId() == GID_RAMA && script == 64908) { - // Script 64908 in the demo of RAMA contains an invalid (empty) - // export - } else -#endif - error("Request for invalid exported function 0x%x of script %d", pubfunct, script); + uint32 exportAddr = scr->validateExportFunc(pubfunct, false); + if (!exportAddr) return NULL; - } - + // Check if a breakpoint is set on this method g_sci->checkExportBreakpoint(script, pubfunct); ExecStack xstack(calling_obj, calling_obj, sp, argc, argp, - seg, make_reg(seg, temp), -1, pubfunct, -1, + seg, make_reg(seg, exportAddr), -1, pubfunct, -1, s->_executionStack.size() - 1, EXEC_STACK_TYPE_CALL); s->_executionStack.push_back(xstack); return &(s->_executionStack.back()); -- cgit v1.2.3 From 20b677080881580706652b17dd5a4c3ed3e36c07 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sat, 23 Jun 2012 21:38:46 +0300 Subject: SCI: Change the program counter (PC) to be a 32-bit variable This is needed for future support of large SCI3 scripts. The program counter is isolated and does not interfere with other parts of the VM, plus it does not get stored in saved games, so it's pretty straightforward to convert --- engines/sci/console.cpp | 14 +++++++++---- engines/sci/console.h | 2 +- engines/sci/engine/script.cpp | 4 ++-- engines/sci/engine/script.h | 2 +- engines/sci/engine/scriptdebug.cpp | 4 ++-- engines/sci/engine/vm.cpp | 15 ++++++------- engines/sci/engine/vm.h | 4 ++-- engines/sci/engine/vm_types.h | 43 ++++++++++++++++++++++++++++++++++++++ 8 files changed, 69 insertions(+), 19 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp index b0ed7e6225..40a6fd1415 100644 --- a/engines/sci/console.cpp +++ b/engines/sci/console.cpp @@ -2913,7 +2913,8 @@ bool Console::cmdDisassemble(int argc, const char **argv) { if (jumpTarget > farthestTarget) farthestTarget = jumpTarget; } - addr = disassemble(_engine->_gamestate, addr, printBWTag, printBytecode); + // TODO: Use a true 32-bit reg_t for the position (addr) + addr = disassemble(_engine->_gamestate, make_reg32(addr.getSegment(), addr.getOffset()), printBWTag, printBytecode); if (addr.isNull() && prevAddr < farthestTarget) addr = prevAddr + 1; // skip past the ret } while (addr.getOffset() > 0); @@ -2961,7 +2962,8 @@ bool Console::cmdDisassembleAddress(int argc, const char **argv) { } do { - vpc = disassemble(_engine->_gamestate, vpc, printBWTag, printBytes); + // TODO: Use a true 32-bit reg_t for the position (vpc) + vpc = disassemble(_engine->_gamestate, make_reg32(vpc.getSegment(), vpc.getOffset()), printBWTag, printBytes); } while ((vpc.getOffset() > 0) && (vpc.getOffset() + 6 < size) && (--opCount)); return true; @@ -3652,10 +3654,14 @@ static int parse_reg_t(EngineState *s, const char *str, reg_t *dest, bool mayBeV relativeOffset = true; if (!scumm_strnicmp(str + 1, "PC", 2)) { - *dest = s->_executionStack.back().addr.pc; + // TODO: Handle 32-bit PC addresses + reg32_t pc = s->_executionStack.back().addr.pc; + *dest = make_reg(pc.getSegment(), (uint16)pc.getOffset()); offsetStr = str + 3; } else if (!scumm_strnicmp(str + 1, "P", 1)) { - *dest = s->_executionStack.back().addr.pc; + // TODO: Handle 32-bit PC addresses + reg32_t pc = s->_executionStack.back().addr.pc; + *dest = make_reg(pc.getSegment(), (uint16)pc.getOffset()); offsetStr = str + 2; } else if (!scumm_strnicmp(str + 1, "PREV", 4)) { *dest = s->r_prev; diff --git a/engines/sci/console.h b/engines/sci/console.h index be17fdb728..1c54748842 100644 --- a/engines/sci/console.h +++ b/engines/sci/console.h @@ -33,7 +33,7 @@ namespace Sci { class SciEngine; struct List; -reg_t disassemble(EngineState *s, reg_t pos, bool printBWTag, bool printBytecode); +reg_t disassemble(EngineState *s, reg32_t pos, bool printBWTag, bool printBytecode); bool isJumpOpcode(EngineState *s, reg_t pos, reg_t& jumpOffset); class Console : public GUI::Debugger { diff --git a/engines/sci/engine/script.cpp b/engines/sci/engine/script.cpp index 80aaedfece..57334b89aa 100644 --- a/engines/sci/engine/script.cpp +++ b/engines/sci/engine/script.cpp @@ -385,7 +385,7 @@ void Script::setLockers(int lockers) { _lockers = lockers; } -uint16 Script::validateExportFunc(int pubfunct, bool relocateSci3) { +uint32 Script::validateExportFunc(int pubfunct, bool relocateSci3) { bool exportsAreWide = (g_sci->_features->detectLofsType() == SCI_VERSION_1_MIDDLE); if (_numExports <= pubfunct) { @@ -396,7 +396,7 @@ uint16 Script::validateExportFunc(int pubfunct, bool relocateSci3) { if (exportsAreWide) pubfunct *= 2; - uint16 offset; + uint32 offset; if (getSciVersion() != SCI_VERSION_3) { offset = READ_SCI11ENDIAN_UINT16(_exportTable + pubfunct); diff --git a/engines/sci/engine/script.h b/engines/sci/engine/script.h index 9747f072c5..1fc8caf313 100644 --- a/engines/sci/engine/script.h +++ b/engines/sci/engine/script.h @@ -201,7 +201,7 @@ public: * @return NULL if the public function is invalid, its * offset into the script's segment otherwise */ - uint16 validateExportFunc(int pubfunct, bool relocateSci3); + uint32 validateExportFunc(int pubfunct, bool relocateSci3); /** * Marks the script as deleted. diff --git a/engines/sci/engine/scriptdebug.cpp b/engines/sci/engine/scriptdebug.cpp index 04cbf1d97c..d3abb9ff41 100644 --- a/engines/sci/engine/scriptdebug.cpp +++ b/engines/sci/engine/scriptdebug.cpp @@ -68,7 +68,7 @@ const char *opcodeNames[] = { #endif // REDUCE_MEMORY_USAGE // Disassembles one command from the heap, returns address of next command or 0 if a ret was encountered. -reg_t disassemble(EngineState *s, reg_t pos, bool printBWTag, bool printBytecode) { +reg_t disassemble(EngineState *s, reg32_t pos, bool printBWTag, bool printBytecode) { SegmentObj *mobj = s->_segMan->getSegment(pos.getSegment(), SEG_TYPE_SCRIPT); Script *script_entity = NULL; const byte *scr; @@ -347,7 +347,7 @@ void SciEngine::scriptDebug() { } if (_debugState.seeking != kDebugSeekNothing) { - const reg_t pc = s->xs->addr.pc; + const reg32_t pc = s->xs->addr.pc; SegmentObj *mobj = s->_segMan->getSegment(pc.getSegment(), SEG_TYPE_SCRIPT); if (mobj) { diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index a42606a6a6..5a2a39def2 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -233,7 +233,7 @@ ExecStack *execute_method(EngineState *s, uint16 script, uint16 pubfunct, StackP g_sci->checkExportBreakpoint(script, pubfunct); ExecStack xstack(calling_obj, calling_obj, sp, argc, argp, - seg, make_reg(seg, exportAddr), -1, pubfunct, -1, + seg, make_reg32(seg, exportAddr), -1, pubfunct, -1, s->_executionStack.size() - 1, EXEC_STACK_TYPE_CALL); s->_executionStack.push_back(xstack); return &(s->_executionStack.back()); @@ -289,11 +289,12 @@ ExecStack *send_selector(EngineState *s, reg_t send_obj, reg_t work_obj, StackPt ExecStackType stackType = EXEC_STACK_TYPE_VARSELECTOR; StackPtr curSP = NULL; - reg_t curFP = NULL_REG; + reg32_t curFP = make_reg32(0, 0); if (selectorType == kSelectorMethod) { stackType = EXEC_STACK_TYPE_CALL; curSP = sp; - curFP = funcp; + // TODO: Will this offset suffice for large SCI3 scripts? + curFP = make_reg32(funcp.getSegment(), funcp.getOffset()); sp = CALL_SP_CARRY; // Destroy sp, as it will be carried over } @@ -327,7 +328,7 @@ static void addKernelCallToExecStack(EngineState *s, int kernelCallNr, int argc, // Add stack frame to indicate we're executing a callk. // This is useful in debugger backtraces if this // kernel function calls a script itself. - ExecStack xstack(NULL_REG, NULL_REG, NULL, argc, argv - 1, 0xFFFF, NULL_REG, + ExecStack xstack(NULL_REG, NULL_REG, NULL, argc, argv - 1, 0xFFFF, make_reg32(0, 0), kernelCallNr, -1, -1, s->_executionStack.size() - 1, EXEC_STACK_TYPE_KERNEL); s->_executionStack.push_back(xstack); } @@ -818,11 +819,11 @@ void run_vm(EngineState *s) { StackPtr call_base = s->xs->sp - argc; s->xs->sp[1].incOffset(s->r_rest); - uint16 localCallOffset = s->xs->addr.pc.getOffset() + opparams[0]; + uint32 localCallOffset = s->xs->addr.pc.getOffset() + opparams[0]; ExecStack xstack(s->xs->objp, s->xs->objp, s->xs->sp, (call_base->requireUint16()) + s->r_rest, call_base, - s->xs->local_segment, make_reg(s->xs->addr.pc.getSegment(), localCallOffset), + s->xs->local_segment, make_reg32(s->xs->addr.pc.getSegment(), localCallOffset), NULL_SELECTOR, -1, localCallOffset, s->_executionStack.size() - 1, EXEC_STACK_TYPE_CALL); @@ -1117,7 +1118,7 @@ void run_vm(EngineState *s) { switch (g_sci->_features->detectLofsType()) { case SCI_VERSION_0_EARLY: - r_temp.setOffset(s->xs->addr.pc.getOffset() + opparams[0]); + r_temp.setOffset((uint16)s->xs->addr.pc.getOffset() + opparams[0]); break; case SCI_VERSION_1_MIDDLE: r_temp.setOffset(opparams[0]); diff --git a/engines/sci/engine/vm.h b/engines/sci/engine/vm.h index f2d225b1d8..a0fd6689df 100644 --- a/engines/sci/engine/vm.h +++ b/engines/sci/engine/vm.h @@ -82,7 +82,7 @@ struct ExecStack { union { ObjVarRef varp; // Variable pointer for r/w access - reg_t pc; // Pointer to the initial program counter. Not accurate for the TOS element + reg32_t pc; // Pointer to the initial program counter. Not accurate for the TOS element } addr; StackPtr fp; // Frame pointer @@ -102,7 +102,7 @@ struct ExecStack { reg_t* getVarPointer(SegManager *segMan) const; ExecStack(reg_t objp_, reg_t sendp_, StackPtr sp_, int argc_, StackPtr argp_, - SegmentId localsSegment_, reg_t pc_, Selector debugSelector_, + SegmentId localsSegment_, reg32_t pc_, Selector debugSelector_, int debugExportId_, int debugLocalCallOffset_, int debugOrigin_, ExecStackType type_) { objp = objp_; diff --git a/engines/sci/engine/vm_types.h b/engines/sci/engine/vm_types.h index 2995ba3c12..9a7589e9a7 100644 --- a/engines/sci/engine/vm_types.h +++ b/engines/sci/engine/vm_types.h @@ -169,6 +169,49 @@ static inline reg_t make_reg(SegmentId segment, uint16 offset) { #define PRINT_REG(r) (0xffff) & (unsigned) (r).getSegment(), (unsigned) (r).getOffset() +// A true 32-bit reg_t +struct reg32_t { + // Segment and offset. These should never be accessed directly + SegmentId _segment; + uint32 _offset; + + inline SegmentId getSegment() const { + return _segment; + } + + inline void setSegment(SegmentId segment) { + _segment = segment; + } + + inline uint32 getOffset() const { + return _offset; + } + + inline void setOffset(uint32 offset) { + _offset = offset; + } + + inline void incOffset(int32 offset) { + setOffset(getOffset() + offset); + } + + // Comparison operators + bool operator==(const reg32_t &x) const { + return (getOffset() == x.getOffset()) && (getSegment() == x.getSegment()); + } + + bool operator!=(const reg32_t &x) const { + return (getOffset() != x.getOffset()) || (getSegment() != x.getSegment()); + } +}; + +static inline reg32_t make_reg32(SegmentId segment, uint32 offset) { + reg32_t r; + r.setSegment(segment); + r.setOffset(offset); + return r; +} + // Stack pointer type typedef reg_t *StackPtr; -- cgit v1.2.3 From 99de89c974fc24bf58b034842750e522d7d441d4 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sun, 24 Jun 2012 19:52:37 +0300 Subject: SCI: Add a workaround for script bug #3537232 The bug in question is "SCI: SQ4 Floppy DOS title screen skipping too quickly", and is caused by game scripts not waiting between palette calls --- engines/sci/engine/kgraphics.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'engines/sci') diff --git a/engines/sci/engine/kgraphics.cpp b/engines/sci/engine/kgraphics.cpp index 0ef268f108..ec8e0dbf1b 100644 --- a/engines/sci/engine/kgraphics.cpp +++ b/engines/sci/engine/kgraphics.cpp @@ -645,6 +645,20 @@ reg_t kPaletteAnimate(EngineState *s, int argc, reg_t *argv) { if (paletteChanged) g_sci->_gfxPalette->kernelAnimateSet(); + // WORKAROUND: The game scripts in SQ4 floppy count the number of elapsed + // cycles in the intro from the number of successive kAnimate calls during + // the palette cycling effect, while showing the SQ4 logo. This worked in + // older computers because each animate call took awhile to complete. + // Normally, such scripts are handled automatically by our speed throttler, + // however in this case there are no calls to kGameIsRestarting (where the + // speed throttler gets called) between the different palette animation calls. + // Thus, we add a small delay between each animate call to make the whole + // palette animation effect slower and visible, and not have the logo screen + // get skipped because the scripts don't wait between animation steps. Fixes + // bug #3537232. + if (g_sci->getGameId() == GID_SQ4 && !g_sci->isCD() && s->currentRoomNumber() == 1) + g_sci->sleep(10); + return s->r_acc; } -- cgit v1.2.3 From 7e66cbd468a5b89eaf170d5e0fb3bb312365628c Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Tue, 26 Jun 2012 11:12:37 +0300 Subject: SCI: Rename a parameter in validateExportFunc() This ensures that it won't be confused with a function with the same name --- engines/sci/engine/script.cpp | 4 ++-- engines/sci/engine/script.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/engine/script.cpp b/engines/sci/engine/script.cpp index 57334b89aa..d4143dcceb 100644 --- a/engines/sci/engine/script.cpp +++ b/engines/sci/engine/script.cpp @@ -385,7 +385,7 @@ void Script::setLockers(int lockers) { _lockers = lockers; } -uint32 Script::validateExportFunc(int pubfunct, bool relocateSci3) { +uint32 Script::validateExportFunc(int pubfunct, bool relocSci3) { bool exportsAreWide = (g_sci->_features->detectLofsType() == SCI_VERSION_1_MIDDLE); if (_numExports <= pubfunct) { @@ -401,7 +401,7 @@ uint32 Script::validateExportFunc(int pubfunct, bool relocateSci3) { if (getSciVersion() != SCI_VERSION_3) { offset = READ_SCI11ENDIAN_UINT16(_exportTable + pubfunct); } else { - if (!relocateSci3) + if (!relocSci3) offset = READ_SCI11ENDIAN_UINT16(_exportTable + pubfunct) + getCodeBlockOffsetSci3(); else offset = relocateOffsetSci3(pubfunct * 2 + 22); diff --git a/engines/sci/engine/script.h b/engines/sci/engine/script.h index 1fc8caf313..0b499203c2 100644 --- a/engines/sci/engine/script.h +++ b/engines/sci/engine/script.h @@ -197,11 +197,11 @@ public: * Validate whether the specified public function is exported by * the script in the specified segment. * @param pubfunct Index of the function to validate - * @param relocateSci3 Decide whether to relocate this SCI3 public function or not + * @param relocSci3 Decide whether to relocate this SCI3 public function or not * @return NULL if the public function is invalid, its * offset into the script's segment otherwise */ - uint32 validateExportFunc(int pubfunct, bool relocateSci3); + uint32 validateExportFunc(int pubfunct, bool relocSci3); /** * Marks the script as deleted. -- cgit v1.2.3 From 152b340a9ac502434e99da79e880625626209adc Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Tue, 26 Jun 2012 13:22:05 +0300 Subject: SCI: Remove a music fading hack used for the intro of Longbow --- engines/sci/sound/soundcmd.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/sound/soundcmd.cpp b/engines/sci/sound/soundcmd.cpp index 989df7c8a1..cbb5cab4fe 100644 --- a/engines/sci/sound/soundcmd.cpp +++ b/engines/sci/sound/soundcmd.cpp @@ -368,6 +368,11 @@ reg_t SoundCommandParser::kDoSoundFade(int argc, reg_t *argv, reg_t acc) { case 4: // SCI01+ case 5: // SCI1+ (SCI1 late sound scheme), with fade and continue musicSlot->fadeTo = CLIP(argv[1].toUint16(), 0, MUSIC_VOLUME_MAX); + // Check if the song is already at the requested volume. If it is, don't + // perform any fading. Happens for example during the intro of Longbow. + if (musicSlot->fadeTo == musicSlot->volume) + return acc; + // sometimes we get objects in that position, fix it up (ffs. workarounds) if (!argv[1].getSegment()) musicSlot->fadeStep = volume > musicSlot->fadeTo ? -argv[3].toUint16() : argv[3].toUint16(); @@ -497,12 +502,7 @@ void SoundCommandParser::processUpdateCues(reg_t obj) { // fireworks). // It is also needed in other games, e.g. LSL6 when talking to the // receptionist (bug #3192166). - if (g_sci->getGameId() == GID_LONGBOW && g_sci->getEngineState()->currentRoomNumber() == 95) { - // HACK: Don't set a signal here in the intro of Longbow, as that makes some dialog - // boxes disappear too soon (bug #3044844). - } else { - writeSelectorValue(_segMan, obj, SELECTOR(signal), SIGNAL_OFFSET); - } + writeSelectorValue(_segMan, obj, SELECTOR(signal), SIGNAL_OFFSET); if (_soundVersion <= SCI_VERSION_0_LATE) { processStopSound(obj, false); } else { -- cgit v1.2.3 From 12b8534e2f56451cd9c142cd3c7725bbde4f9f10 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Thu, 28 Jun 2012 03:27:34 +0300 Subject: SCI: Fix the detection entry for the Spanish version of KQ6 There is no Spanish CD version of KQ6, only floppy. This also seems to fix the bug with the puzzle in the cliffs of wisdom (room 300) --- engines/sci/detection_tables.h | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/detection_tables.h b/engines/sci/detection_tables.h index 9872973e09..7c51c03b06 100644 --- a/engines/sci/detection_tables.h +++ b/engines/sci/detection_tables.h @@ -1447,6 +1447,16 @@ static const struct ADGameDescription SciGameDescriptions[] = { AD_LISTEND}, Common::DE_DEU, Common::kPlatformPC, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + // King's Quest 6 - Spanish DOS Floppy (from jvprat) + // Executable scanning reports "1.cfs.158", VERSION file reports "1.000.000, July 5, 1994" + // SCI interpreter version 1.001.055 + {"kq6", "", { + {"resource.map", 0, "a73a5ab04b8f60c4b75b946a4dccea5a", 8953}, + {"resource.000", 0, "4da3ad5868a775549a7cc4f72770a58e", 8537260}, + {"resource.msg", 0, "41eed2d3893e1ca6c3695deba4e9d2e8", 267102}, + AD_LISTEND}, + Common::ES_ESP, Common::kPlatformPC, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + // King's Quest 6 - English DOS CD (from the King's Quest Collection) // Executable scanning reports "1.cfs.158", VERSION file reports "1.034 9/11/94 - KQ6 version 1.000.00G" // SCI interpreter version 1.001.054 @@ -1465,16 +1475,6 @@ static const struct ADGameDescription SciGameDescriptions[] = { AD_LISTEND}, Common::EN_ANY, Common::kPlatformWindows, ADGF_CD, GUIO5(GUIO_NOASPECT, GAMEOPTION_KQ6_WINDOWS_CURSORS, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, - // King's Quest 6 - Spanish DOS CD (from jvprat) - // Executable scanning reports "1.cfs.158", VERSION file reports "1.000.000, July 5, 1994" - // SCI interpreter version 1.001.055 - {"kq6", "CD", { - {"resource.map", 0, "a73a5ab04b8f60c4b75b946a4dccea5a", 8953}, - {"resource.000", 0, "4da3ad5868a775549a7cc4f72770a58e", 8537260}, - {"resource.msg", 0, "41eed2d3893e1ca6c3695deba4e9d2e8", 267102}, - AD_LISTEND}, - Common::ES_ESP, Common::kPlatformPC, ADGF_CD, GUIO3(GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, - // King's Quest 6 - English Macintosh Floppy // VERSION file reports "1.0" {"kq6", "", { -- cgit v1.2.3 From cc7768869690261d0f6ee3fddc8f0800307813bb Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Thu, 28 Jun 2012 03:29:34 +0300 Subject: SCI: Remove an incorrect error check in validateExportFunc() --- engines/sci/engine/script.cpp | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/engine/script.cpp b/engines/sci/engine/script.cpp index d4143dcceb..037f4ab700 100644 --- a/engines/sci/engine/script.cpp +++ b/engines/sci/engine/script.cpp @@ -422,16 +422,9 @@ uint32 Script::validateExportFunc(int pubfunct, bool relocSci3) { } } - if (!offset) { -#ifdef ENABLE_SCI32 - // WORKAROUNDS for invalid (empty) exports - if (g_sci->getGameId() == GID_TORIN && _nr == 64036) { - } else if (g_sci->getGameId() == GID_RAMA && _nr == 64908) { - } else -#endif - error("Request for invalid exported function 0x%x of script %d", pubfunct, _nr); - return NULL; - } + // Note that it's perfectly normal to return a zero offset, especially in + // SCI1.1 and newer games. Examples include script 64036 in Torin's Passage, + // script 64908 in the demo of RAMA and script 1013 in KQ6 floppy. if (offset >= _bufSize) error("Invalid export function pointer"); -- cgit v1.2.3 From 848575b8264e99eeab2dd0f24dda986909048b93 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Thu, 28 Jun 2012 03:27:34 +0300 Subject: SCI: Fix bug #3538418 in SQ4CD Add a script patch for another speech/subtitles script, which handles the babble icon shown in the quit/death dialogs (e.g. the two guys from Andromeda in the quit dialog). Now, these dialogs have speech both in the speech and the speech + subtitles modes --- engines/sci/engine/script_patches.cpp | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) (limited to 'engines/sci') diff --git a/engines/sci/engine/script_patches.cpp b/engines/sci/engine/script_patches.cpp index 69eb377684..659c13b13e 100644 --- a/engines/sci/engine/script_patches.cpp +++ b/engines/sci/engine/script_patches.cpp @@ -978,7 +978,27 @@ const uint16 sq4CdPatchTextOptionsButton[] = { PATCH_END }; -// Patch 2: Add the ability to toggle among the three available options, +// Patch 2: Adjust a check in babbleIcon::init, which handles the babble icon +// (e.g. the two guys from Andromeda) shown when dying/quitting. +// Fixes bug #3538418. +const byte sq4CdSignatureBabbleIcon[] = { + 7, + 0x89, 0x5a, // lsg 5a + 0x35, 0x02, // ldi 02 + 0x1a, // eq? + 0x31, 0x26, // bnt 26 [02a7] + 0 +}; + +const uint16 sq4CdPatchBabbleIcon[] = { + 0x89, 0x5a, // lsg 5a + 0x35, 0x01, // ldi 01 + 0x1a, // eq? + 0x2f, 0x26, // bt 26 [02a7] + PATCH_END +}; + +// Patch 3: Add the ability to toggle among the three available options, // when the text options button is clicked: "Speech", "Text" and "Both". // Refer to the patch above for additional details. // iconTextSwitch::doit (called when the text options button is clicked) @@ -1030,6 +1050,7 @@ const SciScriptSignature sq4Signatures[] = { { 298, "Floppy: endless flight", 1, PATCH_MAGICDWORD(0x67, 0x08, 0x63, 0x44), -3, sq4FloppySignatureEndlessFlight, sq4FloppyPatchEndlessFlight }, { 298, "Floppy (German): endless flight", 1, PATCH_MAGICDWORD(0x67, 0x08, 0x63, 0x4c), -3, sq4FloppySignatureEndlessFlightGerman, sq4FloppyPatchEndlessFlight }, { 818, "CD: Speech and subtitles option", 1, PATCH_MAGICDWORD(0x89, 0x5a, 0x3c, 0x35), 0, sq4CdSignatureTextOptions, sq4CdPatchTextOptions }, + { 0, "CD: Babble icon speech and subtitles fix", 1, PATCH_MAGICDWORD(0x89, 0x5a, 0x35, 0x02), 0, sq4CdSignatureBabbleIcon, sq4CdPatchBabbleIcon }, { 818, "CD: Speech and subtitles option button", 1, PATCH_MAGICDWORD(0x35, 0x01, 0xa1, 0x53), 0, sq4CdSignatureTextOptionsButton, sq4CdPatchTextOptionsButton }, SCI_SIGNATUREENTRY_TERMINATOR }; -- cgit v1.2.3 From 44935117f493b2e256b5a2c701b63cef57d872af Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Mon, 2 Jul 2012 11:37:55 +0300 Subject: SCI: Fix a workaround for an uninitialized variable in SQ4CD This makes sure that the workaround works for subclassed objects as well, such as "theProfessor" talker. Fixes bug #3539350 - "SCI: SQ4 CD - Crash in sewer when text and speech enabled" --- engines/sci/engine/workarounds.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines/sci') diff --git a/engines/sci/engine/workarounds.cpp b/engines/sci/engine/workarounds.cpp index ecb1e4c2d5..15fca0322c 100644 --- a/engines/sci/engine/workarounds.cpp +++ b/engines/sci/engine/workarounds.cpp @@ -162,7 +162,7 @@ const SciWorkaroundEntry uninitializedReadWorkarounds[] = { { GID_SQ1, -1, 703, 0, "", "export 1", -1, 0, { WORKAROUND_FAKE, 0 } }, // sub that's called from several objects while on sarien battle cruiser { GID_SQ1, -1, 703, 0, "firePulsar", "changeState", 0x18a, 0, { WORKAROUND_FAKE, 0 } }, // export 1, but called locally (when shooting at aliens) { GID_SQ4, -1, 398, 0, "showBox", "changeState", -1, 0, { WORKAROUND_FAKE, 0 } }, // CD: called when rummaging in Software Excess bargain bin - { GID_SQ4, -1, 928, 0, "Narrator", "startText", -1, 1000, { WORKAROUND_FAKE, 1 } }, // CD: method returns this to the caller + { GID_SQ4, -1, 928, -1, "Narrator", "startText", -1, 1000, { WORKAROUND_FAKE, 1 } }, // CD: happens in the options dialog and in-game when speech and subtitles are used simultaneously { GID_SQ5, 201, 201, 0, "buttonPanel", "doVerb", -1, 0, { WORKAROUND_FAKE, 1 } }, // when looking at the orange or red button - bug #3038563 { GID_SQ6, -1, 0, 0, "SQ6", "init", -1, 2, { WORKAROUND_FAKE, 0 } }, // Demo and full version: called when the game starts (demo: room 0, full: room 100) { GID_SQ6, 100, 64950, 0, "View", "handleEvent", -1, 0, { WORKAROUND_FAKE, 0 } }, // called when pressing "Start game" in the main menu -- cgit v1.2.3 From f6e4312665614d7b5b626f997194fbbcb00ddbb0 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Mon, 2 Jul 2012 12:48:02 +0300 Subject: SCI: Add a hack for a bug in the script handling code When resetting the segment manager, sometimes the locals block for a script is placed in a segment smaller than the script itself. This shouldn't be happening, but it isn't fatal, however it should be resolved in a proper manner --- engines/sci/engine/seg_manager.cpp | 41 ++++++++++++++++++++------------------ engines/sci/engine/seg_manager.h | 8 -------- 2 files changed, 22 insertions(+), 27 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/engine/seg_manager.cpp b/engines/sci/engine/seg_manager.cpp index a6c145979f..d425e170ce 100644 --- a/engines/sci/engine/seg_manager.cpp +++ b/engines/sci/engine/seg_manager.cpp @@ -143,16 +143,34 @@ Script *SegManager::allocateScript(int script_nr, SegmentId *segid) { } void SegManager::deallocate(SegmentId seg) { - if (!check(seg)) - error("SegManager::deallocate(): invalid segment ID"); + if (seg < 1 || (uint)seg >= _heap.size()) + error("Attempt to deallocate an invalid segment ID"); SegmentObj *mobj = _heap[seg]; + if (!mobj) + error("Attempt to deallocate an already freed segment"); if (mobj->getType() == SEG_TYPE_SCRIPT) { Script *scr = (Script *)mobj; _scriptSegMap.erase(scr->getScriptNumber()); - if (scr->getLocalsSegment()) - deallocate(scr->getLocalsSegment()); + if (scr->getLocalsSegment()) { + // HACK: Check if the locals segment has already been deallocated. + // This happens sometimes in SQ4CD when resetting the segment + // manager: the locals for script 808 are somehow stored in a + // smaller segment than the script itself, so by the time the script + // is about to be freed, the locals block has already been freed. + // This isn't fatal, but it shouldn't be happening at all. + // FIXME: Check why this happens. Perhaps there's a bug in the + // script handling code? + if (!_heap[scr->getLocalsSegment()]) { + warning("SegManager::deallocate(): The locals block of script " + "%d has already been deallocated. Script segment: %d, " + "locals segment: %d", scr->getScriptNumber(), seg, + scr->getLocalsSegment()); + } else { + deallocate(scr->getLocalsSegment()); + } + } } delete mobj; @@ -307,21 +325,6 @@ reg_t SegManager::findObjectByName(const Common::String &name, int index) { return result[index]; } -// validate the seg -// return: -// false - invalid seg -// true - valid seg -bool SegManager::check(SegmentId seg) { - if (seg < 1 || (uint)seg >= _heap.size()) { - return false; - } - if (!_heap[seg]) { - warning("SegManager: seg %x is removed from memory, but not removed from hash_map", seg); - return false; - } - return true; -} - // return the seg if script_id is valid and in the map, else 0 SegmentId SegManager::getScriptSegment(int script_id) const { return _scriptSegMap.getVal(script_id, 0); diff --git a/engines/sci/engine/seg_manager.h b/engines/sci/engine/seg_manager.h index 356a1b04a7..074d3f6b0a 100644 --- a/engines/sci/engine/seg_manager.h +++ b/engines/sci/engine/seg_manager.h @@ -471,14 +471,6 @@ private: void createClassTable(); SegmentId findFreeSegment() const; - - /** - * Check segment validity - * @param[in] seg The segment to validate - * @return false if 'seg' is an invalid segment, true if - * 'seg' is a valid segment - */ - bool check(SegmentId seg); }; } // End of namespace Sci -- cgit v1.2.3 From b091c0bd090f075e6e0b796785c400dbe9d2b8ac Mon Sep 17 00:00:00 2001 From: Willem Jan Palenstijn Date: Tue, 3 Jul 2012 00:00:38 +0200 Subject: SCI: Remove unnecessary const-cast --- engines/sci/engine/kvideo.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/engine/kvideo.cpp b/engines/sci/engine/kvideo.cpp index 2456ba1100..61d2f935f7 100644 --- a/engines/sci/engine/kvideo.cpp +++ b/engines/sci/engine/kvideo.cpp @@ -90,7 +90,7 @@ void playVideo(Video::VideoDecoder *videoDecoder, VideoState videoState) { EngineState *s = g_sci->getEngineState(); if (videoDecoder->hasDirtyPalette()) { - byte *palette = (byte *)videoDecoder->getPalette() + s->_vmdPalStart * 3; + const byte *palette = videoDecoder->getPalette() + s->_vmdPalStart * 3; g_system->getPaletteManager()->setPalette(palette, s->_vmdPalStart, s->_vmdPalEnd - s->_vmdPalStart); } @@ -108,7 +108,7 @@ void playVideo(Video::VideoDecoder *videoDecoder, VideoState videoState) { } if (videoDecoder->hasDirtyPalette()) { - byte *palette = (byte *)videoDecoder->getPalette() + s->_vmdPalStart * 3; + const byte *palette = videoDecoder->getPalette() + s->_vmdPalStart * 3; g_system->getPaletteManager()->setPalette(palette, s->_vmdPalStart, s->_vmdPalEnd - s->_vmdPalStart); } -- cgit v1.2.3 From c80429008f135c236544846920f488680fa7c200 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Tue, 3 Jul 2012 03:33:42 +0300 Subject: SCI: Remove an unnecessary warning and related FIXME comments It's perfectly normal behavior to have locals with a smaller segment ID than the ID of their respective script, e.g. when scripts are uninstantiated and then instantiated again --- engines/sci/engine/seg_manager.cpp | 23 ++++++++--------------- 1 file changed, 8 insertions(+), 15 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/engine/seg_manager.cpp b/engines/sci/engine/seg_manager.cpp index d425e170ce..951fc7c363 100644 --- a/engines/sci/engine/seg_manager.cpp +++ b/engines/sci/engine/seg_manager.cpp @@ -154,22 +154,15 @@ void SegManager::deallocate(SegmentId seg) { Script *scr = (Script *)mobj; _scriptSegMap.erase(scr->getScriptNumber()); if (scr->getLocalsSegment()) { - // HACK: Check if the locals segment has already been deallocated. - // This happens sometimes in SQ4CD when resetting the segment - // manager: the locals for script 808 are somehow stored in a - // smaller segment than the script itself, so by the time the script - // is about to be freed, the locals block has already been freed. - // This isn't fatal, but it shouldn't be happening at all. - // FIXME: Check why this happens. Perhaps there's a bug in the - // script handling code? - if (!_heap[scr->getLocalsSegment()]) { - warning("SegManager::deallocate(): The locals block of script " - "%d has already been deallocated. Script segment: %d, " - "locals segment: %d", scr->getScriptNumber(), seg, - scr->getLocalsSegment()); - } else { + // Check if the locals segment has already been deallocated. + // If the locals block has been stored in a segment with an ID + // smaller than the segment ID of the script itself, it will be + // already freed at this point. This can happen when scripts are + // uninstantiated and instantiated again: they retain their own + // segment ID, but are allocated a new locals segment, which can + // have an ID smaller than the segment of the script itself. + if (_heap[scr->getLocalsSegment()]) deallocate(scr->getLocalsSegment()); - } } } -- cgit v1.2.3 From 9184a40fcc2263fae7bc67777346f592d50a39eb Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Tue, 3 Jul 2012 03:46:27 +0300 Subject: SCI: Fix incorrect game options for SQ4CD --- engines/sci/detection_tables.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines/sci') diff --git a/engines/sci/detection_tables.h b/engines/sci/detection_tables.h index 7c51c03b06..07b4733cfd 100644 --- a/engines/sci/detection_tables.h +++ b/engines/sci/detection_tables.h @@ -3536,7 +3536,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "ed90a8e3ccc53af6633ff6ab58392bae", 7054}, {"resource.000", 0, "63247e3901ab8963d4eece73747832e0", 5157378}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, ADGF_CD, GUIO1(GAMEOPTION_SQ4_SILVER_CURSORS) }, + Common::EN_ANY, Common::kPlatformPC, ADGF_CD, GUIO5(GUIO_MIDIGM, GAMEOPTION_SQ4_SILVER_CURSORS, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Space Quest 4 - English Windows CD (from the Space Quest Collection) // Executable scanning reports "1.001.064", VERSION file reports "1.0" -- cgit v1.2.3 From 5a47afea9ed5d0cca89ca01d48be937dcba02bbd Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Tue, 3 Jul 2012 18:11:41 +0300 Subject: SCI: Move kGetWindowsOption together with the other misc kernel functions --- engines/sci/engine/kgraphics32.cpp | 12 ------------ engines/sci/engine/kmisc.cpp | 12 ++++++++++++ 2 files changed, 12 insertions(+), 12 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/engine/kgraphics32.cpp b/engines/sci/engine/kgraphics32.cpp index 413ad1ecb1..14ea409a58 100644 --- a/engines/sci/engine/kgraphics32.cpp +++ b/engines/sci/engine/kgraphics32.cpp @@ -197,18 +197,6 @@ reg_t kDisposeTextBitmap(EngineState *s, int argc, reg_t *argv) { return s->r_acc; } -reg_t kGetWindowsOption(EngineState *s, int argc, reg_t *argv) { - uint16 windowsOption = argv[0].toUint16(); - switch (windowsOption) { - case 0: - // Title bar on/off in Phantasmagoria, we return 0 (off) - return NULL_REG; - default: - warning("GetWindowsOption: Unknown option %d", windowsOption); - return NULL_REG; - } -} - reg_t kWinHelp(EngineState *s, int argc, reg_t *argv) { switch (argv[0].toUint16()) { case 1: diff --git a/engines/sci/engine/kmisc.cpp b/engines/sci/engine/kmisc.cpp index 12c830f622..8b7fc4ffec 100644 --- a/engines/sci/engine/kmisc.cpp +++ b/engines/sci/engine/kmisc.cpp @@ -419,6 +419,18 @@ reg_t kGetSierraProfileInt(EngineState *s, int argc, reg_t *argv) { return argv[2]; } +reg_t kGetWindowsOption(EngineState *s, int argc, reg_t *argv) { + uint16 windowsOption = argv[0].toUint16(); + switch (windowsOption) { + case 0: + // Title bar on/off in Phantasmagoria, we return 0 (off) + return NULL_REG; + default: + warning("GetWindowsOption: Unknown option %d", windowsOption); + return NULL_REG; + } +} + #endif // kIconBar is really a subop of kMacPlatform for SCI1.1 Mac -- cgit v1.2.3 From 05bd736d163f7e18ce27cd483a7e0f35adf1dce9 Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Tue, 3 Jul 2012 18:35:43 +0200 Subject: SCI: Slight cleanup in querySaveMetaInfos. --- engines/sci/detection.cpp | 3 --- 1 file changed, 3 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/detection.cpp b/engines/sci/detection.cpp index 78df3065b2..8a74bc817c 100644 --- a/engines/sci/detection.cpp +++ b/engines/sci/detection.cpp @@ -762,9 +762,6 @@ SaveStateDescriptor SciMetaEngine::querySaveMetaInfos(const char *target, int sl Graphics::Surface *const thumbnail = Graphics::loadThumbnail(*in); desc.setThumbnail(thumbnail); - desc.setDeletableFlag(true); - desc.setWriteProtectedFlag(false); - int day = (meta.saveDate >> 24) & 0xFF; int month = (meta.saveDate >> 16) & 0xFF; int year = meta.saveDate & 0xFFFF; -- cgit v1.2.3 From 72c59baf247e09c7b40afd1c48221827ef1d64df Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Wed, 4 Jul 2012 00:57:59 +0300 Subject: SCI: Merge and simplify the code that sets the kernel functions --- engines/sci/engine/kernel.cpp | 125 ++++++++++++++++++++----------------- engines/sci/engine/kernel.h | 18 +----- engines/sci/engine/kernel_tables.h | 4 +- 3 files changed, 69 insertions(+), 78 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/engine/kernel.cpp b/engines/sci/engine/kernel.cpp index c8fe47d9fc..924641cdbe 100644 --- a/engines/sci/engine/kernel.cpp +++ b/engines/sci/engine/kernel.cpp @@ -757,13 +757,26 @@ bool Kernel::debugSetFunction(const char *kernelName, int logging, int breakpoin return true; } -void Kernel::setDefaultKernelNames(GameFeatures *features) { - _kernelNames = Common::StringArray(s_defaultKernelNames, ARRAYSIZE(s_defaultKernelNames)); +#ifdef ENABLE_SCI32 +enum { + kKernelEntriesSci2 = 0x8b, + kKernelEntriesGk2Demo = 0xa0, + kKernelEntriesSci21 = 0x9d, + kKernelEntriesSci3 = 0xa1 +}; +#endif + +void Kernel::loadKernelNames(GameFeatures *features) { + _kernelNames.clear(); - // Some (later) SCI versions replaced CanBeHere by CantBeHere - // If vocab.999 exists, the kernel function is still named CanBeHere - if (_selectorCache.cantBeHere != -1) - _kernelNames[0x4d] = "CantBeHere"; + if (getSciVersion() <= SCI_VERSION_1_1) { + _kernelNames = Common::StringArray(s_defaultKernelNames, ARRAYSIZE(s_defaultKernelNames)); + + // Some (later) SCI versions replaced CanBeHere by CantBeHere + // If vocab.999 exists, the kernel function is still named CanBeHere + if (_selectorCache.cantBeHere != -1) + _kernelNames[0x4d] = "CantBeHere"; + } switch (getSciVersion()) { case SCI_VERSION_0_EARLY: @@ -817,66 +830,60 @@ void Kernel::setDefaultKernelNames(GameFeatures *features) { _kernelNames[0x7c] = "Message"; break; - default: - // Use default table for the other versions - break; - } -} - #ifdef ENABLE_SCI32 + case SCI_VERSION_2: + _kernelNames = Common::StringArray(sci2_default_knames, kKernelEntriesSci2); + break; -enum { - kKernelEntriesSci2 = 0x8b, - kKernelEntriesGk2Demo = 0xa0, - kKernelEntriesSci21 = 0x9d, - kKernelEntriesSci3 = 0xa1 -}; - -void Kernel::setKernelNamesSci2() { - _kernelNames = Common::StringArray(sci2_default_knames, kKernelEntriesSci2); -} + case SCI_VERSION_2_1: + if (features->detectSci21KernelType() == SCI_VERSION_2) { + // Some late SCI2.1 games use a modified SCI2 kernel table instead of + // the SCI2.1 kernel table. We detect which version to use based on + // how kDoSound is called from Sound::play(). + // Known games that use this: + // GK2 demo + // KQ7 1.4 + // PQ4 SWAT demo + // LSL6 + // PQ4CD + // QFG4CD + + // This is interesting because they all have the same interpreter + // version (2.100.002), yet they would not be compatible with other + // games of the same interpreter. + + _kernelNames = Common::StringArray(sci2_default_knames, kKernelEntriesGk2Demo); + // OnMe is IsOnMe here, but they should be compatible + _kernelNames[0x23] = "Robot"; // Graph in SCI2 + _kernelNames[0x2e] = "Priority"; // DisposeTextBitmap in SCI2 + } else { + // Normal SCI2.1 kernel table + _kernelNames = Common::StringArray(sci21_default_knames, kKernelEntriesSci21); + } + break; -void Kernel::setKernelNamesSci21(GameFeatures *features) { - // Some SCI games use a modified SCI2 kernel table instead of the - // SCI2.1 kernel table. We detect which version to use based on - // how kDoSound is called from Sound::play(). - // Known games that use this: - // GK2 demo - // KQ7 1.4 - // PQ4 SWAT demo - // LSL6 - // PQ4CD - // QFG4CD - - // This is interesting because they all have the same interpreter - // version (2.100.002), yet they would not be compatible with other - // games of the same interpreter. - - if (getSciVersion() != SCI_VERSION_3 && features->detectSci21KernelType() == SCI_VERSION_2) { - _kernelNames = Common::StringArray(sci2_default_knames, kKernelEntriesGk2Demo); - // OnMe is IsOnMe here, but they should be compatible - _kernelNames[0x23] = "Robot"; // Graph in SCI2 - _kernelNames[0x2e] = "Priority"; // DisposeTextBitmap in SCI2 - } else if (getSciVersion() != SCI_VERSION_3) { - _kernelNames = Common::StringArray(sci21_default_knames, kKernelEntriesSci21); - } else if (getSciVersion() == SCI_VERSION_3) { + case SCI_VERSION_3: _kernelNames = Common::StringArray(sci21_default_knames, kKernelEntriesSci3); - } -} -#endif - -void Kernel::loadKernelNames(GameFeatures *features) { - _kernelNames.clear(); + // In SCI3, some kernel functions have been removed, and others have been added + _kernelNames[0x18] = "Dummy"; // AddMagnify in SCI2.1 + _kernelNames[0x19] = "Dummy"; // DeleteMagnify in SCI2.1 + _kernelNames[0x30] = "Dummy"; // SetScroll in SCI2.1 + _kernelNames[0x39] = "Dummy"; // ShowMovie in SCI2.1 + _kernelNames[0x4c] = "Dummy"; // ScrollWindow in SCI2.1 + _kernelNames[0x56] = "Dummy"; // VibrateMouse in SCI2.1 (only used in QFG4 floppy) + _kernelNames[0x64] = "Dummy"; // AvoidPath in SCI2.1 + _kernelNames[0x66] = "Dummy"; // MergePoly in SCI2.1 + _kernelNames[0x8d] = "MessageBox"; // Dummy in SCI2.1 + _kernelNames[0x9b] = "Minimize"; // Dummy in SCI2.1 -#ifdef ENABLE_SCI32 - if (getSciVersion() >= SCI_VERSION_2_1) - setKernelNamesSci21(features); - else if (getSciVersion() == SCI_VERSION_2) - setKernelNamesSci2(); - else + break; #endif - setDefaultKernelNames(features); + + default: + // Use default table for the other versions + break; + } mapFunctions(); } diff --git a/engines/sci/engine/kernel.h b/engines/sci/engine/kernel.h index 677b790f93..c3fcdd06e7 100644 --- a/engines/sci/engine/kernel.h +++ b/engines/sci/engine/kernel.h @@ -223,23 +223,6 @@ public: bool debugSetFunction(const char *kernelName, int logging, int breakpoint); private: - /** - * Sets the default kernel function names, based on the SCI version used. - */ - void setDefaultKernelNames(GameFeatures *features); - -#ifdef ENABLE_SCI32 - /** - * Sets the default kernel function names to the SCI2 kernel functions. - */ - void setKernelNamesSci2(); - - /** - * Sets the default kernel function names to the SCI2.1 kernel functions. - */ - void setKernelNamesSci21(GameFeatures *features); -#endif - /** * Loads the kernel selector names. */ @@ -556,6 +539,7 @@ reg_t kFileIOWriteByte(EngineState *s, int argc, reg_t *argv); reg_t kFileIOReadWord(EngineState *s, int argc, reg_t *argv); reg_t kFileIOWriteWord(EngineState *s, int argc, reg_t *argv); reg_t kFileIOCreateSaveSlot(EngineState *s, int argc, reg_t *argv); +reg_t kFileIOIsValidDirectory(EngineState *s, int argc, reg_t *argv); #endif //@} diff --git a/engines/sci/engine/kernel_tables.h b/engines/sci/engine/kernel_tables.h index 6965a5da45..322d82ea08 100644 --- a/engines/sci/engine/kernel_tables.h +++ b/engines/sci/engine/kernel_tables.h @@ -1099,7 +1099,7 @@ static const char *const sci21_default_knames[] = { /*0x8a*/ "LoadChunk", /*0x8b*/ "SetPalStyleRange", /*0x8c*/ "AddPicAt", - /*0x8d*/ "MessageBox", // SCI3, was Dummy in SCI2.1 + /*0x8d*/ "Dummy", // MessageBox in SCI3 /*0x8e*/ "NewRoom", // debug function /*0x8f*/ "Dummy", /*0x90*/ "Priority", @@ -1113,7 +1113,7 @@ static const char *const sci21_default_knames[] = { /*0x98*/ "GetWindowsOption", // Windows only /*0x99*/ "WinDLL", // Windows only /*0x9a*/ "Dummy", - /*0x9b*/ "Minimize", // SCI3, was Dummy in SCI2.1 + /*0x9b*/ "Dummy", // Minimize in SCI3 /*0x9c*/ "DeletePic", // == SCI3 only =============== /*0x9d*/ "Dummy", -- cgit v1.2.3 From e0a3cfd21c607afd0fe9781b5d0a7d8407393d3f Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Wed, 4 Jul 2012 00:59:55 +0300 Subject: SCI: FileIO subop 19 checks for directory validity This is used in Torin's Passage and LSL7 when autosaving --- engines/sci/engine/kernel_tables.h | 2 +- engines/sci/engine/kfile.cpp | 9 ++++++++- 2 files changed, 9 insertions(+), 2 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/engine/kernel_tables.h b/engines/sci/engine/kernel_tables.h index 322d82ea08..69baa1cf47 100644 --- a/engines/sci/engine/kernel_tables.h +++ b/engines/sci/engine/kernel_tables.h @@ -240,7 +240,7 @@ static const SciKernelMapSubEntry kFileIO_subops[] = { { SIG_SCI32, 16, MAP_CALL(FileIOWriteWord), "ii", NULL }, { SIG_SCI32, 17, MAP_CALL(FileIOCreateSaveSlot), "ir", NULL }, { SIG_SCI32, 18, MAP_EMPTY(FileIOChangeDirectory), "r", NULL }, // for SQ6, when changing the savegame directory in the save/load dialog - { SIG_SCI32, 19, MAP_CALL(Stub), "r", NULL }, // for Torin / Torin demo + { SIG_SCI32, 19, MAP_CALL(FileIOIsValidDirectory), "r", NULL }, // for Torin / Torin demo #endif SCI_SUBOPENTRY_TERMINATOR }; diff --git a/engines/sci/engine/kfile.cpp b/engines/sci/engine/kfile.cpp index a21e19802d..786276221c 100644 --- a/engines/sci/engine/kfile.cpp +++ b/engines/sci/engine/kfile.cpp @@ -688,6 +688,13 @@ reg_t kFileIOCreateSaveSlot(EngineState *s, int argc, reg_t *argv) { return TRUE_REG; // slot creation was successful } +reg_t kFileIOIsValidDirectory(EngineState *s, int argc, reg_t *argv) { + // Used in Torin's Passage and LSL7 to determine if the directory passed as + // a parameter (usually the save directory) is valid. We always return true + // here. + return TRUE_REG; +} + #endif // ---- Save operations ------------------------------------------------------- @@ -1002,7 +1009,7 @@ reg_t kAutoSave(EngineState *s, int argc, reg_t *argv) { // the elapsed time from the timer object) // This function has to return something other than 0 to proceed - return s->r_acc; + return TRUE_REG; } #endif -- cgit v1.2.3 From 43224076e785e615d3ab3a5de53c3aff659a64f2 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Wed, 4 Jul 2012 01:00:54 +0300 Subject: SCI: Handle the autosave call of Torin's Passage --- engines/sci/engine/kernel_tables.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines/sci') diff --git a/engines/sci/engine/kernel_tables.h b/engines/sci/engine/kernel_tables.h index 69baa1cf47..126e972bd2 100644 --- a/engines/sci/engine/kernel_tables.h +++ b/engines/sci/engine/kernel_tables.h @@ -248,7 +248,7 @@ static const SciKernelMapSubEntry kFileIO_subops[] = { #ifdef ENABLE_SCI32 static const SciKernelMapSubEntry kSave_subops[] = { - { SIG_SCI32, 0, MAP_CALL(SaveGame), "[r0]i[r0](r)", NULL }, + { SIG_SCI32, 0, MAP_CALL(SaveGame), "[r0]i[r0](r0)", NULL }, { SIG_SCI32, 1, MAP_CALL(RestoreGame), "[r0]i[r0]", NULL }, { SIG_SCI32, 2, MAP_CALL(GetSaveDir), "(r*)", NULL }, { SIG_SCI32, 3, MAP_CALL(CheckSaveGame), ".*", NULL }, -- cgit v1.2.3 From d757b5b94a0b180ce8e2e59617898a322f8ee0d5 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Wed, 4 Jul 2012 01:01:35 +0300 Subject: SCI: Update some version checks in kernelFrameout() to work with SCI3 too --- engines/sci/graphics/frameout.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/graphics/frameout.cpp b/engines/sci/graphics/frameout.cpp index 265a175e66..5703579b1e 100644 --- a/engines/sci/graphics/frameout.cpp +++ b/engines/sci/graphics/frameout.cpp @@ -653,7 +653,7 @@ void GfxFrameout::kernelFrameout() { if (view && view->isSci2Hires()) { view->adjustToUpscaledCoordinates(itemEntry->y, itemEntry->x); view->adjustToUpscaledCoordinates(itemEntry->z, dummyX); - } else if (getSciVersion() == SCI_VERSION_2_1) { + } else if (getSciVersion() >= SCI_VERSION_2_1) { _coordAdjuster->fromScriptToDisplay(itemEntry->y, itemEntry->x); _coordAdjuster->fromScriptToDisplay(itemEntry->z, dummyX); } @@ -691,7 +691,7 @@ void GfxFrameout::kernelFrameout() { if (view && view->isSci2Hires()) { view->adjustBackUpscaledCoordinates(nsRect.top, nsRect.left); view->adjustBackUpscaledCoordinates(nsRect.bottom, nsRect.right); - } else if (getSciVersion() == SCI_VERSION_2_1) { + } else if (getSciVersion() >= SCI_VERSION_2_1) { _coordAdjuster->fromDisplayToScript(nsRect.top, nsRect.left); _coordAdjuster->fromDisplayToScript(nsRect.bottom, nsRect.right); } -- cgit v1.2.3 From a0ad504059470b9ac8f5d4025d7bcec1621e1933 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Wed, 4 Jul 2012 01:06:58 +0300 Subject: SCI: Update some kernel table related comments --- engines/sci/engine/kernel.cpp | 2 +- engines/sci/engine/kernel_tables.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/engine/kernel.cpp b/engines/sci/engine/kernel.cpp index 924641cdbe..46051ef145 100644 --- a/engines/sci/engine/kernel.cpp +++ b/engines/sci/engine/kernel.cpp @@ -837,7 +837,7 @@ void Kernel::loadKernelNames(GameFeatures *features) { case SCI_VERSION_2_1: if (features->detectSci21KernelType() == SCI_VERSION_2) { - // Some late SCI2.1 games use a modified SCI2 kernel table instead of + // Some early SCI2.1 games use a modified SCI2 kernel table instead of // the SCI2.1 kernel table. We detect which version to use based on // how kDoSound is called from Sound::play(). // Known games that use this: diff --git a/engines/sci/engine/kernel_tables.h b/engines/sci/engine/kernel_tables.h index 126e972bd2..114cd58c95 100644 --- a/engines/sci/engine/kernel_tables.h +++ b/engines/sci/engine/kernel_tables.h @@ -828,7 +828,7 @@ static const char *const sci2_default_knames[] = { /*0x20*/ "AddMagnify", /*0x21*/ "DeleteMagnify", /*0x22*/ "IsHiRes", - /*0x23*/ "Graph", + /*0x23*/ "Graph", // Robot in early SCI2.1 games with a SCI2 kernel table /*0x24*/ "InvertRect", // only in SCI2, not used in any SCI2 game /*0x25*/ "TextSize", /*0x26*/ "Message", @@ -839,7 +839,7 @@ static const char *const sci2_default_knames[] = { /*0x2b*/ "EditText", /*0x2c*/ "InputText", // unused function /*0x2d*/ "CreateTextBitmap", - /*0x2e*/ "DisposeTextBitmap", + /*0x2e*/ "DisposeTextBitmap", // Priority in early SCI2.1 games with a SCI2 kernel table /*0x2f*/ "GetEvent", /*0x30*/ "GlobalToLocal", /*0x31*/ "LocalToGlobal", -- cgit v1.2.3 From d74d211479660eee0d9c63f10ddd1191340fdb02 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Wed, 4 Jul 2012 02:14:57 +0300 Subject: SCI: Mark the SetScroll and SetHotRectangles kernel functions as unused --- engines/sci/engine/kernel_tables.h | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/engine/kernel_tables.h b/engines/sci/engine/kernel_tables.h index 114cd58c95..04b221d2b0 100644 --- a/engines/sci/engine/kernel_tables.h +++ b/engines/sci/engine/kernel_tables.h @@ -520,7 +520,6 @@ static SciKernelMapEntry s_kernelMap[] = { // SCI2 unmapped functions - TODO! - // SetScroll - called by script 64909, Styler::doit() // PalCycle - called by Game::newRoom. Related to RemapColors. // SCI2 Empty functions @@ -561,6 +560,11 @@ static SciKernelMapEntry s_kernelMap[] = { { MAP_DUMMY(InputText), SIG_EVERYWHERE, "(.*)", NULL, NULL }, { MAP_DUMMY(TextWidth), SIG_EVERYWHERE, "(.*)", NULL, NULL }, { MAP_DUMMY(PointSize), SIG_EVERYWHERE, "(.*)", NULL, NULL }, + // SetScroll is called by script 64909, Styler::doit(), but it doesn't seem to + // be used at all (plus, it was then changed to a dummy function in SCI3). + // Since this is most likely unused, and we got no test case, error out when + // it is called in order to find an actual call to it. + { MAP_DUMMY(SetScroll), SIG_EVERYWHERE, "(.*)", NULL, NULL }, // SCI2.1 Kernel Functions { MAP_CALL(CD), SIG_EVERYWHERE, "(.*)", NULL, NULL }, @@ -620,6 +624,8 @@ static SciKernelMapEntry s_kernelMap[] = { { MAP_DUMMY(WinDLL), SIG_EVERYWHERE, "(.*)", NULL, NULL }, { MAP_DUMMY(DeletePic), SIG_EVERYWHERE, "(.*)", NULL, NULL }, { MAP_DUMMY(GetSierraProfileString), SIG_EVERYWHERE, "(.*)", NULL, NULL }, + // SetHotRectangles is used by Phantasmagoria 1, script 64981 (a debug script) + { MAP_DUMMY(SetHotRectangles), SIG_EVERYWHERE, "(.*)", NULL, NULL }, // Unused / debug functions in the in-between SCI2.1 interpreters { MAP_DUMMY(PreloadResource), SIG_EVERYWHERE, "(.*)", NULL, NULL }, @@ -633,7 +639,6 @@ static SciKernelMapEntry s_kernelMap[] = { // SetPalStyleRange - 2 integer parameters, start and end. All styles from start-end // (inclusive) are set to 0 // MorphOn - used by SQ6, script 900, the datacorder reprogramming puzzle (from room 270) - // SetHotRectangles - used by Phantasmagoria 1 // SCI3 Kernel Functions { MAP_CALL(PlayDuck), SIG_EVERYWHERE, "(.*)", NULL, NULL }, -- cgit v1.2.3 From dc1a097e508fc4cd323314fd5dde4dfe648f7c64 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Wed, 4 Jul 2012 02:15:39 +0300 Subject: SCI: Make the debug message in kSetShowStyle more verbose --- engines/sci/engine/kgraphics32.cpp | 31 +++++++++++++++++++++---------- 1 file changed, 21 insertions(+), 10 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/engine/kgraphics32.cpp b/engines/sci/engine/kgraphics32.cpp index 14ea409a58..072d4df021 100644 --- a/engines/sci/engine/kgraphics32.cpp +++ b/engines/sci/engine/kgraphics32.cpp @@ -224,12 +224,12 @@ reg_t kSetShowStyle(EngineState *s, int argc, reg_t *argv) { // tables inside graphics/transitions.cpp uint16 showStyle = argv[0].toUint16(); // 0 - 15 reg_t planeObj = argv[1]; // the affected plane - //uint16 seconds = argv[2].toUint16(); // seconds that the transition lasts - //uint16 backColor = argv[3].toUint16(); // target back color(?). When fading out, it's 0x0000. When fading in, it's 0xffff - //int16 priority = argv[4].toSint16(); // always 0xc8 (200) when fading in/out - //uint16 animate = argv[5].toUint16(); // boolean, animate or not while the transition lasts - //uint16 refFrame = argv[6].toUint16(); // refFrame, always 0 when fading in/out -#if 0 + Common::String planeObjName = s->_segMan->getObjectName(planeObj); + uint16 seconds = argv[2].toUint16(); // seconds that the transition lasts + uint16 backColor = argv[3].toUint16(); // target back color(?). When fading out, it's 0x0000. When fading in, it's 0xffff + int16 priority = argv[4].toSint16(); // always 0xc8 (200) when fading in/out + uint16 animate = argv[5].toUint16(); // boolean, animate or not while the transition lasts + uint16 refFrame = argv[6].toUint16(); // refFrame, always 0 when fading in/out int16 divisions; // If the game has the pFadeArray selector, another parameter is used here, @@ -241,7 +241,7 @@ reg_t kSetShowStyle(EngineState *s, int argc, reg_t *argv) { } else { divisions = (argc >= 8) ? argv[7].toSint16() : -1; // divisions (transition steps?) } -#endif + if (showStyle > 15) { warning("kSetShowStyle: Illegal style %d for plane %04x:%04x", showStyle, PRINT_REG(planeObj)); return s->r_acc; @@ -257,18 +257,29 @@ reg_t kSetShowStyle(EngineState *s, int argc, reg_t *argv) { // TODO: Check if the plane is in the list of planes to draw + Common::String effectName = "unknown"; + switch (showStyle) { - //case 0: // no transition, perhaps? (like in the previous SCI versions) + case 0: // no transition / show + effectName = "show"; + break; case 13: // fade out + effectName = "fade out"; // TODO + break; case 14: // fade in + effectName = "fade in"; // TODO + break; default: - // TODO: This is all a stub/skeleton, thus we're invoking kStub() for now - kStub(s, argc, argv); + // TODO break; } + warning("kSetShowStyle: effect %d (%s) - plane: %04x:%04x (%s), sec: %d, " + "back: %d, prio: %d, animate: %d, ref frame: %d, divisions: %d", + showStyle, effectName.c_str(), PRINT_REG(planeObj), planeObjName.c_str(), + seconds, backColor, priority, animate, refFrame, divisions); return s->r_acc; } -- cgit v1.2.3 From 5d3e22ae4f5fcf6c7717eb9e50767b3fbb5a10f8 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Wed, 4 Jul 2012 02:17:27 +0300 Subject: SCI: Some cleanup of the warnings in the SCI32 plane manipulation code --- engines/sci/graphics/frameout.cpp | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/graphics/frameout.cpp b/engines/sci/graphics/frameout.cpp index 5703579b1e..450460023c 100644 --- a/engines/sci/graphics/frameout.cpp +++ b/engines/sci/graphics/frameout.cpp @@ -326,8 +326,10 @@ void GfxFrameout::deletePlaneLine(reg_t object, reg_t hunkId) { void GfxFrameout::kernelAddScreenItem(reg_t object) { // Ignore invalid items - if (!_segMan->isObject(object)) + if (!_segMan->isObject(object)) { + warning("kernelAddScreenItem: Attempt to add an invalid object (%04x:%04x)", PRINT_REG(object)); return; + } FrameoutEntry *itemEntry = new FrameoutEntry(); memset(itemEntry, 0, sizeof(FrameoutEntry)); @@ -341,8 +343,10 @@ void GfxFrameout::kernelAddScreenItem(reg_t object) { void GfxFrameout::kernelUpdateScreenItem(reg_t object) { // Ignore invalid items - if (!_segMan->isObject(object)) + if (!_segMan->isObject(object)) { + warning("kernelUpdateScreenItem: Attempt to update an invalid object (%04x:%04x)", PRINT_REG(object)); return; + } FrameoutEntry *itemEntry = findScreenItem(object); if (!itemEntry) { @@ -372,10 +376,9 @@ void GfxFrameout::kernelUpdateScreenItem(reg_t object) { void GfxFrameout::kernelDeleteScreenItem(reg_t object) { FrameoutEntry *itemEntry = findScreenItem(object); - if (!itemEntry) { - warning("kernelDeleteScreenItem: invalid object %04x:%04x", PRINT_REG(object)); + // If the item could not be found, it may already have been deleted + if (!itemEntry) return; - } _screenItems.remove(itemEntry); delete itemEntry; -- cgit v1.2.3 From 243ea1fa290a919d5f0a07094782465f0ba08d7e Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Wed, 4 Jul 2012 02:20:39 +0300 Subject: SCI: Add a check for invalid clip rectangles Happens in QFG4, when starting a battle --- engines/sci/graphics/frameout.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'engines/sci') diff --git a/engines/sci/graphics/frameout.cpp b/engines/sci/graphics/frameout.cpp index 450460023c..5b857fe3d8 100644 --- a/engines/sci/graphics/frameout.cpp +++ b/engines/sci/graphics/frameout.cpp @@ -722,6 +722,9 @@ void GfxFrameout::kernelFrameout() { translatedClipRect = clipRect; translatedClipRect.translate(it->upscaledPlaneRect.left, it->upscaledPlaneRect.top); } else { + // QFG4 passes invalid rectangles when a battle is starting + if (!clipRect.isValidRect()) + continue; clipRect.clip(it->planeClipRect); translatedClipRect = clipRect; translatedClipRect.translate(it->planeRect.left, it->planeRect.top); -- cgit v1.2.3 From 55d322346832d41c42bb058bdc263d755e0f598b Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Wed, 4 Jul 2012 02:01:47 +0200 Subject: SCI: Fix spelling of Yamaha. Thanks to somaen for noticing. --- engines/sci/detection.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/detection.cpp b/engines/sci/detection.cpp index 8a74bc817c..58ac5f1fa6 100644 --- a/engines/sci/detection.cpp +++ b/engines/sci/detection.cpp @@ -397,8 +397,8 @@ static const ADExtraGuiOptionsMap optionsList[] = { { GAMEOPTION_FB01_MIDI, { - _s("Use IMF/Yahama FB-01 for MIDI output"), - _s("Use an IBM Music Feature card or a Yahama FB-01 FM synth module for MIDI output"), + _s("Use IMF/Yamaha FB-01 for MIDI output"), + _s("Use an IBM Music Feature card or a Yamaha FB-01 FM synth module for MIDI output"), "native_fb01", false } -- cgit v1.2.3 From d61c5ae529e99c641edbde152f8f264073a9cdce Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Wed, 4 Jul 2012 11:55:09 +0300 Subject: SCI: make g_base_opcode_formats and SciOpcodes a bit more readable --- engines/sci/engine/kernel_tables.h | 56 ++++++++++++++++++++++++-------------- engines/sci/engine/vm.h | 4 +++ 2 files changed, 40 insertions(+), 20 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/engine/kernel_tables.h b/engines/sci/engine/kernel_tables.h index 04b221d2b0..c4443c92d3 100644 --- a/engines/sci/engine/kernel_tables.h +++ b/engines/sci/engine/kernel_tables.h @@ -1132,57 +1132,73 @@ static const char *const sci21_default_knames[] = { // Base set of opcode formats. They're copied and adjusted slightly in // script_adjust_opcode_format depending on SCI version. static const opcode_format g_base_opcode_formats[128][4] = { - /*00*/ + // 00 - 03 / bnot, add, sub, mul {Script_None}, {Script_None}, {Script_None}, {Script_None}, - /*04*/ + // 04 - 07 / div, mod, shr, shl {Script_None}, {Script_None}, {Script_None}, {Script_None}, - /*08*/ + // 08 - 0B / xor, and, or, neg {Script_None}, {Script_None}, {Script_None}, {Script_None}, - /*0C*/ + // 0C - 0F / not, eq, ne, gt {Script_None}, {Script_None}, {Script_None}, {Script_None}, - /*10*/ + // 10 - 13 / ge, lt, le, ugt {Script_None}, {Script_None}, {Script_None}, {Script_None}, - /*14*/ + // 14 - 17 / uge, ult, ule, bt {Script_None}, {Script_None}, {Script_None}, {Script_SRelative}, - /*18*/ + // 18 - 1B / bnt, jmp, ldi, push {Script_SRelative}, {Script_SRelative}, {Script_SVariable}, {Script_None}, - /*1C*/ + // 1C - 1F / pushi, toss, dup, link {Script_SVariable}, {Script_None}, {Script_None}, {Script_Variable}, - /*20*/ + // 20 - 23 / call, callk, callb, calle {Script_SRelative, Script_Byte}, {Script_Variable, Script_Byte}, {Script_Variable, Script_Byte}, {Script_Variable, Script_SVariable, Script_Byte}, - /*24 (24=ret)*/ + // 24 - 27 / ret, send, dummy, dummy {Script_End}, {Script_Byte}, {Script_Invalid}, {Script_Invalid}, - /*28*/ + // 28 - 2B / class, dummy, self, super {Script_Variable}, {Script_Invalid}, {Script_Byte}, {Script_Variable, Script_Byte}, - /*2C*/ + // 2C - 2F / rest, lea, selfID, dummy {Script_SVariable}, {Script_SVariable, Script_Variable}, {Script_None}, {Script_Invalid}, - /*30*/ + // 30 - 33 / pprev, pToa, aTop, pTos {Script_None}, {Script_Property}, {Script_Property}, {Script_Property}, - /*34*/ + // 34 - 37 / sTop, ipToa, dpToa, ipTos {Script_Property}, {Script_Property}, {Script_Property}, {Script_Property}, - /*38*/ + // 38 - 3B / dpTos, lofsa, lofss, push0 {Script_Property}, {Script_SRelative}, {Script_SRelative}, {Script_None}, - /*3C*/ + // 3C - 3F / push1, push2, pushSelf, line {Script_None}, {Script_None}, {Script_None}, {Script_Word}, - /*40-4F*/ + // ------------------------------------------------------------------------ + // 40 - 43 / lag, lal, lat, lap {Script_Global}, {Script_Local}, {Script_Temp}, {Script_Param}, + // 44 - 47 / lsg, lsl, lst, lsp {Script_Global}, {Script_Local}, {Script_Temp}, {Script_Param}, + // 48 - 4B / lagi, lali, lati, lapi {Script_Global}, {Script_Local}, {Script_Temp}, {Script_Param}, + // 4C - 4F / lsgi, lsli, lsti, lspi {Script_Global}, {Script_Local}, {Script_Temp}, {Script_Param}, - /*50-5F*/ + // ------------------------------------------------------------------------ + // 50 - 53 / sag, sal, sat, sap {Script_Global}, {Script_Local}, {Script_Temp}, {Script_Param}, + // 54 - 57 / ssg, ssl, sst, ssp {Script_Global}, {Script_Local}, {Script_Temp}, {Script_Param}, + // 58 - 5B / sagi, sali, sati, sapi {Script_Global}, {Script_Local}, {Script_Temp}, {Script_Param}, + // 5C - 5F / ssgi, ssli, ssti, sspi {Script_Global}, {Script_Local}, {Script_Temp}, {Script_Param}, - /*60-6F*/ + // ------------------------------------------------------------------------ + // 60 - 63 / plusag, plusal, plusat, plusap {Script_Global}, {Script_Local}, {Script_Temp}, {Script_Param}, + // 64 - 67 / plussg, plussl, plusst, plussp {Script_Global}, {Script_Local}, {Script_Temp}, {Script_Param}, + // 68 - 6B / plusagi, plusali, plusati, plusapi {Script_Global}, {Script_Local}, {Script_Temp}, {Script_Param}, + // 6C - 6F / plussgi, plussli, plussti, plusspi {Script_Global}, {Script_Local}, {Script_Temp}, {Script_Param}, - /*70-7F*/ + // ------------------------------------------------------------------------ + // 70 - 73 / minusag, minusal, minusat, minusap {Script_Global}, {Script_Local}, {Script_Temp}, {Script_Param}, + // 74 - 77 / minussg, minussl, minusst, minussp {Script_Global}, {Script_Local}, {Script_Temp}, {Script_Param}, + // 78 - 7B / minusagi, minusali, minusati, minusapi {Script_Global}, {Script_Local}, {Script_Temp}, {Script_Param}, + // 7C - 7F / minussgi, minussli, minussti, minusspi {Script_Global}, {Script_Local}, {Script_Temp}, {Script_Param} }; #undef END diff --git a/engines/sci/engine/vm.h b/engines/sci/engine/vm.h index a0fd6689df..8b38faa013 100644 --- a/engines/sci/engine/vm.h +++ b/engines/sci/engine/vm.h @@ -202,6 +202,7 @@ enum SciOpcodes { op_push2 = 0x3d, // 061 op_pushSelf = 0x3e, // 062 op_line = 0x3f, // 063 + // op_lag = 0x40, // 064 op_lal = 0x41, // 065 op_lat = 0x42, // 066 @@ -218,6 +219,7 @@ enum SciOpcodes { op_lsli = 0x4d, // 077 op_lsti = 0x4e, // 078 op_lspi = 0x4f, // 079 + // op_sag = 0x50, // 080 op_sal = 0x51, // 081 op_sat = 0x52, // 082 @@ -234,6 +236,7 @@ enum SciOpcodes { op_ssli = 0x5d, // 093 op_ssti = 0x5e, // 094 op_sspi = 0x5f, // 095 + // op_plusag = 0x60, // 096 op_plusal = 0x61, // 097 op_plusat = 0x62, // 098 @@ -250,6 +253,7 @@ enum SciOpcodes { op_plussli = 0x6d, // 109 op_plussti = 0x6e, // 110 op_plusspi = 0x6f, // 111 + // op_minusag = 0x70, // 112 op_minusal = 0x71, // 113 op_minusat = 0x72, // 114 -- cgit v1.2.3 From fb215929efaefdf0b75521caab8a86e93181c5b2 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Thu, 5 Jul 2012 13:42:00 +0300 Subject: SCI: Some updates to SCI32 kernel graphics functions - Added a stub for kSetScroll, which sets the target picture immediately for now - Added an initial stub of kPalCycle (doesn't work correctly yet) - Adjusted the signatures of kUpdateLine and kDeleteLine for LSL6 - Unmapped kSetHotRectangles again, with updated information on how it is used in Phantasmagoria --- engines/sci/engine/kernel.h | 2 + engines/sci/engine/kernel_tables.h | 16 +++---- engines/sci/engine/kgraphics32.cpp | 90 ++++++++++++++++++++++++++++++++++++++ engines/sci/engine/state.cpp | 3 ++ engines/sci/engine/state.h | 2 + engines/sci/graphics/frameout.cpp | 8 ++++ 6 files changed, 113 insertions(+), 8 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/engine/kernel.h b/engines/sci/engine/kernel.h index c3fcdd06e7..441ea2624f 100644 --- a/engines/sci/engine/kernel.h +++ b/engines/sci/engine/kernel.h @@ -436,6 +436,8 @@ reg_t kObjectIntersect(EngineState *s, int argc, reg_t *argv); reg_t kEditText(EngineState *s, int argc, reg_t *argv); reg_t kMakeSaveCatName(EngineState *s, int argc, reg_t *argv); reg_t kMakeSaveFileName(EngineState *s, int argc, reg_t *argv); +reg_t kSetScroll(EngineState *s, int argc, reg_t *argv); +reg_t kPalCycle(EngineState *s, int argc, reg_t *argv); // SCI2.1 Kernel Functions reg_t kText(EngineState *s, int argc, reg_t *argv); diff --git a/engines/sci/engine/kernel_tables.h b/engines/sci/engine/kernel_tables.h index c4443c92d3..825ec90fa9 100644 --- a/engines/sci/engine/kernel_tables.h +++ b/engines/sci/engine/kernel_tables.h @@ -517,10 +517,8 @@ static SciKernelMapEntry s_kernelMap[] = { { MAP_CALL(EditText), SIG_EVERYWHERE, "o", NULL, NULL }, { MAP_CALL(MakeSaveCatName), SIG_EVERYWHERE, "rr", NULL, NULL }, { MAP_CALL(MakeSaveFileName), SIG_EVERYWHERE, "rri", NULL, NULL }, - - // SCI2 unmapped functions - TODO! - - // PalCycle - called by Game::newRoom. Related to RemapColors. + { MAP_CALL(SetScroll), SIG_EVERYWHERE, "oiiiii(i)", NULL, NULL }, + { MAP_CALL(PalCycle), SIG_EVERYWHERE, "i(.*)", NULL, NULL }, // SCI2 Empty functions @@ -587,8 +585,8 @@ static SciKernelMapEntry s_kernelMap[] = { { MAP_CALL(Font), SIG_EVERYWHERE, "i(.*)", NULL, NULL }, { MAP_CALL(Bitmap), SIG_EVERYWHERE, "(.*)", NULL, NULL }, { MAP_CALL(AddLine), SIG_EVERYWHERE, "oiiiiiiiii", NULL, NULL }, - { MAP_CALL(UpdateLine), SIG_EVERYWHERE, "roiiiiiiiii", NULL, NULL }, - { MAP_CALL(DeleteLine), SIG_EVERYWHERE, "ro", NULL, NULL }, + { MAP_CALL(UpdateLine), SIG_EVERYWHERE, "[r0]oiiiiiiiii", NULL, NULL }, + { MAP_CALL(DeleteLine), SIG_EVERYWHERE, "[r0]o", NULL, NULL }, // SCI2.1 Empty Functions @@ -624,8 +622,6 @@ static SciKernelMapEntry s_kernelMap[] = { { MAP_DUMMY(WinDLL), SIG_EVERYWHERE, "(.*)", NULL, NULL }, { MAP_DUMMY(DeletePic), SIG_EVERYWHERE, "(.*)", NULL, NULL }, { MAP_DUMMY(GetSierraProfileString), SIG_EVERYWHERE, "(.*)", NULL, NULL }, - // SetHotRectangles is used by Phantasmagoria 1, script 64981 (a debug script) - { MAP_DUMMY(SetHotRectangles), SIG_EVERYWHERE, "(.*)", NULL, NULL }, // Unused / debug functions in the in-between SCI2.1 interpreters { MAP_DUMMY(PreloadResource), SIG_EVERYWHERE, "(.*)", NULL, NULL }, @@ -635,6 +631,10 @@ static SciKernelMapEntry s_kernelMap[] = { // SCI2.1 unmapped functions - TODO! + // SetHotRectangles - used by Phantasmagoria 1, script 64981 (used in the chase scene) + // The idea, if I understand correctly, is that the engine generates events + // of a special HotRect type continuously when the mouse is on that rectangle + // MovePlaneItems - used by SQ6 to scroll through the inventory via the up/down buttons // SetPalStyleRange - 2 integer parameters, start and end. All styles from start-end // (inclusive) are set to 0 diff --git a/engines/sci/engine/kgraphics32.cpp b/engines/sci/engine/kgraphics32.cpp index 072d4df021..16e54a5429 100644 --- a/engines/sci/engine/kgraphics32.cpp +++ b/engines/sci/engine/kgraphics32.cpp @@ -637,6 +637,96 @@ reg_t kDeleteLine(EngineState *s, int argc, reg_t *argv) { return s->r_acc; } +reg_t kSetScroll(EngineState *s, int argc, reg_t *argv) { + // Called in the intro of LSL6 hires (room 110) + // The end effect of this is the same as the old screen scroll transition + + // 7 parameters + reg_t planeObject = argv[0]; + //int16 x = argv[1].toSint16(); + //int16 y = argv[2].toSint16(); + uint16 pictureId = argv[3].toUint16(); + // param 4: int (0 in LSL6, probably scroll direction? The picture in LSL6 scrolls down) + // param 5: int (first call is 1, then the subsequent one is 0 in LSL6) + // param 6: optional int (0 in LSL6) + + // Set the new picture directly for now + //writeSelectorValue(s->_segMan, planeObject, SELECTOR(left), x); + //writeSelectorValue(s->_segMan, planeObject, SELECTOR(top), y); + writeSelectorValue(s->_segMan, planeObject, SELECTOR(picture), pictureId); + // and update our draw list + g_sci->_gfxFrameout->kernelUpdatePlane(planeObject); + + // TODO + return kStub(s, argc, argv); +} + +reg_t kPalCycle(EngineState *s, int argc, reg_t *argv) { + // Examples: GK1 room 480 (Bayou ritual), LSL6 room 100 (title screen) + + switch (argv[0].toUint16()) { + case 0: { // Palette animation initialization + // 3 or 4 extra params + // Case 1 sends fromColor and speed again, so we don't need them here. + // Only toColor is stored + //uint16 fromColor = argv[1].toUint16(); + s->_palCycleToColor = argv[2].toUint16(); + //uint16 speed = argv[3].toUint16(); + + // Invalidate the picture, so that the palette steps calls (case 1 + // below) can update its palette without it being overwritten by the + // view/picture palettes. + g_sci->_gfxScreen->_picNotValid = 1; + + // TODO: The fourth optional parameter is an unknown integer, and is 0 by default + if (argc == 5) { + // When this variant is used, picNotValid doesn't seem to be set + // (e.g. GK1 room 480). In this case, the animation step calls are + // not made, so perhaps this signifies the palette cycling steps + // to make. + // GK1 sets this to 6 (6 palette steps?) + g_sci->_gfxScreen->_picNotValid = 0; + } + kStub(s, argc, argv); + } + break; + case 1: { // Palette animation step + // This is the same as the old kPaletteAnimate call, with 1 set of colors. + // The end color is set up during initialization in case 0 above. + + // 1 or 2 extra params + uint16 fromColor = argv[1].toUint16(); + uint16 speed = (argc == 2) ? 1 : argv[2].toUint16(); + // TODO: For some reason, this doesn't set the color correctly + // (e.g. LSL6 intro, room 100, Sierra logo) + if (g_sci->_gfxPalette->kernelAnimate(fromColor, s->_palCycleToColor, speed)) + g_sci->_gfxPalette->kernelAnimateSet(); + } + // No kStub() call here, as this gets called loads of times, like kPaletteAnimate + break; + // case 2 hasn't been encountered + // case 3 hasn't been encountered + case 4: // reset any palette cycling and make the picture valid again + // Gets called when changing rooms and after palette cycling animations finish + // 0 or 1 extra params + if (argc == 1) { + g_sci->_gfxScreen->_picNotValid = 0; + // TODO: This also seems to perform more steps + } else { + // The variant with the 1 extra param resets remapping to base + // TODO + } + kStub(s, argc, argv); + break; + default: + // TODO + kStub(s, argc, argv); + break; + } + + return s->r_acc; +} + #endif } // End of namespace Sci diff --git a/engines/sci/engine/state.cpp b/engines/sci/engine/state.cpp index 94a3fe3ae5..0f0c8dcd66 100644 --- a/engines/sci/engine/state.cpp +++ b/engines/sci/engine/state.cpp @@ -122,8 +122,11 @@ void EngineState::reset(bool isRestoring) { _videoState.reset(); _syncedAudioOptions = false; + _vmdPalStart = 0; _vmdPalEnd = 256; + + _palCycleToColor = 255; } void EngineState::speedThrottler(uint32 neededSleep) { diff --git a/engines/sci/engine/state.h b/engines/sci/engine/state.h index 9ae6299d83..81090876c7 100644 --- a/engines/sci/engine/state.h +++ b/engines/sci/engine/state.h @@ -199,6 +199,8 @@ public: uint16 _vmdPalStart, _vmdPalEnd; bool _syncedAudioOptions; + uint16 _palCycleToColor; + /** * Resets the engine state. */ diff --git a/engines/sci/graphics/frameout.cpp b/engines/sci/graphics/frameout.cpp index 5b857fe3d8..31ad7a50aa 100644 --- a/engines/sci/graphics/frameout.cpp +++ b/engines/sci/graphics/frameout.cpp @@ -294,6 +294,10 @@ reg_t GfxFrameout::addPlaneLine(reg_t object, Common::Point startPoint, Common:: } void GfxFrameout::updatePlaneLine(reg_t object, reg_t hunkId, Common::Point startPoint, Common::Point endPoint, byte color, byte priority, byte control) { + // Check if we're asked to update a line that was never added + if (object.isNull()) + return; + for (PlaneList::iterator it = _planes.begin(); it != _planes.end(); ++it) { if (it->object == object) { for (PlaneLineList::iterator it2 = it->lines.begin(); it2 != it->lines.end(); ++it2) { @@ -311,6 +315,10 @@ void GfxFrameout::updatePlaneLine(reg_t object, reg_t hunkId, Common::Point star } void GfxFrameout::deletePlaneLine(reg_t object, reg_t hunkId) { + // Check if we're asked to delete a line that was never added (happens during the intro of LSL6) + if (object.isNull()) + return; + for (PlaneList::iterator it = _planes.begin(); it != _planes.end(); ++it) { if (it->object == object) { for (PlaneLineList::iterator it2 = it->lines.begin(); it2 != it->lines.end(); ++it2) { -- cgit v1.2.3 From 4ced5ccf306450bc4b0bd6afd66b5bc7bec1e814 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Thu, 5 Jul 2012 13:58:04 +0300 Subject: SCI: Handle calls from MessageState::outputString() to arrays This happens during the intro of LSL6 hires (room 110) --- engines/sci/engine/message.cpp | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/engine/message.cpp b/engines/sci/engine/message.cpp index cddd01e10c..a92d572d35 100644 --- a/engines/sci/engine/message.cpp +++ b/engines/sci/engine/message.cpp @@ -400,11 +400,21 @@ Common::String MessageState::processString(const char *s) { void MessageState::outputString(reg_t buf, const Common::String &str) { #ifdef ENABLE_SCI32 if (getSciVersion() >= SCI_VERSION_2) { - SciString *sciString = _segMan->lookupString(buf); - sciString->setSize(str.size() + 1); - for (uint32 i = 0; i < str.size(); i++) - sciString->setValue(i, str.c_str()[i]); - sciString->setValue(str.size(), 0); + if (_segMan->getSegmentType(buf.getSegment()) == SEG_TYPE_STRING) { + SciString *sciString = _segMan->lookupString(buf); + sciString->setSize(str.size() + 1); + for (uint32 i = 0; i < str.size(); i++) + sciString->setValue(i, str.c_str()[i]); + sciString->setValue(str.size(), 0); + } else if (_segMan->getSegmentType(buf.getSegment()) == SEG_TYPE_ARRAY) { + // Happens in the intro of LSL6, we are asked to write the string + // into an array + SciArray *sciString = _segMan->lookupArray(buf); + sciString->setSize(str.size() + 1); + for (uint32 i = 0; i < str.size(); i++) + sciString->setValue(i, make_reg(0, str.c_str()[i])); + sciString->setValue(str.size(), NULL_REG); + } } else { #endif SegmentRef buffer_r = _segMan->dereference(buf); -- cgit v1.2.3 From 112f03390d308af60d9c5f5e9f29c30988d2e968 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Thu, 5 Jul 2012 14:05:26 +0300 Subject: SCI: Fix typo --- engines/sci/graphics/frameout.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/graphics/frameout.cpp b/engines/sci/graphics/frameout.cpp index 31ad7a50aa..20b8a241aa 100644 --- a/engines/sci/graphics/frameout.cpp +++ b/engines/sci/graphics/frameout.cpp @@ -295,7 +295,7 @@ reg_t GfxFrameout::addPlaneLine(reg_t object, Common::Point startPoint, Common:: void GfxFrameout::updatePlaneLine(reg_t object, reg_t hunkId, Common::Point startPoint, Common::Point endPoint, byte color, byte priority, byte control) { // Check if we're asked to update a line that was never added - if (object.isNull()) + if (hunkId.isNull()) return; for (PlaneList::iterator it = _planes.begin(); it != _planes.end(); ++it) { @@ -316,7 +316,7 @@ void GfxFrameout::updatePlaneLine(reg_t object, reg_t hunkId, Common::Point star void GfxFrameout::deletePlaneLine(reg_t object, reg_t hunkId) { // Check if we're asked to delete a line that was never added (happens during the intro of LSL6) - if (object.isNull()) + if (hunkId.isNull()) return; for (PlaneList::iterator it = _planes.begin(); it != _planes.end(); ++it) { -- cgit v1.2.3 From 75137862967cd18a87dec16a6a322f9f97d54202 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Fri, 6 Jul 2012 12:11:12 +0300 Subject: SCI: Add a hack to handle the internal script resolution in Phantasmagoria --- engines/sci/graphics/frameout.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'engines/sci') diff --git a/engines/sci/graphics/frameout.cpp b/engines/sci/graphics/frameout.cpp index 20b8a241aa..defc55edb2 100644 --- a/engines/sci/graphics/frameout.cpp +++ b/engines/sci/graphics/frameout.cpp @@ -131,6 +131,20 @@ void GfxFrameout::kernelAddPlane(reg_t object) { tmpRunningWidth = 320; tmpRunningHeight = 200; } + + // HACK: Game scripts in Phantasmagoria 1 seem to use a very odd internal + // resolution, or some other extra calculation is taking place. + // Changing the internal script dimensions to these odd values fixes + // object positioning, but makes the interface picture slightly bigger, + // thus there is a small gap between the room picture and the interface + // edges, plus a couple of pixels of the picture are cut off in the + // bottom. + // FIXME: Find how to properly handle the script dimensions in + // Phantasmagoria. This can't be right. + if (g_sci->getGameId() == GID_PHANTASMAGORIA) { + tmpRunningWidth = 325; + tmpRunningHeight = 213; + } _coordAdjuster->setScriptsResolution(tmpRunningWidth, tmpRunningHeight); } -- cgit v1.2.3 From e4378d5bac1b2467190e21333a037a6af34bba52 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Fri, 6 Jul 2012 13:17:04 +0300 Subject: SCI: Better handling for Phantasmagoria's odd screen size Still not right, as the width isn't set --- engines/sci/graphics/frameout.cpp | 13 +++---------- engines/sci/graphics/screen.cpp | 7 +++++++ 2 files changed, 10 insertions(+), 10 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/graphics/frameout.cpp b/engines/sci/graphics/frameout.cpp index defc55edb2..b13c7f4dce 100644 --- a/engines/sci/graphics/frameout.cpp +++ b/engines/sci/graphics/frameout.cpp @@ -132,18 +132,11 @@ void GfxFrameout::kernelAddPlane(reg_t object) { tmpRunningHeight = 200; } - // HACK: Game scripts in Phantasmagoria 1 seem to use a very odd internal - // resolution, or some other extra calculation is taking place. - // Changing the internal script dimensions to these odd values fixes - // object positioning, but makes the interface picture slightly bigger, - // thus there is a small gap between the room picture and the interface - // edges, plus a couple of pixels of the picture are cut off in the - // bottom. - // FIXME: Find how to properly handle the script dimensions in - // Phantasmagoria. This can't be right. + // HACK: Phantasmagoria 1 sets a window size of 630x450. + // We can't set a width of 630, as that messes up the pitch, so we hack + // the internal script width here if (g_sci->getGameId() == GID_PHANTASMAGORIA) { tmpRunningWidth = 325; - tmpRunningHeight = 213; } _coordAdjuster->setScriptsResolution(tmpRunningWidth, tmpRunningHeight); diff --git a/engines/sci/graphics/screen.cpp b/engines/sci/graphics/screen.cpp index 4020518b72..3030fb4386 100644 --- a/engines/sci/graphics/screen.cpp +++ b/engines/sci/graphics/screen.cpp @@ -97,6 +97,13 @@ GfxScreen::GfxScreen(ResourceManager *resMan) : _resMan(resMan) { break; } + // Phantasmagoria 1 sets a window area of 630x450 + if (g_sci->getGameId() == GID_PHANTASMAGORIA) { + // TODO: Also set width to 630 (can't be set right now, as it messes up + // the pitch). For now, a hack has been placed in GfxFrameout::kernelAddPlane() + _height = 450; + } + _displayPixels = _displayWidth * _displayHeight; _visualScreen = (byte *)calloc(_pixels, 1); _priorityScreen = (byte *)calloc(_pixels, 1); -- cgit v1.2.3 From 4c43d6d85dc70e1b9b82629f1af1e9a37a136013 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sun, 8 Jul 2012 12:21:26 +0300 Subject: SCI: Add a hack in kGetAngleWorker to fix bug #3540976 kGetAngle(Worker) has been implemented based on behavior observed with a test program created with SCI Studio. However, the return values have subtle differences from the original, which uses atan(). This temporary hack will do for now till the implementation of kGetAngle is done again. A simpler atan2-based implementation has also been added for future reference --- engines/sci/engine/kmath.cpp | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (limited to 'engines/sci') diff --git a/engines/sci/engine/kmath.cpp b/engines/sci/engine/kmath.cpp index 7570856dff..cbfe00d3ca 100644 --- a/engines/sci/engine/kmath.cpp +++ b/engines/sci/engine/kmath.cpp @@ -78,6 +78,25 @@ reg_t kSqrt(EngineState *s, int argc, reg_t *argv) { } uint16 kGetAngleWorker(int16 x1, int16 y1, int16 x2, int16 y2) { + // TODO: This has been implemented based on behavior observed with a test + // program created with SCI Studio. However, the return values have subtle + // differences from the original, which uses atan(). + // The differences in the return values are the cause of bug #3540976 + // and perhaps bug #3037267 as well. + + // HACK: Return the expected value for Longbow, scene 150 (bug #3540976). + // This is a temporary solution, till the function returns the expected + // results. + if (g_sci->getGameId() == GID_LONGBOW && g_sci->getEngineState()->currentRoomNumber() == 150) { + if (x1 == 207 && y1 == 88 && x2 == 107 && y2 == 184) + return 226; + } + +#if 0 + // A simpler atan2-based implementation + return (360 - atan2((double)(x1 - x2), (double)(y1 - y2)) * 57.2958) % 360; +#endif + int16 xRel = x2 - x1; int16 yRel = y1 - y2; // y-axis is mirrored. int16 angle; -- cgit v1.2.3 From 2ef3f5e6957ce072f9bb5df0fe3f65da578b836c Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sun, 8 Jul 2012 15:58:50 +0300 Subject: SCI: Update the virtual file selected in the QFG4 character import screen This makes the character import screen in QFG4 functional, as the virtual file index was never updated --- engines/sci/engine/kgraphics.cpp | 6 ++++-- engines/sci/engine/klists.cpp | 5 +++++ 2 files changed, 9 insertions(+), 2 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/engine/kgraphics.cpp b/engines/sci/engine/kgraphics.cpp index ec8e0dbf1b..5b483eb4a2 100644 --- a/engines/sci/engine/kgraphics.cpp +++ b/engines/sci/engine/kgraphics.cpp @@ -950,8 +950,8 @@ reg_t kDrawControl(EngineState *s, int argc, reg_t *argv) { } } if (objName == "savedHeros") { - // Import of QfG character files dialog is shown - // display additional popup information before letting user use it + // Import of QfG character files dialog is shown. + // display additional popup information before letting user use it. reg_t changeDirButton = s->_segMan->findObjectByName("changeDirItem"); if (!changeDirButton.isNull()) { // check if checkDirButton is still enabled, in that case we are called the first time during that room @@ -964,6 +964,8 @@ reg_t kDrawControl(EngineState *s, int argc, reg_t *argv) { "for Quest for Glory 2. Example: 'qfg2-thief.sav'."); } } + + // For the SCI32 version of this, check kListAt(). s->_chosenQfGImportItem = readSelectorValue(s->_segMan, controlObject, SELECTOR(mark)); } diff --git a/engines/sci/engine/klists.cpp b/engines/sci/engine/klists.cpp index 15d18eb4bb..342fa95eda 100644 --- a/engines/sci/engine/klists.cpp +++ b/engines/sci/engine/klists.cpp @@ -506,6 +506,11 @@ reg_t kListAt(EngineState *s, int argc, reg_t *argv) { curIndex++; } + // Update the virtual file selected in the character import screen of QFG4. + // For the SCI0-SCI1.1 version of this, check kDrawControl(). + if (g_sci->inQfGImportRoom() && !strcmp(s->_segMan->getObjectName(curObject), "SelectorDText")) + s->_chosenQfGImportItem = listIndex; + return curObject; } -- cgit v1.2.3 From 10b3fdf2478dce3712de6213678f54335d5c46a0 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sun, 8 Jul 2012 16:10:40 +0300 Subject: SCI: Show information for correct file naming in the QFG4 import room This information is shown in previous QFG versions, but it had to be placed in a SCI32 graphics function in order to be shown in QFG4 too --- engines/sci/engine/kgraphics.cpp | 3 ++- engines/sci/graphics/frameout.cpp | 15 +++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) (limited to 'engines/sci') diff --git a/engines/sci/engine/kgraphics.cpp b/engines/sci/engine/kgraphics.cpp index 5b483eb4a2..6d938b6d22 100644 --- a/engines/sci/engine/kgraphics.cpp +++ b/engines/sci/engine/kgraphics.cpp @@ -951,7 +951,8 @@ reg_t kDrawControl(EngineState *s, int argc, reg_t *argv) { } if (objName == "savedHeros") { // Import of QfG character files dialog is shown. - // display additional popup information before letting user use it. + // Display additional popup information before letting user use it. + // For the SCI32 version of this, check kernelAddPlane(). reg_t changeDirButton = s->_segMan->findObjectByName("changeDirItem"); if (!changeDirButton.isNull()) { // check if checkDirButton is still enabled, in that case we are called the first time during that room diff --git a/engines/sci/graphics/frameout.cpp b/engines/sci/graphics/frameout.cpp index b13c7f4dce..cb56e24de9 100644 --- a/engines/sci/graphics/frameout.cpp +++ b/engines/sci/graphics/frameout.cpp @@ -117,6 +117,8 @@ void GfxFrameout::showCurrentScrollText() { } } +extern void showScummVMDialog(const Common::String &message); + void GfxFrameout::kernelAddPlane(reg_t object) { PlaneEntry newPlane; @@ -142,6 +144,19 @@ void GfxFrameout::kernelAddPlane(reg_t object) { _coordAdjuster->setScriptsResolution(tmpRunningWidth, tmpRunningHeight); } + // Import of QfG character files dialog is shown in QFG4. + // Display additional popup information before letting user use it. + // For the SCI0-SCI1.1 version of this, check kDrawControl(). + if (g_sci->inQfGImportRoom() && !strcmp(_segMan->getObjectName(object), "DSPlane")) { + showScummVMDialog("Characters saved inside ScummVM are shown " + "automatically. Character files saved in the original " + "interpreter need to be put inside ScummVM's saved games " + "directory and a prefix needs to be added depending on which " + "game it was saved in: 'qfg1-' for Quest for Glory 1, 'qfg2-' " + "for Quest for Glory 2, 'qfg3-' for Quest for Glory 3. " + "Example: 'qfg2-thief.sav'."); + } + newPlane.object = object; newPlane.priority = readSelectorValue(_segMan, object, SELECTOR(priority)); newPlane.lastPriority = 0xFFFF; // hidden -- cgit v1.2.3 From 3b69816a7d02f5c6ef03efd48062abd532cced18 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sun, 8 Jul 2012 16:15:07 +0300 Subject: SCI: Add another English floppy version of KQ5 (bug #3536863) According to this bug report, there exists another English version with the same file checksums as the vanilla English version, patched to Polish. We need a better way of distinguishing the two versions. Until we do, this is a duplicate entry of the Polish floppy version --- engines/sci/detection_tables.h | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'engines/sci') diff --git a/engines/sci/detection_tables.h b/engines/sci/detection_tables.h index 07b4733cfd..8a6184c7e4 100644 --- a/engines/sci/detection_tables.h +++ b/engines/sci/detection_tables.h @@ -1238,6 +1238,26 @@ static const struct ADGameDescription SciGameDescriptions[] = { AD_LISTEND}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + // King's Quest 5 - English DOS Floppy + // VERSION file reports "0.000.051" + // Supplied by misterhands in bug report #3536863. + // FIXME: According to bug #3536863, there exists another English version + // with the same file checksums as the vanilla English version, patched to + // Polish. We need a better way of distinguishing the two versions. Until + // we do, this is a duplicate entry of the Polish version below. + {"kq5", "", { + {"resource.map", 0, "70010c20138541f89013bb5e1b30f16a", 7998}, + {"resource.000", 0, "a591bd4b879fc832b8095c0b3befe9e2", 276398}, + {"resource.001", 0, "c0f48d4a7ebeaa6aa074fc98d77423e9", 1018560}, + {"resource.002", 0, "7f188a95acdb60bbe32a8379ba299393", 1307048}, + {"resource.003", 0, "0860785af59518b94d54718dddcd6907", 1348500}, + {"resource.004", 0, "c4745dd1e261c22daa6477961d08bf6c", 1239887}, + {"resource.005", 0, "6556ff8e7c4d1acf6a78aea154daa76c", 1287869}, + {"resource.006", 0, "da82e4beb744731d0a151f1d4922fafa", 1170456}, + {"resource.007", 0, "431def14ca29cdb5e6a5e84d3f38f679", 1240176}, + AD_LISTEND}, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + // King's Quest 5 - English DOS Floppy (supplied by omer_mor in bug report #3036996) // VERSION file reports "0.000.051" {"kq5", "", { @@ -1356,6 +1376,10 @@ static const struct ADGameDescription SciGameDescriptions[] = { // King's Quest 5 - Polish DOS Floppy (supplied by jacek909 in bug report #2725722, includes english language?!) // SCI interpreter version 1.000.060 + // FIXME: According to bug #3536863, this is actually a patched English version. + // The vanilla English version has the same MD5 checksums. + // We need a better way of detecting this. Until we do, a duplicate English + // entry has been placed above. {"kq5", "", { {"resource.map", 0, "70010c20138541f89013bb5e1b30f16a", 7998}, {"resource.000", 0, "a591bd4b879fc832b8095c0b3befe9e2", 276398}, -- cgit v1.2.3 From 50dc5009c85f3713d6917d5aba1cbb1428da1c30 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sun, 8 Jul 2012 21:58:47 +0300 Subject: SCI: Ignore another leftover script from KQ7 in the debugger --- engines/sci/console.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp index 40a6fd1415..564bbbbd79 100644 --- a/engines/sci/console.cpp +++ b/engines/sci/console.cpp @@ -2987,8 +2987,9 @@ void Console::printKernelCallsFound(int kernelFuncNum, bool showFoundScripts) { // Ignore specific leftover scripts, which require other non-existing scripts if ((_engine->getGameId() == GID_HOYLE3 && itr->getNumber() == 995) || (_engine->getGameId() == GID_KQ5 && itr->getNumber() == 980) || - (_engine->getGameId() == GID_SLATER && itr->getNumber() == 947) || - (_engine->getGameId() == GID_MOTHERGOOSE256 && itr->getNumber() == 980)) { + (_engine->getGameId() == GID_KQ7 && itr->getNumber() == 111) || + (_engine->getGameId() == GID_MOTHERGOOSE256 && itr->getNumber() == 980) || + (_engine->getGameId() == GID_SLATER && itr->getNumber() == 947)) { continue; } -- cgit v1.2.3 From 262c7a1fb73cb89a7c2db562374bdc0ce6f85d18 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sun, 8 Jul 2012 21:59:54 +0300 Subject: SCI: Fix a typo and add some comments to kGetAngleWorker() --- engines/sci/engine/kmath.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/engine/kmath.cpp b/engines/sci/engine/kmath.cpp index cbfe00d3ca..05c8845288 100644 --- a/engines/sci/engine/kmath.cpp +++ b/engines/sci/engine/kmath.cpp @@ -77,10 +77,16 @@ reg_t kSqrt(EngineState *s, int argc, reg_t *argv) { return make_reg(0, (int16) sqrt((float) ABS(argv[0].toSint16()))); } +/** + * Returns the angle (in degrees) between the two points determined by (x1, y1) + * and (x2, y2). The angle ranges from 0 to 359 degrees. + * What this function does is pretty simple but apparently the original is not + * accurate. + */ uint16 kGetAngleWorker(int16 x1, int16 y1, int16 x2, int16 y2) { // TODO: This has been implemented based on behavior observed with a test // program created with SCI Studio. However, the return values have subtle - // differences from the original, which uses atan(). + // differences from the original, which uses custom implementation of atan(). // The differences in the return values are the cause of bug #3540976 // and perhaps bug #3037267 as well. @@ -94,7 +100,7 @@ uint16 kGetAngleWorker(int16 x1, int16 y1, int16 x2, int16 y2) { #if 0 // A simpler atan2-based implementation - return (360 - atan2((double)(x1 - x2), (double)(y1 - y2)) * 57.2958) % 360; + return (int16)(360 - atan2((double)(x1 - x2), (double)(y1 - y2)) * 57.2958) % 360; #endif int16 xRel = x2 - x1; @@ -122,6 +128,7 @@ uint16 kGetAngleWorker(int16 x1, int16 y1, int16 x2, int16 y2) { // Convert from grads to degrees by merging grad 0 with grad 1, // grad 10 with grad 11, grad 20 with grad 21, etc. This leads to // "degrees" that equal either one or two grads. + // This subtraction is meant to change from 400 "degrees" into 360 degrees angle -= (angle + 9) / 10; return angle; } -- cgit v1.2.3 From b2fb2730d67deccf819701ae98cb49daddf6ac4f Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sun, 8 Jul 2012 22:00:36 +0300 Subject: SCI: Also set the filename of the videoState struct when playing AVIs --- engines/sci/engine/kvideo.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'engines/sci') diff --git a/engines/sci/engine/kvideo.cpp b/engines/sci/engine/kvideo.cpp index 61d2f935f7..cb2a763da9 100644 --- a/engines/sci/engine/kvideo.cpp +++ b/engines/sci/engine/kvideo.cpp @@ -209,6 +209,8 @@ reg_t kShowMovie(EngineState *s, int argc, reg_t *argv) { warning("Failed to open movie file %s", filename.c_str()); delete videoDecoder; videoDecoder = 0; + } else { + s->_videoState.fileName = filename; } break; } -- cgit v1.2.3 From 078c09c13e5ffa2266bccfd85c38a93d730a02e6 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Mon, 9 Jul 2012 01:27:39 +0300 Subject: SCI: Update comments in kGetAngleWorker() --- engines/sci/engine/kmath.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'engines/sci') diff --git a/engines/sci/engine/kmath.cpp b/engines/sci/engine/kmath.cpp index 05c8845288..a643fbe37a 100644 --- a/engines/sci/engine/kmath.cpp +++ b/engines/sci/engine/kmath.cpp @@ -89,6 +89,9 @@ uint16 kGetAngleWorker(int16 x1, int16 y1, int16 x2, int16 y2) { // differences from the original, which uses custom implementation of atan(). // The differences in the return values are the cause of bug #3540976 // and perhaps bug #3037267 as well. + // The results of this function match the expected results of SCI0, but not + // SCI1 (hence the bug in Longbow). We need to find the point in history + // when this function was changed. // HACK: Return the expected value for Longbow, scene 150 (bug #3540976). // This is a temporary solution, till the function returns the expected @@ -128,7 +131,6 @@ uint16 kGetAngleWorker(int16 x1, int16 y1, int16 x2, int16 y2) { // Convert from grads to degrees by merging grad 0 with grad 1, // grad 10 with grad 11, grad 20 with grad 21, etc. This leads to // "degrees" that equal either one or two grads. - // This subtraction is meant to change from 400 "degrees" into 360 degrees angle -= (angle + 9) / 10; return angle; } -- cgit v1.2.3 From 2c5cf9f860ffe5264268379ce6e0c0aa5ff25c0e Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sun, 15 Jul 2012 01:32:11 +0300 Subject: SCI: Properly detect the Polish version of KQ5 Thanks to jacek909 for the extra MD5 checksums of the Polish version. This fixes bugs #2725722 (Polish version checksums) and #3536863 (SCI: KQ5 Floppy English detected as Polish) --- engines/sci/detection_tables.h | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/detection_tables.h b/engines/sci/detection_tables.h index 8a6184c7e4..268914edba 100644 --- a/engines/sci/detection_tables.h +++ b/engines/sci/detection_tables.h @@ -1241,10 +1241,8 @@ static const struct ADGameDescription SciGameDescriptions[] = { // King's Quest 5 - English DOS Floppy // VERSION file reports "0.000.051" // Supplied by misterhands in bug report #3536863. - // FIXME: According to bug #3536863, there exists another English version - // with the same file checksums as the vanilla English version, patched to - // Polish. We need a better way of distinguishing the two versions. Until - // we do, this is a duplicate entry of the Polish version below. + // This is the original English version, which has been externally patched to + // Polish in the Polish release below. {"kq5", "", { {"resource.map", 0, "70010c20138541f89013bb5e1b30f16a", 7998}, {"resource.000", 0, "a591bd4b879fc832b8095c0b3befe9e2", 276398}, @@ -1374,12 +1372,10 @@ static const struct ADGameDescription SciGameDescriptions[] = { AD_LISTEND}, Common::IT_ITA, Common::kPlatformPC, ADGF_ADDENGLISH, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, - // King's Quest 5 - Polish DOS Floppy (supplied by jacek909 in bug report #2725722, includes english language?!) + // King's Quest 5 - Polish DOS Floppy (supplied by jacek909 in bug report #2725722) // SCI interpreter version 1.000.060 - // FIXME: According to bug #3536863, this is actually a patched English version. - // The vanilla English version has the same MD5 checksums. - // We need a better way of detecting this. Until we do, a duplicate English - // entry has been placed above. + // VERSION file reports "0.000.051". + // This is actually an English version with external text resource patches (bug #3536863). {"kq5", "", { {"resource.map", 0, "70010c20138541f89013bb5e1b30f16a", 7998}, {"resource.000", 0, "a591bd4b879fc832b8095c0b3befe9e2", 276398}, @@ -1390,6 +1386,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.005", 0, "6556ff8e7c4d1acf6a78aea154daa76c", 1287869}, {"resource.006", 0, "da82e4beb744731d0a151f1d4922fafa", 1170456}, {"resource.007", 0, "431def14ca29cdb5e6a5e84d3f38f679", 1240176}, + {"text.000", 0, "601aa35a3ddeb558e1280e0963e955a2", 1517}, AD_LISTEND}, Common::PL_POL, Common::kPlatformPC, ADGF_ADDENGLISH, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, -- cgit v1.2.3 From 1a90ca5ecd9eeaaca3b6de79dd940e9b29e472aa Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Mon, 16 Jul 2012 11:49:50 +0300 Subject: SCI: Handle all negative priority values. Fixes graphics in the SQ6 demo --- engines/sci/graphics/frameout.cpp | 17 ++++++----------- engines/sci/graphics/frameout.h | 4 ++-- 2 files changed, 8 insertions(+), 13 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/graphics/frameout.cpp b/engines/sci/graphics/frameout.cpp index cb56e24de9..fedae2eb6f 100644 --- a/engines/sci/graphics/frameout.cpp +++ b/engines/sci/graphics/frameout.cpp @@ -159,7 +159,7 @@ void GfxFrameout::kernelAddPlane(reg_t object) { newPlane.object = object; newPlane.priority = readSelectorValue(_segMan, object, SELECTOR(priority)); - newPlane.lastPriority = 0xFFFF; // hidden + newPlane.lastPriority = -1; // hidden newPlane.planeOffsetX = 0; newPlane.planeOffsetY = 0; newPlane.pictureId = kPlanePlainColored; @@ -465,15 +465,10 @@ bool sortHelper(const FrameoutEntry* entry1, const FrameoutEntry* entry2) { } bool planeSortHelper(const PlaneEntry &entry1, const PlaneEntry &entry2) { -// SegManager *segMan = g_sci->getEngineState()->_segMan; - -// uint16 plane1Priority = readSelectorValue(segMan, entry1, SELECTOR(priority)); -// uint16 plane2Priority = readSelectorValue(segMan, entry2, SELECTOR(priority)); - - if (entry1.priority == 0xffff) + if (entry1.priority < 0) return true; - if (entry2.priority == 0xffff) + if (entry2.priority < 0) return false; return entry1.priority < entry2.priority; @@ -639,13 +634,13 @@ void GfxFrameout::kernelFrameout() { _screen->drawLine(startPoint, endPoint, it2->color, it2->priority, it2->control); } - uint16 planeLastPriority = it->lastPriority; + int16 planeLastPriority = it->lastPriority; // Update priority here, sq6 sets it w/o UpdatePlane - uint16 planePriority = it->priority = readSelectorValue(_segMan, planeObject, SELECTOR(priority)); + int16 planePriority = it->priority = readSelectorValue(_segMan, planeObject, SELECTOR(priority)); it->lastPriority = planePriority; - if (planePriority == 0xffff) { // Plane currently not meant to be shown + if (planePriority < 0) { // Plane currently not meant to be shown // If plane was shown before, delete plane rect if (planePriority != planeLastPriority) _paint32->fillRect(it->planeRect, 0); diff --git a/engines/sci/graphics/frameout.h b/engines/sci/graphics/frameout.h index ecaf450d89..5fd2824224 100644 --- a/engines/sci/graphics/frameout.h +++ b/engines/sci/graphics/frameout.h @@ -40,8 +40,8 @@ typedef Common::List PlaneLineList; struct PlaneEntry { reg_t object; - uint16 priority; - uint16 lastPriority; + int16 priority; + int16 lastPriority; int16 planeOffsetX; int16 planeOffsetY; GuiResourceId pictureId; -- cgit v1.2.3 From 59ea9187457da7b771fbb760ad76805d3a6e3c6e Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Mon, 16 Jul 2012 12:04:34 +0300 Subject: SCI: Temporarily disable text display in the demo of SQ6 to stop crashes --- engines/sci/engine/kgraphics32.cpp | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'engines/sci') diff --git a/engines/sci/engine/kgraphics32.cpp b/engines/sci/engine/kgraphics32.cpp index 16e54a5429..f0989f5f00 100644 --- a/engines/sci/engine/kgraphics32.cpp +++ b/engines/sci/engine/kgraphics32.cpp @@ -173,6 +173,10 @@ reg_t kCreateTextBitmap(EngineState *s, int argc, reg_t *argv) { debugC(kDebugLevelStrings, "%s", text.c_str()); uint16 maxWidth = argv[1].toUint16(); // nsRight - nsLeft + 1 uint16 maxHeight = argv[2].toUint16(); // nsBottom - nsTop + 1 + // These values can be larger than the screen in the SQ6 demo + // TODO: Find out why. For now, don't show any text in the SQ6 demo. + if (g_sci->getGameId() == GID_SQ6 && g_sci->isDemo()) + return NULL_REG; return g_sci->_gfxText32->createTextBitmap(object, maxWidth, maxHeight); } case 1: { -- cgit v1.2.3 From 49c76c835bf000622bd5b078ef87275a335934fa Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Mon, 16 Jul 2012 12:11:22 +0300 Subject: SCI: Only skip text in room 100 in the SQ6 demo --- engines/sci/engine/kgraphics32.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/engine/kgraphics32.cpp b/engines/sci/engine/kgraphics32.cpp index f0989f5f00..093920e148 100644 --- a/engines/sci/engine/kgraphics32.cpp +++ b/engines/sci/engine/kgraphics32.cpp @@ -173,9 +173,9 @@ reg_t kCreateTextBitmap(EngineState *s, int argc, reg_t *argv) { debugC(kDebugLevelStrings, "%s", text.c_str()); uint16 maxWidth = argv[1].toUint16(); // nsRight - nsLeft + 1 uint16 maxHeight = argv[2].toUint16(); // nsBottom - nsTop + 1 - // These values can be larger than the screen in the SQ6 demo - // TODO: Find out why. For now, don't show any text in the SQ6 demo. - if (g_sci->getGameId() == GID_SQ6 && g_sci->isDemo()) + // These values can be larger than the screen in the SQ6 demo, room 100 + // TODO: Find out why. For now, don't show any text in that room. + if (g_sci->getGameId() == GID_SQ6 && g_sci->isDemo() && s->currentRoomNumber() == 100) return NULL_REG; return g_sci->_gfxText32->createTextBitmap(object, maxWidth, maxHeight); } -- cgit v1.2.3 From eba2ed99f8b8bf0d3aaf6a314ffbd9e196da8c8c Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Tue, 17 Jul 2012 00:49:09 +0300 Subject: SCI: Bugfix for kCreateTextBitmap(). Fixes the ComPost text in the SQ6 demo --- engines/sci/engine/kgraphics32.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/engine/kgraphics32.cpp b/engines/sci/engine/kgraphics32.cpp index 093920e148..7cfac57675 100644 --- a/engines/sci/engine/kgraphics32.cpp +++ b/engines/sci/engine/kgraphics32.cpp @@ -39,6 +39,7 @@ #include "sci/graphics/cache.h" #include "sci/graphics/compare.h" #include "sci/graphics/controls16.h" +#include "sci/graphics/coordadjuster.h" #include "sci/graphics/cursor.h" #include "sci/graphics/palette.h" #include "sci/graphics/paint16.h" @@ -171,8 +172,9 @@ reg_t kCreateTextBitmap(EngineState *s, int argc, reg_t *argv) { debugC(kDebugLevelStrings, "kCreateTextBitmap case 0 (%04x:%04x, %04x:%04x, %04x:%04x)", PRINT_REG(argv[1]), PRINT_REG(argv[2]), PRINT_REG(argv[3])); debugC(kDebugLevelStrings, "%s", text.c_str()); - uint16 maxWidth = argv[1].toUint16(); // nsRight - nsLeft + 1 - uint16 maxHeight = argv[2].toUint16(); // nsBottom - nsTop + 1 + int16 maxWidth = argv[1].toUint16(); + int16 maxHeight = argv[2].toUint16(); + g_sci->_gfxCoordAdjuster->fromScriptToDisplay(maxHeight, maxWidth); // These values can be larger than the screen in the SQ6 demo, room 100 // TODO: Find out why. For now, don't show any text in that room. if (g_sci->getGameId() == GID_SQ6 && g_sci->isDemo() && s->currentRoomNumber() == 100) -- cgit v1.2.3 From a12b3ea2dde9db348424f401a35fca3167120011 Mon Sep 17 00:00:00 2001 From: Matthew Hoops Date: Fri, 20 Jul 2012 20:52:58 -0400 Subject: SCI: Move the SEQ code to the new VideoDecoder API --- engines/sci/console.cpp | 5 ++-- engines/sci/engine/kvideo.cpp | 7 +++-- engines/sci/video/seq_decoder.cpp | 61 +++++++++++++++++++-------------------- engines/sci/video/seq_decoder.h | 52 ++++++++++++++++++--------------- 4 files changed, 64 insertions(+), 61 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp index 564bbbbd79..2a4ad1743d 100644 --- a/engines/sci/console.cpp +++ b/engines/sci/console.cpp @@ -250,9 +250,8 @@ void Console::postEnter() { #endif if (_videoFile.hasSuffix(".seq")) { - SeqDecoder *seqDecoder = new SeqDecoder(); - seqDecoder->setFrameDelay(_videoFrameDelay); - videoDecoder = seqDecoder; + videoDecoder = new SEQDecoder(_videoFrameDelay); + ((Video::AdvancedVideoDecoder *)videoDecoder)->start(); // TODO: Remove after new API is complete #ifdef ENABLE_SCI32 } else if (_videoFile.hasSuffix(".vmd")) { videoDecoder = new Video::VMDDecoder(g_system->getMixer()); diff --git a/engines/sci/engine/kvideo.cpp b/engines/sci/engine/kvideo.cpp index cb2a763da9..bfe32a8d82 100644 --- a/engines/sci/engine/kvideo.cpp +++ b/engines/sci/engine/kvideo.cpp @@ -162,15 +162,16 @@ reg_t kShowMovie(EngineState *s, int argc, reg_t *argv) { } else { // DOS SEQ // SEQ's are called with no subops, just the string and delay - SeqDecoder *seqDecoder = new SeqDecoder(); - seqDecoder->setFrameDelay(argv[1].toUint16()); // Time between frames in ticks - videoDecoder = seqDecoder; + // Time is specified as ticks + videoDecoder = new SEQDecoder(argv[1].toUint16()); if (!videoDecoder->loadFile(filename)) { warning("Failed to open movie file %s", filename.c_str()); delete videoDecoder; videoDecoder = 0; } + + ((Video::AdvancedVideoDecoder *)videoDecoder)->start(); // TODO: Remove after new API is complete } } else { // Windows AVI diff --git a/engines/sci/video/seq_decoder.cpp b/engines/sci/video/seq_decoder.cpp index abd64911a7..a7b6346eca 100644 --- a/engines/sci/video/seq_decoder.cpp +++ b/engines/sci/video/seq_decoder.cpp @@ -41,33 +41,44 @@ enum seqFrameTypes { kSeqFrameDiff = 1 }; -SeqDecoder::SeqDecoder() { - _fileStream = 0; - _surface = 0; - _dirtyPalette = false; +SEQDecoder::SEQDecoder(uint frameDelay) : _frameDelay(frameDelay) { } -SeqDecoder::~SeqDecoder() { +SEQDecoder::~SEQDecoder() { close(); } -bool SeqDecoder::loadStream(Common::SeekableReadStream *stream) { +bool SEQDecoder::loadStream(Common::SeekableReadStream *stream) { close(); + addTrack(new SEQVideoTrack(stream, _frameDelay)); + + return true; +} + +SEQDecoder::SEQVideoTrack::SEQVideoTrack(Common::SeekableReadStream *stream, uint frameDelay) { + assert(stream); + assert(frameDelay != 0); _fileStream = stream; + _frameDelay = frameDelay; + _curFrame = -1; + _surface = new Graphics::Surface(); _surface->create(SEQ_SCREEN_WIDTH, SEQ_SCREEN_HEIGHT, Graphics::PixelFormat::createFormatCLUT8()); _frameCount = _fileStream->readUint16LE(); - // Set palette - int paletteChunkSize = _fileStream->readUint32LE(); - readPaletteChunk(paletteChunkSize); + // Set initial palette + readPaletteChunk(_fileStream->readUint32LE()); +} - return true; +SEQDecoder::SEQVideoTrack::~SEQVideoTrack() { + delete _fileStream; + _surface->free(); + delete _surface; } -void SeqDecoder::readPaletteChunk(uint16 chunkSize) { +void SEQDecoder::SEQVideoTrack::readPaletteChunk(uint16 chunkSize) { byte *paletteData = new byte[chunkSize]; _fileStream->read(paletteData, chunkSize); @@ -91,23 +102,7 @@ void SeqDecoder::readPaletteChunk(uint16 chunkSize) { delete[] paletteData; } -void SeqDecoder::close() { - if (!_fileStream) - return; - - _frameDelay = 0; - - delete _fileStream; - _fileStream = 0; - - _surface->free(); - delete _surface; - _surface = 0; - - reset(); -} - -const Graphics::Surface *SeqDecoder::decodeNextFrame() { +const Graphics::Surface *SEQDecoder::SEQVideoTrack::decodeNextFrame() { int16 frameWidth = _fileStream->readUint16LE(); int16 frameHeight = _fileStream->readUint16LE(); int16 frameLeft = _fileStream->readUint16LE(); @@ -142,9 +137,6 @@ const Graphics::Surface *SeqDecoder::decodeNextFrame() { delete[] buf; } - if (_curFrame == -1) - _startTime = g_system->getMillis(); - _curFrame++; return _surface; } @@ -159,7 +151,7 @@ const Graphics::Surface *SeqDecoder::decodeNextFrame() { } \ memcpy(dest + writeRow * SEQ_SCREEN_WIDTH + writeCol, litData + litPos, n); -bool SeqDecoder::decodeFrame(byte *rleData, int rleSize, byte *litData, int litSize, byte *dest, int left, int width, int height, int colorKey) { +bool SEQDecoder::SEQVideoTrack::decodeFrame(byte *rleData, int rleSize, byte *litData, int litSize, byte *dest, int left, int width, int height, int colorKey) { int writeRow = 0; int writeCol = left; int litPos = 0; @@ -237,4 +229,9 @@ bool SeqDecoder::decodeFrame(byte *rleData, int rleSize, byte *litData, int litS return true; } +const byte *SEQDecoder::SEQVideoTrack::getPalette() const { + _dirtyPalette = false; + return _palette; +} + } // End of namespace Sci diff --git a/engines/sci/video/seq_decoder.h b/engines/sci/video/seq_decoder.h index 800a3c9024..c07bcd748b 100644 --- a/engines/sci/video/seq_decoder.h +++ b/engines/sci/video/seq_decoder.h @@ -40,27 +40,16 @@ namespace Sci { /** * Implementation of the Sierra SEQ decoder, used in KQ6 DOS floppy/CD and GK1 DOS */ -class SeqDecoder : public Video::FixedRateVideoDecoder { +class SEQDecoder : public Video::AdvancedVideoDecoder { public: - SeqDecoder(); - virtual ~SeqDecoder(); + SEQDecoder(uint frameDelay); + virtual ~SEQDecoder(); bool loadStream(Common::SeekableReadStream *stream); - void close(); - void setFrameDelay(int frameDelay) { _frameDelay = frameDelay; } - - bool isVideoLoaded() const { return _fileStream != 0; } uint16 getWidth() const { return SEQ_SCREEN_WIDTH; } uint16 getHeight() const { return SEQ_SCREEN_HEIGHT; } - uint32 getFrameCount() const { return _frameCount; } - const Graphics::Surface *decodeNextFrame(); Graphics::PixelFormat getPixelFormat() const { return Graphics::PixelFormat::createFormatCLUT8(); } - const byte *getPalette() { _dirtyPalette = false; return _palette; } - bool hasDirtyPalette() const { return _dirtyPalette; } - -protected: - Common::Rational getFrameRate() const { assert(_frameDelay); return Common::Rational(60, _frameDelay); } private: enum { @@ -68,16 +57,33 @@ private: SEQ_SCREEN_HEIGHT = 200 }; - void readPaletteChunk(uint16 chunkSize); - bool decodeFrame(byte *rleData, int rleSize, byte *litData, int litSize, byte *dest, int left, int width, int height, int colorKey); + class SEQVideoTrack : public FixedRateVideoTrack, public FixedLengthVideoTrack { + public: + SEQVideoTrack(Common::SeekableReadStream *stream, uint frameDelay); + ~SEQVideoTrack(); + + int getCurFrame() const { return _curFrame; } + int getFrameCount() const { return _frameCount; } + const Graphics::Surface *decodeNextFrame(); + const byte *getPalette() const; + bool hasDirtyPalette() const { return _dirtyPalette; } + + protected: + Common::Rational getFrameRate() const { return Common::Rational(60, _frameDelay); } + + private: + void readPaletteChunk(uint16 chunkSize); + bool decodeFrame(byte *rleData, int rleSize, byte *litData, int litSize, byte *dest, int left, int width, int height, int colorKey); + + Common::SeekableReadStream *_fileStream; + int _curFrame, _frameCount; + byte _palette[256 * 3]; + mutable bool _dirtyPalette; + Graphics::Surface *_surface; + uint _frameDelay; + }; - uint16 _width, _height; - uint16 _frameDelay; - Common::SeekableReadStream *_fileStream; - byte _palette[256 * 3]; - bool _dirtyPalette; - uint32 _frameCount; - Graphics::Surface *_surface; + uint _frameDelay; }; } // End of namespace Sci -- cgit v1.2.3 From fb1edcd4fef7fd750b4af18745ca7b3151b56aae Mon Sep 17 00:00:00 2001 From: Matthew Hoops Date: Sat, 21 Jul 2012 12:40:16 -0400 Subject: VIDEO: Add getWidth()/getHeight()/getPixelFormat() functions to VideoTrack The default implementations of those functions in AdvancedVideoDecoder now call into them. --- engines/sci/video/seq_decoder.h | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/video/seq_decoder.h b/engines/sci/video/seq_decoder.h index c07bcd748b..ac801d3f19 100644 --- a/engines/sci/video/seq_decoder.h +++ b/engines/sci/video/seq_decoder.h @@ -47,21 +47,15 @@ public: bool loadStream(Common::SeekableReadStream *stream); - uint16 getWidth() const { return SEQ_SCREEN_WIDTH; } - uint16 getHeight() const { return SEQ_SCREEN_HEIGHT; } - Graphics::PixelFormat getPixelFormat() const { return Graphics::PixelFormat::createFormatCLUT8(); } - private: - enum { - SEQ_SCREEN_WIDTH = 320, - SEQ_SCREEN_HEIGHT = 200 - }; - class SEQVideoTrack : public FixedRateVideoTrack, public FixedLengthVideoTrack { public: SEQVideoTrack(Common::SeekableReadStream *stream, uint frameDelay); ~SEQVideoTrack(); + uint16 getWidth() const { return SEQ_SCREEN_WIDTH; } + uint16 getHeight() const { return SEQ_SCREEN_HEIGHT; } + Graphics::PixelFormat getPixelFormat() const { return Graphics::PixelFormat::createFormatCLUT8(); } int getCurFrame() const { return _curFrame; } int getFrameCount() const { return _frameCount; } const Graphics::Surface *decodeNextFrame(); @@ -72,6 +66,11 @@ private: Common::Rational getFrameRate() const { return Common::Rational(60, _frameDelay); } private: + enum { + SEQ_SCREEN_WIDTH = 320, + SEQ_SCREEN_HEIGHT = 200 + }; + void readPaletteChunk(uint16 chunkSize); bool decodeFrame(byte *rleData, int rleSize, byte *litData, int litSize, byte *dest, int left, int width, int height, int colorKey); -- cgit v1.2.3 From e74c306a7f3847128eb786c2d56f04d559e5a822 Mon Sep 17 00:00:00 2001 From: Matthew Hoops Date: Sat, 21 Jul 2012 14:43:08 -0400 Subject: SCI: Switch SEQDecoder to using the new FixedDurationVideoTrack subclass --- engines/sci/video/seq_decoder.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines/sci') diff --git a/engines/sci/video/seq_decoder.h b/engines/sci/video/seq_decoder.h index ac801d3f19..75d7ce6c3d 100644 --- a/engines/sci/video/seq_decoder.h +++ b/engines/sci/video/seq_decoder.h @@ -48,7 +48,7 @@ public: bool loadStream(Common::SeekableReadStream *stream); private: - class SEQVideoTrack : public FixedRateVideoTrack, public FixedLengthVideoTrack { + class SEQVideoTrack : public FixedDurationVideoTrack { public: SEQVideoTrack(Common::SeekableReadStream *stream, uint frameDelay); ~SEQVideoTrack(); -- cgit v1.2.3 From 7654b2036268bb56f3b08b88858f2a9e4862b056 Mon Sep 17 00:00:00 2001 From: Matthew Hoops Date: Sun, 22 Jul 2012 14:11:11 -0400 Subject: VIDEO: Merge the three Fixed* VideoTrack classes Avoids diamond inheritance, which makes it impossible to downcast without rtti --- engines/sci/video/seq_decoder.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines/sci') diff --git a/engines/sci/video/seq_decoder.h b/engines/sci/video/seq_decoder.h index 75d7ce6c3d..82254990d6 100644 --- a/engines/sci/video/seq_decoder.h +++ b/engines/sci/video/seq_decoder.h @@ -48,7 +48,7 @@ public: bool loadStream(Common::SeekableReadStream *stream); private: - class SEQVideoTrack : public FixedDurationVideoTrack { + class SEQVideoTrack : public FixedRateVideoTrack { public: SEQVideoTrack(Common::SeekableReadStream *stream, uint frameDelay); ~SEQVideoTrack(); -- cgit v1.2.3 From 0f0c6f935443212d76422959d040b87fc78d02c7 Mon Sep 17 00:00:00 2001 From: Matthew Hoops Date: Sun, 22 Jul 2012 14:13:20 -0400 Subject: VIDEO: Rewrite the AVI code to use AdvancedVideoDecoder In addition to using the new API, it should theoretically support multiple audio and video tracks now but that has not been tested. --- engines/sci/console.cpp | 6 ++++-- engines/sci/engine/kvideo.cpp | 7 +++++-- 2 files changed, 9 insertions(+), 4 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp index 2a4ad1743d..a6a6d4496f 100644 --- a/engines/sci/console.cpp +++ b/engines/sci/console.cpp @@ -259,10 +259,12 @@ void Console::postEnter() { videoDecoder = new RobotDecoder(g_system->getMixer(), _engine->getPlatform() == Common::kPlatformMacintosh); } else if (_videoFile.hasSuffix(".duk")) { duckMode = true; - videoDecoder = new Video::AviDecoder(g_system->getMixer()); + videoDecoder = new Video::AVIDecoder(); + ((Video::AdvancedVideoDecoder *)videoDecoder)->start(); #endif } else if (_videoFile.hasSuffix(".avi")) { - videoDecoder = new Video::AviDecoder(g_system->getMixer()); + videoDecoder = new Video::AVIDecoder(); + ((Video::AdvancedVideoDecoder *)videoDecoder)->start(); } else { warning("Unrecognized video type"); } diff --git a/engines/sci/engine/kvideo.cpp b/engines/sci/engine/kvideo.cpp index bfe32a8d82..2c1532cc46 100644 --- a/engines/sci/engine/kvideo.cpp +++ b/engines/sci/engine/kvideo.cpp @@ -191,7 +191,7 @@ reg_t kShowMovie(EngineState *s, int argc, reg_t *argv) { switch (argv[0].toUint16()) { case 0: { Common::String filename = s->_segMan->getString(argv[1]); - videoDecoder = new Video::AviDecoder(g_system->getMixer()); + videoDecoder = new Video::AVIDecoder(); if (filename.equalsIgnoreCase("gk2a.avi")) { // HACK: Switch to 16bpp graphics for Indeo3. @@ -212,6 +212,7 @@ reg_t kShowMovie(EngineState *s, int argc, reg_t *argv) { videoDecoder = 0; } else { s->_videoState.fileName = filename; + ((Video::AdvancedVideoDecoder *)videoDecoder)->start(); } break; } @@ -407,13 +408,15 @@ reg_t kPlayDuck(EngineState *s, int argc, reg_t *argv) { s->_videoState.reset(); s->_videoState.fileName = Common::String::format("%d.duk", argv[1].toUint16()); - videoDecoder = new Video::AviDecoder(g_system->getMixer()); + videoDecoder = new Video::AVIDecoder(); if (!videoDecoder->loadFile(s->_videoState.fileName)) { warning("Could not open Duck %s", s->_videoState.fileName.c_str()); break; } + ((Video::AdvancedVideoDecoder *)videoDecoder)->start(); + if (reshowCursor) g_sci->_gfxCursor->kernelHide(); -- cgit v1.2.3 From d4231fda1cb2399e123054ddaaeca2b4c2749966 Mon Sep 17 00:00:00 2001 From: Matthew Hoops Date: Sun, 22 Jul 2012 23:17:36 -0400 Subject: SCI: Rewrite RobotDecoder to use the AdvancedVideoDecoder API --- engines/sci/console.cpp | 8 +- engines/sci/engine/kvideo.cpp | 9 +- engines/sci/sci.cpp | 2 +- engines/sci/video/robot_decoder.cpp | 377 +++++++++++++++++++----------------- engines/sci/video/robot_decoder.h | 129 ++++++------ 5 files changed, 282 insertions(+), 243 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp index a6a6d4496f..9b5ef35e92 100644 --- a/engines/sci/console.cpp +++ b/engines/sci/console.cpp @@ -251,25 +251,25 @@ void Console::postEnter() { if (_videoFile.hasSuffix(".seq")) { videoDecoder = new SEQDecoder(_videoFrameDelay); - ((Video::AdvancedVideoDecoder *)videoDecoder)->start(); // TODO: Remove after new API is complete #ifdef ENABLE_SCI32 } else if (_videoFile.hasSuffix(".vmd")) { videoDecoder = new Video::VMDDecoder(g_system->getMixer()); } else if (_videoFile.hasSuffix(".rbt")) { - videoDecoder = new RobotDecoder(g_system->getMixer(), _engine->getPlatform() == Common::kPlatformMacintosh); + videoDecoder = new RobotDecoder(_engine->getPlatform() == Common::kPlatformMacintosh); } else if (_videoFile.hasSuffix(".duk")) { duckMode = true; videoDecoder = new Video::AVIDecoder(); - ((Video::AdvancedVideoDecoder *)videoDecoder)->start(); #endif } else if (_videoFile.hasSuffix(".avi")) { videoDecoder = new Video::AVIDecoder(); - ((Video::AdvancedVideoDecoder *)videoDecoder)->start(); } else { warning("Unrecognized video type"); } if (videoDecoder && videoDecoder->loadFile(_videoFile)) { + if (!_videoFile.hasSuffix(".vmd")) // TODO: Remove after new API is complete + ((Video::AdvancedVideoDecoder *)videoDecoder)->start(); + _engine->_gfxCursor->kernelHide(); #ifdef ENABLE_SCI32 diff --git a/engines/sci/engine/kvideo.cpp b/engines/sci/engine/kvideo.cpp index 2c1532cc46..456f860493 100644 --- a/engines/sci/engine/kvideo.cpp +++ b/engines/sci/engine/kvideo.cpp @@ -254,6 +254,7 @@ reg_t kRobot(EngineState *s, int argc, reg_t *argv) { int16 y = argv[5].toUint16(); warning("kRobot(init), id %d, obj %04x:%04x, flag %d, x=%d, y=%d", id, PRINT_REG(obj), flag, x, y); g_sci->_robotDecoder->load(id); + g_sci->_robotDecoder->start(); g_sci->_robotDecoder->setPos(x, y); } break; @@ -269,13 +270,13 @@ reg_t kRobot(EngineState *s, int argc, reg_t *argv) { warning("kRobot(%d)", subop); break; case 8: // sync - //if (false) { // debug: automatically skip all robot videos - if ((uint32)g_sci->_robotDecoder->getCurFrame() != g_sci->_robotDecoder->getFrameCount() - 1) { - writeSelector(s->_segMan, argv[1], SELECTOR(signal), NULL_REG); - } else { + //if (true) { // debug: automatically skip all robot videos + if (g_sci->_robotDecoder->endOfVideo()) { g_sci->_robotDecoder->close(); // Signal the engine scripts that the video is done writeSelector(s->_segMan, argv[1], SELECTOR(signal), SIGNAL_REG); + } else { + writeSelector(s->_segMan, argv[1], SELECTOR(signal), NULL_REG); } break; default: diff --git a/engines/sci/sci.cpp b/engines/sci/sci.cpp index d43a9d06fc..42ae00b525 100644 --- a/engines/sci/sci.cpp +++ b/engines/sci/sci.cpp @@ -632,7 +632,7 @@ void SciEngine::initGraphics() { _gfxPaint = _gfxPaint32; _gfxText32 = new GfxText32(_gamestate->_segMan, _gfxCache, _gfxScreen); _gfxControls32 = new GfxControls32(_gamestate->_segMan, _gfxCache, _gfxScreen, _gfxText32); - _robotDecoder = new RobotDecoder(g_system->getMixer(), getPlatform() == Common::kPlatformMacintosh); + _robotDecoder = new RobotDecoder(getPlatform() == Common::kPlatformMacintosh); _gfxFrameout = new GfxFrameout(_gamestate->_segMan, _resMan, _gfxCoordAdjuster, _gfxCache, _gfxScreen, _gfxPalette, _gfxPaint32); } else { #endif diff --git a/engines/sci/video/robot_decoder.cpp b/engines/sci/video/robot_decoder.cpp index ebcfac6054..6fe4c645f4 100644 --- a/engines/sci/video/robot_decoder.cpp +++ b/engines/sci/video/robot_decoder.cpp @@ -22,11 +22,13 @@ #include "common/archive.h" #include "common/stream.h" +#include "common/substream.h" #include "common/system.h" #include "common/textconsole.h" #include "common/util.h" #include "graphics/surface.h" +#include "audio/audiostream.h" #include "audio/decoders/raw.h" #include "sci/resource.h" @@ -63,57 +65,26 @@ namespace Sci { // our graphics engine, it looks just like a part of the room. A RBT can move // around the screen and go behind other objects. (...) -#ifdef ENABLE_SCI32 - -enum robotPalTypes { +enum RobotPalTypes { kRobotPalVariable = 0, kRobotPalConstant = 1 }; -RobotDecoder::RobotDecoder(Audio::Mixer *mixer, bool isBigEndian) { - _surface = 0; - _width = 0; - _height = 0; +RobotDecoder::RobotDecoder(bool isBigEndian) { _fileStream = 0; - _audioStream = 0; - _dirtyPalette = false; _pos = Common::Point(0, 0); - _mixer = mixer; _isBigEndian = isBigEndian; + _frameTotalSize = 0; } RobotDecoder::~RobotDecoder() { close(); } -bool RobotDecoder::load(GuiResourceId id) { - // TODO: RAMA's robot 1003 cannot be played (shown at the menu screen) - - // its drawn at odd coordinates. SV can't play it either (along with some - // others), so it must be some new functionality added in RAMA's robot - // videos. Skip it for now. - if (g_sci->getGameId() == GID_RAMA && id == 1003) - return false; - - // TODO: The robot video in the Lighthouse demo gets stuck - if (g_sci->getGameId() == GID_LIGHTHOUSE && id == 16) - return false; - - Common::String fileName = Common::String::format("%d.rbt", id); - Common::SeekableReadStream *stream = SearchMan.createReadStreamForMember(fileName); - - if (!stream) { - warning("Unable to open robot file %s", fileName.c_str()); - return false; - } - - return loadStream(stream); -} - bool RobotDecoder::loadStream(Common::SeekableReadStream *stream) { close(); _fileStream = new Common::SeekableSubReadStreamEndian(stream, 0, stream->size(), _isBigEndian, DisposeAfterUse::YES); - _surface = new Graphics::Surface(); readHeaderChunk(); @@ -125,131 +96,60 @@ bool RobotDecoder::loadStream(Common::SeekableReadStream *stream) { if (_header.version < 4 || _header.version > 6) error("Unknown robot version: %d", _header.version); - if (_header.hasSound) { - _audioStream = Audio::makeQueuingAudioStream(11025, false); - _mixer->playStream(Audio::Mixer::kMusicSoundType, &_audioHandle, _audioStream, -1, getVolume(), getBalance()); - } + RobotVideoTrack *videoTrack = new RobotVideoTrack(_header.frameCount); + addTrack(videoTrack); - readPaletteChunk(_header.paletteDataSize); - readFrameSizesChunk(); - calculateVideoDimensions(); - _surface->create(_width, _height, Graphics::PixelFormat::createFormatCLUT8()); + if (_header.hasSound) + addTrack(new RobotAudioTrack()); + videoTrack->readPaletteChunk(_fileStream, _header.paletteDataSize); + readFrameSizesChunk(); + videoTrack->calculateVideoDimensions(_fileStream, _frameTotalSize); return true; } -void RobotDecoder::readHeaderChunk() { - // Header (60 bytes) - _fileStream->skip(6); - _header.version = _fileStream->readUint16(); - _header.audioChunkSize = _fileStream->readUint16(); - _header.audioSilenceSize = _fileStream->readUint16(); - _fileStream->skip(2); - _header.frameCount = _fileStream->readUint16(); - _header.paletteDataSize = _fileStream->readUint16(); - _header.unkChunkDataSize = _fileStream->readUint16(); - _fileStream->skip(5); - _header.hasSound = _fileStream->readByte(); - _fileStream->skip(34); - - // Some videos (e.g. robot 1305 in Phantasmagoria and - // robot 184 in Lighthouse) have an unknown chunk before - // the palette chunk (probably used for sound preloading). - // Skip it here. - if (_header.unkChunkDataSize) - _fileStream->skip(_header.unkChunkDataSize); -} - -void RobotDecoder::readPaletteChunk(uint16 chunkSize) { - byte *paletteData = new byte[chunkSize]; - _fileStream->read(paletteData, chunkSize); - - // SCI1.1 palette - byte palFormat = paletteData[32]; - uint16 palColorStart = paletteData[25]; - uint16 palColorCount = READ_SCI11ENDIAN_UINT16(paletteData + 29); +bool RobotDecoder::load(GuiResourceId id) { + // TODO: RAMA's robot 1003 cannot be played (shown at the menu screen) - + // its drawn at odd coordinates. SV can't play it either (along with some + // others), so it must be some new functionality added in RAMA's robot + // videos. Skip it for now. + if (g_sci->getGameId() == GID_RAMA && id == 1003) + return false; + + // TODO: The robot video in the Lighthouse demo gets stuck + if (g_sci->getGameId() == GID_LIGHTHOUSE && id == 16) + return false; - int palOffset = 37; - memset(_palette, 0, 256 * 3); + Common::String fileName = Common::String::format("%d.rbt", id); + Common::SeekableReadStream *stream = SearchMan.createReadStreamForMember(fileName); - for (uint16 colorNo = palColorStart; colorNo < palColorStart + palColorCount; colorNo++) { - if (palFormat == kRobotPalVariable) - palOffset++; - _palette[colorNo * 3 + 0] = paletteData[palOffset++]; - _palette[colorNo * 3 + 1] = paletteData[palOffset++]; - _palette[colorNo * 3 + 2] = paletteData[palOffset++]; + if (!stream) { + warning("Unable to open robot file %s", fileName.c_str()); + return false; } - _dirtyPalette = true; - delete[] paletteData; + return loadStream(stream); } +void RobotDecoder::close() { + AdvancedVideoDecoder::close(); -void RobotDecoder::readFrameSizesChunk() { - // The robot video file contains 2 tables, with one entry for each frame: - // - A table containing the size of the image in each video frame - // - A table containing the total size of each video frame. - // In v5 robots, the tables contain 16-bit integers, whereas in v6 robots, - // they contain 32-bit integers. - - _frameTotalSize = new uint32[_header.frameCount]; - - // TODO: The table reading code can probably be removed once the - // audio chunk size is figured out (check the TODO inside processNextFrame()) -#if 0 - // We don't need any of the two tables to play the video, so we ignore - // both of them. - uint16 wordSize = _header.version == 6 ? 4 : 2; - _fileStream->skip(_header.frameCount * wordSize * 2); -#else - switch (_header.version) { - case 4: - case 5: // sizes are 16-bit integers - // Skip table with frame image sizes, as we don't need it - _fileStream->skip(_header.frameCount * 2); - for (int i = 0; i < _header.frameCount; ++i) - _frameTotalSize[i] = _fileStream->readUint16(); - break; - case 6: // sizes are 32-bit integers - // Skip table with frame image sizes, as we don't need it - _fileStream->skip(_header.frameCount * 4); - for (int i = 0; i < _header.frameCount; ++i) - _frameTotalSize[i] = _fileStream->readUint32(); - break; - default: - error("Can't yet handle index table for robot version %d", _header.version); - } -#endif - - // 2 more unknown tables - _fileStream->skip(1024 + 512); + delete _fileStream; + _fileStream = 0; - // Pad to nearest 2 kilobytes - uint32 curPos = _fileStream->pos(); - if (curPos & 0x7ff) - _fileStream->seek((curPos & ~0x7ff) + 2048); + delete[] _frameTotalSize; + _frameTotalSize = 0; } -void RobotDecoder::calculateVideoDimensions() { - // This is an O(n) operation, as each frame has a different size. - // We need to know the actual frame size to have a constant video size. - uint32 pos = _fileStream->pos(); - - for (uint32 curFrame = 0; curFrame < _header.frameCount; curFrame++) { - _fileStream->skip(4); - uint16 frameWidth = _fileStream->readUint16(); - uint16 frameHeight = _fileStream->readUint16(); - if (frameWidth > _width) - _width = frameWidth; - if (frameHeight > _height) - _height = frameHeight; - _fileStream->skip(_frameTotalSize[curFrame] - 8); - } +void RobotDecoder::readNextPacket() { + // Get our track + RobotVideoTrack *videoTrack = (RobotVideoTrack *)getTrack(0); + videoTrack->increaseCurFrame(); + Graphics::Surface *surface = videoTrack->getSurface(); - _fileStream->seek(pos); -} + if (videoTrack->endOfTrack()) + return; -const Graphics::Surface *RobotDecoder::decodeNextFrame() { // Read frame image header (24 bytes) _fileStream->skip(3); byte frameScale = _fileStream->readByte(); @@ -258,23 +158,28 @@ const Graphics::Surface *RobotDecoder::decodeNextFrame() { _fileStream->skip(4); // unknown, almost always 0 uint16 frameX = _fileStream->readUint16(); uint16 frameY = _fileStream->readUint16(); + // TODO: In v4 robot files, frameX and frameY have a different meaning. // Set them both to 0 for v4 for now, so that robots in PQ:SWAT show up // correctly. if (_header.version == 4) frameX = frameY = 0; + uint16 compressedSize = _fileStream->readUint16(); uint16 frameFragments = _fileStream->readUint16(); _fileStream->skip(4); // unknown uint32 decompressedSize = frameWidth * frameHeight * frameScale / 100; + // FIXME: A frame's height + position can go off limits... why? With the // following, we cut the contents to fit the frame - uint16 scaledHeight = CLIP(decompressedSize / frameWidth, 0, _height - frameY); + uint16 scaledHeight = CLIP(decompressedSize / frameWidth, 0, surface->h - frameY); + // FIXME: Same goes for the frame's width + position. In this case, we // modify the position to fit the contents on screen. - if (frameWidth + frameX > _width) - frameX = _width - frameWidth; - assert (frameWidth + frameX <= _width && scaledHeight + frameY <= _height); + if (frameWidth + frameX > surface->w) + frameX = surface->w - frameWidth; + + assert(frameWidth + frameX <= surface->w && scaledHeight + frameY <= surface->h); DecompressorLZS lzs; byte *decompressedFrame = new byte[decompressedSize]; @@ -305,24 +210,23 @@ const Graphics::Surface *RobotDecoder::decodeNextFrame() { // Copy over the decompressed frame byte *inFrame = decompressedFrame; - byte *outFrame = (byte *)_surface->pixels; + byte *outFrame = (byte *)surface->pixels; // Black out the surface - memset(outFrame, 0, _width * _height); + memset(outFrame, 0, surface->w * surface->h); // Move to the correct y coordinate - outFrame += _width * frameY; + outFrame += surface->w * frameY; for (uint16 y = 0; y < scaledHeight; y++) { memcpy(outFrame + frameX, inFrame, frameWidth); inFrame += frameWidth; - outFrame += _width; + outFrame += surface->w; } delete[] decompressedFrame; - // +1 because we start with frame number -1 - uint32 audioChunkSize = _frameTotalSize[_curFrame + 1] - (24 + compressedSize); + uint32 audioChunkSize = _frameTotalSize[videoTrack->getCurFrame()] - (24 + compressedSize); // TODO: The audio chunk size below is usually correct, but there are some // exceptions (e.g. robot 4902 in Phantasmagoria, towards its end) @@ -337,51 +241,166 @@ const Graphics::Surface *RobotDecoder::decodeNextFrame() { // Queue the next audio frame // FIXME: For some reason, there are audio hiccups/gaps if (_header.hasSound) { - _fileStream->skip(8); // header - _audioStream->queueBuffer(g_sci->_audio->getDecodedRobotAudioFrame(_fileStream, audioChunkSize - 8), - (audioChunkSize - 8) * 2, DisposeAfterUse::NO, - Audio::FLAG_16BITS | Audio::FLAG_LITTLE_ENDIAN); + RobotAudioTrack *audioTrack = (RobotAudioTrack *)getTrack(1); + _fileStream->skip(8); // header + audioChunkSize -= 8; + audioTrack->queueBuffer(g_sci->_audio->getDecodedRobotAudioFrame(_fileStream, audioChunkSize), audioChunkSize * 2); } else { _fileStream->skip(audioChunkSize); - } - - if (_curFrame == -1) - _startTime = g_system->getMillis(); + } +} - _curFrame++; +void RobotDecoder::readHeaderChunk() { + // Header (60 bytes) + _fileStream->skip(6); + _header.version = _fileStream->readUint16(); + _header.audioChunkSize = _fileStream->readUint16(); + _header.audioSilenceSize = _fileStream->readUint16(); + _fileStream->skip(2); + _header.frameCount = _fileStream->readUint16(); + _header.paletteDataSize = _fileStream->readUint16(); + _header.unkChunkDataSize = _fileStream->readUint16(); + _fileStream->skip(5); + _header.hasSound = _fileStream->readByte(); + _fileStream->skip(34); - return _surface; + // Some videos (e.g. robot 1305 in Phantasmagoria and + // robot 184 in Lighthouse) have an unknown chunk before + // the palette chunk (probably used for sound preloading). + // Skip it here. + if (_header.unkChunkDataSize) + _fileStream->skip(_header.unkChunkDataSize); } -void RobotDecoder::close() { - if (!_fileStream) - return; +void RobotDecoder::readFrameSizesChunk() { + // The robot video file contains 2 tables, with one entry for each frame: + // - A table containing the size of the image in each video frame + // - A table containing the total size of each video frame. + // In v5 robots, the tables contain 16-bit integers, whereas in v6 robots, + // they contain 32-bit integers. - delete _fileStream; - _fileStream = 0; + _frameTotalSize = new uint32[_header.frameCount]; + // TODO: The table reading code can probably be removed once the + // audio chunk size is figured out (check the TODO inside processNextFrame()) +#if 0 + // We don't need any of the two tables to play the video, so we ignore + // both of them. + uint16 wordSize = _header.version == 6 ? 4 : 2; + _fileStream->skip(_header.frameCount * wordSize * 2); +#else + switch (_header.version) { + case 4: + case 5: // sizes are 16-bit integers + // Skip table with frame image sizes, as we don't need it + _fileStream->skip(_header.frameCount * 2); + for (int i = 0; i < _header.frameCount; ++i) + _frameTotalSize[i] = _fileStream->readUint16(); + break; + case 6: // sizes are 32-bit integers + // Skip table with frame image sizes, as we don't need it + _fileStream->skip(_header.frameCount * 4); + for (int i = 0; i < _header.frameCount; ++i) + _frameTotalSize[i] = _fileStream->readUint32(); + break; + default: + error("Can't yet handle index table for robot version %d", _header.version); + } +#endif + + // 2 more unknown tables + _fileStream->skip(1024 + 512); + + // Pad to nearest 2 kilobytes + uint32 curPos = _fileStream->pos(); + if (curPos & 0x7ff) + _fileStream->seek((curPos & ~0x7ff) + 2048); +} + +RobotDecoder::RobotVideoTrack::RobotVideoTrack(int frameCount) : _frameCount(frameCount) { + _surface = new Graphics::Surface(); + _curFrame = -1; + _dirtyPalette = false; +} + +RobotDecoder::RobotVideoTrack::~RobotVideoTrack() { _surface->free(); delete _surface; - _surface = 0; +} - if (_header.hasSound) { - _mixer->stopHandle(_audioHandle); - //delete _audioStream; _audioStream = 0; +uint16 RobotDecoder::RobotVideoTrack::getWidth() const { + return _surface->w; +} + +uint16 RobotDecoder::RobotVideoTrack::getHeight() const { + return _surface->h; +} + +Graphics::PixelFormat RobotDecoder::RobotVideoTrack::getPixelFormat() const { + return _surface->format; +} + +void RobotDecoder::RobotVideoTrack::readPaletteChunk(Common::SeekableSubReadStreamEndian *stream, uint16 chunkSize) { + byte *paletteData = new byte[chunkSize]; + stream->read(paletteData, chunkSize); + + // SCI1.1 palette + byte palFormat = paletteData[32]; + uint16 palColorStart = paletteData[25]; + uint16 palColorCount = READ_SCI11ENDIAN_UINT16(paletteData + 29); + + int palOffset = 37; + memset(_palette, 0, 256 * 3); + + for (uint16 colorNo = palColorStart; colorNo < palColorStart + palColorCount; colorNo++) { + if (palFormat == kRobotPalVariable) + palOffset++; + _palette[colorNo * 3 + 0] = paletteData[palOffset++]; + _palette[colorNo * 3 + 1] = paletteData[palOffset++]; + _palette[colorNo * 3 + 2] = paletteData[palOffset++]; } - reset(); + _dirtyPalette = true; + delete[] paletteData; } -void RobotDecoder::updateVolume() { - if (g_system->getMixer()->isSoundHandleActive(_audioHandle)) - g_system->getMixer()->setChannelVolume(_audioHandle, getVolume()); +void RobotDecoder::RobotVideoTrack::calculateVideoDimensions(Common::SeekableSubReadStreamEndian *stream, uint32 *frameSizes) { + // This is an O(n) operation, as each frame has a different size. + // We need to know the actual frame size to have a constant video size. + uint32 pos = stream->pos(); + + uint16 width = 0, height = 0; + + for (int curFrame = 0; curFrame < _frameCount; curFrame++) { + stream->skip(4); + uint16 frameWidth = stream->readUint16(); + uint16 frameHeight = stream->readUint16(); + if (frameWidth > width) + width = frameWidth; + if (frameHeight > height) + height = frameHeight; + stream->skip(frameSizes[curFrame] - 8); + } + + stream->seek(pos); + + _surface->create(width, height, Graphics::PixelFormat::createFormatCLUT8()); } -void RobotDecoder::updateBalance() { - if (g_system->getMixer()->isSoundHandleActive(_audioHandle)) - g_system->getMixer()->setChannelBalance(_audioHandle, getBalance()); +RobotDecoder::RobotAudioTrack::RobotAudioTrack() { + _audioStream = Audio::makeQueuingAudioStream(11025, false); } -#endif +RobotDecoder::RobotAudioTrack::~RobotAudioTrack() { + delete _audioStream; +} + +void RobotDecoder::RobotAudioTrack::queueBuffer(byte *buffer, int size) { + _audioStream->queueBuffer(buffer, size, DisposeAfterUse::YES, Audio::FLAG_16BITS | Audio::FLAG_LITTLE_ENDIAN); +} + +Audio::AudioStream *RobotDecoder::RobotAudioTrack::getAudioStream() const { + return _audioStream; +} } // End of namespace Sci diff --git a/engines/sci/video/robot_decoder.h b/engines/sci/video/robot_decoder.h index e9cefe7d91..de5b669ab8 100644 --- a/engines/sci/video/robot_decoder.h +++ b/engines/sci/video/robot_decoder.h @@ -25,84 +25,103 @@ #include "common/rational.h" #include "common/rect.h" -#include "common/stream.h" -#include "common/substream.h" -#include "audio/audiostream.h" -#include "audio/mixer.h" -#include "graphics/pixelformat.h" #include "video/video_decoder.h" -namespace Sci { +namespace Audio { +class QueuingAudioStream; +} -#ifdef ENABLE_SCI32 - -struct RobotHeader { - // 6 bytes, identifier bytes - uint16 version; - uint16 audioChunkSize; - uint16 audioSilenceSize; - // 2 bytes, unknown - uint16 frameCount; - uint16 paletteDataSize; - uint16 unkChunkDataSize; - // 5 bytes, unknown - byte hasSound; - // 34 bytes, unknown -}; +namespace Common { +class SeekableSubReadStreamEndian; +} + +namespace Sci { -class RobotDecoder : public Video::FixedRateVideoDecoder { +class RobotDecoder : public Video::AdvancedVideoDecoder { public: - RobotDecoder(Audio::Mixer *mixer, bool isBigEndian); + RobotDecoder(bool isBigEndian); virtual ~RobotDecoder(); bool loadStream(Common::SeekableReadStream *stream); bool load(GuiResourceId id); void close(); - - bool isVideoLoaded() const { return _fileStream != 0; } - uint16 getWidth() const { return _width; } - uint16 getHeight() const { return _height; } - uint32 getFrameCount() const { return _header.frameCount; } - const Graphics::Surface *decodeNextFrame(); - Graphics::PixelFormat getPixelFormat() const { return Graphics::PixelFormat::createFormatCLUT8(); } - const byte *getPalette() { _dirtyPalette = false; return _palette; } - bool hasDirtyPalette() const { return _dirtyPalette; } + void setPos(uint16 x, uint16 y) { _pos = Common::Point(x, y); } Common::Point getPos() const { return _pos; } protected: - // VideoDecoder API - void updateVolume(); - void updateBalance(); - - // FixedRateVideoDecoder API - Common::Rational getFrameRate() const { return Common::Rational(60, 10); } - + void readNextPacket(); + private: + class RobotVideoTrack : public FixedRateVideoTrack { + public: + RobotVideoTrack(int frameCount); + ~RobotVideoTrack(); + + uint16 getWidth() const; + uint16 getHeight() const; + Graphics::PixelFormat getPixelFormat() const; + int getCurFrame() const { return _curFrame; } + int getFrameCount() const { return _frameCount; } + const Graphics::Surface *decodeNextFrame() { return _surface; } + const byte *getPalette() const { _dirtyPalette = false; return _palette; } + bool hasDirtyPalette() const { return _dirtyPalette; } + + void readPaletteChunk(Common::SeekableSubReadStreamEndian *stream, uint16 chunkSize); + void calculateVideoDimensions(Common::SeekableSubReadStreamEndian *stream, uint32 *frameSizes); + Graphics::Surface *getSurface() { return _surface; } + void increaseCurFrame() { _curFrame++; } + + protected: + Common::Rational getFrameRate() const { return Common::Rational(60, 10); } + + private: + int _frameCount; + int _curFrame; + byte _palette[256 * 3]; + mutable bool _dirtyPalette; + Graphics::Surface *_surface; + }; + + class RobotAudioTrack : public AudioTrack { + public: + RobotAudioTrack(); + ~RobotAudioTrack(); + + Audio::Mixer::SoundType getSoundType() const { return Audio::Mixer::kMusicSoundType; } + + void queueBuffer(byte *buffer, int size); + + protected: + Audio::AudioStream *getAudioStream() const; + + private: + Audio::QueuingAudioStream *_audioStream; + }; + + struct RobotHeader { + // 6 bytes, identifier bytes + uint16 version; + uint16 audioChunkSize; + uint16 audioSilenceSize; + // 2 bytes, unknown + uint16 frameCount; + uint16 paletteDataSize; + uint16 unkChunkDataSize; + // 5 bytes, unknown + byte hasSound; + // 34 bytes, unknown + } _header; + void readHeaderChunk(); - void readPaletteChunk(uint16 chunkSize); void readFrameSizesChunk(); - void calculateVideoDimensions(); - - void freeData(); - RobotHeader _header; Common::Point _pos; bool _isBigEndian; + uint32 *_frameTotalSize; Common::SeekableSubReadStreamEndian *_fileStream; - - uint16 _width; - uint16 _height; - uint32 *_frameTotalSize; - byte _palette[256 * 3]; - bool _dirtyPalette; - Graphics::Surface *_surface; - Audio::QueuingAudioStream *_audioStream; - Audio::SoundHandle _audioHandle; - Audio::Mixer *_mixer; }; -#endif } // End of namespace Sci -- cgit v1.2.3 From 61e8fdbf1d05bbe37910a787fa53958f4aa5e7f1 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Tue, 24 Jul 2012 00:16:42 +0300 Subject: SCI: Separate the early SCI11 version of kRemapColors from the SCI32 one --- engines/sci/engine/kernel.h | 1 + engines/sci/engine/kernel_tables.h | 5 ++- engines/sci/engine/kgraphics.cpp | 60 ++++--------------------------- engines/sci/engine/kgraphics32.cpp | 74 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 85 insertions(+), 55 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/engine/kernel.h b/engines/sci/engine/kernel.h index 441ea2624f..f985a69ebc 100644 --- a/engines/sci/engine/kernel.h +++ b/engines/sci/engine/kernel.h @@ -412,6 +412,7 @@ reg_t kListAt(EngineState *s, int argc, reg_t *argv); reg_t kString(EngineState *s, int argc, reg_t *argv); reg_t kMulDiv(EngineState *s, int argc, reg_t *argv); reg_t kCantBeHere32(EngineState *s, int argc, reg_t *argv); +reg_t kRemapColors32(EngineState *s, int argc, reg_t *argv); // "Screen items" in SCI32 are views reg_t kAddScreenItem(EngineState *s, int argc, reg_t *argv); reg_t kUpdateScreenItem(EngineState *s, int argc, reg_t *argv); diff --git a/engines/sci/engine/kernel_tables.h b/engines/sci/engine/kernel_tables.h index 825ec90fa9..f5f46285be 100644 --- a/engines/sci/engine/kernel_tables.h +++ b/engines/sci/engine/kernel_tables.h @@ -419,7 +419,10 @@ static SciKernelMapEntry s_kernelMap[] = { { MAP_CALL(PriCoord), SIG_EVERYWHERE, "i", NULL, NULL }, { MAP_CALL(Random), SIG_EVERYWHERE, "i(i)(i)", NULL, NULL }, { MAP_CALL(ReadNumber), SIG_EVERYWHERE, "r", NULL, NULL }, - { MAP_CALL(RemapColors), SIG_EVERYWHERE, "i(i)(i)(i)(i)(i)", NULL, NULL }, + { MAP_CALL(RemapColors), SIG_SCI11, SIGFOR_ALL, "i(i)(i)(i)(i)", NULL, NULL }, +#ifdef ENABLE_SCI32 + { "RemapColors", kRemapColors32, SIG_SCI32, SIGFOR_ALL, "i(i)(i)(i)(i)(i)", NULL, NULL }, +#endif { MAP_CALL(ResCheck), SIG_EVERYWHERE, "ii(iiii)", NULL, NULL }, { MAP_CALL(RespondsTo), SIG_EVERYWHERE, ".i", NULL, NULL }, { MAP_CALL(RestartGame), SIG_EVERYWHERE, "", NULL, NULL }, diff --git a/engines/sci/engine/kgraphics.cpp b/engines/sci/engine/kgraphics.cpp index 6d938b6d22..2ce44db772 100644 --- a/engines/sci/engine/kgraphics.cpp +++ b/engines/sci/engine/kgraphics.cpp @@ -1221,73 +1221,25 @@ reg_t kShow(EngineState *s, int argc, reg_t *argv) { return s->r_acc; } +// Early variant of the SCI32 remapcolors kernel function, used in the demo of QFG4 reg_t kRemapColors(EngineState *s, int argc, reg_t *argv) { uint16 operation = argv[0].toUint16(); switch (operation) { - case 0: { // Set remapping to base. 0 turns remapping off. - int16 base = (argc >= 2) ? argv[1].toSint16() : 0; - if (base != 0) // 0 is the default behavior when changing rooms in GK1, thus silencing the warning - warning("kRemapColors: Set remapping to base %d", base); + case 0: { // remap by percent + uint16 percent = argv[1].toUint16(); + warning("RemapColors(RemapByPercent) %d", percent); } break; case 1: { // unknown - // The demo of QFG4 calls this with 1+3 parameters, thus there are differences here //int16 unk1 = argv[1].toSint16(); //int16 unk2 = argv[2].toSint16(); //int16 unk3 = argv[3].toSint16(); - //uint16 unk4 = argv[4].toUint16(); - //uint16 unk5 = (argc >= 6) ? argv[5].toUint16() : 0; kStub(s, argc, argv); } break; - case 2: { // remap by percent - // This adjusts the alpha value of a specific color, and it operates on - // an RGBA palette. Since we're operating on an RGB palette, we just - // modify the color intensity instead - // TODO: From what I understand, palette remapping should be placed - // separately, so that it can be reset by case 0 above. Thus, we - // should adjust the functionality of the Palette class accordingly. - int16 color = argv[1].toSint16(); - if (color >= 10) - color -= 10; - uint16 percent = argv[2].toUint16(); // 0 - 100 - if (argc >= 4) - warning("RemapByPercent called with 4 parameters, unknown parameter is %d", argv[3].toUint16()); - warning("kRemapColors: RemapByPercent color %d by %d percent", color, percent); - // TODO: It's not correct to set intensity here - //g_sci->_gfxPalette->kernelSetIntensity(color, 255, percent, false); - } - break; - case 3: { // remap to gray - // NOTE: This adjusts the alpha value of a specific color, and it operates on - // an RGBA palette - int16 color = argv[1].toSint16(); // this is subtracted from a maximum color value, and can be offset by 10 - int16 percent = argv[2].toSint16(); // 0 - 100 - uint16 unk3 = (argc >= 4) ? argv[3].toUint16() : 0; - warning("kRemapColors: RemapToGray color %d by %d percent (unk3 = %d)", color, percent, unk3); - } - break; - case 4: { // unknown - //int16 unk1 = argv[1].toSint16(); - //uint16 unk2 = argv[2].toUint16(); - //uint16 unk3 = argv[3].toUint16(); - //uint16 unk4 = (argc >= 5) ? argv[4].toUint16() : 0; - kStub(s, argc, argv); - } - break; - case 5: { // set color intensity - // TODO: This isn't right, it should be setting a mapping table instead. - // For PQ4, we can emulate this with kernelSetIntensity(). In QFG4, this - // won't do. - //int16 mapping = argv[1].toSint16(); - uint16 intensity = argv[2].toUint16(); - // HACK for PQ4 - if (g_sci->getGameId() == GID_PQ4) - g_sci->_gfxPalette->kernelSetIntensity(0, 255, intensity, true); - - kStub(s, argc, argv); - } + case 2: // turn remapping off (unused) + error("Unused subop kRemapColors(2) has been called"); break; default: break; diff --git a/engines/sci/engine/kgraphics32.cpp b/engines/sci/engine/kgraphics32.cpp index 7cfac57675..245c265ba6 100644 --- a/engines/sci/engine/kgraphics32.cpp +++ b/engines/sci/engine/kgraphics32.cpp @@ -733,6 +733,80 @@ reg_t kPalCycle(EngineState *s, int argc, reg_t *argv) { return s->r_acc; } +reg_t kRemapColors32(EngineState *s, int argc, reg_t *argv) { + uint16 operation = argv[0].toUint16(); + + switch (operation) { + case 0: { // Set remapping to base. 0 turns remapping off. + int16 base = (argc >= 2) ? argv[1].toSint16() : 0; + if (base != 0) // 0 is the default behavior when changing rooms in GK1, thus silencing the warning + warning("kRemapColors: Set remapping to base %d", base); + } + break; + case 1: { // unknown + //int16 unk1 = argv[1].toSint16(); + //int16 unk2 = argv[2].toSint16(); + //int16 unk3 = argv[3].toSint16(); + //uint16 unk4 = argv[4].toUint16(); + //uint16 unk5 = (argc >= 6) ? argv[5].toUint16() : 0; + kStub(s, argc, argv); + } + break; + case 2: { // remap by percent + // This adjusts the alpha value of a specific color, and it operates on + // an RGBA palette. Since we're operating on an RGB palette, we just + // modify the color intensity instead + // TODO: From what I understand, palette remapping should be placed + // separately, so that it can be reset by case 0 above. Thus, we + // should adjust the functionality of the Palette class accordingly. + int16 color = argv[1].toSint16(); + if (color >= 10) + color -= 10; + uint16 percent = argv[2].toUint16(); // 0 - 100 + if (argc >= 4) + warning("RemapByPercent called with 4 parameters, unknown parameter is %d", argv[3].toUint16()); + warning("kRemapColors: RemapByPercent color %d by %d percent", color, percent); + // TODO: It's not correct to set intensity here + //g_sci->_gfxPalette->kernelSetIntensity(color, 255, percent, false); + } + break; + case 3: { // remap to gray + // NOTE: This adjusts the alpha value of a specific color, and it operates on + // an RGBA palette + int16 color = argv[1].toSint16(); // this is subtracted from a maximum color value, and can be offset by 10 + int16 percent = argv[2].toSint16(); // 0 - 100 + uint16 unk3 = (argc >= 4) ? argv[3].toUint16() : 0; + warning("kRemapColors: RemapToGray color %d by %d percent (unk3 = %d)", color, percent, unk3); + } + break; + case 4: { // unknown + //int16 unk1 = argv[1].toSint16(); + //uint16 unk2 = argv[2].toUint16(); + //uint16 unk3 = argv[3].toUint16(); + //uint16 unk4 = (argc >= 5) ? argv[4].toUint16() : 0; + kStub(s, argc, argv); + } + break; + case 5: { // set color intensity + // TODO: This isn't right, it should be setting a mapping table instead. + // For PQ4, we can emulate this with kernelSetIntensity(). In QFG4, this + // won't do. + //int16 mapping = argv[1].toSint16(); + uint16 intensity = argv[2].toUint16(); + // HACK for PQ4 + if (g_sci->getGameId() == GID_PQ4) + g_sci->_gfxPalette->kernelSetIntensity(0, 255, intensity, true); + + kStub(s, argc, argv); + } + break; + default: + break; + } + + return s->r_acc; +} + #endif } // End of namespace Sci -- cgit v1.2.3 From bd281928cb6e87cfb7175189cafd2b25991f3e01 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Tue, 24 Jul 2012 03:53:44 +0300 Subject: SCI: Initial implementation of kRemapColors(kRemapByPercent) Fixes some graphics glitches in the QFG4 demo and the menus of QFG4, by implementing one of the transparency effects used mainly in SCI32. Many thanks to fuzzie for her debugging info on QFG4 demo and to wjp for his great help on the dissassembly --- engines/sci/engine/kgraphics.cpp | 7 ++++--- engines/sci/engine/kgraphics32.cpp | 21 +++++++++------------ engines/sci/graphics/palette.cpp | 23 +++++++++++++++++++++++ engines/sci/graphics/palette.h | 9 +++++++++ engines/sci/graphics/view.cpp | 10 ++++++++-- 5 files changed, 53 insertions(+), 17 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/engine/kgraphics.cpp b/engines/sci/engine/kgraphics.cpp index 2ce44db772..bd78c56416 100644 --- a/engines/sci/engine/kgraphics.cpp +++ b/engines/sci/engine/kgraphics.cpp @@ -1221,17 +1221,18 @@ reg_t kShow(EngineState *s, int argc, reg_t *argv) { return s->r_acc; } -// Early variant of the SCI32 remapcolors kernel function, used in the demo of QFG4 +// Early variant of the SCI32 kRemapColors kernel function, used in the demo of QFG4 reg_t kRemapColors(EngineState *s, int argc, reg_t *argv) { uint16 operation = argv[0].toUint16(); switch (operation) { case 0: { // remap by percent uint16 percent = argv[1].toUint16(); - warning("RemapColors(RemapByPercent) %d", percent); + g_sci->_gfxPalette->toggleRemap(true); + g_sci->_gfxPalette->setRemappingPercent(percent); } break; - case 1: { // unknown + case 1: { // set remapping base //int16 unk1 = argv[1].toSint16(); //int16 unk2 = argv[2].toSint16(); //int16 unk3 = argv[3].toSint16(); diff --git a/engines/sci/engine/kgraphics32.cpp b/engines/sci/engine/kgraphics32.cpp index 245c265ba6..1b7b628e7d 100644 --- a/engines/sci/engine/kgraphics32.cpp +++ b/engines/sci/engine/kgraphics32.cpp @@ -742,8 +742,11 @@ reg_t kRemapColors32(EngineState *s, int argc, reg_t *argv) { if (base != 0) // 0 is the default behavior when changing rooms in GK1, thus silencing the warning warning("kRemapColors: Set remapping to base %d", base); } + // TODO: Don't turn remapping off always + g_sci->_gfxPalette->toggleRemap(false); + g_sci->_gfxPalette->setRemappingPercent(0); break; - case 1: { // unknown + case 1: { // set remapping base //int16 unk1 = argv[1].toSint16(); //int16 unk2 = argv[2].toSint16(); //int16 unk3 = argv[3].toSint16(); @@ -753,21 +756,15 @@ reg_t kRemapColors32(EngineState *s, int argc, reg_t *argv) { } break; case 2: { // remap by percent - // This adjusts the alpha value of a specific color, and it operates on - // an RGBA palette. Since we're operating on an RGB palette, we just - // modify the color intensity instead - // TODO: From what I understand, palette remapping should be placed - // separately, so that it can be reset by case 0 above. Thus, we - // should adjust the functionality of the Palette class accordingly. - int16 color = argv[1].toSint16(); + // TODO: Use the color index. The -10 offset is wrong. + /*int16 color = argv[1].toSint16(); if (color >= 10) - color -= 10; + color -= 10;*/ uint16 percent = argv[2].toUint16(); // 0 - 100 if (argc >= 4) warning("RemapByPercent called with 4 parameters, unknown parameter is %d", argv[3].toUint16()); - warning("kRemapColors: RemapByPercent color %d by %d percent", color, percent); - // TODO: It's not correct to set intensity here - //g_sci->_gfxPalette->kernelSetIntensity(color, 255, percent, false); + g_sci->_gfxPalette->toggleRemap(true); + g_sci->_gfxPalette->setRemappingPercent(percent); } break; case 3: { // remap to gray diff --git a/engines/sci/graphics/palette.cpp b/engines/sci/graphics/palette.cpp index ea154c5037..f16d607a29 100644 --- a/engines/sci/graphics/palette.cpp +++ b/engines/sci/graphics/palette.cpp @@ -100,6 +100,9 @@ GfxPalette::GfxPalette(ResourceManager *resMan, GfxScreen *screen) default: error("GfxPalette: Unknown view type"); } + + _remapOn = false; + _remappingPercent = 0; } GfxPalette::~GfxPalette() { @@ -329,6 +332,26 @@ void GfxPalette::set(Palette *newPalette, bool force, bool forceRealMerge) { } } +bool GfxPalette::isRemapColor(byte color) { + // TODO: Expand this for SCI32 (more than one remap color can be set). + // Now, it is assumed that colors 253 and 254 are the remap colors. + return _remapOn && (color == 253 || color == 254); +} + +byte GfxPalette::remapColor(byte color) { + assert(_remapOn); + + // TODO: Change this to use a table instead, like the original. + if (_remappingPercent) { + byte r = _sysPalette.colors[color].r * _remappingPercent / 100; + byte g = _sysPalette.colors[color].g * _remappingPercent / 100; + byte b = _sysPalette.colors[color].b * _remappingPercent / 100; + return kernelFindColor(r, g, b); + } else { + return color; + } +} + bool GfxPalette::insert(Palette *newPalette, Palette *destPalette) { bool paletteChanged = false; diff --git a/engines/sci/graphics/palette.h b/engines/sci/graphics/palette.h index a9ea1c32de..5b9ae9e016 100644 --- a/engines/sci/graphics/palette.h +++ b/engines/sci/graphics/palette.h @@ -53,6 +53,11 @@ public: void getSys(Palette *pal); uint16 getTotalColorCount() const { return _totalScreenColors; } + void toggleRemap(bool remap) { _remapOn = remap; } + void setRemappingPercent(uint16 percent) { _remappingPercent = percent; } + bool isRemapColor(byte color); + byte remapColor(byte color); + void setOnScreen(); void copySysPaletteToScreen(); @@ -123,6 +128,10 @@ private: int _palVarySignal; uint16 _totalScreenColors; + bool _remapOn; + uint16 _remappingBaseR, _remappingBaseG, _remappingBaseB; + uint16 _remappingPercent; + void loadMacIconBarPalette(); byte *_macClut; diff --git a/engines/sci/graphics/view.cpp b/engines/sci/graphics/view.cpp index 4e5c4da8b2..ae135d141c 100644 --- a/engines/sci/graphics/view.cpp +++ b/engines/sci/graphics/view.cpp @@ -741,8 +741,14 @@ void GfxView::draw(const Common::Rect &rect, const Common::Rect &clipRect, const const int x2 = clipRectTranslated.left + x; const int y2 = clipRectTranslated.top + y; if (!upscaledHires) { - if (priority >= _screen->getPriority(x2, y2)) - _screen->putPixel(x2, y2, drawMask, palette->mapping[color], priority, 0); + if (priority >= _screen->getPriority(x2, y2)) { + if (!_palette->isRemapColor(palette->mapping[color])) { + _screen->putPixel(x2, y2, drawMask, palette->mapping[color], priority, 0); + } else { + byte remappedColor = _palette->remapColor(_screen->getVisual(x2, y2)); + _screen->putPixel(x2, y2, drawMask, remappedColor, priority, 0); + } + } } else { // UpscaledHires means view is hires and is supposed to // get drawn onto lowres screen. -- cgit v1.2.3 From 3d395545cb1514ba4a07a785e58782462a3b1a94 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Tue, 24 Jul 2012 04:07:08 +0300 Subject: SCI: Remove unused variables --- engines/sci/graphics/palette.h | 1 - 1 file changed, 1 deletion(-) (limited to 'engines/sci') diff --git a/engines/sci/graphics/palette.h b/engines/sci/graphics/palette.h index 5b9ae9e016..6774094810 100644 --- a/engines/sci/graphics/palette.h +++ b/engines/sci/graphics/palette.h @@ -129,7 +129,6 @@ private: uint16 _totalScreenColors; bool _remapOn; - uint16 _remappingBaseR, _remappingBaseG, _remappingBaseB; uint16 _remappingPercent; void loadMacIconBarPalette(); -- cgit v1.2.3 From 6f351302040be620aa039a7c605f3c23463b27db Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Tue, 24 Jul 2012 22:34:03 +0300 Subject: SCI: More work on color remapping More transparency/color mapping effects are now working (e.g. the flashlight at the Gedde tomb in GK1, the rays of light at Schloss Ritter in GK1, the torch in the QFG4 demo and the shadows in QFG4, PQ4 and KQ7) --- engines/sci/engine/kgraphics.cpp | 17 +++++----- engines/sci/engine/kgraphics32.cpp | 47 +++++++++++++--------------- engines/sci/graphics/palette.cpp | 64 ++++++++++++++++++++++++++++++-------- engines/sci/graphics/palette.h | 12 ++++--- engines/sci/graphics/view.cpp | 9 ++++-- 5 files changed, 97 insertions(+), 52 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/engine/kgraphics.cpp b/engines/sci/engine/kgraphics.cpp index bd78c56416..55c0202048 100644 --- a/engines/sci/engine/kgraphics.cpp +++ b/engines/sci/engine/kgraphics.cpp @@ -1228,15 +1228,18 @@ reg_t kRemapColors(EngineState *s, int argc, reg_t *argv) { switch (operation) { case 0: { // remap by percent uint16 percent = argv[1].toUint16(); - g_sci->_gfxPalette->toggleRemap(true); - g_sci->_gfxPalette->setRemappingPercent(percent); + g_sci->_gfxPalette->toggleRemapping(true); + g_sci->_gfxPalette->resetRemapping(); + g_sci->_gfxPalette->setRemappingPercent(254, percent); } break; - case 1: { // set remapping base - //int16 unk1 = argv[1].toSint16(); - //int16 unk2 = argv[2].toSint16(); - //int16 unk3 = argv[3].toSint16(); - kStub(s, argc, argv); + case 1: { // remap by range + uint16 from = argv[1].toUint16(); + uint16 to = argv[2].toUint16(); + uint16 base = argv[3].toUint16(); + g_sci->_gfxPalette->toggleRemapping(true); + g_sci->_gfxPalette->resetRemapping(); + g_sci->_gfxPalette->setRemappingRange(254, from, to, base); } break; case 2: // turn remapping off (unused) diff --git a/engines/sci/engine/kgraphics32.cpp b/engines/sci/engine/kgraphics32.cpp index 1b7b628e7d..7240308f4a 100644 --- a/engines/sci/engine/kgraphics32.cpp +++ b/engines/sci/engine/kgraphics32.cpp @@ -737,46 +737,44 @@ reg_t kRemapColors32(EngineState *s, int argc, reg_t *argv) { uint16 operation = argv[0].toUint16(); switch (operation) { - case 0: { // Set remapping to base. 0 turns remapping off. + case 0: { // turn remapping off int16 base = (argc >= 2) ? argv[1].toSint16() : 0; - if (base != 0) // 0 is the default behavior when changing rooms in GK1, thus silencing the warning - warning("kRemapColors: Set remapping to base %d", base); + if (base > 0) + warning("kRemapColors(0) called with base %d", base); + g_sci->_gfxPalette->toggleRemapping(false); + g_sci->_gfxPalette->resetRemapping(); } - // TODO: Don't turn remapping off always - g_sci->_gfxPalette->toggleRemap(false); - g_sci->_gfxPalette->setRemappingPercent(0); break; - case 1: { // set remapping base - //int16 unk1 = argv[1].toSint16(); - //int16 unk2 = argv[2].toSint16(); - //int16 unk3 = argv[3].toSint16(); - //uint16 unk4 = argv[4].toUint16(); - //uint16 unk5 = (argc >= 6) ? argv[5].toUint16() : 0; - kStub(s, argc, argv); + case 1: { // remap by range + uint16 color = argv[1].toUint16(); + uint16 from = argv[2].toUint16(); + uint16 to = argv[3].toUint16(); + uint16 base = argv[4].toUint16(); + uint16 unk5 = (argc >= 6) ? argv[5].toUint16() : 0; + if (unk5 > 0) + warning("kRemapColors(1) called with 6 parameters, unknown parameter is %d", unk5); + g_sci->_gfxPalette->toggleRemapping(true); + g_sci->_gfxPalette->setRemappingRange(color, from, to, base); } break; case 2: { // remap by percent - // TODO: Use the color index. The -10 offset is wrong. - /*int16 color = argv[1].toSint16(); - if (color >= 10) - color -= 10;*/ + uint16 color = argv[1].toUint16(); uint16 percent = argv[2].toUint16(); // 0 - 100 if (argc >= 4) warning("RemapByPercent called with 4 parameters, unknown parameter is %d", argv[3].toUint16()); - g_sci->_gfxPalette->toggleRemap(true); - g_sci->_gfxPalette->setRemappingPercent(percent); + g_sci->_gfxPalette->toggleRemapping(true); + g_sci->_gfxPalette->setRemappingPercent(color, percent); } break; case 3: { // remap to gray - // NOTE: This adjusts the alpha value of a specific color, and it operates on - // an RGBA palette int16 color = argv[1].toSint16(); // this is subtracted from a maximum color value, and can be offset by 10 int16 percent = argv[2].toSint16(); // 0 - 100 uint16 unk3 = (argc >= 4) ? argv[3].toUint16() : 0; warning("kRemapColors: RemapToGray color %d by %d percent (unk3 = %d)", color, percent, unk3); + // TODO } break; - case 4: { // unknown + case 4: { // remap to percent gray //int16 unk1 = argv[1].toSint16(); //uint16 unk2 = argv[2].toUint16(); //uint16 unk3 = argv[3].toUint16(); @@ -784,10 +782,7 @@ reg_t kRemapColors32(EngineState *s, int argc, reg_t *argv) { kStub(s, argc, argv); } break; - case 5: { // set color intensity - // TODO: This isn't right, it should be setting a mapping table instead. - // For PQ4, we can emulate this with kernelSetIntensity(). In QFG4, this - // won't do. + case 5: { // don't map to range //int16 mapping = argv[1].toSint16(); uint16 intensity = argv[2].toUint16(); // HACK for PQ4 diff --git a/engines/sci/graphics/palette.cpp b/engines/sci/graphics/palette.cpp index f16d607a29..b5154ef860 100644 --- a/engines/sci/graphics/palette.cpp +++ b/engines/sci/graphics/palette.cpp @@ -102,7 +102,7 @@ GfxPalette::GfxPalette(ResourceManager *resMan, GfxScreen *screen) } _remapOn = false; - _remappingPercent = 0; + resetRemapping(); } GfxPalette::~GfxPalette() { @@ -332,24 +332,62 @@ void GfxPalette::set(Palette *newPalette, bool force, bool forceRealMerge) { } } -bool GfxPalette::isRemapColor(byte color) { - // TODO: Expand this for SCI32 (more than one remap color can be set). - // Now, it is assumed that colors 253 and 254 are the remap colors. - return _remapOn && (color == 253 || color == 254); +bool GfxPalette::isRemapMask(byte color) { + return (_remapOn && (color >= _remappingMaskFrom && color <= _remappingMaskTo)); +} + +void GfxPalette::resetRemapping() { + _remappingMaskFrom = 0; + _remappingMaskTo = 0; + _remappingPercentToSet = 0; + + for (int i = 0; i < 256; i++) { + _remappingTable[i] = i; + } +} + +void GfxPalette::setRemappingPercent(byte color, byte percent) { + // We need to defer the setup of the remapping table until something is + // shown on screen, otherwise kernelFindColor() won't find correct + // colors. The actual setup of the remapping table will be performed in + // remapColor(). + _remappingPercentToSet = percent; + + if (_remappingMaskFrom > color || _remappingMaskFrom == 0) + _remappingMaskFrom = color; + if (_remappingMaskTo < color) + _remappingMaskTo = color; +} + +void GfxPalette::setRemappingRange(byte color, byte from, byte to, byte base) { + for (int i = from; i <= to; i++) { + _remappingTable[i] = i + base; + } + + if (_remappingMaskFrom > color || _remappingMaskFrom == 0) + _remappingMaskFrom = color; + if (_remappingMaskTo < color) + _remappingMaskTo = color; } byte GfxPalette::remapColor(byte color) { assert(_remapOn); - // TODO: Change this to use a table instead, like the original. - if (_remappingPercent) { - byte r = _sysPalette.colors[color].r * _remappingPercent / 100; - byte g = _sysPalette.colors[color].g * _remappingPercent / 100; - byte b = _sysPalette.colors[color].b * _remappingPercent / 100; - return kernelFindColor(r, g, b); - } else { - return color; + // Check if we need to set remapping by percent. This can only be + // performed when something is shown on screen, so that the screen + // palette is set up and kernelFindColor() can work correctly. + if (_remappingPercentToSet) { + for (int i = 0; i < 256; i++) { + byte r = _sysPalette.colors[i].r * _remappingPercentToSet / 100; + byte g = _sysPalette.colors[i].g * _remappingPercentToSet / 100; + byte b = _sysPalette.colors[i].b * _remappingPercentToSet / 100; + _remappingTable[i] = kernelFindColor(r, g, b); + } + + _remappingPercentToSet = 0; } + + return _remappingTable[color]; } bool GfxPalette::insert(Palette *newPalette, Palette *destPalette) { diff --git a/engines/sci/graphics/palette.h b/engines/sci/graphics/palette.h index 6774094810..372f3c7090 100644 --- a/engines/sci/graphics/palette.h +++ b/engines/sci/graphics/palette.h @@ -53,9 +53,11 @@ public: void getSys(Palette *pal); uint16 getTotalColorCount() const { return _totalScreenColors; } - void toggleRemap(bool remap) { _remapOn = remap; } - void setRemappingPercent(uint16 percent) { _remappingPercent = percent; } - bool isRemapColor(byte color); + void toggleRemapping(bool remap) { _remapOn = remap; } + void resetRemapping(); + void setRemappingPercent(byte color, byte percent); + void setRemappingRange(byte color, byte from, byte to, byte base); + bool isRemapMask(byte color); byte remapColor(byte color); void setOnScreen(); @@ -129,7 +131,9 @@ private: uint16 _totalScreenColors; bool _remapOn; - uint16 _remappingPercent; + byte _remappingTable[256]; + uint16 _remappingMaskFrom, _remappingMaskTo; + uint16 _remappingPercentToSet; void loadMacIconBarPalette(); byte *_macClut; diff --git a/engines/sci/graphics/view.cpp b/engines/sci/graphics/view.cpp index ae135d141c..f68ed1443a 100644 --- a/engines/sci/graphics/view.cpp +++ b/engines/sci/graphics/view.cpp @@ -742,7 +742,7 @@ void GfxView::draw(const Common::Rect &rect, const Common::Rect &clipRect, const const int y2 = clipRectTranslated.top + y; if (!upscaledHires) { if (priority >= _screen->getPriority(x2, y2)) { - if (!_palette->isRemapColor(palette->mapping[color])) { + if (!_palette->isRemapMask(palette->mapping[color])) { _screen->putPixel(x2, y2, drawMask, palette->mapping[color], priority, 0); } else { byte remappedColor = _palette->remapColor(_screen->getVisual(x2, y2)); @@ -857,7 +857,12 @@ void GfxView::drawScaled(const Common::Rect &rect, const Common::Rect &clipRect, const int x2 = clipRectTranslated.left + x; const int y2 = clipRectTranslated.top + y; if (color != clearKey && priority >= _screen->getPriority(x2, y2)) { - _screen->putPixel(x2, y2, drawMask, palette->mapping[color], priority, 0); + if (!_palette->isRemapMask(palette->mapping[color])) { + _screen->putPixel(x2, y2, drawMask, palette->mapping[color], priority, 0); + } else { + byte remappedColor = _palette->remapColor(_screen->getVisual(x2, y2)); + _screen->putPixel(x2, y2, drawMask, remappedColor, priority, 0); + } } } } -- cgit v1.2.3 From fe3fb1873c60e7ed21c573e09030bd6d0a5018cb Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Tue, 24 Jul 2012 22:54:37 +0300 Subject: SCI: Cleanup of the palette remapping code --- engines/sci/engine/kgraphics.cpp | 2 -- engines/sci/engine/kgraphics32.cpp | 3 --- engines/sci/graphics/palette.cpp | 5 +++++ engines/sci/graphics/palette.h | 1 - 4 files changed, 5 insertions(+), 6 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/engine/kgraphics.cpp b/engines/sci/engine/kgraphics.cpp index 55c0202048..da377319c0 100644 --- a/engines/sci/engine/kgraphics.cpp +++ b/engines/sci/engine/kgraphics.cpp @@ -1228,7 +1228,6 @@ reg_t kRemapColors(EngineState *s, int argc, reg_t *argv) { switch (operation) { case 0: { // remap by percent uint16 percent = argv[1].toUint16(); - g_sci->_gfxPalette->toggleRemapping(true); g_sci->_gfxPalette->resetRemapping(); g_sci->_gfxPalette->setRemappingPercent(254, percent); } @@ -1237,7 +1236,6 @@ reg_t kRemapColors(EngineState *s, int argc, reg_t *argv) { uint16 from = argv[1].toUint16(); uint16 to = argv[2].toUint16(); uint16 base = argv[3].toUint16(); - g_sci->_gfxPalette->toggleRemapping(true); g_sci->_gfxPalette->resetRemapping(); g_sci->_gfxPalette->setRemappingRange(254, from, to, base); } diff --git a/engines/sci/engine/kgraphics32.cpp b/engines/sci/engine/kgraphics32.cpp index 7240308f4a..3d2c2af81b 100644 --- a/engines/sci/engine/kgraphics32.cpp +++ b/engines/sci/engine/kgraphics32.cpp @@ -741,7 +741,6 @@ reg_t kRemapColors32(EngineState *s, int argc, reg_t *argv) { int16 base = (argc >= 2) ? argv[1].toSint16() : 0; if (base > 0) warning("kRemapColors(0) called with base %d", base); - g_sci->_gfxPalette->toggleRemapping(false); g_sci->_gfxPalette->resetRemapping(); } break; @@ -753,7 +752,6 @@ reg_t kRemapColors32(EngineState *s, int argc, reg_t *argv) { uint16 unk5 = (argc >= 6) ? argv[5].toUint16() : 0; if (unk5 > 0) warning("kRemapColors(1) called with 6 parameters, unknown parameter is %d", unk5); - g_sci->_gfxPalette->toggleRemapping(true); g_sci->_gfxPalette->setRemappingRange(color, from, to, base); } break; @@ -762,7 +760,6 @@ reg_t kRemapColors32(EngineState *s, int argc, reg_t *argv) { uint16 percent = argv[2].toUint16(); // 0 - 100 if (argc >= 4) warning("RemapByPercent called with 4 parameters, unknown parameter is %d", argv[3].toUint16()); - g_sci->_gfxPalette->toggleRemapping(true); g_sci->_gfxPalette->setRemappingPercent(color, percent); } break; diff --git a/engines/sci/graphics/palette.cpp b/engines/sci/graphics/palette.cpp index b5154ef860..5a551bab2c 100644 --- a/engines/sci/graphics/palette.cpp +++ b/engines/sci/graphics/palette.cpp @@ -337,6 +337,7 @@ bool GfxPalette::isRemapMask(byte color) { } void GfxPalette::resetRemapping() { + _remapOn = false; _remappingMaskFrom = 0; _remappingMaskTo = 0; _remappingPercentToSet = 0; @@ -347,6 +348,8 @@ void GfxPalette::resetRemapping() { } void GfxPalette::setRemappingPercent(byte color, byte percent) { + _remapOn = true; + // We need to defer the setup of the remapping table until something is // shown on screen, otherwise kernelFindColor() won't find correct // colors. The actual setup of the remapping table will be performed in @@ -360,6 +363,8 @@ void GfxPalette::setRemappingPercent(byte color, byte percent) { } void GfxPalette::setRemappingRange(byte color, byte from, byte to, byte base) { + _remapOn = true; + for (int i = from; i <= to; i++) { _remappingTable[i] = i + base; } diff --git a/engines/sci/graphics/palette.h b/engines/sci/graphics/palette.h index 372f3c7090..134ade5e36 100644 --- a/engines/sci/graphics/palette.h +++ b/engines/sci/graphics/palette.h @@ -53,7 +53,6 @@ public: void getSys(Palette *pal); uint16 getTotalColorCount() const { return _totalScreenColors; } - void toggleRemapping(bool remap) { _remapOn = remap; } void resetRemapping(); void setRemappingPercent(byte color, byte percent); void setRemappingRange(byte color, byte from, byte to, byte base); -- cgit v1.2.3 From 37b209dac14bea6b8f08c3ee3f66e3d5772652bb Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Tue, 24 Jul 2012 22:55:34 +0300 Subject: SCI: Refresh remapping by percent whenever the screen palette changes --- engines/sci/graphics/palette.cpp | 31 +++++++++++++------------------ 1 file changed, 13 insertions(+), 18 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/graphics/palette.cpp b/engines/sci/graphics/palette.cpp index 5a551bab2c..cb5c0fe614 100644 --- a/engines/sci/graphics/palette.cpp +++ b/engines/sci/graphics/palette.cpp @@ -350,10 +350,10 @@ void GfxPalette::resetRemapping() { void GfxPalette::setRemappingPercent(byte color, byte percent) { _remapOn = true; - // We need to defer the setup of the remapping table until something is - // shown on screen, otherwise kernelFindColor() won't find correct + // We need to defer the setup of the remapping table every time the screen + // palette is changed, so that kernelFindColor() can find the correct // colors. The actual setup of the remapping table will be performed in - // remapColor(). + // copySysPaletteToScreen(). _remappingPercentToSet = percent; if (_remappingMaskFrom > color || _remappingMaskFrom == 0) @@ -377,21 +377,6 @@ void GfxPalette::setRemappingRange(byte color, byte from, byte to, byte base) { byte GfxPalette::remapColor(byte color) { assert(_remapOn); - - // Check if we need to set remapping by percent. This can only be - // performed when something is shown on screen, so that the screen - // palette is set up and kernelFindColor() can work correctly. - if (_remappingPercentToSet) { - for (int i = 0; i < 256; i++) { - byte r = _sysPalette.colors[i].r * _remappingPercentToSet / 100; - byte g = _sysPalette.colors[i].g * _remappingPercentToSet / 100; - byte b = _sysPalette.colors[i].b * _remappingPercentToSet / 100; - _remappingTable[i] = kernelFindColor(r, g, b); - } - - _remappingPercentToSet = 0; - } - return _remappingTable[color]; } @@ -557,6 +542,16 @@ void GfxPalette::copySysPaletteToScreen() { } } + // Check if we need to reset remapping by percent with the new colors. + if (_remappingPercentToSet) { + for (int i = 0; i < 256; i++) { + byte r = _sysPalette.colors[i].r * _remappingPercentToSet / 100; + byte g = _sysPalette.colors[i].g * _remappingPercentToSet / 100; + byte b = _sysPalette.colors[i].b * _remappingPercentToSet / 100; + _remappingTable[i] = kernelFindColor(r, g, b); + } + } + g_system->getPaletteManager()->setPalette(bpal, 0, 256); } -- cgit v1.2.3 From 537b1969bf896ee4e72e9d042e4b7f41c921d38c Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Wed, 25 Jul 2012 00:58:16 +0300 Subject: SCI: Rewrite the color remapping code to support simultaneous effects Fixes the torch in the full version of QFG4 --- engines/sci/graphics/palette.cpp | 43 ++++++++++++++++++++-------------------- engines/sci/graphics/palette.h | 17 ++++++++++++---- engines/sci/graphics/view.cpp | 8 ++++---- 3 files changed, 38 insertions(+), 30 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/graphics/palette.cpp b/engines/sci/graphics/palette.cpp index cb5c0fe614..9b8618c0ef 100644 --- a/engines/sci/graphics/palette.cpp +++ b/engines/sci/graphics/palette.cpp @@ -143,8 +143,9 @@ void GfxPalette::createFromData(byte *data, int bytesLeft, Palette *paletteOut) memset(paletteOut, 0, sizeof(Palette)); // Setup 1:1 mapping - for (colorNo = 0; colorNo < 256; colorNo++) + for (colorNo = 0; colorNo < 256; colorNo++) { paletteOut->mapping[colorNo] = colorNo; + } if (bytesLeft < 37) { // This happens when loading palette of picture 0 in sq5 - the resource is broken and doesn't contain a full @@ -332,18 +333,26 @@ void GfxPalette::set(Palette *newPalette, bool force, bool forceRealMerge) { } } -bool GfxPalette::isRemapMask(byte color) { - return (_remapOn && (color >= _remappingMaskFrom && color <= _remappingMaskTo)); +byte GfxPalette::remapColor(byte remappedColor, byte screenColor) { + assert(_remapOn); + if (_remappingType[remappedColor] == kRemappingByRange) + return _remappingByRange[screenColor]; + else if (_remappingType[remappedColor] == kRemappingByPercent) + return _remappingByPercent[screenColor]; + else + error("remapColor(): Color %d isn't remapped", remappedColor); + + return 0; // should never reach here } void GfxPalette::resetRemapping() { _remapOn = false; - _remappingMaskFrom = 0; - _remappingMaskTo = 0; _remappingPercentToSet = 0; for (int i = 0; i < 256; i++) { - _remappingTable[i] = i; + _remappingType[i] = kRemappingNone; + _remappingByPercent[i] = i; + _remappingByRange[i] = i; } } @@ -356,28 +365,17 @@ void GfxPalette::setRemappingPercent(byte color, byte percent) { // copySysPaletteToScreen(). _remappingPercentToSet = percent; - if (_remappingMaskFrom > color || _remappingMaskFrom == 0) - _remappingMaskFrom = color; - if (_remappingMaskTo < color) - _remappingMaskTo = color; + _remappingType[color] = kRemappingByPercent; } void GfxPalette::setRemappingRange(byte color, byte from, byte to, byte base) { _remapOn = true; for (int i = from; i <= to; i++) { - _remappingTable[i] = i + base; + _remappingByRange[i] = i + base; } - if (_remappingMaskFrom > color || _remappingMaskFrom == 0) - _remappingMaskFrom = color; - if (_remappingMaskTo < color) - _remappingMaskTo = color; -} - -byte GfxPalette::remapColor(byte color) { - assert(_remapOn); - return _remappingTable[color]; + _remappingType[color] = kRemappingByRange; } bool GfxPalette::insert(Palette *newPalette, Palette *destPalette) { @@ -548,7 +546,7 @@ void GfxPalette::copySysPaletteToScreen() { byte r = _sysPalette.colors[i].r * _remappingPercentToSet / 100; byte g = _sysPalette.colors[i].g * _remappingPercentToSet / 100; byte b = _sysPalette.colors[i].b * _remappingPercentToSet / 100; - _remappingTable[i] = kernelFindColor(r, g, b); + _remappingByPercent[i] = kernelFindColor(r, g, b); } } @@ -1060,8 +1058,9 @@ bool GfxPalette::loadClut(uint16 clutId) { memset(&pal, 0, sizeof(Palette)); // Setup 1:1 mapping - for (int i = 0; i < 256; i++) + for (int i = 0; i < 256; i++) { pal.mapping[i] = i; + } // Now load in the palette for (int i = 1; i <= 236; i++) { diff --git a/engines/sci/graphics/palette.h b/engines/sci/graphics/palette.h index 134ade5e36..9898315897 100644 --- a/engines/sci/graphics/palette.h +++ b/engines/sci/graphics/palette.h @@ -31,6 +31,12 @@ namespace Sci { class ResourceManager; class GfxScreen; +enum ColorRemappingType { + kRemappingNone = 0, + kRemappingByRange = 1, + kRemappingByPercent = 2 +}; + /** * Palette class, handles palette operations like changing intensity, setting up the palette, merging different palettes */ @@ -56,8 +62,10 @@ public: void resetRemapping(); void setRemappingPercent(byte color, byte percent); void setRemappingRange(byte color, byte from, byte to, byte base); - bool isRemapMask(byte color); - byte remapColor(byte color); + bool isRemapped(byte color) const { + return _remapOn && (_remappingType[color] != kRemappingNone); + } + byte remapColor(byte remappedColor, byte screenColor); void setOnScreen(); void copySysPaletteToScreen(); @@ -130,8 +138,9 @@ private: uint16 _totalScreenColors; bool _remapOn; - byte _remappingTable[256]; - uint16 _remappingMaskFrom, _remappingMaskTo; + ColorRemappingType _remappingType[256]; + byte _remappingByPercent[256]; + byte _remappingByRange[256]; uint16 _remappingPercentToSet; void loadMacIconBarPalette(); diff --git a/engines/sci/graphics/view.cpp b/engines/sci/graphics/view.cpp index f68ed1443a..36aaae9232 100644 --- a/engines/sci/graphics/view.cpp +++ b/engines/sci/graphics/view.cpp @@ -742,10 +742,10 @@ void GfxView::draw(const Common::Rect &rect, const Common::Rect &clipRect, const const int y2 = clipRectTranslated.top + y; if (!upscaledHires) { if (priority >= _screen->getPriority(x2, y2)) { - if (!_palette->isRemapMask(palette->mapping[color])) { + if (!_palette->isRemapped(palette->mapping[color])) { _screen->putPixel(x2, y2, drawMask, palette->mapping[color], priority, 0); } else { - byte remappedColor = _palette->remapColor(_screen->getVisual(x2, y2)); + byte remappedColor = _palette->remapColor(palette->mapping[color], _screen->getVisual(x2, y2)); _screen->putPixel(x2, y2, drawMask, remappedColor, priority, 0); } } @@ -857,10 +857,10 @@ void GfxView::drawScaled(const Common::Rect &rect, const Common::Rect &clipRect, const int x2 = clipRectTranslated.left + x; const int y2 = clipRectTranslated.top + y; if (color != clearKey && priority >= _screen->getPriority(x2, y2)) { - if (!_palette->isRemapMask(palette->mapping[color])) { + if (!_palette->isRemapped(palette->mapping[color])) { _screen->putPixel(x2, y2, drawMask, palette->mapping[color], priority, 0); } else { - byte remappedColor = _palette->remapColor(_screen->getVisual(x2, y2)); + byte remappedColor = _palette->remapColor(palette->mapping[color], _screen->getVisual(x2, y2)); _screen->putPixel(x2, y2, drawMask, remappedColor, priority, 0); } } -- cgit v1.2.3 From 797dbfe506d5273c0385997401aa32524995df33 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Wed, 25 Jul 2012 01:16:13 +0300 Subject: SCI: Set the RemapByPercent palette initially This needs to be performed because the screen palette might not change after the call. Fixes the display of the bat in the character selection screen in the full version of QFG4 --- engines/sci/graphics/palette.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/graphics/palette.cpp b/engines/sci/graphics/palette.cpp index 9b8618c0ef..68104b0ac8 100644 --- a/engines/sci/graphics/palette.cpp +++ b/engines/sci/graphics/palette.cpp @@ -361,10 +361,17 @@ void GfxPalette::setRemappingPercent(byte color, byte percent) { // We need to defer the setup of the remapping table every time the screen // palette is changed, so that kernelFindColor() can find the correct - // colors. The actual setup of the remapping table will be performed in - // copySysPaletteToScreen(). + // colors. Set it once here, in case the palette stays the same and update + // it on each palette change by copySysPaletteToScreen(). _remappingPercentToSet = percent; + for (int i = 0; i < 256; i++) { + byte r = _sysPalette.colors[i].r * _remappingPercentToSet / 100; + byte g = _sysPalette.colors[i].g * _remappingPercentToSet / 100; + byte b = _sysPalette.colors[i].b * _remappingPercentToSet / 100; + _remappingByPercent[i] = kernelFindColor(r, g, b); + } + _remappingType[color] = kRemappingByPercent; } -- cgit v1.2.3 From 55e508b91f840cd4f6358d1a1ff192b16ab1338c Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Wed, 25 Jul 2012 01:32:34 +0300 Subject: SCI: Add a workaround for QFG4, screen 140 (character selection screen) --- engines/sci/engine/kgraphics32.cpp | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'engines/sci') diff --git a/engines/sci/engine/kgraphics32.cpp b/engines/sci/engine/kgraphics32.cpp index 3d2c2af81b..d3db28226a 100644 --- a/engines/sci/engine/kgraphics32.cpp +++ b/engines/sci/engine/kgraphics32.cpp @@ -738,6 +738,12 @@ reg_t kRemapColors32(EngineState *s, int argc, reg_t *argv) { switch (operation) { case 0: { // turn remapping off + // WORKAROUND: Game scripts in QFG4 erroneously turn remapping off in room + // 140 (the character point allocation screen) and never turn it back on, + // even if it's clearly used in that screen. + if (g_sci->getGameId() == GID_QFG4 && s->currentRoomNumber() == 140) + return s->r_acc; + int16 base = (argc >= 2) ? argv[1].toSint16() : 0; if (base > 0) warning("kRemapColors(0) called with base %d", base); -- cgit v1.2.3 From 6ade0e145717410cd1268b01f7820d6c851c4375 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Wed, 25 Jul 2012 02:29:57 +0300 Subject: SCI: Expand an uninitialized read workaround for SQ6 --- engines/sci/engine/workarounds.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines/sci') diff --git a/engines/sci/engine/workarounds.cpp b/engines/sci/engine/workarounds.cpp index 15fca0322c..ccb78776dd 100644 --- a/engines/sci/engine/workarounds.cpp +++ b/engines/sci/engine/workarounds.cpp @@ -165,7 +165,7 @@ const SciWorkaroundEntry uninitializedReadWorkarounds[] = { { GID_SQ4, -1, 928, -1, "Narrator", "startText", -1, 1000, { WORKAROUND_FAKE, 1 } }, // CD: happens in the options dialog and in-game when speech and subtitles are used simultaneously { GID_SQ5, 201, 201, 0, "buttonPanel", "doVerb", -1, 0, { WORKAROUND_FAKE, 1 } }, // when looking at the orange or red button - bug #3038563 { GID_SQ6, -1, 0, 0, "SQ6", "init", -1, 2, { WORKAROUND_FAKE, 0 } }, // Demo and full version: called when the game starts (demo: room 0, full: room 100) - { GID_SQ6, 100, 64950, 0, "View", "handleEvent", -1, 0, { WORKAROUND_FAKE, 0 } }, // called when pressing "Start game" in the main menu + { GID_SQ6, -1, 64950, -1, "Feature", "handleEvent", -1, 0, { WORKAROUND_FAKE, 0 } }, // called when pressing "Start game" in the main menu, when entering the Orion's Belt bar (room 300), and perhaps other places { GID_SQ6, -1, 64964, 0, "DPath", "init", -1, 1, { WORKAROUND_FAKE, 0 } }, // during the game { GID_TORIN, -1, 64017, 0, "oFlags", "clear", -1, 0, { WORKAROUND_FAKE, 0 } }, // entering Torin's home in the French version SCI_WORKAROUNDENTRY_TERMINATOR -- cgit v1.2.3 From e7836beabb47c5415c6239cc1e344450b7bb3c8d Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Wed, 25 Jul 2012 12:13:35 +0300 Subject: SCI: Silence some very chatty warnings Also, add an example room where kRemapToGray is called --- engines/sci/engine/kgraphics32.cpp | 6 ++++-- engines/sci/engine/ksound.cpp | 11 +++++++++-- 2 files changed, 13 insertions(+), 4 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/engine/kgraphics32.cpp b/engines/sci/engine/kgraphics32.cpp index d3db28226a..685b3c0bd3 100644 --- a/engines/sci/engine/kgraphics32.cpp +++ b/engines/sci/engine/kgraphics32.cpp @@ -369,7 +369,8 @@ reg_t kScrollWindow(EngineState *s, int argc, reg_t *argv) { case 10: // Where, called by ScrollableWindow::where // TODO // argv[2] is an unknown integer - kStub(s, argc, argv); + // Silenced the warnings because of the high amount of console spam + //kStub(s, argc, argv); break; case 11: // Go, called by ScrollableWindow::scrollTo // 2 extra parameters here @@ -770,7 +771,8 @@ reg_t kRemapColors32(EngineState *s, int argc, reg_t *argv) { } break; case 3: { // remap to gray - int16 color = argv[1].toSint16(); // this is subtracted from a maximum color value, and can be offset by 10 + // Example call: QFG4 room 490 (Baba Yaga's hut) - params are color 253, 75% and 0 + int16 color = argv[1].toSint16(); int16 percent = argv[2].toSint16(); // 0 - 100 uint16 unk3 = (argc >= 4) ? argv[3].toUint16() : 0; warning("kRemapColors: RemapToGray color %d by %d percent (unk3 = %d)", color, percent, unk3); diff --git a/engines/sci/engine/ksound.cpp b/engines/sci/engine/ksound.cpp index b378b4d58b..0633267db4 100644 --- a/engines/sci/engine/ksound.cpp +++ b/engines/sci/engine/ksound.cpp @@ -140,12 +140,14 @@ reg_t kDoAudio(EngineState *s, int argc, reg_t *argv) { ((argv[3].toUint16() & 0xff) << 16) | ((argv[4].toUint16() & 0xff) << 8) | (argv[5].toUint16() & 0xff); - if (argc == 8) { + // Removed warning because of the high amount of console spam + /*if (argc == 8) { + // TODO: Handle the extra 2 SCI21 params // argv[6] is always 1 // argv[7] is the contents of global 229 (0xE5) warning("kDoAudio: Play called with SCI2.1 extra parameters: %04x:%04x and %04x:%04x", PRINT_REG(argv[6]), PRINT_REG(argv[7])); - } + }*/ } else { warning("kDoAudio: Play called with an unknown number of parameters (%d)", argc); return NULL_REG; @@ -244,6 +246,11 @@ reg_t kDoAudio(EngineState *s, int argc, reg_t *argv) { // Used in Pharkas whenever a speech sample starts (takes no params) //warning("kDoAudio: Unhandled case 13, %d extra arguments passed", argc - 1); break; + case 17: + // Seems to be some sort of audio sync, used in SQ6. Silenced the + // warning due to the high level of spam it produces. (takes no params) + //warning("kDoAudio: Unhandled case 17, %d extra arguments passed", argc - 1); + break; default: warning("kDoAudio: Unhandled case %d, %d extra arguments passed", argv[0].toUint16(), argc - 1); } -- cgit v1.2.3 From 31f9e96aeef546ab5d0bf829fe427ce98a62c40f Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Wed, 25 Jul 2012 12:14:33 +0300 Subject: SCI: Add a workaround for a script bug in QFG4 --- engines/sci/engine/workarounds.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'engines/sci') diff --git a/engines/sci/engine/workarounds.cpp b/engines/sci/engine/workarounds.cpp index ccb78776dd..821549bb8c 100644 --- a/engines/sci/engine/workarounds.cpp +++ b/engines/sci/engine/workarounds.cpp @@ -397,6 +397,7 @@ const SciWorkaroundEntry kUnLoad_workarounds[] = { { GID_LSL6, 740, 740, 0, "showCartoon", "changeState", -1, 0, { WORKAROUND_IGNORE, 0 } }, // during ending, 4 additional parameters are passed by accident { GID_LSL6HIRES, 130, 130, 0, "recruitLarryScr", "changeState", -1, 0, { WORKAROUND_IGNORE, 0 } }, // during intro, a 3rd parameter is passed by accident { GID_SQ1, 43, 303, 0, "slotGuy", "dispose", -1, 0, { WORKAROUND_IGNORE, 0 } }, // when leaving ulence flats bar, parameter 1 is not passed - script error + { GID_QFG4, 770, 110, 0, "dreamer", "dispose", -1, 0, { WORKAROUND_IGNORE, 0 } }, // during the dream sequence, a 3rd parameter is passed by accident SCI_WORKAROUNDENTRY_TERMINATOR }; -- cgit v1.2.3 From dc8d9f4c9f7498f501b567262d0e90229b973e6e Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Wed, 25 Jul 2012 21:11:45 +0200 Subject: SCI: Fix delete[] formatting. --- engines/sci/graphics/font.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines/sci') diff --git a/engines/sci/graphics/font.cpp b/engines/sci/graphics/font.cpp index fcdd057509..30184cc091 100644 --- a/engines/sci/graphics/font.cpp +++ b/engines/sci/graphics/font.cpp @@ -54,7 +54,7 @@ GfxFontFromResource::GfxFontFromResource(ResourceManager *resMan, GfxScreen *scr } GfxFontFromResource::~GfxFontFromResource() { - delete []_chars; + delete[] _chars; _resMan->unlockResource(_resource); } -- cgit v1.2.3 From c0beaf2337bdadc8b18425c9a38182ba30910174 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Thu, 26 Jul 2012 11:05:50 +0300 Subject: SCI: Differentiate between screen width and pitch This properly addresses the odd screen width (630) in Phantasmagoria 1 --- engines/sci/graphics/frameout.cpp | 36 +++++++++++-------------- engines/sci/graphics/screen.cpp | 55 +++++++++++++++++++++------------------ engines/sci/graphics/screen.h | 1 + 3 files changed, 46 insertions(+), 46 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/graphics/frameout.cpp b/engines/sci/graphics/frameout.cpp index fedae2eb6f..0098728e5d 100644 --- a/engines/sci/graphics/frameout.cpp +++ b/engines/sci/graphics/frameout.cpp @@ -125,23 +125,17 @@ void GfxFrameout::kernelAddPlane(reg_t object) { if (_planes.empty()) { // There has to be another way for sierra sci to do this or maybe script resolution is compiled into // interpreter (TODO) - uint16 tmpRunningWidth = readSelectorValue(_segMan, object, SELECTOR(resX)); - uint16 tmpRunningHeight = readSelectorValue(_segMan, object, SELECTOR(resY)); + uint16 scriptWidth = readSelectorValue(_segMan, object, SELECTOR(resX)); + uint16 scriptHeight = readSelectorValue(_segMan, object, SELECTOR(resY)); - // The above can be 0 in SCI3 (e.g. Phantasmagoria 2) - if (tmpRunningWidth == 0 && tmpRunningHeight == 0) { - tmpRunningWidth = 320; - tmpRunningHeight = 200; - } - - // HACK: Phantasmagoria 1 sets a window size of 630x450. - // We can't set a width of 630, as that messes up the pitch, so we hack - // the internal script width here - if (g_sci->getGameId() == GID_PHANTASMAGORIA) { - tmpRunningWidth = 325; + // Phantasmagoria 2 doesn't specify a script width/height + if (g_sci->getGameId() == GID_PHANTASMAGORIA2) { + scriptWidth = 640; + scriptHeight = 480; } - _coordAdjuster->setScriptsResolution(tmpRunningWidth, tmpRunningHeight); + assert(scriptWidth > 0 && scriptHeight > 0); + _coordAdjuster->setScriptsResolution(scriptWidth, scriptHeight); } // Import of QfG character files dialog is shown in QFG4. @@ -704,13 +698,13 @@ void GfxFrameout::kernelFrameout() { // TODO: maybe we should clip the cels rect with this, i'm not sure // the only currently known usage is game menu of gk1 } else if (view) { - if ((itemEntry->scaleX == 128) && (itemEntry->scaleY == 128)) - view->getCelRect(itemEntry->loopNo, itemEntry->celNo, - itemEntry->x, itemEntry->y, itemEntry->z, itemEntry->celRect); - else - view->getCelScaledRect(itemEntry->loopNo, itemEntry->celNo, - itemEntry->x, itemEntry->y, itemEntry->z, itemEntry->scaleX, - itemEntry->scaleY, itemEntry->celRect); + if ((itemEntry->scaleX == 128) && (itemEntry->scaleY == 128)) + view->getCelRect(itemEntry->loopNo, itemEntry->celNo, + itemEntry->x, itemEntry->y, itemEntry->z, itemEntry->celRect); + else + view->getCelScaledRect(itemEntry->loopNo, itemEntry->celNo, + itemEntry->x, itemEntry->y, itemEntry->z, itemEntry->scaleX, + itemEntry->scaleY, itemEntry->celRect); Common::Rect nsRect = itemEntry->celRect; // Translate back to actual coordinate within scrollable plane diff --git a/engines/sci/graphics/screen.cpp b/engines/sci/graphics/screen.cpp index 3030fb4386..246b6bfff9 100644 --- a/engines/sci/graphics/screen.cpp +++ b/engines/sci/graphics/screen.cpp @@ -53,23 +53,35 @@ GfxScreen::GfxScreen(ResourceManager *resMan) : _resMan(resMan) { #ifdef ENABLE_SCI32 // GK1 Mac uses a 640x480 resolution too - if (g_sci->getGameId() == GID_GK1 && g_sci->getPlatform() == Common::kPlatformMacintosh) - _upscaledHires = GFX_SCREEN_UPSCALED_640x480; + if (g_sci->getPlatform() == Common::kPlatformMacintosh) { + if (g_sci->getGameId() == GID_GK1) + _upscaledHires = GFX_SCREEN_UPSCALED_640x480; + } #endif if (_resMan->detectHires()) { _width = 640; + _pitch = 640; _height = 480; } else { _width = 320; + _pitch = 320; _height = getLowResScreenHeight(); } +#ifdef ENABLE_SCI32 + // Phantasmagoria 1 sets a window area of 630x450 + if (g_sci->getGameId() == GID_PHANTASMAGORIA) { + _width = 630; + _height = 450; + } +#endif + // Japanese versions of games use hi-res font on upscaled version of the game. if ((g_sci->getLanguage() == Common::JA_JPN) && (getSciVersion() <= SCI_VERSION_1_1)) _upscaledHires = GFX_SCREEN_UPSCALED_640x400; - _pixels = _width * _height; + _pixels = _pitch * _height; switch (_upscaledHires) { case GFX_SCREEN_UPSCALED_640x400: @@ -91,19 +103,12 @@ GfxScreen::GfxScreen(ResourceManager *resMan) : _resMan(resMan) { _upscaledMapping[i] = (i * 12) / 5; break; default: - _displayWidth = _width; + _displayWidth = _pitch; _displayHeight = _height; memset(&_upscaledMapping, 0, sizeof(_upscaledMapping) ); break; } - // Phantasmagoria 1 sets a window area of 630x450 - if (g_sci->getGameId() == GID_PHANTASMAGORIA) { - // TODO: Also set width to 630 (can't be set right now, as it messes up - // the pitch). For now, a hack has been placed in GfxFrameout::kernelAddPlane() - _height = 450; - } - _displayPixels = _displayWidth * _displayHeight; _visualScreen = (byte *)calloc(_pixels, 1); _priorityScreen = (byte *)calloc(_pixels, 1); @@ -214,7 +219,7 @@ byte GfxScreen::getDrawingMask(byte color, byte prio, byte control) { } void GfxScreen::putPixel(int x, int y, byte drawMask, byte color, byte priority, byte control) { - int offset = y * _width + x; + int offset = y * _pitch + x; if (drawMask & GFX_SCREEN_MASK_VISUAL) { _visualScreen[offset] = color; @@ -247,7 +252,7 @@ void GfxScreen::putFontPixel(int startingY, int x, int y, byte color) { // Do not scale ourselves, but put it on the display directly putPixelOnDisplay(x, y + startingY, color); } else { - int offset = (startingY + y) * _width + x; + int offset = (startingY + y) * _pitch + x; _visualScreen[offset] = color; if (!_upscaledHires) { @@ -349,19 +354,19 @@ void GfxScreen::putKanjiChar(Graphics::FontSJIS *commonFont, int16 x, int16 y, u } byte GfxScreen::getVisual(int x, int y) { - return _visualScreen[y * _width + x]; + return _visualScreen[y * _pitch + x]; } byte GfxScreen::getPriority(int x, int y) { - return _priorityScreen[y * _width + x]; + return _priorityScreen[y * _pitch + x]; } byte GfxScreen::getControl(int x, int y) { - return _controlScreen[y * _width + x]; + return _controlScreen[y * _pitch + x]; } byte GfxScreen::isFillMatch(int16 x, int16 y, byte screenMask, byte t_color, byte t_pri, byte t_con, bool isEGA) { - int offset = y * _width + x; + int offset = y * _pitch + x; byte match = 0; if (screenMask & GFX_SCREEN_MASK_VISUAL) { @@ -422,14 +427,14 @@ void GfxScreen::bitsSave(Common::Rect rect, byte mask, byte *memoryPtr) { memcpy(memoryPtr, (void *)&mask, sizeof(mask)); memoryPtr += sizeof(mask); if (mask & GFX_SCREEN_MASK_VISUAL) { - bitsSaveScreen(rect, _visualScreen, _width, memoryPtr); + bitsSaveScreen(rect, _visualScreen, _pitch, memoryPtr); bitsSaveDisplayScreen(rect, memoryPtr); } if (mask & GFX_SCREEN_MASK_PRIORITY) { - bitsSaveScreen(rect, _priorityScreen, _width, memoryPtr); + bitsSaveScreen(rect, _priorityScreen, _pitch, memoryPtr); } if (mask & GFX_SCREEN_MASK_CONTROL) { - bitsSaveScreen(rect, _controlScreen, _width, memoryPtr); + bitsSaveScreen(rect, _controlScreen, _pitch, memoryPtr); } if (mask & GFX_SCREEN_MASK_DISPLAY) { if (!_upscaledHires) @@ -482,14 +487,14 @@ void GfxScreen::bitsRestore(byte *memoryPtr) { memcpy((void *)&mask, memoryPtr, sizeof(mask)); memoryPtr += sizeof(mask); if (mask & GFX_SCREEN_MASK_VISUAL) { - bitsRestoreScreen(rect, memoryPtr, _visualScreen, _width); + bitsRestoreScreen(rect, memoryPtr, _visualScreen, _pitch); bitsRestoreDisplayScreen(rect, memoryPtr); } if (mask & GFX_SCREEN_MASK_PRIORITY) { - bitsRestoreScreen(rect, memoryPtr, _priorityScreen, _width); + bitsRestoreScreen(rect, memoryPtr, _priorityScreen, _pitch); } if (mask & GFX_SCREEN_MASK_CONTROL) { - bitsRestoreScreen(rect, memoryPtr, _controlScreen, _width); + bitsRestoreScreen(rect, memoryPtr, _controlScreen, _pitch); } if (mask & GFX_SCREEN_MASK_DISPLAY) { if (!_upscaledHires) @@ -567,7 +572,7 @@ void GfxScreen::dither(bool addToFlag) { if (!_unditheringEnabled) { // Do dithering on visual and display-screen for (y = 0; y < _height; y++) { - for (x = 0; x < _width; x++) { + for (x = 0; x < _pitch; x++) { color = *visualPtr; if (color & 0xF0) { color ^= color << 4; @@ -592,7 +597,7 @@ void GfxScreen::dither(bool addToFlag) { memset(&_ditheredPicColors, 0, sizeof(_ditheredPicColors)); // Do dithering on visual screen and put decoded but undithered byte onto display-screen for (y = 0; y < _height; y++) { - for (x = 0; x < _width; x++) { + for (x = 0; x < _pitch; x++) { color = *visualPtr; if (color & 0xF0) { color ^= color << 4; diff --git a/engines/sci/graphics/screen.h b/engines/sci/graphics/screen.h index 73ea596ba1..01fb899edb 100644 --- a/engines/sci/graphics/screen.h +++ b/engines/sci/graphics/screen.h @@ -132,6 +132,7 @@ public: private: uint16 _width; + uint16 _pitch; uint16 _height; uint _pixels; uint16 _displayWidth; -- cgit v1.2.3 From 34d00f59365cf05a8817ade955a6440ab3019860 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Thu, 26 Jul 2012 11:06:19 +0300 Subject: SCI: Add some debug code to op_line --- engines/sci/engine/vm.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'engines/sci') diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index 5a2a39def2..3f43966976 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -1173,6 +1173,7 @@ void run_vm(EngineState *s) { case op_line: // 0x3f (63) // Debug opcode (line number) + //debug("Script %d, line %d", scr->getScriptNumber(), opparams[0]); break; case op_lag: // 0x40 (64) -- cgit v1.2.3 From 7eded163d8088d97f65e482f63e9ecd194d00c68 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Fri, 27 Jul 2012 01:30:37 +0300 Subject: SCI: Add support for kCD(0) with a parameter It's now possible to start a chapter in Phantasmagoria 1 --- engines/sci/engine/kfile.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/engine/kfile.cpp b/engines/sci/engine/kfile.cpp index 786276221c..f7cc4f44b5 100644 --- a/engines/sci/engine/kfile.cpp +++ b/engines/sci/engine/kfile.cpp @@ -197,8 +197,15 @@ reg_t kCD(EngineState *s, int argc, reg_t *argv) { // TODO: Stub switch (argv[0].toUint16()) { case 0: - // Return whether the contents of disc argv[1] is available. - return TRUE_REG; + if (argc == 1) { + // Check if a disc is in the drive + return TRUE_REG; + } else { + // Check if the specified disc is in the drive + // and return the current disc number. We just + // return the requested disc number. + return argv[1]; + } case 1: // Return the current CD number return make_reg(0, 1); -- cgit v1.2.3 From 831e1b27dc5b114eaceb49bad08576b3bdf81ab5 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Fri, 27 Jul 2012 01:31:12 +0300 Subject: SCI: Add a workaround for a bug in Phantasmagoria 1 --- engines/sci/engine/workarounds.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'engines/sci') diff --git a/engines/sci/engine/workarounds.cpp b/engines/sci/engine/workarounds.cpp index 821549bb8c..fea3aed9ae 100644 --- a/engines/sci/engine/workarounds.cpp +++ b/engines/sci/engine/workarounds.cpp @@ -40,6 +40,7 @@ const SciWorkaroundEntry arithmeticWorkarounds[] = { { GID_MOTHERGOOSE256, -1, 999, 0, "Event", "new", -1, 0, { WORKAROUND_FAKE, 0 } }, // op_and: constantly during the game (SCI1 version) { GID_MOTHERGOOSE256, -1, 4, 0, "rm004", "doit", -1, 0, { WORKAROUND_FAKE, 0 } }, // op_or: when going north and reaching the castle (rooms 4 and 37) - bug #3038228 { GID_MOTHERGOOSEHIRES,90, 90, 0, "newGameButton", "select", -1, 0, { WORKAROUND_FAKE, 0 } }, // op_ge: MUMG Deluxe, when selecting "New Game" in the main menu. It tries to compare an integer with a list. Needs to return false for the game to continue. + { GID_PHANTASMAGORIA, 902, 0, 0, "", "export 7", -1, 0, { WORKAROUND_FAKE, 0 } }, // op_shr: when starting a chapter in Phantasmagoria { GID_QFG1VGA, 301, 928, 0, "Blink", "init", -1, 0, { WORKAROUND_FAKE, 0 } }, // op_div: when entering the inn, gets called with 1 parameter, but 2nd parameter is used for div which happens to be an object { GID_QFG2, 200, 200, 0, "astro", "messages", -1, 0, { WORKAROUND_FAKE, 0 } }, // op_lsi: when getting asked for your name by the astrologer bug #3039879 { GID_GK1, 800,64992, 0, "Fwd", "doit", -1, 0, { WORKAROUND_FAKE, 1 } }, // op_gt: when Mosely finds Gabriel and Grace near the end of the game, compares the Grooper object with 7 -- cgit v1.2.3 From 991710d0a158bfce4e54bd240482a4e3044271d3 Mon Sep 17 00:00:00 2001 From: Matthew Hoops Date: Fri, 27 Jul 2012 11:32:51 -0400 Subject: VIDEO: Adapt QuickTimeDecoder to the AdvancedVideoDecoder API --- engines/sci/engine/kvideo.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/engine/kvideo.cpp b/engines/sci/engine/kvideo.cpp index 456f860493..da63aa3a8d 100644 --- a/engines/sci/engine/kvideo.cpp +++ b/engines/sci/engine/kvideo.cpp @@ -170,8 +170,6 @@ reg_t kShowMovie(EngineState *s, int argc, reg_t *argv) { delete videoDecoder; videoDecoder = 0; } - - ((Video::AdvancedVideoDecoder *)videoDecoder)->start(); // TODO: Remove after new API is complete } } else { // Windows AVI @@ -212,7 +210,6 @@ reg_t kShowMovie(EngineState *s, int argc, reg_t *argv) { videoDecoder = 0; } else { s->_videoState.fileName = filename; - ((Video::AdvancedVideoDecoder *)videoDecoder)->start(); } break; } @@ -222,6 +219,7 @@ reg_t kShowMovie(EngineState *s, int argc, reg_t *argv) { } if (videoDecoder) { + ((Video::AdvancedVideoDecoder *)videoDecoder)->start(); // TODO: Remove after new API is complete playVideo(videoDecoder, s->_videoState); // HACK: Switch back to 8bpp if we played a true color video. -- cgit v1.2.3 From 259f262592bab9b779bad7aff6752ca69ffb26de Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Thu, 2 Aug 2012 03:46:58 +0300 Subject: SCI: Add a workaround for a script bug in QFG4 Thanks to Charles for testing --- engines/sci/engine/workarounds.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'engines/sci') diff --git a/engines/sci/engine/workarounds.cpp b/engines/sci/engine/workarounds.cpp index fea3aed9ae..a4c2355e8f 100644 --- a/engines/sci/engine/workarounds.cpp +++ b/engines/sci/engine/workarounds.cpp @@ -36,6 +36,7 @@ const SciWorkaroundEntry arithmeticWorkarounds[] = { { GID_ECOQUEST2, 100, 0, 0, "Rain", "points", 0xcc6, 0, { WORKAROUND_FAKE, 0 } }, // op_or: when giving the papers to the customs officer, gets called against a pointer instead of a number - bug #3034464 { GID_ECOQUEST2, 100, 0, 0, "Rain", "points", 0xce0, 0, { WORKAROUND_FAKE, 0 } }, // Same as above, for the Spanish version - bug #3313962 { GID_FANMADE, 516, 983, 0, "Wander", "setTarget", -1, 0, { WORKAROUND_FAKE, 0 } }, // op_mul: The Legend of the Lost Jewel Demo (fan made): called with object as second parameter when attacked by insects - bug #3038913 + { GID_GK1, 800,64992, 0, "Fwd", "doit", -1, 0, { WORKAROUND_FAKE, 1 } }, // op_gt: when Mosely finds Gabriel and Grace near the end of the game, compares the Grooper object with 7 { GID_ICEMAN, 199, 977, 0, "Grooper", "doit", -1, 0, { WORKAROUND_FAKE, 0 } }, // op_add: While dancing with the girl { GID_MOTHERGOOSE256, -1, 999, 0, "Event", "new", -1, 0, { WORKAROUND_FAKE, 0 } }, // op_and: constantly during the game (SCI1 version) { GID_MOTHERGOOSE256, -1, 4, 0, "rm004", "doit", -1, 0, { WORKAROUND_FAKE, 0 } }, // op_or: when going north and reaching the castle (rooms 4 and 37) - bug #3038228 @@ -43,7 +44,7 @@ const SciWorkaroundEntry arithmeticWorkarounds[] = { { GID_PHANTASMAGORIA, 902, 0, 0, "", "export 7", -1, 0, { WORKAROUND_FAKE, 0 } }, // op_shr: when starting a chapter in Phantasmagoria { GID_QFG1VGA, 301, 928, 0, "Blink", "init", -1, 0, { WORKAROUND_FAKE, 0 } }, // op_div: when entering the inn, gets called with 1 parameter, but 2nd parameter is used for div which happens to be an object { GID_QFG2, 200, 200, 0, "astro", "messages", -1, 0, { WORKAROUND_FAKE, 0 } }, // op_lsi: when getting asked for your name by the astrologer bug #3039879 - { GID_GK1, 800,64992, 0, "Fwd", "doit", -1, 0, { WORKAROUND_FAKE, 1 } }, // op_gt: when Mosely finds Gabriel and Grace near the end of the game, compares the Grooper object with 7 + { GID_QFG4, 710,64941, 0, "RandCycle", "doit", -1, 0, { WORKAROUND_FAKE, 1 } }, // op_gt: when the tentacle appears in the third room of the caves SCI_WORKAROUNDENTRY_TERMINATOR }; -- cgit v1.2.3 From aedd0d2a16bc06617c30a3ed1a2fa8f2bf88ba68 Mon Sep 17 00:00:00 2001 From: D G Turner Date: Tue, 7 Aug 2012 10:23:31 +0100 Subject: SCI: Add missing QFG2 detection entry from bug #3554614. --- engines/sci/detection_tables.h | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'engines/sci') diff --git a/engines/sci/detection_tables.h b/engines/sci/detection_tables.h index 268914edba..ebfd66868c 100644 --- a/engines/sci/detection_tables.h +++ b/engines/sci/detection_tables.h @@ -3002,6 +3002,21 @@ static const struct ADGameDescription SciGameDescriptions[] = { AD_LISTEND}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + // Quest for Glory 2 - English DOS (supplied by digitoxin1 in bug report #3554614) + // 1.102 9x3.5" + {"qfg2", "", { + {"resource.map", 0, "367023314ea33e3156297402f6c1da49", 8166}, + {"resource.000", 0, "a17e374c4d33b81208c862bc0ffc1a38", 212119}, + {"resource.001", 0, "e08d7887e30b12008c40f9570447711a", 331995}, + {"resource.002", 0, "df137dc7869cab07e1149ba2333c815c", 467461}, + {"resource.003", 0, "df137dc7869cab07e1149ba2333c815c", 502560}, + {"resource.004", 0, "df137dc7869cab07e1149ba2333c815c", 488532}, + {"resource.005", 0, "df137dc7869cab07e1149ba2333c815c", 478574}, + {"resource.006", 0, "b1944bd664ddbd2859cdaa0c4a0d6281", 507489}, + {"resource.007", 0, "cd2de58e27665d5853530de93fae7cd6", 490794}, + AD_LISTEND}, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + // Quest for Glory 2 - English DOS Non-Interactive Demo // Executable scanning reports "1.000.046" {"qfg2", "Demo", { -- cgit v1.2.3 From 611905aa9718afd0320f518af6976d3316035622 Mon Sep 17 00:00:00 2001 From: D G Turner Date: Tue, 7 Aug 2012 11:28:10 +0100 Subject: SCI: Add missing QFG1 detection entries from bug #3554611. --- engines/sci/detection_tables.h | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) (limited to 'engines/sci') diff --git a/engines/sci/detection_tables.h b/engines/sci/detection_tables.h index ebfd66868c..11ece3decd 100644 --- a/engines/sci/detection_tables.h +++ b/engines/sci/detection_tables.h @@ -2798,6 +2798,32 @@ static const struct ADGameDescription SciGameDescriptions[] = { AD_LISTEND}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + // Quest for Glory 1 / Hero's Quest - English DOS 3.5" Floppy v1.102 (suppled by digitoxin1 in bug report #3554611) + // Note: Identical detection entry to English Amiga versions, so will trigger version choice dialog. + {"qfg1", "", { + {"resource.map", 0, "b162dbd4632250d4d83bed46d0783c10", 6396}, + {"resource.000", 0, "40332d3ebfc70a4b6a6a0443c2763287", 78800}, + {"resource.001", 0, "a270012fa74445d74c044d1b65a9ff8c", 459835}, + {"resource.002", 0, "e64004e020fdf1813be52b639b08be89", 635561}, + {"resource.003", 0, "f0af87c60ec869946da442833aa5afa8", 640502}, + {"resource.004", 0, "f0af87c60ec869946da442833aa5afa8", 644575}, + AD_LISTEND}, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + + // Quest for Glory 1 / Hero's Quest - English DOS 5.25" Floppy v1.102 (suppled by digitoxin1 in bug report #3554611) + {"qfg1", "", { + {"resource.map", 0, "5772a2c1bfae46f26582582c9901121e", 6858}, + {"resource.000", 0, "40332d3ebfc70a4b6a6a0443c2763287", 78800}, + {"resource.001", 0, "a270012fa74445d74c044d1b65a9ff8c", 75090}, + {"resource.002", 0, "d22695c53835dfdece056d86f26c251e", 271354}, + {"resource.003", 0, "3cd085e27078f269b3ece5838812ff41", 258084}, + {"resource.004", 0, "8927c7a04a78f1e76f342db3ccc9d879", 267835}, + {"resource.005", 0, "13d16cc9b90b51e2c8643cdf52a62957", 268807}, + {"resource.006", 0, "48b2b3c964dcbeccb68e984e6d4e97db", 278473}, + {"resource.007", 0, "f0af87c60ec869946da442833aa5afa8", 269237}, + AD_LISTEND}, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + // Quest for Glory 1 / Hero's Quest - English DOS 5.25" Floppy (supplied by markcoolio in bug report #2723843) // Executable scanning reports "0.000.566" {"qfg1", "", { -- cgit v1.2.3 From d83382a9ef92cd485438873c98f420b794190ff7 Mon Sep 17 00:00:00 2001 From: D G Turner Date: Tue, 7 Aug 2012 19:27:22 +0100 Subject: SCI: Add extra comments to new detection entries. No functional changes. --- engines/sci/detection_tables.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/detection_tables.h b/engines/sci/detection_tables.h index 11ece3decd..10f89a94e2 100644 --- a/engines/sci/detection_tables.h +++ b/engines/sci/detection_tables.h @@ -2798,7 +2798,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { AD_LISTEND}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, - // Quest for Glory 1 / Hero's Quest - English DOS 3.5" Floppy v1.102 (suppled by digitoxin1 in bug report #3554611) + // Quest for Glory 1 / Hero's Quest - English DOS 3.5" Floppy v1.102 Int#0.000.629 (suppled by digitoxin1 in bug report #3554611) // Note: Identical detection entry to English Amiga versions, so will trigger version choice dialog. {"qfg1", "", { {"resource.map", 0, "b162dbd4632250d4d83bed46d0783c10", 6396}, @@ -2810,7 +2810,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { AD_LISTEND}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, - // Quest for Glory 1 / Hero's Quest - English DOS 5.25" Floppy v1.102 (suppled by digitoxin1 in bug report #3554611) + // Quest for Glory 1 / Hero's Quest - English DOS 5.25" Floppy v1.102 Int#0.000.629 (suppled by digitoxin1 in bug report #3554611) {"qfg1", "", { {"resource.map", 0, "5772a2c1bfae46f26582582c9901121e", 6858}, {"resource.000", 0, "40332d3ebfc70a4b6a6a0443c2763287", 78800}, @@ -3029,7 +3029,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Quest for Glory 2 - English DOS (supplied by digitoxin1 in bug report #3554614) - // 1.102 9x3.5" + // v1.102 9x3.5" (label: Int#11.20.90) {"qfg2", "", { {"resource.map", 0, "367023314ea33e3156297402f6c1da49", 8166}, {"resource.000", 0, "a17e374c4d33b81208c862bc0ffc1a38", 212119}, -- cgit v1.2.3 From 546e2086e32c42602cede84c961bbacab75ebdb4 Mon Sep 17 00:00:00 2001 From: Willem Jan Palenstijn Date: Tue, 7 Aug 2012 21:01:33 +0200 Subject: SCI: Remove duplicate detection entry There is no indication in the corresponding bug report this was for an Amiga version. --- engines/sci/detection_tables.h | 12 ------------ 1 file changed, 12 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/detection_tables.h b/engines/sci/detection_tables.h index 10f89a94e2..b39dad118e 100644 --- a/engines/sci/detection_tables.h +++ b/engines/sci/detection_tables.h @@ -2799,7 +2799,6 @@ static const struct ADGameDescription SciGameDescriptions[] = { Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Quest for Glory 1 / Hero's Quest - English DOS 3.5" Floppy v1.102 Int#0.000.629 (suppled by digitoxin1 in bug report #3554611) - // Note: Identical detection entry to English Amiga versions, so will trigger version choice dialog. {"qfg1", "", { {"resource.map", 0, "b162dbd4632250d4d83bed46d0783c10", 6396}, {"resource.000", 0, "40332d3ebfc70a4b6a6a0443c2763287", 78800}, @@ -2911,17 +2910,6 @@ static const struct ADGameDescription SciGameDescriptions[] = { AD_LISTEND}, Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, - // Quest for Glory 1 (from abevi, bug report #2612718) - {"qfg1", "", { - {"resource.map", 0, "b162dbd4632250d4d83bed46d0783c10", 6396}, - {"resource.000", 0, "40332d3ebfc70a4b6a6a0443c2763287", 78800}, - {"resource.001", 0, "a270012fa74445d74c044d1b65a9ff8c", 459835}, - {"resource.002", 0, "e64004e020fdf1813be52b639b08be89", 635561}, - {"resource.003", 0, "f0af87c60ec869946da442833aa5afa8", 640502}, - {"resource.004", 0, "f0af87c60ec869946da442833aa5afa8", 644575}, - AD_LISTEND}, - Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, - // Quest for Glory 1 - English DOS // SCI interpreter version 0.000.629 {"qfg1", "", { -- cgit v1.2.3 From 2d1a63c9305db01049ac0642169ac995442e77f8 Mon Sep 17 00:00:00 2001 From: D G Turner Date: Sat, 11 Aug 2012 17:37:14 +0100 Subject: SCI: Add KQ5 Spanish DOS detection entry from bug #3555646. --- engines/sci/detection_tables.h | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'engines/sci') diff --git a/engines/sci/detection_tables.h b/engines/sci/detection_tables.h index b39dad118e..d739891e8f 100644 --- a/engines/sci/detection_tables.h +++ b/engines/sci/detection_tables.h @@ -1326,6 +1326,21 @@ static const struct ADGameDescription SciGameDescriptions[] = { AD_LISTEND}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + // King's Quest 5 DOS Spanish Floppy 0.000.062 VGA (5 x 3.5" disks) + // Supplied by dianiu in bug report #3555646 + {"kq5", "", { + {"resource.map", 0, "c09896a2a30c9b002c5cbbc62f5a5c3a", 8169}, + {"resource.000", 0, "1f1d03aead44da46362ff40c0074a3ec", 335871}, + {"resource.001", 0, "d1803ad904127ae091edb274ee8c047f", 1180637}, + {"resource.002", 0, "d9cd5972016f650cc31fb7c2a2b0953a", 1102207}, + {"resource.003", 0, "829c8caeff793f3cfcea2cb01aaa4150", 965586}, + {"resource.004", 0, "0bd9e570ee04b025e43d3075998fae5b", 1117965}, + {"resource.005", 0, "4aaa2e9a69089b9afbaaccbbf2c4e647", 1202936}, + {"resource.006", 0, "65b520e60c4217e6a6572d9edf77193b", 1141985}, + {"resource.007", 0, "f42b0100f0a1c30806814f8648b6bc28", 1145583}, + AD_LISTEND}, + Common::ES_ESP, Common::kPlatformPC, ADGF_ADDENGLISH, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + // King's Quest 5 - German DOS Floppy (supplied by markcoolio in bug report #2727101, also includes english language) // SCI interpreter version 1.000.060 {"kq5", "", { -- cgit v1.2.3 From 1f91cc1aa0a21c80aa6d31934078b5d2a5e18f08 Mon Sep 17 00:00:00 2001 From: D G Turner Date: Sat, 11 Aug 2012 17:55:31 +0100 Subject: SCI: Add PQ3 Spanish DOS detection entry from bug #3555647. --- engines/sci/detection_tables.h | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'engines/sci') diff --git a/engines/sci/detection_tables.h b/engines/sci/detection_tables.h index d739891e8f..b978f40aba 100644 --- a/engines/sci/detection_tables.h +++ b/engines/sci/detection_tables.h @@ -2696,6 +2696,13 @@ static const struct ADGameDescription SciGameDescriptions[] = { AD_LISTEND}, Common::DE_DEU, Common::kPlatformPC, ADGF_ADDENGLISH, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + // Police Quest 3 - Spanish DOS v1.000 - Supplied by dianiu in bug report #3555647 + {"pq3", "", { + {"resource.map", 0, "ffa0b4631c4e36d69631256d19ba29e7", 5421}, + {"resource.000", 0, "5ee460af3d70c06a745cc482b6c783ba", 5410263}, + AD_LISTEND}, + Common::ES_ESP, Common::kPlatformPC, ADGF_ADDENGLISH, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + // Police Quest 3 EGA // Reported by musiclyinspired in bug report #3046573 {"pq3", "", { -- cgit v1.2.3 From 7294a1cbcf1cf5e8c846faf8838e537bd8c638dc Mon Sep 17 00:00:00 2001 From: Matthew Hoops Date: Thu, 16 Aug 2012 12:17:23 -0400 Subject: VIDEO: Remove the Coktel video code from using the VideoDecoder API After discussing with DrMcCoy, we felt this the best way to proceed. A wrapper class that implements AdvancedVideoDecoder is still around for use in SCI. --- engines/sci/console.cpp | 5 ++--- engines/sci/engine/kvideo.cpp | 7 +++---- 2 files changed, 5 insertions(+), 7 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp index 9b5ef35e92..de852ca9c0 100644 --- a/engines/sci/console.cpp +++ b/engines/sci/console.cpp @@ -253,7 +253,7 @@ void Console::postEnter() { videoDecoder = new SEQDecoder(_videoFrameDelay); #ifdef ENABLE_SCI32 } else if (_videoFile.hasSuffix(".vmd")) { - videoDecoder = new Video::VMDDecoder(g_system->getMixer()); + videoDecoder = new Video::AdvancedVMDDecoder(); } else if (_videoFile.hasSuffix(".rbt")) { videoDecoder = new RobotDecoder(_engine->getPlatform() == Common::kPlatformMacintosh); } else if (_videoFile.hasSuffix(".duk")) { @@ -267,8 +267,7 @@ void Console::postEnter() { } if (videoDecoder && videoDecoder->loadFile(_videoFile)) { - if (!_videoFile.hasSuffix(".vmd")) // TODO: Remove after new API is complete - ((Video::AdvancedVideoDecoder *)videoDecoder)->start(); + ((Video::AdvancedVideoDecoder *)videoDecoder)->start(); _engine->_gfxCursor->kernelHide(); diff --git a/engines/sci/engine/kvideo.cpp b/engines/sci/engine/kvideo.cpp index da63aa3a8d..3e0f35c037 100644 --- a/engines/sci/engine/kvideo.cpp +++ b/engines/sci/engine/kvideo.cpp @@ -50,6 +50,8 @@ void playVideo(Video::VideoDecoder *videoDecoder, VideoState videoState) { if (!videoDecoder) return; + ((Video::AdvancedVideoDecoder *)videoDecoder)->start(); + byte *scaleBuffer = 0; byte bytesPerPixel = videoDecoder->getPixelFormat().bytesPerPixel; uint16 width = videoDecoder->getWidth(); @@ -219,7 +221,6 @@ reg_t kShowMovie(EngineState *s, int argc, reg_t *argv) { } if (videoDecoder) { - ((Video::AdvancedVideoDecoder *)videoDecoder)->start(); // TODO: Remove after new API is complete playVideo(videoDecoder, s->_videoState); // HACK: Switch back to 8bpp if we played a true color video. @@ -349,7 +350,7 @@ reg_t kPlayVMD(EngineState *s, int argc, reg_t *argv) { break; } case 6: // Play - videoDecoder = new Video::VMDDecoder(g_system->getMixer()); + videoDecoder = new Video::AdvancedVMDDecoder(); if (s->_videoState.fileName.empty()) { // Happens in Lighthouse @@ -414,8 +415,6 @@ reg_t kPlayDuck(EngineState *s, int argc, reg_t *argv) { break; } - ((Video::AdvancedVideoDecoder *)videoDecoder)->start(); - if (reshowCursor) g_sci->_gfxCursor->kernelHide(); -- cgit v1.2.3 From fb35c7f46f986a22235638e2946ba8492e735109 Mon Sep 17 00:00:00 2001 From: Matthew Hoops Date: Thu, 16 Aug 2012 13:30:32 -0400 Subject: VIDEO: Remove setSystemPalette() --- engines/sci/graphics/frameout.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/graphics/frameout.cpp b/engines/sci/graphics/frameout.cpp index fedae2eb6f..0056f6c78b 100644 --- a/engines/sci/graphics/frameout.cpp +++ b/engines/sci/graphics/frameout.cpp @@ -28,6 +28,7 @@ #include "common/system.h" #include "common/textconsole.h" #include "engines/engine.h" +#include "graphics/palette.h" #include "graphics/surface.h" #include "sci/sci.h" @@ -494,7 +495,7 @@ void GfxFrameout::showVideo() { uint16 y = videoDecoder->getPos().y; if (videoDecoder->hasDirtyPalette()) - videoDecoder->setSystemPalette(); + g_system->getPaletteManager()->setPalette(videoDecoder->getPalette(), 0, 256); while (!g_engine->shouldQuit() && !videoDecoder->endOfVideo() && !skipVideo) { if (videoDecoder->needsUpdate()) { @@ -503,7 +504,7 @@ void GfxFrameout::showVideo() { g_system->copyRectToScreen(frame->pixels, frame->pitch, x, y, frame->w, frame->h); if (videoDecoder->hasDirtyPalette()) - videoDecoder->setSystemPalette(); + g_system->getPaletteManager()->setPalette(videoDecoder->getPalette(), 0, 256); g_system->updateScreen(); } -- cgit v1.2.3 From 18823198ad4e7dedd0ca33760eb453e9fe673551 Mon Sep 17 00:00:00 2001 From: Matthew Hoops Date: Thu, 16 Aug 2012 14:00:14 -0400 Subject: VIDEO: Merge AdvancedVideoDecoder into VideoDecoder --- engines/sci/console.cpp | 2 -- engines/sci/engine/kvideo.cpp | 2 +- engines/sci/video/robot_decoder.cpp | 2 +- engines/sci/video/robot_decoder.h | 2 +- engines/sci/video/seq_decoder.h | 2 +- 5 files changed, 4 insertions(+), 6 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp index de852ca9c0..1889d53480 100644 --- a/engines/sci/console.cpp +++ b/engines/sci/console.cpp @@ -267,8 +267,6 @@ void Console::postEnter() { } if (videoDecoder && videoDecoder->loadFile(_videoFile)) { - ((Video::AdvancedVideoDecoder *)videoDecoder)->start(); - _engine->_gfxCursor->kernelHide(); #ifdef ENABLE_SCI32 diff --git a/engines/sci/engine/kvideo.cpp b/engines/sci/engine/kvideo.cpp index 3e0f35c037..6bf9aff2fe 100644 --- a/engines/sci/engine/kvideo.cpp +++ b/engines/sci/engine/kvideo.cpp @@ -50,7 +50,7 @@ void playVideo(Video::VideoDecoder *videoDecoder, VideoState videoState) { if (!videoDecoder) return; - ((Video::AdvancedVideoDecoder *)videoDecoder)->start(); + videoDecoder->start(); byte *scaleBuffer = 0; byte bytesPerPixel = videoDecoder->getPixelFormat().bytesPerPixel; diff --git a/engines/sci/video/robot_decoder.cpp b/engines/sci/video/robot_decoder.cpp index 6fe4c645f4..608c77136f 100644 --- a/engines/sci/video/robot_decoder.cpp +++ b/engines/sci/video/robot_decoder.cpp @@ -132,7 +132,7 @@ bool RobotDecoder::load(GuiResourceId id) { } void RobotDecoder::close() { - AdvancedVideoDecoder::close(); + VideoDecoder::close(); delete _fileStream; _fileStream = 0; diff --git a/engines/sci/video/robot_decoder.h b/engines/sci/video/robot_decoder.h index de5b669ab8..ebc3262939 100644 --- a/engines/sci/video/robot_decoder.h +++ b/engines/sci/video/robot_decoder.h @@ -37,7 +37,7 @@ class SeekableSubReadStreamEndian; namespace Sci { -class RobotDecoder : public Video::AdvancedVideoDecoder { +class RobotDecoder : public Video::VideoDecoder { public: RobotDecoder(bool isBigEndian); virtual ~RobotDecoder(); diff --git a/engines/sci/video/seq_decoder.h b/engines/sci/video/seq_decoder.h index 82254990d6..890f349feb 100644 --- a/engines/sci/video/seq_decoder.h +++ b/engines/sci/video/seq_decoder.h @@ -40,7 +40,7 @@ namespace Sci { /** * Implementation of the Sierra SEQ decoder, used in KQ6 DOS floppy/CD and GK1 DOS */ -class SEQDecoder : public Video::AdvancedVideoDecoder { +class SEQDecoder : public Video::VideoDecoder { public: SEQDecoder(uint frameDelay); virtual ~SEQDecoder(); -- cgit v1.2.3 From 8524ebd699254a6786033f0e41b9a45c563feb11 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Mon, 20 Aug 2012 02:58:37 +0300 Subject: SCI: Fix script bug #3555404 - "SCI: KQ6 Spider Scene Game Freeze" --- engines/sci/sound/soundcmd.cpp | 39 +++++++++++++++++++++++---------------- 1 file changed, 23 insertions(+), 16 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/sound/soundcmd.cpp b/engines/sci/sound/soundcmd.cpp index cbb5cab4fe..1570e360e8 100644 --- a/engines/sci/sound/soundcmd.cpp +++ b/engines/sci/sound/soundcmd.cpp @@ -367,29 +367,36 @@ reg_t SoundCommandParser::kDoSoundFade(int argc, reg_t *argv, reg_t acc) { case 4: // SCI01+ case 5: // SCI1+ (SCI1 late sound scheme), with fade and continue - musicSlot->fadeTo = CLIP(argv[1].toUint16(), 0, MUSIC_VOLUME_MAX); - // Check if the song is already at the requested volume. If it is, don't - // perform any fading. Happens for example during the intro of Longbow. - if (musicSlot->fadeTo == musicSlot->volume) - return acc; - - // sometimes we get objects in that position, fix it up (ffs. workarounds) - if (!argv[1].getSegment()) - musicSlot->fadeStep = volume > musicSlot->fadeTo ? -argv[3].toUint16() : argv[3].toUint16(); - else - musicSlot->fadeStep = volume > musicSlot->fadeTo ? -5 : 5; - musicSlot->fadeTickerStep = argv[2].toUint16() * 16667 / _music->soundGetTempo(); - musicSlot->fadeTicker = 0; - if (argc == 5) { // TODO: We currently treat this argument as a boolean, but may // have to handle different non-zero values differently. (e.g., - // some KQ6 scripts pass 3 here) - musicSlot->stopAfterFading = (argv[4].toUint16() != 0); + // some KQ6 scripts pass 3 here). + // There is a script bug in KQ6, room 460 (the room with the flying + // books). An object is passed here, which should not be treated as + // a true flag. Fixes bugs #3555404 and #3291115. + musicSlot->stopAfterFading = (argv[4].isNumber() && argv[4].toUint16() != 0); } else { musicSlot->stopAfterFading = false; } + musicSlot->fadeTo = CLIP(argv[1].toUint16(), 0, MUSIC_VOLUME_MAX); + // Check if the song is already at the requested volume. If it is, don't + // perform any fading. Happens for example during the intro of Longbow. + if (musicSlot->fadeTo != musicSlot->volume) { + // sometimes we get objects in that position, fix it up (ffs. workarounds) + if (!argv[1].getSegment()) + musicSlot->fadeStep = volume > musicSlot->fadeTo ? -argv[3].toUint16() : argv[3].toUint16(); + else + musicSlot->fadeStep = volume > musicSlot->fadeTo ? -5 : 5; + musicSlot->fadeTickerStep = argv[2].toUint16() * 16667 / _music->soundGetTempo(); + } else { + // Stop the music, if requested. Fixes bug #3555404. + if (musicSlot->stopAfterFading) + processStopSound(obj, false); + } + + musicSlot->fadeTicker = 0; + // WORKAROUND/HACK: In the labyrinth in KQ6, when falling in the pit and // lighting the lantern, the game scripts perform a fade in of the game // music, but set it to stop after fading. Remove that flag here. This is -- cgit v1.2.3 From b19ccb9d1edcdf238727f0c3b0a731b2f00e9d3d Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Mon, 20 Aug 2012 03:22:56 +0300 Subject: SCI: Set the correct audio type for SCI1.1 sound effects, fixing bug #3554709 Now, sound effects in SCI1.1 games will no longer be incorrectly using the speech sound volume. This avoids them being silenced in floppy games that are flagged as not having speech. Fixes bug #3554709 - "SCI: Digital SFX don't play when Override Global Audio set" --- engines/sci/sound/audio.cpp | 3 ++- engines/sci/sound/soundcmd.cpp | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/sound/audio.cpp b/engines/sci/sound/audio.cpp index 123dd21894..528bb51393 100644 --- a/engines/sci/sound/audio.cpp +++ b/engines/sci/sound/audio.cpp @@ -67,7 +67,8 @@ int AudioPlayer::startAudio(uint16 module, uint32 number) { if (audioStream) { _wPlayFlag = false; - _mixer->playStream(Audio::Mixer::kSpeechSoundType, &_audioHandle, audioStream); + Audio::Mixer::SoundType soundType = (module == 65535) ? Audio::Mixer::kSFXSoundType : Audio::Mixer::kSpeechSoundType; + _mixer->playStream(soundType, &_audioHandle, audioStream); return sampleLen; } else { // Don't throw a warning in this case. getAudioStream() already has. Some games diff --git a/engines/sci/sound/soundcmd.cpp b/engines/sci/sound/soundcmd.cpp index 1570e360e8..5d32f40f18 100644 --- a/engines/sci/sound/soundcmd.cpp +++ b/engines/sci/sound/soundcmd.cpp @@ -96,7 +96,7 @@ void SoundCommandParser::initSoundResource(MusicEntry *newSound) { if (_useDigitalSFX || !newSound->soundRes) { int sampleLen; newSound->pStreamAud = _audio->getAudioStream(newSound->resourceId, 65535, &sampleLen); - newSound->soundType = Audio::Mixer::kSpeechSoundType; + newSound->soundType = Audio::Mixer::kSFXSoundType; } } -- cgit v1.2.3 From 9568b78babdbdf350fd6c47b261c3f21902c31fc Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Tue, 21 Aug 2012 03:28:34 +0300 Subject: SCI: Use a simpler atan implementation for kGetAngle in SCI1 and newer games SCI1 games (QFG2 and newer) use a simpler and more accurate atan implementation for kGetAngle. This properly fixes bug #3540976. --- engines/sci/engine/kmath.cpp | 25 ++++--------------------- 1 file changed, 4 insertions(+), 21 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/engine/kmath.cpp b/engines/sci/engine/kmath.cpp index a643fbe37a..4b8fadbb84 100644 --- a/engines/sci/engine/kmath.cpp +++ b/engines/sci/engine/kmath.cpp @@ -84,27 +84,10 @@ reg_t kSqrt(EngineState *s, int argc, reg_t *argv) { * accurate. */ uint16 kGetAngleWorker(int16 x1, int16 y1, int16 x2, int16 y2) { - // TODO: This has been implemented based on behavior observed with a test - // program created with SCI Studio. However, the return values have subtle - // differences from the original, which uses custom implementation of atan(). - // The differences in the return values are the cause of bug #3540976 - // and perhaps bug #3037267 as well. - // The results of this function match the expected results of SCI0, but not - // SCI1 (hence the bug in Longbow). We need to find the point in history - // when this function was changed. - - // HACK: Return the expected value for Longbow, scene 150 (bug #3540976). - // This is a temporary solution, till the function returns the expected - // results. - if (g_sci->getGameId() == GID_LONGBOW && g_sci->getEngineState()->currentRoomNumber() == 150) { - if (x1 == 207 && y1 == 88 && x2 == 107 && y2 == 184) - return 226; - } - -#if 0 - // A simpler atan2-based implementation - return (int16)(360 - atan2((double)(x1 - x2), (double)(y1 - y2)) * 57.2958) % 360; -#endif + // SCI1 games (QFG2 and newer) use a simple atan implementation. SCI0 games + // use a somewhat less accurate calculation (below). + if (getSciVersion() >= SCI_VERSION_1_EGA_ONLY) + return (int16)(360 - atan2((double)(x1 - x2), (double)(y1 - y2)) * 57.2958) % 360; int16 xRel = x2 - x1; int16 yRel = y1 - y2; // y-axis is mirrored. -- cgit v1.2.3 From 1a61056b06dc4ea5fe534f6ff13eb4e281bb9c03 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Tue, 21 Aug 2012 03:29:55 +0300 Subject: SCI: Extend a workaround for the dream sequence in QFG4 --- engines/sci/engine/workarounds.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines/sci') diff --git a/engines/sci/engine/workarounds.cpp b/engines/sci/engine/workarounds.cpp index a4c2355e8f..9fa0368784 100644 --- a/engines/sci/engine/workarounds.cpp +++ b/engines/sci/engine/workarounds.cpp @@ -399,7 +399,7 @@ const SciWorkaroundEntry kUnLoad_workarounds[] = { { GID_LSL6, 740, 740, 0, "showCartoon", "changeState", -1, 0, { WORKAROUND_IGNORE, 0 } }, // during ending, 4 additional parameters are passed by accident { GID_LSL6HIRES, 130, 130, 0, "recruitLarryScr", "changeState", -1, 0, { WORKAROUND_IGNORE, 0 } }, // during intro, a 3rd parameter is passed by accident { GID_SQ1, 43, 303, 0, "slotGuy", "dispose", -1, 0, { WORKAROUND_IGNORE, 0 } }, // when leaving ulence flats bar, parameter 1 is not passed - script error - { GID_QFG4, 770, 110, 0, "dreamer", "dispose", -1, 0, { WORKAROUND_IGNORE, 0 } }, // during the dream sequence, a 3rd parameter is passed by accident + { GID_QFG4, -1, 110, 0, "dreamer", "dispose", -1, 0, { WORKAROUND_IGNORE, 0 } }, // during the dream sequence, a 3rd parameter is passed by accident SCI_WORKAROUNDENTRY_TERMINATOR }; -- cgit v1.2.3 From 7d436622a8e10437488f6dfa930e3ff15e254a55 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Tue, 21 Aug 2012 03:31:00 +0300 Subject: SCI: More work on kRemapColors This implements some more color remap-based palette effects, found in QFG4 --- engines/sci/engine/kgraphics32.cpp | 21 ++++++++++++--------- engines/sci/graphics/palette.cpp | 21 +++++++++++++++++++++ engines/sci/graphics/palette.h | 1 + 3 files changed, 34 insertions(+), 9 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/engine/kgraphics32.cpp b/engines/sci/engine/kgraphics32.cpp index 685b3c0bd3..8b3afeef99 100644 --- a/engines/sci/engine/kgraphics32.cpp +++ b/engines/sci/engine/kgraphics32.cpp @@ -771,20 +771,23 @@ reg_t kRemapColors32(EngineState *s, int argc, reg_t *argv) { } break; case 3: { // remap to gray - // Example call: QFG4 room 490 (Baba Yaga's hut) - params are color 253, 75% and 0 + // Example call: QFG4 room 490 (Baba Yaga's hut) - params are color 253, 75% and 0. + // In this room, it's used for the cloud before Baba Yaga appears. int16 color = argv[1].toSint16(); int16 percent = argv[2].toSint16(); // 0 - 100 - uint16 unk3 = (argc >= 4) ? argv[3].toUint16() : 0; - warning("kRemapColors: RemapToGray color %d by %d percent (unk3 = %d)", color, percent, unk3); - // TODO + if (argc >= 4) + warning("RemapToGray called with 4 parameters, unknown parameter is %d", argv[3].toUint16()); + g_sci->_gfxPalette->setRemappingPercentGray(color, percent); } break; case 4: { // remap to percent gray - //int16 unk1 = argv[1].toSint16(); - //uint16 unk2 = argv[2].toUint16(); - //uint16 unk3 = argv[3].toUint16(); - //uint16 unk4 = (argc >= 5) ? argv[4].toUint16() : 0; - kStub(s, argc, argv); + // Example call: QFG4 rooms 530/535 (swamp) - params are 253, 100%, 200 + int16 color = argv[1].toSint16(); + int16 percent = argv[2].toSint16(); // 0 - 100 + // argv[3] is unknown (a number, e.g. 200) - start color, perhaps? + if (argc >= 5) + warning("RemapToGrayPercent called with 5 parameters, unknown parameter is %d", argv[4].toUint16()); + g_sci->_gfxPalette->setRemappingPercentGray(color, percent); } break; case 5: { // don't map to range diff --git a/engines/sci/graphics/palette.cpp b/engines/sci/graphics/palette.cpp index 68104b0ac8..53d69cdcca 100644 --- a/engines/sci/graphics/palette.cpp +++ b/engines/sci/graphics/palette.cpp @@ -375,6 +375,27 @@ void GfxPalette::setRemappingPercent(byte color, byte percent) { _remappingType[color] = kRemappingByPercent; } +void GfxPalette::setRemappingPercentGray(byte color, byte percent) { + _remapOn = true; + + // We need to defer the setup of the remapping table every time the screen + // palette is changed, so that kernelFindColor() can find the correct + // colors. Set it once here, in case the palette stays the same and update + // it on each palette change by copySysPaletteToScreen(). + _remappingPercentToSet = percent; + + // Note: This is not what the original does, but the results are the same visually + for (int i = 0; i < 256; i++) { + byte rComponent = _sysPalette.colors[i].r * _remappingPercentToSet * 0.30 / 100; + byte gComponent = _sysPalette.colors[i].g * _remappingPercentToSet * 0.59 / 100; + byte bComponent = _sysPalette.colors[i].b * _remappingPercentToSet * 0.11 / 100; + byte luminosity = rComponent + gComponent + bComponent; + _remappingByPercent[i] = kernelFindColor(luminosity, luminosity, luminosity); + } + + _remappingType[color] = kRemappingByPercent; +} + void GfxPalette::setRemappingRange(byte color, byte from, byte to, byte base) { _remapOn = true; diff --git a/engines/sci/graphics/palette.h b/engines/sci/graphics/palette.h index 9898315897..e974781d49 100644 --- a/engines/sci/graphics/palette.h +++ b/engines/sci/graphics/palette.h @@ -61,6 +61,7 @@ public: void resetRemapping(); void setRemappingPercent(byte color, byte percent); + void setRemappingPercentGray(byte color, byte percent); void setRemappingRange(byte color, byte from, byte to, byte base); bool isRemapped(byte color) const { return _remapOn && (_remappingType[color] != kRemappingNone); -- cgit v1.2.3 From a391599403faf864f1583ababdba577fb6393afd Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Tue, 21 Aug 2012 11:55:21 +0300 Subject: SCI: Update a comment --- engines/sci/graphics/frameout.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'engines/sci') diff --git a/engines/sci/graphics/frameout.cpp b/engines/sci/graphics/frameout.cpp index 0098728e5d..6628247127 100644 --- a/engines/sci/graphics/frameout.cpp +++ b/engines/sci/graphics/frameout.cpp @@ -728,7 +728,9 @@ void GfxFrameout::kernelFrameout() { g_sci->_gfxCompare->setNSRect(itemEntry->object, nsRect); } - // FIXME: When does this happen, and why? + // Don't attempt to draw sprites that are outside the visible + // screen area. An example is the random people walking in + // Jackson Square in GK1. if (itemEntry->celRect.bottom < 0 || itemEntry->celRect.top >= _screen->getDisplayHeight() || itemEntry->celRect.right < 0 || itemEntry->celRect.left >= _screen->getDisplayWidth()) continue; -- cgit v1.2.3 From 60c2061710838c494fddb3e73f16b583a555b448 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sat, 1 Sep 2012 17:59:52 +0300 Subject: SCI: Allow the Fun Seeker's Guide demo to run This demo doesn't have any music, and the original doesn't work with any sound driver, so don't error out when the sound driver can't be initialized properly --- engines/sci/sound/music.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'engines/sci') diff --git a/engines/sci/sound/music.cpp b/engines/sci/sound/music.cpp index 918b045cb9..ffd51da673 100644 --- a/engines/sci/sound/music.cpp +++ b/engines/sci/sound/music.cpp @@ -125,7 +125,10 @@ void SciMusic::init() { _pMidiDrv->setTimerCallback(this, &miditimerCallback); _dwTempo = _pMidiDrv->getBaseTempo(); } else { - error("Failed to initialize sound driver"); + // Happens in the Fun Seeker's Guide demo, which doesn't have any sound + // anyway (nor works if anything other than PC Spearker is set), so this + // shouldn't be fatal + warning("Failed to initialize sound driver"); } // Find out what the first possible channel is (used, when doing channel -- cgit v1.2.3 From 7824d0e8e9116e2610072a92c99c6d80ae9db19f Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sat, 1 Sep 2012 20:15:12 +0300 Subject: SCI: Limit the hack used for sound initialization to the Fun Seeker's demo only --- engines/sci/sound/drivers/adlib.cpp | 3 +++ engines/sci/sound/music.cpp | 11 +++++++---- 2 files changed, 10 insertions(+), 4 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/sound/drivers/adlib.cpp b/engines/sci/sound/drivers/adlib.cpp index db9317e071..191e13db0a 100644 --- a/engines/sci/sound/drivers/adlib.cpp +++ b/engines/sci/sound/drivers/adlib.cpp @@ -807,6 +807,9 @@ int MidiPlayer_AdLib::open(ResourceManager *resMan) { int size = f.size(); const uint patchSize = 1344; + // Note: Funseeker's Guide also has another version of adl.drv, 8803 bytes. + // This isn't supported, but it's not really used anywhere, as that demo + // doesn't have sound anyway. if ((size == 5684) || (size == 5720) || (size == 5727)) { byte *buf = new byte[patchSize]; diff --git a/engines/sci/sound/music.cpp b/engines/sci/sound/music.cpp index ffd51da673..a8a65d2aa4 100644 --- a/engines/sci/sound/music.cpp +++ b/engines/sci/sound/music.cpp @@ -125,10 +125,13 @@ void SciMusic::init() { _pMidiDrv->setTimerCallback(this, &miditimerCallback); _dwTempo = _pMidiDrv->getBaseTempo(); } else { - // Happens in the Fun Seeker's Guide demo, which doesn't have any sound - // anyway (nor works if anything other than PC Spearker is set), so this - // shouldn't be fatal - warning("Failed to initialize sound driver"); + if (g_sci->getGameId() == GID_FUNSEEKER) { + // HACK: The Fun Seeker's Guide demo doesn't have patch 3 and the version + // of the Adlib driver (adl.drv) that it includes is unsupported. That demo + // doesn't have any sound anyway, so this shouldn't be fatal. + } else { + error("Failed to initialize sound driver"); + } } // Find out what the first possible channel is (used, when doing channel -- cgit v1.2.3 From f08978a0750e6a6a5dbea1f8fe5d80267049f8c8 Mon Sep 17 00:00:00 2001 From: Alyssa Milburn Date: Fri, 7 Sep 2012 22:57:14 +0200 Subject: JANITORIAL: Remove underscores from MidiParser variable names. --- engines/sci/sound/midiparser_sci.cpp | 80 ++++++++++++++++++------------------ engines/sci/sound/midiparser_sci.h | 2 +- 2 files changed, 41 insertions(+), 41 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/sound/midiparser_sci.cpp b/engines/sci/sound/midiparser_sci.cpp index 422948f975..4e54797960 100644 --- a/engines/sci/sound/midiparser_sci.cpp +++ b/engines/sci/sound/midiparser_sci.cpp @@ -98,7 +98,7 @@ bool MidiParser_SCI::loadMusic(SoundResource::Track *track, MusicEntry *psnd, in midiMixChannels(); } - _num_tracks = 1; + _numTracks = 1; _tracks[0] = _mixedData; if (_pSnd) setTrack(0); @@ -144,7 +144,7 @@ byte *MidiParser_SCI::midiMixChannels() { _mixedData = outData; long ticker = 0; byte channelNr, curDelta; - byte midiCommand = 0, midiParam, global_prev = 0; + byte midiCommand = 0, midiParam, globalPrev = 0; long newDelta; SoundResource::Channel *channel; @@ -190,13 +190,13 @@ byte *MidiParser_SCI::midiMixChannels() { byte midiChannel = midiCommand & 0xF; _channelUsed[midiChannel] = true; - if (midiCommand != global_prev) + if (midiCommand != globalPrev) *outData++ = midiCommand; *outData++ = midiParam; if (nMidiParams[(midiCommand >> 4) - 8] == 2) *outData++ = channel->data[channel->curPos++]; channel->prev = midiCommand; - global_prev = midiCommand; + globalPrev = midiCommand; } } @@ -372,8 +372,8 @@ void MidiParser_SCI::unloadMusic() { resetTracking(); allNotesOff(); } - _num_tracks = 0; - _active_track = 255; + _numTracks = 0; + _activeTrack = 255; _resetOnPause = false; if (_mixedData) { @@ -454,26 +454,26 @@ void MidiParser_SCI::parseNextEvent(EventInfo &info) { debugC(4, kDebugLevelSound, "signal %04x", _signalToSet); } - info.start = _position._play_pos; + info.start = _position._playPos; info.delta = 0; - while (*_position._play_pos == 0xF8) { + while (*_position._playPos == 0xF8) { info.delta += 240; - _position._play_pos++; + _position._playPos++; } - info.delta += *(_position._play_pos++); + info.delta += *(_position._playPos++); // Process the next info. - if ((_position._play_pos[0] & 0xF0) >= 0x80) - info.event = *(_position._play_pos++); + if ((_position._playPos[0] & 0xF0) >= 0x80) + info.event = *(_position._playPos++); else - info.event = _position._running_status; + info.event = _position._runningStatus; if (info.event < 0x80) return; - _position._running_status = info.event; + _position._runningStatus = info.event; switch (info.command()) { case 0xC: - info.basic.param1 = *(_position._play_pos++); + info.basic.param1 = *(_position._playPos++); info.basic.param2 = 0; if (info.channel() == 0xF) {// SCI special case if (info.basic.param1 != kSetSignalLoop) { @@ -488,23 +488,23 @@ void MidiParser_SCI::parseNextEvent(EventInfo &info) { // in glitches (e.g. the intro of LB1 Amiga gets stuck - bug // #3297883). Refer to MusicEntry::setSignal() in sound/music.cpp. if (_soundVersion <= SCI_VERSION_0_LATE || - _position._play_tick || info.delta) { + _position._playTick || info.delta) { _signalSet = true; _signalToSet = info.basic.param1; } } else { - _loopTick = _position._play_tick + info.delta; + _loopTick = _position._playTick + info.delta; } } break; case 0xD: - info.basic.param1 = *(_position._play_pos++); + info.basic.param1 = *(_position._playPos++); info.basic.param2 = 0; break; case 0xB: - info.basic.param1 = *(_position._play_pos++); - info.basic.param2 = *(_position._play_pos++); + info.basic.param1 = *(_position._playPos++); + info.basic.param2 = *(_position._playPos++); // Reference for some events: // http://wiki.scummvm.org/index.php/SCI/Specifications/Sound/SCI0_Resource_Format#Status_Reference @@ -588,8 +588,8 @@ void MidiParser_SCI::parseNextEvent(EventInfo &info) { case 0x9: case 0xA: case 0xE: - info.basic.param1 = *(_position._play_pos++); - info.basic.param2 = *(_position._play_pos++); + info.basic.param1 = *(_position._playPos++); + info.basic.param2 = *(_position._playPos++); if (info.command() == 0x9 && info.basic.param2 == 0) info.event = info.channel() | 0x80; info.length = 0; @@ -598,12 +598,12 @@ void MidiParser_SCI::parseNextEvent(EventInfo &info) { case 0xF: // System Common, Meta or SysEx event switch (info.event & 0x0F) { case 0x2: // Song Position Pointer - info.basic.param1 = *(_position._play_pos++); - info.basic.param2 = *(_position._play_pos++); + info.basic.param1 = *(_position._playPos++); + info.basic.param2 = *(_position._playPos++); break; case 0x3: // Song Select - info.basic.param1 = *(_position._play_pos++); + info.basic.param1 = *(_position._playPos++); info.basic.param2 = 0; break; @@ -617,16 +617,16 @@ void MidiParser_SCI::parseNextEvent(EventInfo &info) { break; case 0x0: // SysEx - info.length = readVLQ(_position._play_pos); - info.ext.data = _position._play_pos; - _position._play_pos += info.length; + info.length = readVLQ(_position._playPos); + info.ext.data = _position._playPos; + _position._playPos += info.length; break; case 0xF: // META event - info.ext.type = *(_position._play_pos++); - info.length = readVLQ(_position._play_pos); - info.ext.data = _position._play_pos; - _position._play_pos += info.length; + info.ext.type = *(_position._playPos++); + info.length = readVLQ(_position._playPos); + info.ext.data = _position._playPos; + _position._playPos += info.length; if (info.ext.type == 0x2F) {// end of track reached if (_pSnd->loop) _pSnd->loop--; @@ -677,21 +677,21 @@ void MidiParser_SCI::allNotesOff() { // Turn off all active notes for (i = 0; i < 128; ++i) { for (j = 0; j < 16; ++j) { - if ((_active_notes[i] & (1 << j)) && (_channelRemap[j] != -1)){ + if ((_activeNotes[i] & (1 << j)) && (_channelRemap[j] != -1)){ sendToDriver(0x80 | j, i, 0); } } } // Turn off all hanging notes - for (i = 0; i < ARRAYSIZE(_hanging_notes); i++) { - byte midiChannel = _hanging_notes[i].channel; - if ((_hanging_notes[i].time_left) && (_channelRemap[midiChannel] != -1)) { - sendToDriver(0x80 | midiChannel, _hanging_notes[i].note, 0); - _hanging_notes[i].time_left = 0; + for (i = 0; i < ARRAYSIZE(_hangingNotes); i++) { + byte midiChannel = _hangingNotes[i].channel; + if ((_hangingNotes[i].timeLeft) && (_channelRemap[midiChannel] != -1)) { + sendToDriver(0x80 | midiChannel, _hangingNotes[i].note, 0); + _hangingNotes[i].timeLeft = 0; } } - _hanging_notes_count = 0; + _hangingNotesCount = 0; // To be sure, send an "All Note Off" event (but not all MIDI devices // support this...). @@ -703,7 +703,7 @@ void MidiParser_SCI::allNotesOff() { } } - memset(_active_notes, 0, sizeof(_active_notes)); + memset(_activeNotes, 0, sizeof(_activeNotes)); } void MidiParser_SCI::setMasterVolume(byte masterVolume) { diff --git a/engines/sci/sound/midiparser_sci.h b/engines/sci/sound/midiparser_sci.h index 82f34070a4..d3fd337644 100644 --- a/engines/sci/sound/midiparser_sci.h +++ b/engines/sci/sound/midiparser_sci.h @@ -65,7 +65,7 @@ public: void setMasterVolume(byte masterVolume); void setVolume(byte volume); void stop() { - _abort_parse = true; + _abortParse = true; allNotesOff(); } void pause() { -- cgit v1.2.3 From 89abab97e3124fa25eb4c7d3e8b38501747a8d17 Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Wed, 26 Sep 2012 04:17:31 +0200 Subject: JANITORIAL: Remove trailing whitespaces. Powered by: git ls-files "*.cpp" "*.h" "*.m" "*.mm" | xargs sed -i -e 's/[ \t]*$//' --- engines/sci/engine/file.cpp | 4 ++-- engines/sci/engine/kernel_tables.h | 2 +- engines/sci/engine/kfile.cpp | 6 +++--- engines/sci/engine/kvideo.cpp | 2 +- engines/sci/engine/seg_manager.cpp | 2 +- engines/sci/engine/vm.cpp | 2 +- engines/sci/graphics/controls32.cpp | 6 +++--- engines/sci/graphics/frameout.cpp | 14 +++++++------- engines/sci/graphics/paint16.cpp | 4 ++-- engines/sci/sound/drivers/fmtowns.cpp | 12 ++++++------ engines/sci/video/robot_decoder.cpp | 6 +++--- engines/sci/video/robot_decoder.h | 4 ++-- 12 files changed, 32 insertions(+), 32 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/engine/file.cpp b/engines/sci/engine/file.cpp index a0f7ebf4a2..3dc042389e 100644 --- a/engines/sci/engine/file.cpp +++ b/engines/sci/engine/file.cpp @@ -95,7 +95,7 @@ reg_t file_open(EngineState *s, const Common::String &filename, int mode, bool u outFile = saveFileMan->openForSaving(wrappedName, isCompressed); if (!outFile) debugC(kDebugLevelFile, " -> file_open(_K_FILE_MODE_CREATE): failed to create file '%s'", englishName.c_str()); - + // QfG1 opens the character export file with _K_FILE_MODE_CREATE first, // closes it immediately and opens it again with this here. Perhaps // other games use this for read access as well. I guess changing this @@ -387,7 +387,7 @@ uint32 VirtualIndexFile::read(char *buffer, uint32 size) { uint32 VirtualIndexFile::write(const char *buffer, uint32 size) { _changed = true; uint32 curPos = _ptr - _buffer; - + // Check if the buffer needs to be resized if (curPos + size >= _bufferSize) { _bufferSize = curPos + size + 1; diff --git a/engines/sci/engine/kernel_tables.h b/engines/sci/engine/kernel_tables.h index f5f46285be..b6b36c47e7 100644 --- a/engines/sci/engine/kernel_tables.h +++ b/engines/sci/engine/kernel_tables.h @@ -524,7 +524,7 @@ static SciKernelMapEntry s_kernelMap[] = { { MAP_CALL(PalCycle), SIG_EVERYWHERE, "i(.*)", NULL, NULL }, // SCI2 Empty functions - + // Debug function used to track resources { MAP_EMPTY(ResourceTrack), SIG_EVERYWHERE, "(.*)", NULL, NULL }, // Future TODO: This call is used in the floppy version of QFG4 to add diff --git a/engines/sci/engine/kfile.cpp b/engines/sci/engine/kfile.cpp index f7cc4f44b5..e977f15c0c 100644 --- a/engines/sci/engine/kfile.cpp +++ b/engines/sci/engine/kfile.cpp @@ -340,7 +340,7 @@ reg_t kFileIOClose(EngineState *s, int argc, reg_t *argv) { if (argv[0] == SIGNAL_REG) return s->r_acc; - + uint16 handle = argv[0].toUint16(); #ifdef ENABLE_SCI32 @@ -624,7 +624,7 @@ reg_t kFileIOExists(EngineState *s, int argc, reg_t *argv) { // Special case for KQ6 Mac: The game checks for two video files to see // if they exist before it plays them. Since we support multiple naming // schemes for resource fork files, we also need to support that here in - // case someone has a "HalfDome.bin" file, etc. + // case someone has a "HalfDome.bin" file, etc. if (!exists && g_sci->getGameId() == GID_KQ6 && g_sci->getPlatform() == Common::kPlatformMacintosh && (name == "HalfDome" || name == "Kq6Movie")) exists = Common::MacResManager::exists(name); @@ -998,7 +998,7 @@ reg_t kMakeSaveFileName(EngineState *s, int argc, reg_t *argv) { if ((virtualId < SAVEGAMEID_OFFICIALRANGE_START) || (virtualId > SAVEGAMEID_OFFICIALRANGE_END)) error("kMakeSaveFileName: invalid savegame ID specified"); uint saveSlot = virtualId - SAVEGAMEID_OFFICIALRANGE_START; - + Common::Array saves; listSavegames(saves); diff --git a/engines/sci/engine/kvideo.cpp b/engines/sci/engine/kvideo.cpp index 6bf9aff2fe..9b0cb38f51 100644 --- a/engines/sci/engine/kvideo.cpp +++ b/engines/sci/engine/kvideo.cpp @@ -275,7 +275,7 @@ reg_t kRobot(EngineState *s, int argc, reg_t *argv) { // Signal the engine scripts that the video is done writeSelector(s->_segMan, argv[1], SELECTOR(signal), SIGNAL_REG); } else { - writeSelector(s->_segMan, argv[1], SELECTOR(signal), NULL_REG); + writeSelector(s->_segMan, argv[1], SELECTOR(signal), NULL_REG); } break; default: diff --git a/engines/sci/engine/seg_manager.cpp b/engines/sci/engine/seg_manager.cpp index 951fc7c363..04c1dab158 100644 --- a/engines/sci/engine/seg_manager.cpp +++ b/engines/sci/engine/seg_manager.cpp @@ -825,7 +825,7 @@ byte *SegManager::allocDynmem(int size, const char *descr, reg_t *addr) { } bool SegManager::freeDynmem(reg_t addr) { - if (addr.getSegment() < 1 || addr.getSegment() >= _heap.size() || + if (addr.getSegment() < 1 || addr.getSegment() >= _heap.size() || !_heap[addr.getSegment()] || _heap[addr.getSegment()]->getType() != SEG_TYPE_DYNMEM) return false; // error diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index 3f43966976..ef8f165084 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -228,7 +228,7 @@ ExecStack *execute_method(EngineState *s, uint16 script, uint16 pubfunct, StackP uint32 exportAddr = scr->validateExportFunc(pubfunct, false); if (!exportAddr) return NULL; - + // Check if a breakpoint is set on this method g_sci->checkExportBreakpoint(script, pubfunct); diff --git a/engines/sci/graphics/controls32.cpp b/engines/sci/graphics/controls32.cpp index ad1d9e8623..5535a7408a 100644 --- a/engines/sci/graphics/controls32.cpp +++ b/engines/sci/graphics/controls32.cpp @@ -68,7 +68,7 @@ void GfxControls32::kernelTexteditChange(reg_t controlObject) { while (captureEvents) { curEvent = g_sci->getEventManager()->getSciEvent(SCI_EVENT_KEYBOARD | SCI_EVENT_PEEK); - + if (curEvent.type == SCI_EVENT_NONE) { eventMan->getSciEvent(SCI_EVENT_KEYBOARD); // consume the event } else { @@ -170,11 +170,11 @@ void GfxControls32::kernelTexteditChange(reg_t controlObject) { // Note: the following checkAltInput call might make the text // too wide to fit, but SSCI fails to check that too. } - + reg_t hunkId = readSelector(_segMan, controlObject, SELECTOR(bitmap)); Common::Rect nsRect = g_sci->_gfxCompare->getNSRect(controlObject); //texteditCursorErase(); // TODO: Cursor - + // Write back string _segMan->strcpy(textReference, text.c_str()); // Modify the buffer and show it diff --git a/engines/sci/graphics/frameout.cpp b/engines/sci/graphics/frameout.cpp index 968014c032..8b7fa2c384 100644 --- a/engines/sci/graphics/frameout.cpp +++ b/engines/sci/graphics/frameout.cpp @@ -197,7 +197,7 @@ void GfxFrameout::kernelUpdatePlane(reg_t object) { } else { it->planeOffsetX = 0; } - + if (it->planeRect.top < 0) { it->planeOffsetY = -it->planeRect.top; it->planeRect.top = 0; @@ -420,7 +420,7 @@ void GfxFrameout::deletePlaneItems(reg_t planeObject) { } else { objectMatches = true; } - + if (objectMatches) { FrameoutEntry *itemEntry = *listIterator; listIterator = _screenItems.erase(listIterator); @@ -661,7 +661,7 @@ void GfxFrameout::kernelFrameout() { if (!itemEntry->visible) continue; - + if (itemEntry->object.isNull()) { // Picture cel data _coordAdjuster->fromScriptToDisplay(itemEntry->y, itemEntry->x); @@ -703,7 +703,7 @@ void GfxFrameout::kernelFrameout() { view->getCelRect(itemEntry->loopNo, itemEntry->celNo, itemEntry->x, itemEntry->y, itemEntry->z, itemEntry->celRect); else - view->getCelScaledRect(itemEntry->loopNo, itemEntry->celNo, + view->getCelScaledRect(itemEntry->loopNo, itemEntry->celNo, itemEntry->x, itemEntry->y, itemEntry->z, itemEntry->scaleX, itemEntry->scaleY, itemEntry->celRect); @@ -755,10 +755,10 @@ void GfxFrameout::kernelFrameout() { if (view) { if (!clipRect.isEmpty()) { if ((itemEntry->scaleX == 128) && (itemEntry->scaleY == 128)) - view->draw(itemEntry->celRect, clipRect, translatedClipRect, + view->draw(itemEntry->celRect, clipRect, translatedClipRect, itemEntry->loopNo, itemEntry->celNo, 255, 0, view->isSci2Hires()); else - view->drawScaled(itemEntry->celRect, clipRect, translatedClipRect, + view->drawScaled(itemEntry->celRect, clipRect, translatedClipRect, itemEntry->loopNo, itemEntry->celNo, 255, itemEntry->scaleX, itemEntry->scaleY); } } @@ -817,7 +817,7 @@ void GfxFrameout::printPlaneItemList(Console *con, reg_t planeObject) { for (FrameoutList::iterator listIterator = _screenItems.begin(); listIterator != _screenItems.end(); listIterator++) { FrameoutEntry *e = *listIterator; reg_t itemPlane = readSelector(_segMan, e->object, SELECTOR(plane)); - + if (planeObject == itemPlane) { Common::String curItemName = _segMan->getObjectName(e->object); Common::Rect icr = e->celRect; diff --git a/engines/sci/graphics/paint16.cpp b/engines/sci/graphics/paint16.cpp index 89f3625e2c..d20aa80c77 100644 --- a/engines/sci/graphics/paint16.cpp +++ b/engines/sci/graphics/paint16.cpp @@ -559,8 +559,8 @@ reg_t GfxPaint16::kernelDisplay(const char *text, int argc, reg_t *argv) { SciTrackOriginReply originReply; SciWorkaroundSolution solution = trackOriginAndFindWorkaround(0, kDisplay_workarounds, &originReply); if (solution.type == WORKAROUND_NONE) - error("Unknown kDisplay argument (%04x:%04x) from method %s::%s (script %d, localCall %x)", - PRINT_REG(displayArg), originReply.objectName.c_str(), originReply.methodName.c_str(), + error("Unknown kDisplay argument (%04x:%04x) from method %s::%s (script %d, localCall %x)", + PRINT_REG(displayArg), originReply.objectName.c_str(), originReply.methodName.c_str(), originReply.scriptNr, originReply.localCallOffset); assert(solution.type == WORKAROUND_IGNORE); break; diff --git a/engines/sci/sound/drivers/fmtowns.cpp b/engines/sci/sound/drivers/fmtowns.cpp index 6d8bb2e525..21cb2f1e43 100644 --- a/engines/sci/sound/drivers/fmtowns.cpp +++ b/engines/sci/sound/drivers/fmtowns.cpp @@ -52,8 +52,8 @@ public: uint16 _duration; private: - uint8 _id; - uint8 _velo; + uint8 _id; + uint8 _velo; uint8 _program; MidiDriver_FMTowns *_drv; @@ -76,7 +76,7 @@ public: void addChannels(int num); void dropChannels(int num); - + uint8 currentProgram() const; private: @@ -132,7 +132,7 @@ private: TownsMidiPart **_parts; TownsChannel **_out; - + uint8 _masterVolume; bool _soundOn; @@ -590,7 +590,7 @@ void MidiDriver_FMTowns::addMissingChannels() { avlChan -= _parts[i]->_chanMissing; uint8 m = _parts[i]->_chanMissing; _parts[i]->_chanMissing = 0; - _parts[i]->addChannels(m); + _parts[i]->addChannels(m); } else { _parts[i]->_chanMissing -= avlChan; _parts[i]->addChannels(avlChan); @@ -601,7 +601,7 @@ void MidiDriver_FMTowns::addMissingChannels() { void MidiDriver_FMTowns::updateParser() { if (_timerProc) - _timerProc(_timerProcPara); + _timerProc(_timerProcPara); } void MidiDriver_FMTowns::updateChannels() { diff --git a/engines/sci/video/robot_decoder.cpp b/engines/sci/video/robot_decoder.cpp index 608c77136f..0337a8d306 100644 --- a/engines/sci/video/robot_decoder.cpp +++ b/engines/sci/video/robot_decoder.cpp @@ -109,13 +109,13 @@ bool RobotDecoder::loadStream(Common::SeekableReadStream *stream) { } bool RobotDecoder::load(GuiResourceId id) { - // TODO: RAMA's robot 1003 cannot be played (shown at the menu screen) - + // TODO: RAMA's robot 1003 cannot be played (shown at the menu screen) - // its drawn at odd coordinates. SV can't play it either (along with some // others), so it must be some new functionality added in RAMA's robot // videos. Skip it for now. if (g_sci->getGameId() == GID_RAMA && id == 1003) return false; - + // TODO: The robot video in the Lighthouse demo gets stuck if (g_sci->getGameId() == GID_LIGHTHOUSE && id == 16) return false; @@ -247,7 +247,7 @@ void RobotDecoder::readNextPacket() { audioTrack->queueBuffer(g_sci->_audio->getDecodedRobotAudioFrame(_fileStream, audioChunkSize), audioChunkSize * 2); } else { _fileStream->skip(audioChunkSize); - } + } } void RobotDecoder::readHeaderChunk() { diff --git a/engines/sci/video/robot_decoder.h b/engines/sci/video/robot_decoder.h index ebc3262939..437954f7fb 100644 --- a/engines/sci/video/robot_decoder.h +++ b/engines/sci/video/robot_decoder.h @@ -45,13 +45,13 @@ public: bool loadStream(Common::SeekableReadStream *stream); bool load(GuiResourceId id); void close(); - + void setPos(uint16 x, uint16 y) { _pos = Common::Point(x, y); } Common::Point getPos() const { return _pos; } protected: void readNextPacket(); - + private: class RobotVideoTrack : public FixedRateVideoTrack { public: -- cgit v1.2.3 From 17887e24a24695cb47b33a5d0ea38282ea319d88 Mon Sep 17 00:00:00 2001 From: Willem Jan Palenstijn Date: Sun, 30 Sep 2012 18:12:20 +0200 Subject: SCI: Implement kMergePoly Thanks to Walter for creating debugging tools for MergePoly and testing. --- engines/sci/engine/kpathing.cpp | 636 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 619 insertions(+), 17 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/engine/kpathing.cpp b/engines/sci/engine/kpathing.cpp index 002ef1ff07..ee65d5955d 100644 --- a/engines/sci/engine/kpathing.cpp +++ b/engines/sci/engine/kpathing.cpp @@ -31,6 +31,9 @@ #include "common/debug-channels.h" #include "common/list.h" #include "common/system.h" +#include "common/math.h" + +//#define DEBUG_MERGEPOLY namespace Sci { @@ -71,11 +74,25 @@ enum { struct FloatPoint { FloatPoint() : x(0), y(0) {} FloatPoint(float x_, float y_) : x(x_), y(y_) {} + FloatPoint(Common::Point p) : x(p.x), y(p.y) {} Common::Point toPoint() { return Common::Point((int16)(x + 0.5), (int16)(y + 0.5)); } + float operator*(const FloatPoint &p) const { + return x*p.x + y*p.y; + } + FloatPoint operator*(float l) const { + return FloatPoint(l*x, l*y); + } + FloatPoint operator-(const FloatPoint &p) const { + return FloatPoint(x-p.x, y-p.y); + } + float norm() const { + return x*x+y*y; + } + float x, y; }; @@ -135,15 +152,20 @@ public: return _head; } - void insertHead(Vertex *elm) { + void insertAtEnd(Vertex *elm) { if (_head == NULL) { elm->_next = elm->_prev = elm; + _head = elm; } else { elm->_next = _head; elm->_prev = _head->_prev; _head->_prev = elm; elm->_prev->_next = elm; } + } + + void insertHead(Vertex *elm) { + insertAtEnd(elm); _head = elm; } @@ -788,10 +810,10 @@ int PathfindingState::findNearPoint(const Common::Point &p, Polygon *polygon, Co * including the vertices themselves) * Parameters: (const Common::Point &) a, b: The line segment (a, b) * (Vertex *) vertex: The first vertex of the edge - * Returns : (int) FP_OK on success, PF_ERROR otherwise + * Returns : (int) PF_OK on success, PF_ERROR otherwise * (FloatPoint) *ret: The intersection point */ -static int intersection(const Common::Point &a, const Common::Point &b, Vertex *vertex, FloatPoint *ret) { +static int intersection(const Common::Point &a, const Common::Point &b, const Vertex *vertex, FloatPoint *ret) { // Parameters of parametric equations float s, t; // Numerator and denominator of equations @@ -1783,39 +1805,619 @@ reg_t kIntersections(EngineState *s, int argc, reg_t *argv) { } } +// ========================================================================== +// kMergePoly utility functions + +// Compute square of the distance of p to the segment a-b. +static float pointSegDistance(const Common::Point &a, const Common::Point &b, + const Common::Point &p) { + FloatPoint ba(b-a); + FloatPoint pa(p-a); + FloatPoint bp(b-p); + + // Check if the projection of p on the line a-b lies between a and b + if (ba*pa >= 0.0f && ba*bp >= 0.0f) { + // If yes, return the (squared) distance of p to the line a-b: + // translate a to origin, project p and subtract + float linedist = (ba*((ba*pa)/(ba*ba)) - pa).norm(); + + return linedist; + } else { + // If no, return the (squared) distance to either a or b, whichever + // is closest. + + // distance to a: + float adist = pa.norm(); + // distance to b: + float bdist = FloatPoint(p-b).norm(); + + return MIN(adist, bdist); + } +} + +// find intersection between edges of two polygons. +// endpoints count, except v2->_next +static bool segSegIntersect(const Vertex *v1, const Vertex *v2, Common::Point &intp) { + const Common::Point &a = v1->v; + const Common::Point &b = v1->_next->v; + const Common::Point &c = v2->v; + const Common::Point &d = v2->_next->v; + + // First handle the endpoint cases manually + + if (collinear(a, b, c) && collinear(a, b, d)) + return false; + + if (collinear(a, b, c)) { + // a, b, c collinear + // return true/c if c is between a and b + intp = c; + if (a.x != b.x) { + if ((a.x <= c.x && c.x <= b.x) || (b.x <= c.x && c.x <= a.x)) + return true; + } else { + if ((a.y <= c.y && c.y <= b.y) || (b.y <= c.y && c.y <= a.y)) + return true; + } + } + + if (collinear(a, b, d)) { + intp = d; + // a, b, d collinear + // return false/d if d is between a and b + if (a.x != b.x) { + if ((a.x <= d.x && d.x <= b.x) || (b.x <= d.x && d.x <= a.x)) + return false; + } else { + if ((a.y <= d.y && d.y <= b.y) || (b.y <= d.y && d.y <= a.y)) + return false; + } + } + + int len_dc = c.sqrDist(d); + + if (!len_dc) error("zero length edge in polygon"); + + if (pointSegDistance(c, d, a) <= 2.0f) { + intp = a; + return true; + } + + if (pointSegDistance(c, d, b) <= 2.0f) { + intp = b; + return true; + } + + // If not an endpoint, call the generic intersection function + + FloatPoint p; + if (intersection(a, b, v2, &p) == PF_OK) { + intp = p.toPoint(); + return true; + } else { + return false; + } +} + +// For intersecting polygon segments, determine if +// * the v2 edge enters polygon 1 at this intersection: positive return value +// * the v2 edge and the v1 edges are parallel: zero return value +// * the v2 edge exits polygon 1 at this intersection: negative return value +static int intersectDir(const Vertex *v1, const Vertex *v2) { + Common::Point p1 = v1->_next->v - v1->v; + Common::Point p2 = v2->_next->v - v2->v; + return (p1.x*p2.y - p2.x*p1.y); +} + +// Direction of edge in degrees from pos. x-axis, between -180 and 180 +static int edgeDir(const Vertex *v) { + Common::Point p = v->_next->v - v->v; + int deg = (int)Common::rad2deg(atan2(p.y, p.x)); + if (deg < -180) deg += 360; + if (deg > 180) deg -= 360; + return deg; +} + +// For points p1, p2 on the polygon segment v, determine if +// * p1 lies before p2: negative return value +// * p1 and p2 are the same: zero return value +// * p1 lies after p2: positive return value +static int liesBefore(const Vertex *v, const Common::Point &p1, const Common::Point &p2) { + return v->v.sqrDist(p1) - v->v.sqrDist(p2); +} + +// Structure describing an "extension" to the work polygon following edges +// of the polygon being merged. + +// The patch begins on the point intersection1, being the intersection +// of the edges starting at indexw1/vertexw1 on the work polygon, and at +// indexp1/vertexp1 on the polygon being merged. +// It ends with the point intersection2, being the analogous intersection. +struct Patch { + unsigned int indexw1; + unsigned int indexp1; + const Vertex *vertexw1; + const Vertex *vertexp1; + Common::Point intersection1; + + unsigned int indexw2; + unsigned int indexp2; + const Vertex *vertexw2; + const Vertex *vertexp2; + Common::Point intersection2; + + bool disabled; // If true, this Patch was made superfluous by another Patch +}; + + +// Check if the given vertex on the work polygon is bypassed by this patch. +static bool isVertexCovered(const Patch &p, unsigned int wi) { + + // / v (outside) + // ---w1--1----p----w2--2---- + // ^ \ (inside) + if (wi > p.indexw1 && wi <= p.indexw2) + return true; + + // v / (outside) + // ---w2--2----p----w1--1---- + // \ ^ (inside) + if (p.indexw1 > p.indexw2 && (wi <= p.indexw2 || wi > p.indexw1)) + return true; + + // v / (outside) + // ---w1--2--1-------p----- + // w2 \ ^ (inside) + if (p.indexw1 == p.indexw2 && liesBefore(p.vertexw1, p.intersection1, p.intersection2) > 0) + return true; // This patch actually covers _all_ vertices on work + + return false; +} + +// Check if patch p1 makes patch p2 superfluous. +static bool isPatchCovered(const Patch &p1, const Patch &p2) { + + // Same exit and entry points + if (p1.intersection1 == p2.intersection1 && p1.intersection2 == p2.intersection2) + return true; + + // / * v (outside) + // ---p1w1--1----p2w1-1---p1w2--2---- + // ^ * \ (inside) + if (p1.indexw1 < p2.indexw1 && p2.indexw1 < p1.indexw2) + return true; + if (p1.indexw1 > p1.indexw2 && (p2.indexw1 > p1.indexw1 || p2.indexw1 < p1.indexw2)) + return true; + + + // / * v (outside) + // ---p1w1--11----p2w2-2---p1w2--12---- + // ^ * \ (inside) + if (p1.indexw1 < p2.indexw2 && p2.indexw2 < p1.indexw2) + return true; + if (p1.indexw1 > p1.indexw2 && (p2.indexw2 > p1.indexw1 || p2.indexw2 < p1.indexw2)) + return true; + + // Opposite of two above situations + if (p2.indexw1 < p1.indexw1 && p1.indexw1 < p2.indexw2) + return false; + if (p2.indexw1 > p2.indexw2 && (p1.indexw1 > p2.indexw1 || p1.indexw1 < p2.indexw2)) + return false; + + if (p2.indexw1 < p1.indexw2 && p1.indexw2 < p2.indexw2) + return false; + if (p2.indexw1 > p2.indexw2 && (p1.indexw2 > p2.indexw1 || p1.indexw2 < p2.indexw2)) + return false; + + + // The above checks covered the cases where one patch covers the other and + // the intersections of the patches are on different edges. + + // So, if we passed the above checks, we have to check the order of + // intersections on edges. + + + if (p1.indexw1 != p1.indexw2) { + + // / * v (outside) + // ---p1w1--11---21--------p1w2--2---- + // p2w1 ^ * \ (inside) + if (p1.indexw1 == p2.indexw1) + return (liesBefore(p1.vertexw1, p1.intersection1, p2.intersection1) < 0); + + // / * v (outside) + // ---p1w1--11---------p1w2--21---12---- + // ^ p2w1 * \ (inside) + if (p1.indexw2 == p2.indexw1) + return (liesBefore(p1.vertexw2, p1.intersection2, p2.intersection1) > 0); + + // If neither of the above, then the intervals of the polygon + // covered by patch1 and patch2 are disjoint + return false; + } + + // p1w1 == p1w2 + // Also, p1w1/p1w2 isn't strictly between p2 + + + // v / * (outside) + // ---p1w1--12--11-------p2w1-21---- + // p1w2 \ ^ * (inside) + + // v / / (outside) + // ---p1w1--12--21--11--------- + // p1w2 \ ^ ^ (inside) + // p2w1 + if (liesBefore(p1.vertexw1, p1.intersection1, p1.intersection2) > 0) + return (p1.indexw1 != p2.indexw1); + + // CHECKME: This is meaningless if p2w1 != p2w2 ?? + if (liesBefore(p2.vertexw1, p2.intersection1, p2.intersection2) > 0) + return false; + + // CHECKME: This is meaningless if p1w1 != p2w1 ?? + if (liesBefore(p2.vertexw1, p2.intersection1, p1.intersection1) <= 0) + return false; + + // CHECKME: This is meaningless if p1w2 != p2w1 ?? + if (liesBefore(p2.vertexw1, p2.intersection1, p1.intersection2) >= 0) + return false; + + return true; +} + +// Merge a single polygon into the work polygon. +// If there is an intersection between work and polygon, this function +// returns true, and replaces the vertex list of work by an extended version, +// that covers polygon. +// +// NOTE: The strategy used matches qfg1new closely, and is a bit error-prone. +// A more robust strategy would be inserting all intersection points directly +// into both vertex lists as a first pass. This would make finding the merged +// polygon a much more straightforward edge-walk, and avoid cases where SSCI's +// algorithm mixes up the order of multiple intersections on a single edge. +bool mergeSinglePolygon(Polygon &work, const Polygon &polygon) { +#ifdef DEBUG_MERGEPOLY + const Vertex *vertex; + debugN("work:"); + CLIST_FOREACH(vertex, &(work.vertices)) { + debugN(" (%d,%d) ", vertex->v.x, vertex->v.y); + } + debugN("\n"); + debugN("poly:"); + CLIST_FOREACH(vertex, &(polygon.vertices)) { + debugN(" (%d,%d) ", vertex->v.x, vertex->v.y); + } + debugN("\n"); +#endif + uint workSize = work.vertices.size(); + uint polygonSize = polygon.vertices.size(); + + int patchCount = 0; + Patch patchList[8]; + + const Vertex *workv = work.vertices._head; + const Vertex *polyv = polygon.vertices._head; + for (uint wi = 0; wi < workSize; ++wi, workv = workv->_next) { + for (uint pi = 0; pi < polygonSize; ++pi, polyv = polyv->_next) { + Common::Point intersection1; + Common::Point intersection2; + + bool intersects = segSegIntersect(workv, polyv, intersection1); + if (!intersects) + continue; + +#ifdef DEBUG_MERGEPOLY + debug("mergePoly: intersection at work %d, poly %d", wi, pi); +#endif + + if (intersectDir(workv, polyv) >= 0) + continue; + +#ifdef DEBUG_MERGEPOLY + debug("mergePoly: intersection in right direction"); +#endif + + int angle = 0; + int baseAngle = edgeDir(workv); + + // We now found the point where an edge of 'polygon' left 'work'. + // Now find the re-entry point. + + // NOTE: The order in which this searches does not always work + // properly if the correct patch would only use a single partial + // edge of poly. Because it starts at polyv->_next, it will skip + // the correct re-entry and proceed to the next. + + const Vertex *workv2; + const Vertex *polyv2 = polyv->_next; + + intersects = false; + + uint pi2, wi2; + for (pi2 = 0; pi2 < polygonSize; ++pi2, polyv2 = polyv2->_next) { + + int newAngle = edgeDir(polyv2); + + int relAngle = newAngle - baseAngle; + if (relAngle > 180) relAngle -= 360; + if (relAngle < -180) relAngle += 360; + + angle += relAngle; + baseAngle = newAngle; + + workv2 = workv; + for (wi2 = 0; wi2 < workSize; ++wi2, workv2 = workv2->_next) { + intersects = segSegIntersect(workv2, polyv2, intersection2); + if (!intersects) + continue; +#ifdef DEBUG_MERGEPOLY + debug("mergePoly: re-entry intersection at work %d, poly %d", (wi + wi2) % workSize, (pi + 1 + pi2) % polygonSize); +#endif + + if (intersectDir(workv2, polyv2) > 0) { +#ifdef DEBUG_MERGEPOLY + debug("mergePoly: re-entry intersection in right direction, angle = %d", angle); +#endif + break; // found re-entry point + } + + } + + if (intersects) + break; + + } + + if (!intersects || angle < 0) + continue; + + + if (patchCount >= 8) + error("kMergePoly: Too many patches"); + + // convert relative to absolute vertex indices + pi2 = (pi + 1 + pi2) % polygonSize; + wi2 = (wi + wi2) % workSize; + + Patch &newPatch = patchList[patchCount]; + newPatch.indexw1 = wi; + newPatch.vertexw1 = workv; + newPatch.indexp1 = pi; + newPatch.vertexp1 = polyv; + newPatch.intersection1 = intersection1; + + newPatch.indexw2 = wi2; + newPatch.vertexw2 = workv2; + newPatch.indexp2 = pi2; + newPatch.vertexp2 = polyv2; + newPatch.intersection2 = intersection2; + newPatch.disabled = false; + +#ifdef DEBUG_MERGEPOLY + debug("mergePoly: adding patch at work %d, poly %d", wi, pi); +#endif + + if (patchCount == 0) { + patchCount++; + continue; + } + + bool necessary = true; + for (int i = 0; i < patchCount; ++i) { + if (isPatchCovered(patchList[i], newPatch)) { + necessary = false; + break; + } + } + + if (!necessary) + continue; + + patchCount++; + + if (patchCount > 1) { + // check if this patch makes other patches superfluous + for (int i = 0; i < patchCount-1; ++i) + if (isPatchCovered(newPatch, patchList[i])) + patchList[i].disabled = true; + } + } + } + + + if (patchCount == 0) + return false; // nothing changed + + + // Determine merged work by doing a walk over the edges + // of work, crossing over to polygon when encountering a patch. + + Polygon output(0); + + workv = work.vertices._head; + for (uint wi = 0; wi < workSize; ++wi, workv = workv->_next) { + + bool covered = false; + for (int p = 0; p < patchCount; ++p) { + if (patchList[p].disabled) continue; + if (isVertexCovered(patchList[p], wi)) { + covered = true; + break; + } + } + + if (!covered) { + // Add vertex to output + output.vertices.insertAtEnd(new Vertex(workv->v)); + } + + + // CHECKME: Why is this the correct order in which to process + // the patches? (What if two of them start on this line segment + // in the opposite order?) + + for (int p = 0; p < patchCount; ++p) { + + const Patch &patch = patchList[p]; + if (patch.disabled) continue; + if (patch.indexw1 != wi) continue; + if (patch.intersection1 != workv->v) { + // Add intersection point to output + output.vertices.insertAtEnd(new Vertex(patch.intersection1)); + } + + // Add vertices from polygon between vertexp1 (excl) and vertexp2 (incl) + for (polyv = patch.vertexp1->_next; polyv != patch.vertexp2; polyv = polyv->_next) + output.vertices.insertAtEnd(new Vertex(polyv->v)); + + output.vertices.insertAtEnd(new Vertex(patch.vertexp2->v)); + + if (patch.intersection2 != patch.vertexp2->v) { + // Add intersection point to output + output.vertices.insertAtEnd(new Vertex(patch.intersection2)); + } + + // TODO: We could continue after the re-entry point here? + } + } + // Remove last vertex if it's the same as the first vertex + if (output.vertices._head->v == output.vertices._head->_prev->v) + output.vertices.remove(output.vertices._head->_prev); + + + // Slight hack: swap vertex lists of output and work polygons. + SWAP(output.vertices._head, work.vertices._head); + + return true; +} + + /** * This is a quite rare kernel function. An example of when it's called * is in QFG1VGA, after killing any monster. + * + * It takes a polygon, and extends it to also cover any polygons from the + * input list with which it intersects. Any of those polygons so covered + * from the input list are marked by adding 0x10 to their type field. */ reg_t kMergePoly(EngineState *s, int argc, reg_t *argv) { -#if 0 // 3 parameters: raw polygon data, polygon list, list size reg_t polygonData = argv[0]; List *list = s->_segMan->lookupList(argv[1]); - Node *node = s->_segMan->lookupNode(list->first); - // List size is not needed - Polygon *polygon; - int count = 0; + // The size of the "work" point list SSCI uses. We use a dynamic one instead + //reg_t listSize = argv[2]; + + SegmentRef pointList = s->_segMan->dereference(polygonData); + if (!pointList.isValid() || pointList.skipByte) { + warning("kMergePoly: Polygon data pointer is invalid"); + return make_reg(0, 0); + } + + Node *node; + +#ifdef DEBUG_MERGEPOLY + node = s->_segMan->lookupNode(list->first); + while (node) { + draw_polygon(s, node->value, 320, 190); + node = s->_segMan->lookupNode(node->succ); + } + Common::Point prev, first; + prev = first = readPoint(pointList, 0); + for (int i = 1; readPoint(pointList, i).x != 0x7777; i++) { + Common::Point point = readPoint(pointList, i); + draw_line(s, prev, point, 1, 320, 190); + prev = point; + } + draw_line(s, prev, first, 1, 320, 190); + // Update the whole screen + g_sci->_gfxScreen->copyToScreen(); + g_system->updateScreen(); + g_system->delayMillis(1000); +#endif + + // The work polygon which we're going to merge with the polygons in list + Polygon work(0); + + for (int i = 0; true; ++i) { + Common::Point p = readPoint(pointList, i); + if (p.x == POLY_LAST_POINT) + break; + Vertex *vertex = new Vertex(p); + work.vertices.insertAtEnd(vertex); + } + + // TODO: Check behaviour for single-vertex polygons + node = s->_segMan->lookupNode(list->first); while (node) { - polygon = convert_polygon(s, node->value); + Polygon *polygon = convert_polygon(s, node->value); if (polygon) { - count += readSelectorValue(s->_segMan, node->value, SELECTOR(size)); + // CHECKME: Confirm vertex order that convert_polygon and + // fix_vertex_order output. For now, we re-reverse the order since + // convert_polygon reads the vertices reversed, and fix up head. + polygon->vertices.reverse(); + polygon->vertices._head = polygon->vertices._head->_next; + + // Merge this polygon into the work polygon if there is an + // intersection. + bool intersected = mergeSinglePolygon(work, *polygon); + + // If so, flag it + if (intersected) { + writeSelectorValue(s->_segMan, node->value, + SELECTOR(type), polygon->type + 0x10); +#ifdef DEBUG_MERGEPOLY + debugN("Merged polygon: "); + // Iterate over edges + Vertex *vertex; + CLIST_FOREACH(vertex, &(work.vertices)) { + debugN(" (%d,%d) ", vertex->v.x, vertex->v.y); + } + debugN("\n"); +#endif + } } node = s->_segMan->lookupNode(node->succ); } -#endif - // TODO: actually merge the polygon. We return an empty polygon for now. - // In QFG1VGA, you can walk over enemy bodies after killing them, since - // this is a stub. - reg_t output = allocateOutputArray(s->_segMan, 1); + + // Allocate output array + reg_t output = allocateOutputArray(s->_segMan, work.vertices.size()+1); SegmentRef arrayRef = s->_segMan->dereference(output); - writePoint(arrayRef, 0, Common::Point(POLY_LAST_POINT, POLY_LAST_POINT)); - warning("Stub: kMergePoly"); + + // Copy work.vertices into arrayRef + Vertex *vertex; + unsigned int n = 0; + CLIST_FOREACH(vertex, &work.vertices) { + if (vertex == work.vertices._head || vertex->v != vertex->_prev->v) + writePoint(arrayRef, n++, vertex->v); + } + + writePoint(arrayRef, n, Common::Point(POLY_LAST_POINT, POLY_LAST_POINT)); + +#ifdef DEBUG_MERGEPOLY + prev = first = readPoint(arrayRef, 0); + for (int i = 1; readPoint(arrayRef, i).x != 0x7777; i++) { + Common::Point point = readPoint(arrayRef, i); + draw_line(s, prev, point, 3, 320, 190); + prev = point; + } + + draw_line(s, prev, first, 3, 320, 190); + + // Update the whole screen + g_sci->_gfxScreen->copyToScreen(); + g_system->updateScreen(); + if (!g_sci->_gfxPaint16) + g_system->delayMillis(1000); + + debug("kMergePoly done"); +#endif + return output; } -- cgit v1.2.3 From f2fa6a934d838b4edb5386598d1415782e965d26 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Mon, 1 Oct 2012 03:06:59 +0300 Subject: SCI: Fix compilation with MSVC (atan2() was ambiguous) --- engines/sci/engine/kpathing.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines/sci') diff --git a/engines/sci/engine/kpathing.cpp b/engines/sci/engine/kpathing.cpp index ee65d5955d..4061795f82 100644 --- a/engines/sci/engine/kpathing.cpp +++ b/engines/sci/engine/kpathing.cpp @@ -1912,7 +1912,7 @@ static int intersectDir(const Vertex *v1, const Vertex *v2) { // Direction of edge in degrees from pos. x-axis, between -180 and 180 static int edgeDir(const Vertex *v) { Common::Point p = v->_next->v - v->v; - int deg = (int)Common::rad2deg(atan2(p.y, p.x)); + int deg = (int)Common::rad2deg(atan2((double)p.y, (double)p.x)); if (deg < -180) deg += 360; if (deg > 180) deg -= 360; return deg; -- cgit v1.2.3 From ba1307b0ce37dd8f2f3be36da37d1d88de1fb70e Mon Sep 17 00:00:00 2001 From: Willem Jan Palenstijn Date: Fri, 5 Oct 2012 16:40:57 +0200 Subject: SCI: Add kReadNumber fixme Thanks to Walter for noticing this. --- engines/sci/engine/kstring.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'engines/sci') diff --git a/engines/sci/engine/kstring.cpp b/engines/sci/engine/kstring.cpp index c22d7c7b1e..c4db0b891c 100644 --- a/engines/sci/engine/kstring.cpp +++ b/engines/sci/engine/kstring.cpp @@ -165,6 +165,7 @@ reg_t kReadNumber(EngineState *s, int argc, reg_t *argv) { // do clipping. In SQ4 we get the door code in here and that's even // larger than uint32! if (*source == '-') { + // FIXME: Setting result to -1 does _not_ negate the output. result = -1; source++; } -- cgit v1.2.3 From 5f3f21e20ed86f4056544dbb5c3fcd471e20b377 Mon Sep 17 00:00:00 2001 From: Willem Jan Palenstijn Date: Sat, 6 Oct 2012 10:21:57 +0200 Subject: SCI: Fix some console output formatting --- engines/sci/console.cpp | 6 +++--- engines/sci/engine/scriptdebug.cpp | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp index 1889d53480..5ae8245e5a 100644 --- a/engines/sci/console.cpp +++ b/engines/sci/console.cpp @@ -2882,17 +2882,17 @@ bool Console::cmdDisassemble(int argc, const char **argv) { reg_t addr = NULL_REG; if (!obj) { - DebugPrintf("Not an object."); + DebugPrintf("Not an object.\n"); return true; } if (selectorId < 0) { - DebugPrintf("Not a valid selector name."); + DebugPrintf("Not a valid selector name.\n"); return true; } if (lookupSelector(_engine->_gamestate->_segMan, objAddr, selectorId, NULL, &addr) != kSelectorMethod) { - DebugPrintf("Not a method."); + DebugPrintf("Not a method.\n"); return true; } diff --git a/engines/sci/engine/scriptdebug.cpp b/engines/sci/engine/scriptdebug.cpp index d3abb9ff41..5594c0461c 100644 --- a/engines/sci/engine/scriptdebug.cpp +++ b/engines/sci/engine/scriptdebug.cpp @@ -514,7 +514,7 @@ void Kernel::dissectScript(int scriptNumber, Vocabulary *vocab) { if (!objType) { debugN("End of script object (#0) encountered.\n"); - debugN("Classes: %i, Objects: %i, Export: %i,\n Var: %i (all base 10)", + debugN("Classes: %i, Objects: %i, Export: %i,\n Var: %i (all base 10)\n", objectctr[6], objectctr[1], objectctr[7], objectctr[10]); return; } -- cgit v1.2.3 From e38d4f20e8251937fd582e1ebb17568144a41e92 Mon Sep 17 00:00:00 2001 From: Willem Jan Palenstijn Date: Sat, 6 Oct 2012 10:22:08 +0200 Subject: SCI: Fix dissect_script crash with invalid object types --- engines/sci/engine/scriptdebug.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'engines/sci') diff --git a/engines/sci/engine/scriptdebug.cpp b/engines/sci/engine/scriptdebug.cpp index 5594c0461c..b2f22aa985 100644 --- a/engines/sci/engine/scriptdebug.cpp +++ b/engines/sci/engine/scriptdebug.cpp @@ -527,7 +527,8 @@ void Kernel::dissectScript(int scriptNumber, Vocabulary *vocab) { _seeker += objsize; - objectctr[objType]++; + if (objType >= 0 && objType < ARRAYSIZE(objectctr)) + objectctr[objType]++; switch (objType) { case SCI_OBJ_OBJECT: -- cgit v1.2.3 From 8f754ced422eec38766e3d0dd50c82c6fe862f53 Mon Sep 17 00:00:00 2001 From: Willem Jan Palenstijn Date: Sun, 7 Oct 2012 12:21:32 +0200 Subject: SCI: Flip assert This way the assert is checking that the allocated buffer is large enough for the memcpy that follows it. --- engines/sci/engine/script.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines/sci') diff --git a/engines/sci/engine/script.cpp b/engines/sci/engine/script.cpp index 037f4ab700..36d2841b07 100644 --- a/engines/sci/engine/script.cpp +++ b/engines/sci/engine/script.cpp @@ -144,7 +144,7 @@ void Script::load(int script_nr, ResourceManager *resMan) { _heapStart = _buf + _scriptSize; - assert(_bufSize - _scriptSize <= heap->size); + assert(_bufSize - _scriptSize >= heap->size); memcpy(_heapStart, heap->data, heap->size); } -- cgit v1.2.3 From d1e2d61b781aab5a0cc832a05a0981765fc4b0fe Mon Sep 17 00:00:00 2001 From: Willem Jan Palenstijn Date: Sun, 7 Oct 2012 12:24:16 +0200 Subject: SCI: Fix Uhura's Woo conversation option This is bug #3040722. It was trying to open a non-existent submenu. We now force a return after handling the conversation option right before it tries to look for this submenu. --- engines/sci/engine/script_patches.cpp | 44 +++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) (limited to 'engines/sci') diff --git a/engines/sci/engine/script_patches.cpp b/engines/sci/engine/script_patches.cpp index 659c13b13e..8454be514a 100644 --- a/engines/sci/engine/script_patches.cpp +++ b/engines/sci/engine/script_patches.cpp @@ -915,9 +915,53 @@ const uint16 qfg3PatchImportDialog[] = { PATCH_END }; + + +// =========================================================================== +// Patch for the Woo dialog option in Uhura's conversation. Bug #3040722 +// Problem: The Woo dialog option (0xffb5) is negative, and therefore +// treated as an option opening a submenu. This leads to uhuraTell::doChild +// being called, which calls hero::solvePuzzle and then proceeds with +// Teller::doChild to open the submenu. However, there is no actual submenu +// defined for option -75 since -75 does not show up in uhuraTell::keys. +// This will cause Teller::doChild to run out of bounds while scanning through +// uhuraTell::keys. +// Strategy: there is another conversation option in uhuraTell::doChild calling +// hero::solvePuzzle (0xfffc) which does a ret afterwards without going to +// Teller::doChild. We jump to this call of hero::solvePuzzle to get that same +// behaviour. + +const byte qfg3SignatureWooDialog[] = { + 30, + 0x67, 0x12, // pTos 12 (query) + 0x35, 0xb6, // ldi b6 + 0x1a, // eq? + 0x2f, 0x05, // bt 05 + 0x67, 0x12, // pTos 12 (query) + 0x35, 0x9b, // ldi 9b + 0x1a, // eq? + 0x31, 0x0c, // bnt 0c + 0x38, 0x97, 0x02, // pushi 0297 + 0x7a, // push2 + 0x38, 0x0c, 0x01, // pushi 010c + 0x7a, // push2 + 0x81, 0x00, // lag 00 + 0x4a, 0x08, // send 08 + 0x67, 0x12, // pTos 12 (query) + 0x35, 0xb5, // ldi b5 + 0 +}; + +const uint16 qfg3PatchWooDialog[] = { + PATCH_ADDTOOFFSET | +0x29, + 0x33, 0x11, // jmp to 0x6a2, the call to hero::solvePuzzle for 0xFFFC + PATCH_END +}; + // script, description, magic DWORD, adjust const SciScriptSignature qfg3Signatures[] = { { 944, "import dialog continuous calls", 1, PATCH_MAGICDWORD(0x2a, 0x31, 0x0b, 0x7a), -1, qfg3SignatureImportDialog, qfg3PatchImportDialog }, + { 440, "dialog crash when asking about Woo", 1, PATCH_MAGICDWORD(0x67, 0x12, 0x35, 0xb5), -26, qfg3SignatureWooDialog, qfg3PatchWooDialog }, SCI_SIGNATUREENTRY_TERMINATOR }; -- cgit v1.2.3 From a73e3f44add407f28f1b790d11a9317200a2cb39 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Mon, 8 Oct 2012 22:37:47 +0300 Subject: SCI: Add a workaround for the large text boxes in Freddy Pharkas CD Fixes bug #3575276 - "SCI: Freddy Pharkas: Text sometimes drawn/erased incorrectly" --- engines/sci/graphics/ports.cpp | 41 +++++++++++++++++++++++++++++++++++++---- 1 file changed, 37 insertions(+), 4 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/graphics/ports.cpp b/engines/sci/graphics/ports.cpp index 6b4c8180bf..8acdeed763 100644 --- a/engines/sci/graphics/ports.cpp +++ b/engines/sci/graphics/ports.cpp @@ -380,17 +380,50 @@ Window *GfxPorts::addWindow(const Common::Rect &dims, const Common::Rect *restor int16 oldtop = pwnd->dims.top; int16 oldleft = pwnd->dims.left; - if (wmprect.top > pwnd->dims.top) + // WORKAROUND: We also adjust the restore rect when adjusting the window + // rect. + // SSCI does not do this. It wasn't necessary in the original interpreter, + // but it is needed for Freddy Pharkas CD. This version does not normally + // have text, but we allow this by modifying the text/speech setting + // according to what is set in the ScummVM GUI (refer to syncIngameAudioOptions() + // in sci.cpp). Since the text used in Freddy Pharkas CD is quite large in + // some cases, it ends up being offset in order to fit inside the screen, + // but the associated restore rect isn't adjusted accordingly, leading to + // artifacts being left on screen when some text boxes are removed. The + // fact that the restore rect wasn't ever adjusted doesn't make sense, and + // adjusting it shouldn't have any negative side-effects (it *should* be + // adjusted, normally, but SCI doesn't do it). The big text boxes are still + // odd-looking, because the text rect is drawn outside the text window rect, + // but at least there aren't any leftover textbox artifacts left when the + // boxes are removed. Adjusting the text window rect would require more + // invasive changes than this one, thus it's not really worth the effort + // for a feature that was not present in the original game, and its + // implementation is buggy in the first place. + // Adjusting the restore rect properly fixes bug #3575276. + + if (wmprect.top > pwnd->dims.top) { pwnd->dims.moveTo(pwnd->dims.left, wmprect.top); + if (restoreRect) + pwnd->restoreRect.moveTo(pwnd->restoreRect.left, wmprect.top); + } - if (wmprect.bottom < pwnd->dims.bottom) + if (wmprect.bottom < pwnd->dims.bottom) { pwnd->dims.moveTo(pwnd->dims.left, wmprect.bottom - pwnd->dims.bottom + pwnd->dims.top); + if (restoreRect) + pwnd->restoreRect.moveTo(pwnd->restoreRect.left, wmprect.bottom - pwnd->restoreRect.bottom + pwnd->restoreRect.top); + } - if (wmprect.right < pwnd->dims.right) + if (wmprect.right < pwnd->dims.right) { pwnd->dims.moveTo(wmprect.right + pwnd->dims.left - pwnd->dims.right, pwnd->dims.top); + if (restoreRect) + pwnd->restoreRect.moveTo(wmprect.right + pwnd->restoreRect.left - pwnd->restoreRect.right, pwnd->restoreRect.top); + } - if (wmprect.left > pwnd->dims.left) + if (wmprect.left > pwnd->dims.left) { pwnd->dims.moveTo(wmprect.left, pwnd->dims.top); + if (restoreRect) + pwnd->restoreRect.moveTo(wmprect.left, pwnd->restoreRect.top); + } pwnd->rect.moveTo(pwnd->rect.left + pwnd->dims.left - oldleft, pwnd->rect.top + pwnd->dims.top - oldtop); -- cgit v1.2.3 From 676f303a33859d603b8838e185dcfd08f50125d8 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Mon, 8 Oct 2012 23:14:02 +0300 Subject: SCI: Document syncIngameAudioOptions() --- engines/sci/sci.h | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'engines/sci') diff --git a/engines/sci/sci.h b/engines/sci/sci.h index 9f18219cb7..5dcc64462d 100644 --- a/engines/sci/sci.h +++ b/engines/sci/sci.h @@ -228,6 +228,13 @@ public: bool canLoadGameStateCurrently(); bool canSaveGameStateCurrently(); void syncSoundSettings(); + + /** + * Syncs the audio options of the ScummVM launcher (speech, subtitles or + * both) with the in-game audio options of certain CD game versions. For + * some games, this allows simultaneous playing of speech and subtitles, + * even if the original games didn't support this feature. + */ void syncIngameAudioOptions(); const SciGameId &getGameId() const { return _gameId; } -- cgit v1.2.3 From 3a852fb96acf7aaa0fa7a36c04be54b1902cc175 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Mon, 8 Oct 2012 23:49:49 +0300 Subject: SCI: Also add LSL6 CD to syncIngameAudioOptions() --- engines/sci/sci.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'engines/sci') diff --git a/engines/sci/sci.cpp b/engines/sci/sci.cpp index 42ae00b525..15b18ce8e6 100644 --- a/engines/sci/sci.cpp +++ b/engines/sci/sci.cpp @@ -876,6 +876,7 @@ void SciEngine::syncIngameAudioOptions() { if (getGameId() == GID_SQ4 || getGameId() == GID_FREDDYPHARKAS || getGameId() == GID_ECOQUEST + || getGameId() == GID_LSL6 // TODO: The following need script patches for simultaneous speech and subtitles //|| getGameId() == GID_KQ6 //|| getGameId() == GID_LAURABOW2 -- cgit v1.2.3 From dbb09fe984373205453ca7989f9f4aefb245bc4f Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Mon, 8 Oct 2012 23:50:47 +0300 Subject: SCI: Add documentation regarding all SCI1.1 CD games in syncIngameAudioOptions() --- engines/sci/sci.h | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'engines/sci') diff --git a/engines/sci/sci.h b/engines/sci/sci.h index 5dcc64462d..3441e26c01 100644 --- a/engines/sci/sci.h +++ b/engines/sci/sci.h @@ -234,6 +234,19 @@ public: * both) with the in-game audio options of certain CD game versions. For * some games, this allows simultaneous playing of speech and subtitles, * even if the original games didn't support this feature. + * + * SCI1.1 games which support simultaneous speech and subtitles: + * - EcoQuest 1 CD + * - Leisure Suit Larry 6 CD + * SCI1.1 games which don't support simultaneous speech and subtitles, + * and we add this functionality in ScummVM: + * - Space Quest 4 CD + * - Freddy Pharkas CD + * SCI1.1 games which don't support simultaneous speech and subtitles, + * and we haven't added any extra functionality in ScummVM because extra + * script patches are needed: + * - Laura Bow 2 CD + * - King's Quest 6 CD */ void syncIngameAudioOptions(); -- cgit v1.2.3