diff options
author | Travis Howell | 2006-09-28 23:22:07 +0000 |
---|---|---|
committer | Travis Howell | 2006-09-28 23:22:07 +0000 |
commit | 1c6cd9d2498e7d905aed1930ad2cde006a4b1f20 (patch) | |
tree | b3f064324065b3977790b321f7aea37955c1e8f9 | |
parent | 03b3d596b66436f8b3768240a059cadca5dbf8cb (diff) | |
download | scummvm-rg350-1c6cd9d2498e7d905aed1930ad2cde006a4b1f20.tar.gz scummvm-rg350-1c6cd9d2498e7d905aed1930ad2cde006a4b1f20.tar.bz2 scummvm-rg350-1c6cd9d2498e7d905aed1930ad2cde006a4b1f20.zip |
Expand Simon engine more
svn-id: r23994
-rw-r--r-- | engines/simon/debug.cpp | 22 | ||||
-rw-r--r-- | engines/simon/game.cpp | 98 | ||||
-rw-r--r-- | engines/simon/intern.h | 7 | ||||
-rw-r--r-- | engines/simon/items.cpp | 188 | ||||
-rw-r--r-- | engines/simon/midiparser_s1d.cpp | 2 | ||||
-rw-r--r-- | engines/simon/res.cpp | 213 | ||||
-rw-r--r-- | engines/simon/simon.cpp | 274 | ||||
-rw-r--r-- | engines/simon/simon.h | 30 | ||||
-rw-r--r-- | engines/simon/sound.cpp | 3 | ||||
-rw-r--r-- | engines/simon/subroutine.cpp | 116 | ||||
-rw-r--r-- | engines/simon/vga.cpp | 194 |
11 files changed, 833 insertions, 314 deletions
diff --git a/engines/simon/debug.cpp b/engines/simon/debug.cpp index 663f5ad68e..f1fe5759dd 100644 --- a/engines/simon/debug.cpp +++ b/engines/simon/debug.cpp @@ -37,10 +37,18 @@ const byte *SimonEngine::dumpOpcode(const byte *p) { byte opcode; const char *s, *st; - opcode = *p++; - if (opcode == 255) - return NULL; - if (getGameType() == GType_FF) { + if (getGameType() == GType_ELVIRA || getGameType() == GType_ELVIRA2) { + opcode = READ_BE_UINT16(p); + p += 2; + if (opcode = 10000) + return NULL; + } else { + opcode = *p++; + if (opcode == 255) + return NULL; + } + + if (getGameType() == GType_FF || getGameType() == GType_PP) { st = s = feeblefiles_opcode_name_table[opcode]; } else if (getGameType() == GType_SIMON2 && getFeatures() & GF_TALKIE) { st = s = simon2talkie_opcode_name_table[opcode]; @@ -192,7 +200,7 @@ void SimonEngine::dump_video_script(const byte *src, bool one_opcode_only) { return; } - if (getGameType() == GType_FF) { + if (getGameType() == GType_FF || getGameType() == GType_PP) { strn = str = feeblefiles_video_opcode_name_table[opcode]; } else if (getGameType() == GType_SIMON2) { strn = str = simon2_video_opcode_name_table[opcode]; @@ -206,7 +214,7 @@ void SimonEngine::dump_video_script(const byte *src, bool one_opcode_only) { strn++; printf("%.2d: %s ", opcode, strn + 1); - int end = (getGameType() == GType_FF) ? 9999 : 999; + int end = (getGameType() == GType_FF || getGameType() == GType_PP) ? 9999 : 999; for (; *str != '|'; str++) { switch (*str) { case 'x': @@ -344,7 +352,7 @@ void SimonEngine::dump_bitmap(const char *filename, const byte *offs, int w, int state.dh = h; state.y_skip = 0; - if (getGameType() == GType_FF) { + if (getGameType() == GType_FF || getGameType() == GType_PP) { for (i = 0; i != w; i++) { byte *c = vc10_depackColumn(&state); for (j = 0; j != h; j++) { diff --git a/engines/simon/game.cpp b/engines/simon/game.cpp index 9b32fe90b1..4a14c904bc 100644 --- a/engines/simon/game.cpp +++ b/engines/simon/game.cpp @@ -67,10 +67,15 @@ static const ObsoleteGameID obsoleteGameIDsTable[] = { }; static const PlainGameDescriptor simonGames[] = { + {"jumble", "Jumble"}, + {"puzzle", "Puzzle"}, + {"swampy", "Swampy Adventures"}, {"feeble", "The Feeble Files"}, {"simon1", "Simon the Sorcerer 1"}, {"simon2", "Simon the Sorcerer 2"}, {"waxworks", "Waxworks"}, + {"elvira2", "Elvira 2"}, + {"elvira", "Elvira"}, {NULL, NULL} }; @@ -596,8 +601,59 @@ static GameFileDescription WAXWORKS_GameFiles[] = { { "xtbllist", GAME_XTBLFILE, "6c7b3db345d46349a5226f695c03e20f"}, }; +static GameFileDescription ELVIRA2_GameFiles[] = { + { "gamepc", GAME_BASEFILE, "00000000000000000000000000000000"}, + { "icon.dat", GAME_ICONFILE, "00000000000000000000000000000000"}, + { "stripped.txt", GAME_STRFILE, "00000000000000000000000000000000"}, + { "tbllist", GAME_TBLFILE, "00000000000000000000000000000000"}, +}; + +static GameFileDescription ELVIRA_GameFiles[] = { + { "gamepc", GAME_BASEFILE, "9076d507d60cc454df662316438ec843"}, + { "icon.dat", GAME_ICONFILE, "fda48c9da7f3e72d0313e2f5f760fc45"}, + { "tbllist", GAME_TBLFILE, "319f6b227c7822a551f57d24e70f8149"}, +}; + +static GameFileDescription JUMBLE_GameFiles[] = { + { "Gjumble", GAME_BASEFILE, "d54cce46d339038d1a6b74ea213655bc"}, +}; + +static GameFileDescription PUZZLE_GameFiles[] = { + { "Gpuzzle", GAME_BASEFILE, "3f80dac8e0d85401a1058a560fe49ab6"}, +}; + +static GameFileDescription SWAMPY_GameFiles[] = { + { "Gswampy", GAME_BASEFILE, "3a6d4d7b2433e660f2483f9396cc87a2"}, +}; + static GameDescription gameDescriptions[] = { - // Waxworks - English Floopy + // Elvira - English Floppy + { + "elvira", + GType_ELVIRA, + GID_ELVIRA, + "Floppy", + ARRAYSIZE(ELVIRA_GameFiles), + ELVIRA_GameFiles, + GF_OLD_BUNDLE, + Common::EN_ANY, + Common::kPlatformPC, + }, + + // Elvira 2 - English Floppy + { + "elvira2", + GType_ELVIRA2, + GID_ELVIRA2, + "Floppy", + ARRAYSIZE(ELVIRA2_GameFiles), + ELVIRA2_GameFiles, + GF_OLD_BUNDLE, + Common::EN_ANY, + Common::kPlatformPC, + }, + + // Waxworks - English Floppy { "waxworks", GType_WW, @@ -1379,6 +1435,46 @@ static GameDescription gameDescriptions[] = { Common::ES_ESP, Common::kPlatformWindows, }, + + // Jumble + { + "jumble", + GType_PP, + GID_JUMBLE, + "CD", + ARRAYSIZE(JUMBLE_GameFiles), + JUMBLE_GameFiles, + GF_OLD_BUNDLE | GF_TALKIE, + Common::EN_ANY, + Common::kPlatformWindows, + }, + + // Puzzle + { + "puzzle", + GType_PP, + GID_PUZZLE, + "CD", + ARRAYSIZE(PUZZLE_GameFiles), + PUZZLE_GameFiles, + GF_OLD_BUNDLE | GF_TALKIE, + Common::EN_ANY, + Common::kPlatformWindows, + }, + + // Swampy Adventures + { + "swampy", + GType_PP, + GID_SWAMPY, + "CD", + ARRAYSIZE(SWAMPY_GameFiles), + SWAMPY_GameFiles, + GF_OLD_BUNDLE | GF_TALKIE, + Common::EN_ANY, + Common::kPlatformWindows, + }, + }; DetectedGame toDetectedGame(const GameDescription &g) { diff --git a/engines/simon/intern.h b/engines/simon/intern.h index 3d82d6f284..8bdcef29a2 100644 --- a/engines/simon/intern.h +++ b/engines/simon/intern.h @@ -71,6 +71,7 @@ struct Item { int16 adjective; int16 state; /* signed int */ uint16 classFlags; + uint16 itemName; Child *children; Item() { memset(this, 0, sizeof(*this)); } @@ -248,7 +249,11 @@ enum GameIds { GID_FEEBLEFILES_FR, GID_FEEBLEFILES_DE, GID_FEEBLEFILES_IT, - GID_FEEBLEFILES_ES + GID_FEEBLEFILES_ES, + + GID_JUMBLE, + GID_PUZZLE, + GID_SWAMPY }; } // End of namespace Simon diff --git a/engines/simon/items.cpp b/engines/simon/items.cpp index fbe8591de6..e5ff31c5ee 100644 --- a/engines/simon/items.cpp +++ b/engines/simon/items.cpp @@ -288,6 +288,55 @@ void SimonEngine::setupOpcodes() { _numOpcodes = ARRAYSIZE(opcode_table); switch (getGameType()) { + case GType_ELVIRA: + case GType_ELVIRA2: + // Confirmed + opcode_table[48] = &SimonEngine::o_destroy; + opcode_table[51] = &SimonEngine::o_place; + opcode_table[91] = &SimonEngine::o_message; + + opcode_table[70] = &SimonEngine::o1_printLongText; + opcode_table[83] = &SimonEngine::o1_rescan; + opcode_table[98] = &SimonEngine::o1_animate; + opcode_table[99] = &SimonEngine::o1_stopAnimate; + opcode_table[85] = &SimonEngine::oww_whereTo; + opcode_table[105] = &SimonEngine::oww_menu; + opcode_table[106] = &SimonEngine::oww_textMenu; + opcode_table[127] = &SimonEngine::o1_playTune; + opcode_table[148] = &SimonEngine::oww_ifDoorOpen; + opcode_table[179] = &SimonEngine::o_isAdjNoun; + opcode_table[180] = &SimonEngine::o_b2Set; + opcode_table[181] = &SimonEngine::o_b2Clear; + opcode_table[182] = &SimonEngine::o_b2Zero; + opcode_table[183] = &SimonEngine::o_b2NotZero; + + // Code difference, check if triggered + opcode_table[161] = NULL; + opcode_table[162] = NULL; + opcode_table[163] = NULL; + opcode_table[164] = NULL; + opcode_table[165] = NULL; + opcode_table[166] = NULL; + opcode_table[167] = NULL; + opcode_table[168] = NULL; + opcode_table[169] = NULL; + opcode_table[170] = NULL; + opcode_table[171] = NULL; + opcode_table[172] = NULL; + opcode_table[173] = NULL; + opcode_table[174] = NULL; + opcode_table[175] = NULL; + opcode_table[176] = NULL; + opcode_table[177] = NULL; + opcode_table[178] = NULL; + opcode_table[184] = NULL; + opcode_table[185] = NULL; + opcode_table[186] = NULL; + opcode_table[187] = NULL; + opcode_table[188] = NULL; + opcode_table[189] = NULL; + opcode_table[190] = NULL; + break; case GType_WW: // Confirmed opcode_table[70] = &SimonEngine::o1_printLongText; @@ -398,6 +447,50 @@ void SimonEngine::setupOpcodes() { opcode_table[198] = &SimonEngine::o3_b3Zero; opcode_table[199] = &SimonEngine::o3_b3NotZero; break; + case GType_PP: + // Confirmed + opcode_table[30] = &SimonEngine::o4_opcode30; + opcode_table[38] = &SimonEngine::o4_opcode38; + opcode_table[105] = &SimonEngine::o4_loadHiScores; + opcode_table[106] = &SimonEngine::o4_checkHiScores; + + // To check + opcode_table[23] = &SimonEngine::o3_chance; + opcode_table[37] = &SimonEngine::o3_jumpOut; + opcode_table[65] = &SimonEngine::o3_addTextBox; + opcode_table[70] = &SimonEngine::o3_printLongText; + opcode_table[83] = &SimonEngine::o2_rescan; + opcode_table[98] = &SimonEngine::o2_animate; + opcode_table[99] = &SimonEngine::o2_stopAnimate; + opcode_table[107] = &SimonEngine::o3_addBox; + opcode_table[122] = &SimonEngine::o3_oracleTextDown; + opcode_table[123] = &SimonEngine::o3_oracleTextUp; + opcode_table[124] = &SimonEngine::o3_ifTime; + opcode_table[127] = &SimonEngine::o3_playTune; + opcode_table[131] = &SimonEngine::o3_setTime; + opcode_table[132] = &SimonEngine::o3_saveUserGame, + opcode_table[133] = &SimonEngine::o3_loadUserGame; + opcode_table[134] = &SimonEngine::o3_listSaveGames; + opcode_table[135] = &SimonEngine::o3_checkCD; + opcode_table[161] = &SimonEngine::o3_screenTextBox; + opcode_table[165] = &SimonEngine::o3_isAdjNoun; + opcode_table[171] = &SimonEngine::o3_hyperLinkOn; + opcode_table[172] = &SimonEngine::o3_hyperLinkOff; + opcode_table[173] = &SimonEngine::o3_checkPaths; + opcode_table[177] = &SimonEngine::o3_screenTextPObj; + opcode_table[181] = &SimonEngine::o3_mouseOff; + opcode_table[182] = &SimonEngine::o3_loadVideo; + opcode_table[183] = &SimonEngine::o3_playVideo; + opcode_table[187] = &SimonEngine::o3_centreScroll; + opcode_table[188] = &SimonEngine::o2_isShortText; + opcode_table[189] = &SimonEngine::o2_clearMarks; + opcode_table[190] = &SimonEngine::o2_waitMark; + opcode_table[191] = &SimonEngine::o3_resetPVCount; + opcode_table[192] = &SimonEngine::o3_setPathValues; + opcode_table[193] = &SimonEngine::o3_stopClock; + opcode_table[194] = &SimonEngine::o3_restartClock; + opcode_table[195] = &SimonEngine::o3_setColour; + break; default: error("setupOpcodes: Unknown game"); } @@ -588,7 +681,7 @@ void SimonEngine::o_clear() { void SimonEngine::o_let() { // 42: set var - uint var = getVarOrByte(); + uint var = getVarWrapper(); writeVariable(var, getVarOrWord()); } @@ -600,31 +693,31 @@ void SimonEngine::o_add() { void SimonEngine::o_sub() { // 44: sub - uint var = getVarOrByte(); + uint var = getVarWrapper(); writeVariable(var, readVariable(var) - getVarOrWord()); } void SimonEngine::o_addf() { // 45: add f - uint var = getVarOrByte(); + uint var = getVarWrapper(); writeVariable(var, readVariable(var) + getNextVarContents()); } void SimonEngine::o_subf() { // 46: sub f - uint var = getVarOrByte(); + uint var = getVarWrapper(); writeVariable(var, readVariable(var) - getNextVarContents()); } void SimonEngine::o_mul() { // 47: mul - uint var = getVarOrByte(); + uint var = getVarWrapper(); writeVariable(var, readVariable(var) * getVarOrWord()); } void SimonEngine::o_div() { // 48: div - uint var = getVarOrByte(); + uint var = getVarWrapper(); int value = getVarOrWord(); if (value == 0) error("o_div: Division by zero"); @@ -633,13 +726,13 @@ void SimonEngine::o_div() { void SimonEngine::o_mulf() { // 49: mul f - uint var = getVarOrByte(); + uint var = getVarWrapper(); writeVariable(var, readVariable(var) * getNextVarContents()); } void SimonEngine::o_divf() { // 50: div f - uint var = getVarOrByte(); + uint var = getVarWrapper(); int value = getNextVarContents(); if (value == 0) error("o_divf: Division by zero"); @@ -648,7 +741,7 @@ void SimonEngine::o_divf() { void SimonEngine::o_mod() { // 51: mod - uint var = getVarOrByte(); + uint var = getVarWrapper(); int value = getVarOrWord(); if (value == 0) error("o_mod: Division by zero"); @@ -657,7 +750,7 @@ void SimonEngine::o_mod() { void SimonEngine::o_modf() { // 52: mod f - uint var = getVarOrByte(); + uint var = getVarWrapper(); int value = getNextVarContents(); if (value == 0) error("o_modf: Division by zero"); @@ -666,7 +759,7 @@ void SimonEngine::o_modf() { void SimonEngine::o_random() { // 53: random - uint var = getVarOrByte(); + uint var = getVarWrapper(); uint value = (uint16)getVarOrWord(); // Disable random in simon1amiga for now @@ -765,8 +858,13 @@ void SimonEngine::o_setShortText() { // 66: set item name uint var = getVarOrByte(); uint stringId = getNextStringID(); - if (var < _numTextBoxes) + if (var < _numTextBoxes) { _stringIdArray2[var] = stringId; + if (getGameType() == GType_PP) { + getVarOrWord(); + getVarOrWord(); + } + } } void SimonEngine::o_setLongText() { @@ -1270,22 +1368,22 @@ void SimonEngine::o_getItem() { void SimonEngine::o_bSet() { // 153: set bit - setBitFlag(getVarOrByte(), true); + setBitFlag(getVarWrapper(), true); } void SimonEngine::o_bClear() { // 154: clear bit - setBitFlag(getVarOrByte(), false); + setBitFlag(getVarWrapper(), false); } void SimonEngine::o_bZero() { // 155: is bit clear - setScriptCondition(!getBitFlag(getVarOrByte())); + setScriptCondition(!getBitFlag(getVarWrapper())); } void SimonEngine::o_bNotZero() { // 156: is bit set - uint bit = getVarOrByte(); + uint bit = getVarWrapper(); // WORKAROUND: Fix for glitch in some versions if (getGameType() == GType_SIMON1 && _subroutine == 2962 && bit == 63) { @@ -1355,7 +1453,7 @@ void SimonEngine::o_screenTextMsg() { speechId = (uint16)getNextWord(); } - if (getGameType() == GType_FF) + if (getGameType() == GType_FF || getGameType() == GType_PP) vgaSpriteId = 1; tl = getTextLocation(vgaSpriteId); @@ -2263,29 +2361,67 @@ void SimonEngine::o3_b3NotZero() { } // ----------------------------------------------------------------------- +// Puzzle Pack Opcodes +// ----------------------------------------------------------------------- + +void SimonEngine::o4_opcode30() { + getNextItemPtr(); +} + +void SimonEngine::o4_opcode38() { + getVarOrByte(); + getNextItemPtr(); +} + +void SimonEngine::o4_loadHiScores() { + getVarOrByte(); +} + +void SimonEngine::o4_checkHiScores() { + getVarOrByte(); + getVarOrByte(); +} + +// ----------------------------------------------------------------------- int SimonEngine::runScript() { - byte opcode; + int opcode; bool flag; do { if (_continousMainScript) dumpOpcode(_codePtr); - opcode = getByte(); - if (opcode == 0xFF) - return 0; + if (getGameType() == GType_ELVIRA || getGameType() == GType_ELVIRA2) { + opcode = getVarOrWord(); + if (opcode == 10000) + return 0; + } else { + opcode = getByte(); + if (opcode == 0xFF) + return 0; + } + debug(1, "runScript: opcode %d", opcode); if (_runScriptReturn1) return 1; /* Invert condition? */ flag = false; - if (opcode == 0) { - flag = true; - opcode = getByte(); - if (opcode == 0xFF) - return 0; + if (getGameType() == GType_ELVIRA || getGameType() == GType_ELVIRA2) { + if (opcode == 203) { + flag = true; + opcode = getVarOrWord(); + if (opcode == 10000) + return 0; + } + } else { + if (opcode == 0) { + flag = true; + opcode = getByte(); + if (opcode == 0xFF) + return 0; + } } setScriptCondition(true); diff --git a/engines/simon/midiparser_s1d.cpp b/engines/simon/midiparser_s1d.cpp index 7df057a104..2b58c9ffa1 100644 --- a/engines/simon/midiparser_s1d.cpp +++ b/engines/simon/midiparser_s1d.cpp @@ -115,7 +115,7 @@ void MidiParser_S1D::parseNextEvent(EventInfo &info) { // OTherwise fall through to default. default: - warning("MidiParser_S1D: Unexpected byte 0x%02X found", (int) info.command()); + debug(3, "MidiParser_S1D: Unexpected byte 0x%02X found", (int) info.command()); break; } } diff --git a/engines/simon/res.cpp b/engines/simon/res.cpp index 212b66bcbe..03a43e02e2 100644 --- a/engines/simon/res.cpp +++ b/engines/simon/res.cpp @@ -40,6 +40,30 @@ using Common::File; namespace Simon { // Script opcodes to load into memory +static const char *const opcode_arg_table_elvira[300] = { + "I ", "I ", "I ", "I ", "I ", "I ", "I ", "I ", "II ", "II ", "II ", "II ", "F ", "F ", "FN ", /* EQ", */ + "FN ", "FN ", "FN ", "FF ", "FF ", "FF ", "FF ", "II ", "II ", "a ", "a ", "n ", "n ", "p ", /* PREP", */ + "N ", "I ", "I ", "I ", "I ", "IN ", "IB ", "IB ", "II ", "IB ", "N ", " ", " ", " ", "I ", /* GET", */ + "I ","I ","I ", "I ","I ","I ", "II ","II ","II ","II ","IBF ", "FIB ", "FF ", "N ", "NI ", + "IF ", "F ", "F ", "IB ", "IB ", "FN ", "FN ", "FN ", "FF ", "FF ", "FN ", "FN ", "FF ", "FF ", /* DIVF", */ + "FN ", "FF ", "FN ", "F ", "I ", "IN ", "IN ", "IB ", "IB ", "IB ", "IB ", "II ", "I ", "I ", /* DEC", */ + "IN ", "T ", "F ", " ", "T ", "T ", "I ", "I ", " ", " ", "T ", " ", " ", " ", " ", " ", "T ", /* PARSE", */ + " ", "N ", "INN ", "II ", "II ", "ITN ", "ITIN ", "ITIN ", "I3 ", "IN ", "I ", "I ", "Ivnn ", + "vnn ", "Ivnn ", "NN ", "IT ", "INN ", " ", "N ", "N ", "N ", "T ", "v ", " ", " ", " ", " ", + "FN ", "I ", "TN ", "IT ", "II ", "I ", " ", "N ", "I ", " ", "I ", "NI ", "I ", "I ", "T ", /* BECOME", */ + "I ", "I ", "N ", "N ", " ", "N ", "IF ", "IF ", "IF ", "IF ", "IF ", "IF ", "T ", "IB ", + "IB ", "IB ", "I ", " ", "vnnN ", "Ivnn ", "T ", "T ", "T ", "IF ", " ", " ", " ", "Ivnn ", + "IF ", "INI ", "INN ", "IN ", "II ", "IFF ", "IIF ", "I ", "II ", "I ", "I ", "IN ", "IN ", /* ROPENEXT", */ + "II ", "II ", "II ", "II ", "IIN ", "IIN ", "IN ", "II ", "IN ", "IN ", "T ", "vanpan ", + "vIpI ", "T ", "T ", " ", " ", "IN ", "IN ", "IN ", "IN ", "N ", "INTTT ", "ITTT ", + "ITTT ", "I ", "I ", "IN ", "I ", " ", "F ", "NN ", "INN ", "INN ", "INNN ", "TF ", "NN ", /* PICTURE", */ + "N ", "NNNNN ", "N ", " ", "NNNNNNN ", "N ", " ", "N ", "NN ", "N ", "NNNNNIN ", "N ", "N ", /* ENABLEBOX", */ + "N ", "NNN ", "NNNN ", "INNN ", "IN ", "IN ", "TT ", "I ", "I ", "I ", "TTT ", "IN ", "IN ", /* UNSETCLASS",*/ + "FN ", "FN ", "FN ", "N ", "N ", "N ", "NI ", " ", " ", "N ", "I ", "INN ", "NN ", "N ", /* WAITENDTUNE */ + "N ", "Nan ", "NN ", " ", " ", " ", " ", " ", " ", " ", "IF ", "N ", " ", " ", " ", "II ", /* PLACENOICONS*/ + " ", "NI ","N ", +}; + static const char *const opcode_arg_table_waxworks[256] = { " ", "I ", "I ", "I ", "I ", "I ", "I ", "II ", "II ", "II ", "II ", "B ", "B ", "BN ", "BN ", "BN ", "BN ", "BB ", "BB ", "BB ", "BB ", "II ", "II ", "N ", "I ", "I ", "I ", "IN ", "IB ", @@ -142,22 +166,39 @@ static const char *const opcode_arg_table_feeblefiles[256] = { " ", " ", "BT ", " ", "B ", " ", "BBBB ", " ", " ", "BBBB ", "B ", "B ", "B ", "B " }; +static const char *const opcode_arg_table_puzzlepack[256] = { + " ", "I ", "I ", "I ", "I ", "I ", "I ", "II ", "II ", "II ", "II ", "N ", "N ", "NN ", "NN ", + "NN ", "NN ", "NN ", "NN ", "NN ", "NN ", "II ", "II ", "N ", "I ", "I ", "I ", "IN ", "IB ", + "II ", "I ", "I ", "II ", "II ", "IBN ", "NIB ", "NN ", "B ", "BI ", "IN ", "N ", "N ", "NN ", + "NN ", "NN ", "NN ", "NN ", "NN ", "NN ", "NN ", "NN ", "NN ", "NN ", "NN ", "B ", "I ", "IB ", + "IB ", "II ", "I ", "I ", "IN ", "N ", "T ", "T ", "NNNNNB ", "BTNN ", "BTS ", "T ", " ", "B ", + "N ", "IBN ", "I ", "I ", "I ", "NN ", " ", " ", "IT ", "II ", "I ", "B ", " ", "IB ", "IBB ", + "IIB ", "T ", " ", " ", "IB ", "IB ", "IB ", "B ", "BB ", "IBB ", "NB ", "N ", "NNBNNN ", "NN ", + " ", "BNNNNNN ", "B ", " ", "B ", "B ", "BB ", "NNNNNIN ", "N ", "N ", "N ", "NNN ", "NBNN ", + "IBNN ", "IB ", "IB ", "IB ", "IB ", "N ", "N ", "N ", "BI ", " ", " ", "N ", "I ", "IBB ", + "NNB ", "N ", "N ", "Ban ", " ", " ", " ", " ", " ", "IN ", "B ", " ", "II ", " ", "BI ", + "N ", "I ", "IB ", "IB ", "IB ", "IB ", "IB ", "IB ", "IB ", "BI ", "BB ", "N ", "N ", "N ", + "N ", "IBN ", "IBN ", "IN ", "B ", "BNNN ", "BBTS ", "N ", " ", "Ian ", "B ", "B ", "B ", "B ", + "T ", "N ", " ", " ", "I ", " ", " ", "BBI ", "NNBB ", "BBB ", " ", " ", "T ", " ", "N ", "N ", + " ", " ", "BT ", " ", "B ", " ", "BBBB ", " ", " ", "BBBB ", "B ", "B ", "B ", "B " +}; + uint16 SimonEngine::to16Wrapper(uint value) { - if (getGameType() == GType_FF) + if (getGameType() == GType_FF || getGameType() == GType_PP) return TO_LE_16(value); else return TO_BE_16(value); } uint16 SimonEngine::readUint16Wrapper(const void *src) { - if (getGameType() == GType_FF) + if (getGameType() == GType_FF || getGameType() == GType_PP) return READ_LE_UINT16(src); else return READ_BE_UINT16(src); } uint32 SimonEngine::readUint32Wrapper(const void *src) { - if (getGameType() == GType_FF) + if (getGameType() == GType_FF || getGameType() == GType_PP) return READ_LE_UINT32(src); else return READ_BE_UINT32(src); @@ -214,15 +255,21 @@ void SimonEngine::loadOffsets(const char *filename, int number, uint32 &file, ui int SimonEngine::allocGamePcVars(File *in) { uint item_array_size, item_array_inited, stringtable_num; uint32 version; - uint i; + uint i, start; item_array_size = in->readUint32BE(); version = in->readUint32BE(); item_array_inited = in->readUint32BE(); stringtable_num = in->readUint32BE(); - item_array_inited += 2; // first two items are predefined - item_array_size += 2; + if (getGameType() == GType_ELVIRA || getGameType() == GType_ELVIRA2) { + item_array_inited = item_array_size; + start = 0; + } else { + item_array_inited += 2; // first two items are predefined + item_array_size += 2; + start = 1; + } if (version != 0x80) error("allocGamePcVars: Not a runtime database"); @@ -234,7 +281,7 @@ int SimonEngine::allocGamePcVars(File *in) { _itemArraySize = item_array_size; _itemArrayInited = item_array_inited; - for (i = 1; i < item_array_inited; i++) { + for (i = start; i < item_array_inited; i++) { _itemArrayPtr[i] = (Item *)allocateItem(sizeof(Item)); } @@ -261,7 +308,14 @@ void SimonEngine::loadGamePcFile() { createPlayer(); readGamePcText(&in); - for (i = 2; i < num_inited_objects; i++) { + int start; + if (getGameType() == GType_ELVIRA || getGameType() == GType_ELVIRA2) { + start = 0; + } else { + start = 2; + } + + for (i = start; i < num_inited_objects; i++) { readItemFromGamePc(&in, _itemArrayPtr[i]); } @@ -269,6 +323,9 @@ void SimonEngine::loadGamePcFile() { in.close(); + if (getGameId() == GID_SWAMPY) + return; + /* Read list of TABLE resources */ in.open(getFileName(GAME_TBLFILE)); if (in.isOpen() == false) { @@ -288,7 +345,7 @@ void SimonEngine::loadGamePcFile() { _tablesHeapPtrOrg = _tablesHeapPtr; _tablesHeapCurPosOrg = _tablesHeapCurPos; - if (getGameType() == GType_FF) + if (getGameType() == GType_ELVIRA || getGameType() == GType_FF || getGameType() == GType_PP) return; /* Read list of TEXT resources */ @@ -355,15 +412,32 @@ void SimonEngine::readGamePcText(Common::File *in) { void SimonEngine::readItemFromGamePc(Common::File *in, Item *item) { uint32 type; - item->adjective = in->readUint16BE(); - item->noun = in->readUint16BE(); - item->state = in->readUint16BE(); - item->sibling = (uint16)fileReadItemID(in); - item->child = (uint16)fileReadItemID(in); - item->parent = (uint16)fileReadItemID(in); - in->readUint16BE(); - item->classFlags = in->readUint16BE(); - item->children = NULL; + if (getGameType() == GType_ELVIRA || getGameType() == GType_ELVIRA2) { + item->itemName = (uint16)in->readUint32BE(); + item->adjective = in->readUint16BE(); + item->noun = in->readUint16BE(); + item->state = in->readUint16BE(); + in->readUint16BE(); + item->sibling = (uint16)fileReadItemID(in); + item->child = (uint16)fileReadItemID(in); + item->parent = (uint16)fileReadItemID(in); + in->readUint16BE(); + in->readUint16BE(); + in->readUint16BE(); + item->classFlags = in->readUint16BE(); + item->children = NULL; + } else { + item->adjective = in->readUint16BE(); + item->noun = in->readUint16BE(); + item->state = in->readUint16BE(); + item->sibling = (uint16)fileReadItemID(in); + item->child = (uint16)fileReadItemID(in); + item->parent = (uint16)fileReadItemID(in); + in->readUint16BE(); + item->classFlags = in->readUint16BE(); + item->children = NULL; + } + type = in->readUint32BE(); while (type) { @@ -375,24 +449,31 @@ void SimonEngine::readItemFromGamePc(Common::File *in, Item *item) { void SimonEngine::readItemChildren(Common::File *in, Item *item, uint type) { if (type == 1) { - uint fr1 = in->readUint16BE(); - uint fr2 = in->readUint16BE(); - uint i, size; - uint j, k; - SubRoom *subRoom; - - size = SubRoom_SIZE; - for (i = 0, j = fr2; i != 6; i++, j >>= 2) - if (j & 3) - size += sizeof(subRoom->roomExit[0]); - - subRoom = (SubRoom *)allocateChildBlock(item, 1, size); - subRoom->subroutine_id = fr1; - subRoom->roomExitStates = fr2; - - for (i = k = 0, j = fr2; i != 6; i++, j >>= 2) - if (j & 3) - subRoom->roomExit[k++] = (uint16)fileReadItemID(in); + if (getGameType() == GType_ELVIRA || getGameType() == GType_ELVIRA2) { + // FIXME + in->readUint32BE(); + in->readUint32BE(); + in->readUint16BE(); + } else { + uint fr1 = in->readUint16BE(); + uint fr2 = in->readUint16BE(); + uint i, size; + uint j, k; + SubRoom *subRoom; + + size = SubRoom_SIZE; + for (i = 0, j = fr2; i != 6; i++, j >>= 2) + if (j & 3) + size += sizeof(subRoom->roomExit[0]); + + subRoom = (SubRoom *)allocateChildBlock(item, 1, size); + subRoom->subroutine_id = fr1; + subRoom->roomExitStates = fr2; + + for (i = k = 0, j = fr2; i != 6; i++, j >>= 2) + if (j & 3) + subRoom->roomExit[k++] = (uint16)fileReadItemID(in); + } } else if (type == 2) { uint32 fr = in->readUint32BE(); uint i, k, size; @@ -415,6 +496,24 @@ void SimonEngine::readItemChildren(Common::File *in, Item *item, uint type) { subObject->objectFlagValue[k++] = in->readUint16BE(); subObject->objectName = (uint16)in->readUint32BE(); + } else if (type == 4) { + // FIXME + fileReadItemID(in); + fileReadItemID(in); + fileReadItemID(in); + fileReadItemID(in); + fileReadItemID(in); + fileReadItemID(in); + fileReadItemID(in); + fileReadItemID(in); + fileReadItemID(in); + fileReadItemID(in); + fileReadItemID(in); + fileReadItemID(in); + } else if (type == 7) { + // FIXME + in->readUint16BE(); + in->readUint16BE(); } else if (type == 8) { SubUserChain *chain = (SubUserChain *)allocateChildBlock(item, 8, sizeof(SubUserChain)); chain->chChained = (uint16)fileReadItemID(in); @@ -423,6 +522,17 @@ void SimonEngine::readItemChildren(Common::File *in, Item *item, uint type) { setUserFlag(item, 1, in->readUint16BE()); setUserFlag(item, 2, in->readUint16BE()); setUserFlag(item, 3, in->readUint16BE()); + if (getGameType() == GType_ELVIRA || getGameType() == GType_ELVIRA2) { + setUserFlag(item, 4, in->readUint16BE()); + setUserFlag(item, 5, in->readUint16BE()); + setUserFlag(item, 6, in->readUint16BE()); + setUserFlag(item, 7, in->readUint16BE()); + // FIXME + fileReadItemID(in); + fileReadItemID(in); + fileReadItemID(in); + fileReadItemID(in); + } } else if (type == 255) { SubUserInherit *inherit = (SubUserInherit *)allocateChildBlock(item, 255, sizeof(SubUserInherit)); inherit->inMaster = (uint16)fileReadItemID(in); @@ -441,11 +551,13 @@ uint fileReadItemID(Common::File *in) { byte *SimonEngine::readSingleOpcode(Common::File *in, byte *ptr) { int i, l; const char *string_ptr; - uint val; + uint opcode, val; const char *const *table; - if (getGameType() == GType_FF) + if (getGameType() == GType_PP) + table = opcode_arg_table_puzzlepack; + else if (getGameType() == GType_FF) table = opcode_arg_table_feeblefiles; else if (getGameType() == GType_SIMON2 && (getFeatures() & GF_TALKIE)) table = opcode_arg_table_simon2win; @@ -455,12 +567,20 @@ byte *SimonEngine::readSingleOpcode(Common::File *in, byte *ptr) { table = opcode_arg_table_simon1win; else if (getGameType() == GType_SIMON1) table = opcode_arg_table_simon1dos; - else /* if (getGameType() == GType_WW) */ + else if (getGameType() == GType_WW) table = opcode_arg_table_waxworks; + else + table = opcode_arg_table_elvira; i = 0; + if (getGameType() == GType_ELVIRA || getGameType() == GType_ELVIRA2) { + opcode = READ_BE_UINT16(ptr); + ptr += 2; + } else { + opcode = *ptr++; + } - string_ptr = table[*ptr++]; + string_ptr = table[opcode]; if (!string_ptr) error("Unable to locate opcode table. Perhaps you are using the wrong game target?"); @@ -469,22 +589,31 @@ byte *SimonEngine::readSingleOpcode(Common::File *in, byte *ptr) { return ptr; l = string_ptr[i++]; + switch (l) { + case 'F': case 'N': case 'S': case 'a': case 'n': case 'p': case 'v': + case '3': val = in->readUint16BE(); *ptr++ = val >> 8; *ptr++ = val & 255; break; case 'B': - *ptr++ = in->readByte(); - if (ptr[-1] == 0xFF) { + if (getGameType() == GType_ELVIRA || getGameType() == GType_ELVIRA2) { + val = in->readUint16BE(); + *ptr++ = val >> 8; + *ptr++ = val & 255; + } else { *ptr++ = in->readByte(); + if (ptr[-1] == 0xFF) { + *ptr++ = in->readByte(); + } } break; diff --git a/engines/simon/simon.cpp b/engines/simon/simon.cpp index 993039dc4d..85a3bf5349 100644 --- a/engines/simon/simon.cpp +++ b/engines/simon/simon.cpp @@ -317,8 +317,8 @@ SimonEngine::SimonEngine(OSystem *syst) memset(_bitArrayTwo, 0, sizeof(_bitArrayTwo)); memset(_bitArrayThree, 0, sizeof(_bitArrayThree)); - memset(_variableArray, 0, sizeof(_variableArray)); - memset(_variableArray2, 0, sizeof(_variableArray2)); + _variableArray = 0; + _variableArray2 = 0; _variableArrayPtr = 0; memset(_windowArray, 0, sizeof(_windowArray)); @@ -415,9 +415,7 @@ int SimonEngine::init() { return -1; } - setupOpcodes(); - - if (getGameType() == GType_FF) { + if (getGameType() == GType_FF || getGameType() == GType_PP) { _screenWidth = 640; _screenHeight = 480; } else { @@ -426,7 +424,7 @@ int SimonEngine::init() { } _system->beginGFXTransaction(); - initCommonGFX(getGameType() == GType_FF); + initCommonGFX(getGameType() == GType_FF || getGameType() == GType_PP); _system->initSize(_screenWidth, _screenHeight); _system->endGFXTransaction(); @@ -439,7 +437,7 @@ int SimonEngine::init() { // Setup midi driver MidiDriver *driver = 0; - if (getGameType() == GType_FF || getGameId() == GID_SIMON1CD32) { + if (getGameType() == GType_FF || getGameType() == GType_PP || getGameId() == GID_SIMON1CD32) { driver = MidiDriver::createMidi(MD_NULL); _native_mt32 = false; } else { @@ -462,21 +460,67 @@ int SimonEngine::init() { if (ConfMan.hasKey("music_mute") && ConfMan.getBool("music_mute") == 1) midi.pause(_musicPaused ^= 1); - _currentMouseCursor = 255; - _currentMouseAnim = 255; + // allocate buffers + _backGroundBuf = (byte *)calloc(_screenWidth * _screenHeight, 1); + _frontBuf = (byte *)calloc(_screenWidth * _screenHeight, 1); + _backBuf = (byte *)calloc(_screenWidth * _screenHeight, 1); + if (getGameType() == GType_FF || getGameType() == GType_PP) + _scaleBuf = (byte *)calloc(_screenWidth * _screenHeight, 1); - _frameRate = 1; + setupGame(); - _lastMusicPlayed = -1; - _nextMusicToPlay = -1; + _debugger = new Debugger(this); + _moviePlay = new MoviePlayer(this, _mixer); + _sound = new Sound(this, gss, _mixer); - _noOverWrite = 0xFFFF; + if (ConfMan.hasKey("sfx_mute") && ConfMan.getBool("sfx_mute") == 1) { + if (getGameId() == GID_SIMON1DOS) + midi._enable_sfx ^= 1; + else + _sound->effectsPause(_effectsPaused ^= 1); + } - _stringIdLocalMin = 1; + _language = Common::parseLanguage(ConfMan.get("language")); - _variableArrayPtr = _variableArray; + if (getGameType() == GType_PP) { + _speech = false; + _subtitles = false; + } else if (getFeatures() & GF_TALKIE) { + _speech = !ConfMan.getBool("speech_mute"); + _subtitles = ConfMan.getBool("subtitles"); - if (getGameType() == GType_FF) { + if (getGameType() == GType_SIMON1) { + // English and German versions don't have full subtitles + if (_language == Common::EN_ANY || _language == Common::DE_DEU) + _subtitles = false; + // Other versions require speech to be enabled + else + _speech = true; + } + + // Default to speech only, if both speech and subtitles disabled + if (!_speech && !_subtitles) + _speech = true; + } else { + _speech = false; + _subtitles = true; + } + + _debugMode = (gDebugLevel >= 0); + if (gDebugLevel == 2) + _continousMainScript = true; + if (gDebugLevel == 3) + _continousVgaScript = true; + if (gDebugLevel == 4) + _startMainScript = true; + if (gDebugLevel == 5) + _startVgaScript = true; + + return 0; +} + +void SimonEngine::setupGame() { + if (getGameType() == GType_PP) { gss = PTR(feeblefiles_settings); _numTextBoxes = 40; _numVideoOpcodes = 85; @@ -487,6 +531,19 @@ int SimonEngine::init() { #endif _tableMemSize = 200000; _vgaBaseDelay = 5; + _numVars = 2048; + } else if (getGameType() == GType_FF) { + gss = PTR(feeblefiles_settings); + _numTextBoxes = 40; + _numVideoOpcodes = 85; +#ifndef PALMOS_68K + _vgaMemSize = 7000000; +#else + _vgaMemSize = gVars->memory[kMemSimon2Games]; +#endif + _tableMemSize = 200000; + _vgaBaseDelay = 5; + _numVars = 256; } else if (getGameType() == GType_SIMON2) { gss = PTR(simon2_settings); _tableIndexBase = 1580 / 4; @@ -506,6 +563,7 @@ int SimonEngine::init() { _musicIndexBase = 1128 / 4; _soundIndexBase = 1660 / 4; _vgaBaseDelay = 1; + _numVars = 256; } else { gss = PTR(simon1_settings); _tableIndexBase = 1576 / 4; @@ -517,69 +575,36 @@ int SimonEngine::init() { #else _vgaMemSize = gVars->memory[kMemSimon1Games]; #endif - _tableMemSize = 50000; + _tableMemSize = 150000; _musicIndexBase = 1316 / 4; _soundIndexBase = 0; _vgaBaseDelay = 1; + _numVars = 256; } - // allocate buffers - _backGroundBuf = (byte *)calloc(_screenWidth * _screenHeight, 1); - _frontBuf = (byte *)calloc(_screenWidth * _screenHeight, 1); - _backBuf = (byte *)calloc(_screenWidth * _screenHeight, 1); - if (getGameType() == GType_FF) - _scaleBuf = (byte *)calloc(_screenWidth * _screenHeight, 1); - allocItemHeap(); allocTablesHeap(); - setZoneBuffers(); + _variableArray = (int16 *)calloc(_numVars, sizeof(int16)); + _variableArray2 = (int16 *)calloc(_numVars, sizeof(int16)); - _debugger = new Debugger(this); - _moviePlay = new MoviePlayer(this, _mixer); - _sound = new Sound(this, gss, _mixer); + setupOpcodes(); - if (ConfMan.hasKey("sfx_mute") && ConfMan.getBool("sfx_mute") == 1) { - if (getGameId() == GID_SIMON1DOS) - midi._enable_sfx ^= 1; - else - _sound->effectsPause(_effectsPaused ^= 1); - } + setZoneBuffers(); - _language = Common::parseLanguage(ConfMan.get("language")); + _currentMouseCursor = 255; + _currentMouseAnim = 255; - if (getFeatures() & GF_TALKIE) { - _speech = !ConfMan.getBool("speech_mute"); - _subtitles = ConfMan.getBool("subtitles"); + _frameRate = 1; - if (getGameType() == GType_SIMON1) { - // English and German versions don't have full subtitles - if (_language == Common::EN_ANY || _language == Common::DE_DEU) - _subtitles = false; - // Other versions require speech to be enabled - else - _speech = true; - } + _lastMusicPlayed = -1; + _nextMusicToPlay = -1; - // Default to speech only, if both speech and subtitles disabled - if (!_speech && !_subtitles) - _speech = true; - } else { - _speech = false; - _subtitles = true; - } + _noOverWrite = 0xFFFF; - _debugMode = (gDebugLevel >= 0); - if (gDebugLevel == 2) - _continousMainScript = true; - if (gDebugLevel == 3) - _continousVgaScript = true; - if (gDebugLevel == 4) - _startMainScript = true; - if (gDebugLevel == 5) - _startVgaScript = true; + _stringIdLocalMin = 1; - return 0; + _variableArrayPtr = _variableArray; } SimonEngine::~SimonEngine() { @@ -713,9 +738,9 @@ Child *SimonEngine::allocateChildBlock(Item *i, uint type, uint size) { } void SimonEngine::allocItemHeap() { - _itemHeapSize = 32000; + _itemHeapSize = 64000; _itemHeapCurPos = 0; - _itemHeapPtr = (byte *)calloc(32000, 1); + _itemHeapPtr = (byte *)calloc(64000, 1); } void SimonEngine::allocTablesHeap() { @@ -758,6 +783,13 @@ uint SimonEngine::getVarOrWord() { return a; } +uint SimonEngine::getVarWrapper() { + if (getGameId() == GID_SWAMPY) + return getVarOrWord(); + else + return getVarOrByte(); +} + Item *SimonEngine::getNextItemPtr() { int a = getNextWord(); @@ -827,11 +859,11 @@ Item *SimonEngine::actor() { } uint SimonEngine::getNextVarContents() { - return (uint16)readVariable(getVarOrByte()); + return (uint16)readVariable(getVarWrapper()); } uint SimonEngine::readVariable(uint variable) { - if (variable >= 255) + if (variable >= _numVars) error("readVariable: Variable %d out of range", variable); if (getGameType() == GType_FF) { @@ -845,11 +877,11 @@ uint SimonEngine::readVariable(uint variable) { } void SimonEngine::writeNextVarContents(uint16 contents) { - writeVariable(getVarOrByte(), contents); + writeVariable(getVarWrapper(), contents); } void SimonEngine::writeVariable(uint variable, uint16 contents) { - if (variable >= 256) + if (variable >= _numVars) error("writeVariable: Variable %d out of range", variable); if (getGameType() == GType_FF && getBitFlag(83)) @@ -918,8 +950,10 @@ void SimonEngine::unlinkItem(Item *item) { for (;;) { if (!first) error("unlinkItem: parent empty"); - if (first->sibling == 0) - error("unlinkItem: parent does not contain child"); + if (first->sibling == 0) { + warning("unlinkItem: parent does not contain child"); + return; + } next = derefItem(first->sibling); if (next == item) { @@ -1170,7 +1204,7 @@ startOver: void SimonEngine::hitarea_stuff_helper() { time_t cur_time; - if (getGameType() == GType_SIMON2 || getGameType() == GType_FF) { + if (getGameType() == GType_SIMON2 || getGameType() == GType_FF || getGameType() == GType_PP) { if (_variableArray[254] || _variableArray[249]) { hitarea_stuff_helper_2(); } @@ -1231,7 +1265,7 @@ void SimonEngine::permitInput() { _curWindow = 0; if (_windowArray[0] != 0) { _textWindow = _windowArray[0]; - if (getGameType() == GType_FF) + if (getGameType() == GType_FF || getGameType() == GType_PP) showmessage_helper_3(_textWindow->textColumn, _textWindow->width); else showmessage_helper_3(_textWindow->textLength, _textWindow->textMaxLength); @@ -1273,8 +1307,7 @@ void SimonEngine::loadZone(uint vga_res) { vpe->vgaFile2End = vpe->vgaFile2 + size; vpe->sfxFile = NULL; - if ((getGameType() == GType_FF && getPlatform() == Common::kPlatformWindows) || - getGameType() == GType_WW) { + if (!(getFeatures() & GF_ZLIBCOMP)) { vpe->sfxFile = loadVGAFile(vga_res * 2, 3, size); vpe->sfxFileEnd = vpe->sfxFile + size; } @@ -1325,7 +1358,7 @@ void SimonEngine::checkNoOverWrite(byte *end) { vpe = &_vgaBufferPointers[_noOverWrite]; - if (getGameType() == GType_FF) { + if (getGameType() == GType_FF || getGameType() == GType_PP) { if (vpe->vgaFile1 < end && vpe->vgaFile1End > _vgaMemPtr) { _rejectBlock = true; _vgaMemPtr = vpe->vgaFile1End; @@ -1351,7 +1384,7 @@ void SimonEngine::checkNoOverWrite(byte *end) { void SimonEngine::checkRunningAnims(byte *end) { VgaSprite *vsp; - if (getGameType() != GType_FF && (_lockWord & 0x20)) { + if (getGameType() != GType_FF && getGameType() != GType_PP && (_lockWord & 0x20)) { return; } @@ -1367,7 +1400,7 @@ void SimonEngine::checkAnims(uint a, byte *end) { vpe = &_vgaBufferPointers[a]; - if (getGameType() == GType_FF) { + if (getGameType() == GType_FF || getGameType() == GType_PP) { if (vpe->vgaFile1 < end && vpe->vgaFile1End > _vgaMemPtr) { _rejectBlock = true; _vgaMemPtr = vpe->vgaFile1End; @@ -1395,7 +1428,7 @@ void SimonEngine::checkZonePtrs(byte *end) { uint count = ARRAYSIZE(_vgaBufferPointers); VgaPointersEntry *vpe = _vgaBufferPointers; do { - if (getGameType() == GType_FF) { + if (getGameType() == GType_FF || getGameType() == GType_PP) { if (vpe->vgaFile1 < end && vpe->vgaFile1End > _vgaMemPtr || vpe->vgaFile2 < end && vpe->vgaFile2End > _vgaMemPtr || vpe->sfxFile < end && vpe->sfxFileEnd > _vgaMemPtr) { @@ -1426,7 +1459,7 @@ void SimonEngine::set_video_mode_internal(uint16 mode, uint16 vga_res_id) { _windowNum = mode; _lockWord |= 0x20; - if (getGameType() == GType_FF) { + if (getGameType() == GType_FF || getGameType() == GType_PP) { vc27_resetSprite(); } @@ -1458,21 +1491,7 @@ void SimonEngine::set_video_mode_internal(uint16 mode, uint16 vga_res_id) { bb = _curVgaFile1; - if (getGameType() == GType_WW) { - b = bb + READ_BE_UINT16(bb + 10); - b += 20; - - count = READ_BE_UINT16(&((VgaFileHeader2_WW *) b)->imageCount); - b = bb + READ_BE_UINT16(&((VgaFileHeader2_WW *) b)->imageTable); - - while (count--) { - if (READ_BE_UINT16(&((ImageHeader_WW *) b)->id) == vga_res_id) - break; - b += sizeof(ImageHeader_WW); - } - assert(READ_BE_UINT16(&((ImageHeader_WW *) b)->id) == vga_res_id); - - } else if (getGameType() == GType_FF) { + if (getGameType() == GType_FF || getGameType() == GType_PP) { b = bb + READ_LE_UINT16(&((VgaFileHeader_Feeble *) bb)->hdr2_start); count = READ_LE_UINT16(&((VgaFileHeader2_Feeble *) b)->imageCount); b = bb + READ_LE_UINT16(&((VgaFileHeader2_Feeble *) b)->imageTable); @@ -1484,7 +1503,7 @@ void SimonEngine::set_video_mode_internal(uint16 mode, uint16 vga_res_id) { } assert(READ_LE_UINT16(&((ImageHeader_Feeble *) b)->id) == vga_res_id); - } else { + } else if (getGameType() == GType_SIMON1 || getGameType() == GType_SIMON2) { b = bb + READ_BE_UINT16(&((VgaFileHeader_Simon *) bb)->hdr2_start); count = READ_BE_UINT16(&((VgaFileHeader2_Simon *) b)->imageCount); b = bb + READ_BE_UINT16(&((VgaFileHeader2_Simon *) b)->imageTable); @@ -1495,6 +1514,19 @@ void SimonEngine::set_video_mode_internal(uint16 mode, uint16 vga_res_id) { b += sizeof(ImageHeader_Simon); } assert(READ_BE_UINT16(&((ImageHeader_Simon *) b)->id) == vga_res_id); + } else { + b = bb + READ_BE_UINT16(bb + 10); + b += 20; + + count = READ_BE_UINT16(&((VgaFileHeader2_WW *) b)->imageCount); + b = bb + READ_BE_UINT16(&((VgaFileHeader2_WW *) b)->imageTable); + + while (count--) { + if (READ_BE_UINT16(&((ImageHeader_WW *) b)->id) == vga_res_id) + break; + b += sizeof(ImageHeader_WW); + } + assert(READ_BE_UINT16(&((ImageHeader_WW *) b)->id) == vga_res_id); } if (getGameType() == GType_SIMON1) { @@ -1520,12 +1552,12 @@ void SimonEngine::set_video_mode_internal(uint16 mode, uint16 vga_res_id) { vc_ptr_org = _vcPtr; - if (getGameType() == GType_WW) { - _vcPtr = _curVgaFile1 + READ_BE_UINT16(&((ImageHeader_WW *) b)->scriptOffs); - } else if (getGameType() == GType_FF) { + if (getGameType() == GType_FF || getGameType() == GType_PP) { _vcPtr = _curVgaFile1 + READ_LE_UINT16(&((ImageHeader_Feeble *) b)->scriptOffs); - } else { + } else if (getGameType() == GType_SIMON1 || getGameType() == GType_SIMON2) { _vcPtr = _curVgaFile1 + READ_BE_UINT16(&((ImageHeader_Simon *) b)->scriptOffs); + } else { + _vcPtr = _curVgaFile1 + READ_BE_UINT16(&((ImageHeader_WW *) b)->scriptOffs); } //dump_vga_script(_vcPtr, num, vga_res_id); @@ -1533,7 +1565,7 @@ void SimonEngine::set_video_mode_internal(uint16 mode, uint16 vga_res_id) { _vcPtr = vc_ptr_org; - if (getGameType() == GType_FF) { + if (getGameType() == GType_FF || getGameType() == GType_PP) { fillFrontFromBack(0, 0, _screenWidth, _screenHeight); fillBackGroundFromBack(_screenHeight); _syncFlag2 = 1; @@ -1836,33 +1868,24 @@ void SimonEngine::loadSprite(uint windowNum, uint zoneNum, uint vgaSpriteId, uin } pp = _curVgaFile1; - if (getGameType() == GType_WW) { - p = pp + READ_BE_UINT16(pp + 10); - p += 20; - - count = READ_BE_UINT16(&((VgaFileHeader2_WW *) p)->animationCount); - p = pp + READ_BE_UINT16(&((VgaFileHeader2_WW *) p)->animationTable); - } else if (getGameType() == GType_FF) { + if (getGameType() == GType_FF || getGameType() == GType_PP) { p = pp + READ_LE_UINT16(&((VgaFileHeader_Feeble *) pp)->hdr2_start); count = READ_LE_UINT16(&((VgaFileHeader2_Feeble *) p)->animationCount); p = pp + READ_LE_UINT16(&((VgaFileHeader2_Feeble *) p)->animationTable); - } else { + } else if (getGameType() == GType_SIMON1 || getGameType() == GType_SIMON2) { p = pp + READ_BE_UINT16(&((VgaFileHeader_Simon *) pp)->hdr2_start); count = READ_BE_UINT16(&((VgaFileHeader2_Simon *) p)->animationCount); p = pp + READ_BE_UINT16(&((VgaFileHeader2_Simon *) p)->animationTable); + } else { + p = pp + READ_BE_UINT16(pp + 10); + p += 20; + + count = READ_BE_UINT16(&((VgaFileHeader2_WW *) p)->animationCount); + p = pp + READ_BE_UINT16(&((VgaFileHeader2_WW *) p)->animationTable); } for (;;) { - if (getGameType() == GType_WW) { - if (READ_BE_UINT16(&((AnimationHeader_WW *) p)->id) == vgaSpriteId) { - if (_startVgaScript) - dump_vga_script(pp + READ_BE_UINT16(&((AnimationHeader_WW *)p)->scriptOffs), zoneNum, vgaSpriteId); - - addVgaEvent(_vgaBaseDelay, pp + READ_BE_UINT16(&((AnimationHeader_WW *) p)->scriptOffs), vgaSpriteId, zoneNum); - break; - } - p += sizeof(AnimationHeader_WW); - } else if (getGameType() == GType_FF) { + if (getGameType() == GType_FF || getGameType() == GType_PP) { if (READ_LE_UINT16(&((AnimationHeader_Feeble *) p)->id) == vgaSpriteId) { if (_startVgaScript) dump_vga_script(pp + READ_LE_UINT16(&((AnimationHeader_Feeble*)p)->scriptOffs), zoneNum, vgaSpriteId); @@ -1871,7 +1894,7 @@ void SimonEngine::loadSprite(uint windowNum, uint zoneNum, uint vgaSpriteId, uin break; } p += sizeof(AnimationHeader_Feeble); - } else { + } else if (getGameType() == GType_SIMON1 || getGameType() == GType_SIMON2) { if (READ_BE_UINT16(&((AnimationHeader_Simon *) p)->id) == vgaSpriteId) { if (_startVgaScript) dump_vga_script(pp + READ_BE_UINT16(&((AnimationHeader_Simon*)p)->scriptOffs), zoneNum, vgaSpriteId); @@ -1880,6 +1903,15 @@ void SimonEngine::loadSprite(uint windowNum, uint zoneNum, uint vgaSpriteId, uin break; } p += sizeof(AnimationHeader_Simon); + } else { + if (READ_BE_UINT16(&((AnimationHeader_WW *) p)->id) == vgaSpriteId) { + if (_startVgaScript) + dump_vga_script(pp + READ_BE_UINT16(&((AnimationHeader_WW *)p)->scriptOffs), zoneNum, vgaSpriteId); + + addVgaEvent(_vgaBaseDelay, pp + READ_BE_UINT16(&((AnimationHeader_WW *) p)->scriptOffs), vgaSpriteId, zoneNum); + break; + } + p += sizeof(AnimationHeader_WW); } if (!--count) { @@ -1952,7 +1984,7 @@ int SimonEngine::go() { if (getGameType() == GType_FF) loadIconData(); - else + else if (getGameType() != GType_PP) loadIconFile(); vc34_setMouseOff(); diff --git a/engines/simon/simon.h b/engines/simon/simon.h index f792d91a50..01265404c8 100644 --- a/engines/simon/simon.h +++ b/engines/simon/simon.h @@ -110,10 +110,13 @@ struct VgaTimerEntry { }; enum SIMONGameType { - GType_FF = 0, - GType_SIMON1 = 1, - GType_SIMON2 = 2, - GType_WW = 3 + GType_ELVIRA = 0, + GType_ELVIRA2 = 1, + GType_WW = 2, + GType_SIMON1 = 3, + GType_SIMON2 = 4, + GType_FF = 6, + GType_PP = 7 }; struct GameFileDescription { @@ -157,6 +160,7 @@ public: GameDescription *_gameDescription; bool initGame(void); + void setupGame(); int getGameId() const { return _gameDescription->gameId; } int getGameType() const { return _gameDescription->gameType; } @@ -188,6 +192,7 @@ protected: uint _tableMemSize; uint _musicIndexBase; uint _soundIndexBase; + uint _numVars; const GameSpecificSettings *gss; byte _keyPressed; @@ -403,11 +408,11 @@ protected: uint16 _stringIdArray3[40]; uint16 _speechIdArray4[40]; - uint16 _bitArray[16]; + uint16 _bitArray[128]; uint16 _bitArrayTwo[16]; uint16 _bitArrayThree[16]; - int16 _variableArray[256]; - int16 _variableArray2[256]; + int16 *_variableArray; + int16 *_variableArray2; int16 *_variableArrayPtr; WindowBlock *_windowArray[16]; @@ -552,6 +557,7 @@ protected: int getNextWord(); uint getNextVarContents(); + uint getVarWrapper(); uint getVarOrWord(); uint getVarOrByte(); uint readVariable(uint variable); @@ -629,9 +635,11 @@ protected: void mouseOff(); void mouseOn(); - void loadTextIntoMem(uint stringId); bool loadTablesIntoMem(uint subr_id); + bool loadTablesOldIntoMem(uint subr_id); + bool loadTablesNewIntoMem(uint subr_id); bool loadXTablesIntoMem(uint subr_id); + void loadTextIntoMem(uint stringId); bool loadRoomItems(uint item); @@ -1029,6 +1037,12 @@ public: void o3_b3Zero(); void o3_b3NotZero(); + // Opcodes, Puzzle Pack only + void o4_opcode30(); + void o4_opcode38(); + void o4_loadHiScores(); + void o4_checkHiScores(); + protected: void drawImages(VC10_state *state); void drawImages_Feeble(VC10_state *state); diff --git a/engines/simon/sound.cpp b/engines/simon/sound.cpp index a9d65f2def..894bbce2e0 100644 --- a/engines/simon/sound.cpp +++ b/engines/simon/sound.cpp @@ -288,7 +288,8 @@ Sound::~Sound() { void Sound::loadVoiceFile(const GameSpecificSettings *gss) { // Game versions which use separate voice files - if (_vm->getGameType() == GType_FF || _vm->getGameId() == GID_SIMON1CD32) + if (_vm->getGameType() == GType_FF || _vm->getGameType() == GType_PP || + _vm->getGameId() == GID_SIMON1CD32) return; char filename[16]; diff --git a/engines/simon/subroutine.cpp b/engines/simon/subroutine.cpp index 2b9ed04432..eebf67cb19 100644 --- a/engines/simon/subroutine.cpp +++ b/engines/simon/subroutine.cpp @@ -107,6 +107,63 @@ File *SimonEngine::openTablesFile_gme(const char *filename) { } bool SimonEngine::loadTablesIntoMem(uint subr_id) { + if (getGameType() == GType_ELVIRA || getGameType() == GType_ELVIRA2) + return loadTablesOldIntoMem(subr_id); + else + return loadTablesNewIntoMem(subr_id); +} + + +bool SimonEngine::loadTablesOldIntoMem(uint subr_id) { + byte *p; + uint16 min_num, max_num, file_num; + File *in; + char filename[30]; + + if (_tblList == NULL) + return 0; + + p = _tblList + 32; + + min_num = READ_BE_UINT16(p); + max_num = READ_BE_UINT16(p + 2); + file_num = *(p + 4); + p += 6; + + while (min_num) { + if ((subr_id >= min_num) && (subr_id <= max_num)) { + _subroutineList = _subroutineListOrg; + _tablesHeapPtr = _tablesHeapPtrOrg; + _tablesHeapCurPos = _tablesHeapCurPosOrg; + _stringIdLocalMin = 1; + _stringIdLocalMax = 0; + + sprintf(filename, "TABLES%.2d", file_num); + in = openTablesFile(filename); + readSubroutineBlock(in); + closeTablesFile(in); + + alignTableMem(); + + _tablesheapPtrNew = _tablesHeapPtr; + _tablesHeapCurPosNew = _tablesHeapCurPos; + + if (_tablesHeapCurPos > _tablesHeapSize) + error("loadTablesOldIntoMem: Out of table memory"); + return 1; + } + + min_num = READ_BE_UINT16(p); + max_num = READ_BE_UINT16(p + 2); + file_num = *(p + 4); + p += 6; + } + + debug(1,"loadTablesOldIntoMem: didn't find %d", subr_id); + return 0; +} + +bool SimonEngine::loadTablesNewIntoMem(uint subr_id) { byte *p; int i; uint min_num, max_num; @@ -124,14 +181,11 @@ bool SimonEngine::loadTablesIntoMem(uint subr_id) { p++; for (;;) { - min_num = (p[0] * 256) | p[1]; - p += 2; - + min_num = READ_BE_UINT16(p); p += 2; if (min_num == 0) break; - max_num = (p[0] * 256) | p[1]; - p += 2; + max_num = READ_BE_UINT16(p); p += 2; if (subr_id >= min_num && subr_id <= max_num) { _subroutineList = _subroutineListOrg; @@ -157,20 +211,17 @@ bool SimonEngine::loadTablesIntoMem(uint subr_id) { _tablesHeapCurPosNew = _tablesHeapCurPos; if (_tablesHeapCurPos > _tablesHeapSize) - error("loadTablesIntoMem: Out of table memory"); + error("loadTablesNewIntoMem: Out of table memory"); return 1; } } } - debug(1,"loadTablesIntoMem: didn't find %d", subr_id); + debug(1,"loadTablesNewIntoMem: didn't find %d", subr_id); return 0; } bool SimonEngine::loadXTablesIntoMem(uint subr_id) { - if (getGameType() != GType_WW) - return 0; - byte *p; int i; uint min_num, max_num; @@ -188,13 +239,13 @@ bool SimonEngine::loadXTablesIntoMem(uint subr_id) { p++; for (;;) { - min_num = (p[0] * 256) | p[1]; + min_num = READ_BE_UINT16(p); p += 2; if (min_num == 0) break; - max_num = (p[0] * 256) | p[1]; + max_num = READ_BE_UINT16(p); p += 2; if (subr_id >= min_num && subr_id <= max_num) { @@ -374,26 +425,49 @@ void SimonEngine::readSubroutine(File *in, Subroutine *sub) { } void SimonEngine::readSubroutineLine(File *in, SubroutineLine *sl, Subroutine *sub) { - byte line_buffer[1024], *q = line_buffer; + byte line_buffer[2048], *q = line_buffer; int size; if (sub->id == 0) { sl->verb = in->readUint16BE(); sl->noun1 = in->readUint16BE(); sl->noun2 = in->readUint16BE(); + } else if (getGameType() == GType_ELVIRA || getGameType() == GType_ELVIRA2) { + in->readUint16BE(); + in->readUint16BE(); + in->readUint16BE(); } - while ((*q = in->readByte()) != 0xFF) { - if (*q == 87) { - in->readUint16BE(); - } else { - q = readSingleOpcode(in, q); + if (getGameType() == GType_ELVIRA || getGameType() == GType_ELVIRA2) { + int16 tmp; + + tmp = in->readUint16BE(); + WRITE_BE_UINT16(q, tmp); + while (tmp != 10000) { + if (READ_BE_UINT16(q) == 0xC6) { + in->readUint16BE(); + } else { + q = readSingleOpcode(in, q); + } + + tmp = in->readUint16BE(); + WRITE_BE_UINT16(q, tmp); } - } - size = q - line_buffer + 1; + size = (q - line_buffer + 1) * 2; + memcpy(allocateTable(size), line_buffer, size); + } else { + while ((*q = in->readByte()) != 0xFF) { + if (*q == 87) { + in->readUint16BE(); + } else { + q = readSingleOpcode(in, q); + } + } - memcpy(allocateTable(size), line_buffer, size); + size = (q - line_buffer + 1); + memcpy(allocateTable(size), line_buffer, size); + } } void SimonEngine::readSubroutineBlock(File *in) { diff --git a/engines/simon/vga.cpp b/engines/simon/vga.cpp index bc06ab68fb..bcb9d9f341 100644 --- a/engines/simon/vga.cpp +++ b/engines/simon/vga.cpp @@ -286,7 +286,7 @@ void SimonEngine::vcSkipNextInstruction() { }; uint16 opcode; - if (getGameType() == GType_FF) { + if (getGameType() == GType_FF || getGameType() == GType_PP) { opcode = vcReadNextByte(); _vcPtr += opcodeParamLenFeebleFiles[opcode]; } else if (getGameType() == GType_SIMON2) { @@ -339,21 +339,7 @@ void SimonEngine::vc2_call() { bb = _curVgaFile1; - if (getGameType() == GType_WW) { - b = bb + READ_BE_UINT16(bb + 10); - b += 20; - - count = READ_BE_UINT16(&((VgaFileHeader2_WW *) b)->imageCount); - b = bb + READ_BE_UINT16(&((VgaFileHeader2_WW *) b)->imageTable); - - while (count--) { - if (READ_BE_UINT16(&((ImageHeader_WW *) b)->id) == num) - break; - b += sizeof(ImageHeader_WW); - } - assert(READ_BE_UINT16(&((ImageHeader_WW *) b)->id) == num); - - } else if (getGameType() == GType_FF) { + if (getGameType() == GType_FF || getGameType() == GType_PP) { b = bb + READ_LE_UINT16(&((VgaFileHeader_Feeble *) bb)->hdr2_start); count = READ_LE_UINT16(&((VgaFileHeader2_Feeble *) b)->imageCount); b = bb + READ_LE_UINT16(&((VgaFileHeader2_Feeble *) b)->imageTable); @@ -364,7 +350,7 @@ void SimonEngine::vc2_call() { b += sizeof(ImageHeader_Feeble); } assert(READ_LE_UINT16(&((ImageHeader_Feeble *) b)->id) == num); - } else { + } else if (getGameType() == GType_SIMON1 || getGameType() == GType_SIMON2) { b = bb + READ_BE_UINT16(&((VgaFileHeader_Simon *) bb)->hdr2_start); count = READ_BE_UINT16(&((VgaFileHeader2_Simon *) b)->imageCount); b = bb + READ_BE_UINT16(&((VgaFileHeader2_Simon *) b)->imageTable); @@ -375,16 +361,29 @@ void SimonEngine::vc2_call() { b += sizeof(ImageHeader_Simon); } assert(READ_BE_UINT16(&((ImageHeader_Simon *) b)->id) == num); + } else { + b = bb + READ_BE_UINT16(bb + 10); + b += 20; + + count = READ_BE_UINT16(&((VgaFileHeader2_WW *) b)->imageCount); + b = bb + READ_BE_UINT16(&((VgaFileHeader2_WW *) b)->imageTable); + + while (count--) { + if (READ_BE_UINT16(&((ImageHeader_WW *) b)->id) == num) + break; + b += sizeof(ImageHeader_WW); + } + assert(READ_BE_UINT16(&((ImageHeader_WW *) b)->id) == num); } vcPtrOrg = _vcPtr; - if (getGameType() == GType_WW) { - _vcPtr = _curVgaFile1 + READ_BE_UINT16(&((ImageHeader_WW *) b)->scriptOffs); - } else if (getGameType() == GType_FF) { + if (getGameType() == GType_FF || getGameType() == GType_PP) { _vcPtr = _curVgaFile1 + READ_LE_UINT16(&((ImageHeader_Feeble *) b)->scriptOffs); - } else { + } else if (getGameType() == GType_SIMON1 || getGameType() == GType_SIMON2) { _vcPtr = _curVgaFile1 + READ_BE_UINT16(&((ImageHeader_Simon *) b)->scriptOffs); + } else { + _vcPtr = _curVgaFile1 + READ_BE_UINT16(&((ImageHeader_WW *) b)->scriptOffs); } //dump_vga_script(_vcPtr, res, num); @@ -453,20 +452,7 @@ void SimonEngine::vc3_loadSprite() { } pp = _curVgaFile1; - if (getGameType() == GType_WW) { - p = pp + READ_BE_UINT16(pp + 10); - p += 20; - - count = READ_BE_UINT16(&((VgaFileHeader2_WW *) p)->animationCount); - p = pp + READ_BE_UINT16(&((VgaFileHeader2_WW *) p)->animationTable); - - while (count--) { - if (READ_BE_UINT16(&((AnimationHeader_WW *) p)->id) == vgaSpriteId) - break; - p += sizeof(AnimationHeader_WW); - } - assert(READ_BE_UINT16(&((AnimationHeader_WW *) p)->id) == vgaSpriteId); - } else if (getGameType() == GType_FF) { + if (getGameType() == GType_FF || getGameType() == GType_PP) { p = pp + READ_LE_UINT16(&((VgaFileHeader_Feeble *) pp)->hdr2_start); count = READ_LE_UINT16(&((VgaFileHeader2_Feeble *) p)->animationCount); p = pp + READ_LE_UINT16(&((VgaFileHeader2_Feeble *) p)->animationTable); @@ -477,7 +463,7 @@ void SimonEngine::vc3_loadSprite() { p += sizeof(AnimationHeader_Feeble); } assert(READ_LE_UINT16(&((AnimationHeader_Feeble *) p)->id) == vgaSpriteId); - } else { + } else if (getGameType() == GType_SIMON1 || getGameType() == GType_SIMON2) { p = pp + READ_BE_UINT16(&((VgaFileHeader_Simon *) pp)->hdr2_start); count = READ_BE_UINT16(&((VgaFileHeader2_Simon *) p)->animationCount); p = pp + READ_BE_UINT16(&((VgaFileHeader2_Simon *) p)->animationTable); @@ -488,6 +474,19 @@ void SimonEngine::vc3_loadSprite() { p += sizeof(AnimationHeader_Simon); } assert(READ_BE_UINT16(&((AnimationHeader_Simon *) p)->id) == vgaSpriteId); + } else { + p = pp + READ_BE_UINT16(pp + 10); + p += 20; + + count = READ_BE_UINT16(&((VgaFileHeader2_WW *) p)->animationCount); + p = pp + READ_BE_UINT16(&((VgaFileHeader2_WW *) p)->animationTable); + + while (count--) { + if (READ_BE_UINT16(&((AnimationHeader_WW *) p)->id) == vgaSpriteId) + break; + p += sizeof(AnimationHeader_WW); + } + assert(READ_BE_UINT16(&((AnimationHeader_WW *) p)->id) == vgaSpriteId); } #ifdef DUMP_FILE_NR @@ -511,22 +510,21 @@ void SimonEngine::vc3_loadSprite() { #endif if (_startVgaScript) { - if (getGameType() == GType_WW) { - dump_vga_script(_curVgaFile1 + READ_BE_UINT16(&((AnimationHeader_WW*)p)->scriptOffs), res, vgaSpriteId); - } else if (getGameType() == GType_FF) { + if (getGameType() == GType_FF || getGameType() == GType_PP) { dump_vga_script(_curVgaFile1 + READ_LE_UINT16(&((AnimationHeader_Feeble*)p)->scriptOffs), res, vgaSpriteId); - } else { + } else if (getGameType() == GType_SIMON1 || getGameType() == GType_SIMON2) { dump_vga_script(_curVgaFile1 + READ_BE_UINT16(&((AnimationHeader_Simon*)p)->scriptOffs), res, vgaSpriteId); - + } else { + dump_vga_script(_curVgaFile1 + READ_BE_UINT16(&((AnimationHeader_WW*)p)->scriptOffs), res, vgaSpriteId); } } - if (getGameType() == GType_WW) { - addVgaEvent(_vgaBaseDelay, _curVgaFile1 + READ_BE_UINT16(&((AnimationHeader_WW *) p)->scriptOffs), vgaSpriteId, res); - } else if (getGameType() == GType_FF) { + if (getGameType() == GType_FF || getGameType() == GType_PP) { addVgaEvent(_vgaBaseDelay, _curVgaFile1 + READ_LE_UINT16(&((AnimationHeader_Feeble *) p)->scriptOffs), vgaSpriteId, res); - } else { + } else if (getGameType() == GType_SIMON1 || getGameType() == GType_SIMON2) { addVgaEvent(_vgaBaseDelay, _curVgaFile1 + READ_BE_UINT16(&((AnimationHeader_Simon *) p)->scriptOffs), vgaSpriteId, res); + } else { + addVgaEvent(_vgaBaseDelay, _curVgaFile1 + READ_BE_UINT16(&((AnimationHeader_WW *) p)->scriptOffs), vgaSpriteId, res); } _curVgaFile1 = old_file_1; @@ -714,12 +712,22 @@ byte *SimonEngine::vc10_flip(const byte *src, uint w, uint h) { /* must not be const */ static uint16 _video_windows[128] = { - 0, 0, 20, 200, - 0, 0, 3, 136, - 17, 0, 3, 136, - 0, 0, 20, 200, - 0, 0, 20, 134 + 0, 0, 20, 200, + 0, 0, 3, 136, + 17, 0, 3, 136, + 0, 0, 20, 200, + 0, 0, 20, 134 +}; + +/* Elvira 1/2 & Waxworks +static uint16 _video_windows[128] = { + 3, 0, 14, 136, + 0, 0, 3, 136, + 17, 0, 3, 136, + 0, 0, 20, 200, + 3, 3, 14, 127, }; + */ void SimonEngine::decodeColumn(byte *dst, const byte *src, int height) { const uint pitch = _dxSurfacePitch; @@ -819,7 +827,7 @@ void SimonEngine::vc10_draw() { if (state.image == 0) return; - if (getGameType() == GType_FF) { + if (getGameType() == GType_FF || getGameType() == GType_PP) { state.palette = (_vcPtr[0] * 16); _vcPtr += 2; } else if (getGameType() == GType_SIMON1 || getGameType() == GType_SIMON2) { @@ -846,7 +854,7 @@ void SimonEngine::vc10_draw() { p2 = _curVgaFile2 + state.image * 8; state.depack_src = _curVgaFile2 + readUint32Wrapper(p2); - if (getGameType() == GType_FF) { + if (getGameType() == GType_FF || getGameType() == GType_PP) { width = READ_LE_UINT16(p2 + 6); height = READ_LE_UINT16(p2 + 4) & 0x7FFF; flags = p2[5]; @@ -863,7 +871,7 @@ void SimonEngine::vc10_draw() { dump_single_bitmap(_vgaCurZoneNum, state.image, state.depack_src, width, height, state.palette); // Check if image is compressed - if (getGameType() == GType_FF) { + if (getGameType() == GType_FF || getGameType() == GType_PP) { if (flags & 0x80) { state.flags |= kDFCompressed; } @@ -886,7 +894,7 @@ void SimonEngine::vc10_draw() { state.x_skip = 0; /* colums to skip = bh */ state.y_skip = 0; /* rows to skip = bl */ - uint maxWidth = (getGameType() == GType_FF) ? 640 : 20; + uint maxWidth = (getGameType() == GType_FF || getGameType() == GType_PP) ? 640 : 20; if ((getGameType() == GType_SIMON2 || getGameType() == GType_FF) && width > maxWidth) { horizontalScroll(&state); return; @@ -910,7 +918,7 @@ void SimonEngine::vc10_draw() { state.surf_addr = getBackBuf(); state.surf_pitch = _dxSurfacePitch; - if (getGameType() == GType_FF) { + if (getGameType() == GType_FF || getGameType() == GType_PP) { drawImages_Feeble(&state); } else { drawImages(&state); @@ -938,7 +946,7 @@ bool SimonEngine::drawImages_clip(VC10_state *state) { } state->x = cur; - maxWidth = (getGameType() == GType_FF) ? 640 : (vlut[2] * 2); + maxWidth = (getGameType() == GType_FF || getGameType() == GType_PP) ? 640 : (vlut[2] * 2); cur += state->draw_width - maxWidth; if (cur > 0) { do { @@ -957,7 +965,7 @@ bool SimonEngine::drawImages_clip(VC10_state *state) { } state->y = cur; - maxHeight = (getGameType() == GType_FF) ? 480 : vlut[3]; + maxHeight = (getGameType() == GType_FF || getGameType() == GType_PP) ? 480 : vlut[3]; cur += state->draw_height - maxHeight; if (cur > 0) { do { @@ -1147,9 +1155,22 @@ void SimonEngine::drawImages(VC10_state *state) { uint offs, offs2; // Allow one section of Simon the Sorcerer 1 introduction to be displayed // in lower half of screen - if ((getGameType() == GType_SIMON1) && _subroutine == 2926) { - offs = ((vlut[0]) * 2 + state->x) * 8; - offs2 = (vlut[1] + state->y); + if (getGameType() == GType_WW) { + //if (_windowNum == 4 || _windowNum >= 10) { + offs = state->x * 8; + offs2 = state->y; + //} else { + // offs = ((vlut[0] - _video_windows[16]) * 2 + state->x) * 8; + // offs2 = (vlut[1] - _video_windows[17] + state->y); + //} + } else if (getGameType() == GType_SIMON1) { + if (_windowNum != 2 || _windowNum != 3) { + offs = ((vlut[0]) * 2 + state->x) * 8; + offs2 = (vlut[1] + state->y); + } else { + offs = ((vlut[0] - _video_windows[16]) * 2 + state->x) * 8; + offs2 = (vlut[1] - _video_windows[17] + state->y); + } } else { offs = ((vlut[0] - _video_windows[16]) * 2 + state->x) * 8; offs2 = (vlut[1] - _video_windows[17] + state->y); @@ -1480,7 +1501,7 @@ void SimonEngine::vc12_delay() { VgaSprite *vsp = findCurSprite(); uint16 num; - if (getGameType() == GType_FF) { + if (getGameType() == GType_FF || getGameType() == GType_PP) { num = vcReadNextByte(); } else if (getGameType() == GType_SIMON2) { num = vcReadNextByte() * _frameRate; @@ -1554,7 +1575,7 @@ void SimonEngine::vc17_setPathfinderItem() { uint16 a = vcReadNextWord(); _pathFindArray[a - 1] = (const uint16 *)_vcPtr; - int end = (getGameType() == GType_FF) ? 9999 : 999; + int end = (getGameType() == GType_FF || getGameType() == GType_PP) ? 9999 : 999; while (readUint16Wrapper(_vcPtr) != end) _vcPtr += 4; _vcPtr += 2; @@ -1608,24 +1629,25 @@ void SimonEngine::vc22_setSpritePalette() { a = vcReadNextWord(); b = vcReadNextWord(); - if (getGameType() == GType_WW) { - num = 16; - palSize = 32; - palptr = _displayPalette; - offs = _curVgaFile1 + READ_BE_UINT16(_curVgaFile1 + 6); - } else if (getGameType() == GType_FF) { + if (getGameType() == GType_FF || getGameType() == GType_PP) { num = 256; palSize = 768; palptr = _displayPalette; offs = _curVgaFile1 + 6; - } else { + } else if (getGameType() == GType_SIMON1 || getGameType() == GType_SIMON2) { num = a == 0 ? 32 : 16; palSize = 96; palptr = &_displayPalette[(a * 64)]; offs = _curVgaFile1 + 6; + } else { + num = 16; + palSize = 32; + palptr = _displayPalette; + offs = _curVgaFile1 + READ_BE_UINT16(_curVgaFile1 + 6); } + src = offs + b * palSize; do { @@ -1818,7 +1840,7 @@ void SimonEngine::vc36_setWindowImage() { uint16 vga_res = vcReadNextWord(); uint16 windowNum = vcReadNextWord(); - if (getGameType() == GType_FF) { + if (getGameType() == GType_FF || getGameType() == GType_PP) { _copyPartialMode = 2; } else if (getGameType() == GType_SIMON2) { set_video_mode_internal(windowNum, vga_res); @@ -1966,7 +1988,7 @@ void SimonEngine::vc48_setPathFinder() { if (getGameType() == GType_WW) { //FIXME vcReadNextWord(); - } else if (getGameType() == GType_FF) { + } else if (getGameType() == GType_FF || getGameType() == GType_PP) { VgaSprite *vsp = findCurSprite(); int16 x, y, ydiff; int16 x1, y1, x2, y2; @@ -2074,7 +2096,7 @@ void SimonEngine::vc52_playSound() { sound = -sound; } - if (getGameType() == GType_FF) { + if (getGameType() == GType_FF || getGameType() == GType_PP) { int16 pan = vcReadNextWord(); int16 vol = vcReadNextWord(); @@ -2175,6 +2197,9 @@ void SimonEngine::vc57_blackPalette() { } void SimonEngine::vc58() { + if (getGameType() == GType_WW) + return; + uint16 sprite = _vgaCurSpriteId; uint16 file = _vgaCurZoneNum; const byte *vcPtrOrg; @@ -2195,7 +2220,7 @@ void SimonEngine::vc58() { } void SimonEngine::vc59() { - if (getGameType() == GType_SIMON2 || getGameType() == GType_FF) { + if (getGameType() == GType_SIMON2 || getGameType() == GType_FF || getGameType() == GType_PP) { uint16 file = vcReadNextWord(); uint16 start = vcReadNextWord(); uint16 end = vcReadNextWord() + 1; @@ -2273,17 +2298,16 @@ void SimonEngine::vc61_setMaskImage() { if (getGameType() == GType_WW) { // FIXME vcReadVarOrWord(); - return; - } + } else { + VgaSprite *vsp = findCurSprite(); - VgaSprite *vsp = findCurSprite(); + vsp->image = vcReadVarOrWord(); + vsp->x += vcReadNextWord(); + vsp->y += vcReadNextWord(); + vsp->flags = kDFMasked | kDFUseFrontBuf; - vsp->image = vcReadVarOrWord(); - vsp->x += vcReadNextWord(); - vsp->y += vcReadNextWord(); - vsp->flags = kDFMasked | kDFUseFrontBuf; - - _vgaSpriteChanged++; + _vgaSpriteChanged++; + } } void SimonEngine::vc62_fastFadeOut() { @@ -2303,7 +2327,7 @@ void SimonEngine::vc62_fastFadeOut() { memcpy(_videoBuf1, _currentPalette, _fastFadeCount * 4); - if (getGameType() == GType_FF && !getBitFlag(75)) { + if ((getGameType() == GType_FF || getGameType() == GType_PP) && !getBitFlag(75)) { fadeCount = 32; fadeSize = 8; } else { @@ -2357,7 +2381,7 @@ void SimonEngine::vc62_fastFadeOut() { // in lower half of screen if ((getGameType() == GType_SIMON1) && (_subroutine == 2923 || _subroutine == 2926)) { dx_clear_surfaces(200); - } else if (getGameType() == GType_FF) { + } else if (getGameType() == GType_FF || getGameType() == GType_PP) { dx_clear_surfaces(480); } else { dx_clear_surfaces(_windowNum == 4 ? 134 : 200); @@ -2370,7 +2394,7 @@ void SimonEngine::vc62_fastFadeOut() { } void SimonEngine::vc63_fastFadeIn() { - if (getGameType() == GType_FF) { + if (getGameType() == GType_FF || getGameType() == GType_PP) { _fastFadeInFlag = 256; } else { _fastFadeInFlag = 208; |