diff options
author | Travis Howell | 2006-09-19 11:59:13 +0000 |
---|---|---|
committer | Travis Howell | 2006-09-19 11:59:13 +0000 |
commit | ab2cb0b30ad15c2cd33c82989461bdcf44644bd2 (patch) | |
tree | d8209b59ea5b444d2a7b7694c8b1cd13449d4ee3 | |
parent | fd85c13d8f5a8c58e056fe51658a5b83da323053 (diff) | |
download | scummvm-rg350-ab2cb0b30ad15c2cd33c82989461bdcf44644bd2.tar.gz scummvm-rg350-ab2cb0b30ad15c2cd33c82989461bdcf44644bd2.tar.bz2 scummvm-rg350-ab2cb0b30ad15c2cd33c82989461bdcf44644bd2.zip |
Expand Simon engine
svn-id: r23939
-rw-r--r-- | engines/simon/debug.cpp | 10 | ||||
-rw-r--r-- | engines/simon/debug.h | 321 | ||||
-rw-r--r-- | engines/simon/draw.cpp | 40 | ||||
-rw-r--r-- | engines/simon/game.cpp | 24 | ||||
-rw-r--r-- | engines/simon/intern.h | 18 | ||||
-rw-r--r-- | engines/simon/items.cpp | 116 | ||||
-rw-r--r-- | engines/simon/midiparser_s1d.cpp | 3 | ||||
-rw-r--r-- | engines/simon/res.cpp | 67 | ||||
-rw-r--r-- | engines/simon/simon.cpp | 98 | ||||
-rw-r--r-- | engines/simon/simon.h | 28 | ||||
-rw-r--r-- | engines/simon/subroutine.cpp | 80 | ||||
-rw-r--r-- | engines/simon/vga.cpp | 265 | ||||
-rw-r--r-- | engines/simon/vga.h | 28 |
13 files changed, 973 insertions, 125 deletions
diff --git a/engines/simon/debug.cpp b/engines/simon/debug.cpp index 8054383abb..663f5ad68e 100644 --- a/engines/simon/debug.cpp +++ b/engines/simon/debug.cpp @@ -48,8 +48,10 @@ const byte *SimonEngine::dumpOpcode(const byte *p) { st = s = simon1talkie_opcode_name_table[opcode]; } else if (getGameType() == GType_SIMON2) { st = s = simon2dos_opcode_name_table[opcode]; - } else { + } else if (getGameType() == GType_SIMON1) { st = s = simon1dos_opcode_name_table[opcode]; + } else { + st = s = ww_opcode_name_table[opcode]; } if (s == NULL) { //error("INVALID OPCODE %d", opcode); @@ -178,7 +180,7 @@ void SimonEngine::dump_video_script(const byte *src, bool one_opcode_only) { const char *str, *strn; do { - if (getGameType() == GType_SIMON1) { + if (getGameType() == GType_SIMON1 || getGameType() == GType_WW) { opcode = READ_BE_UINT16(src); src += 2; } else { @@ -194,8 +196,10 @@ void SimonEngine::dump_video_script(const byte *src, bool one_opcode_only) { strn = str = feeblefiles_video_opcode_name_table[opcode]; } else if (getGameType() == GType_SIMON2) { strn = str = simon2_video_opcode_name_table[opcode]; - } else { + } else if (getGameType() == GType_SIMON1) { strn = str = simon1_video_opcode_name_table[opcode]; + } else { + strn = str = ww_video_opcode_name_table[opcode]; } while (*strn != '|') diff --git a/engines/simon/debug.h b/engines/simon/debug.h index 452cc8f2da..51587a4f59 100644 --- a/engines/simon/debug.h +++ b/engines/simon/debug.h @@ -26,6 +26,244 @@ namespace Simon { +static const char *const ww_opcode_name_table[256] = { + /* 0 */ + "|NOT", + "IJ|AT", + "IJ|NOT_AT", + NULL, + /* 4 */ + NULL, + "IJ|CARRIED", + "IJ|NOT_CARRIED", + "IIJ|IS_AT", + /* 8 */ + NULL, + NULL, + NULL, + "VJ|IS_ZERO", + /* 12 */ + "VJ|ISNOT_ZERO", + "VWJ|IS_EQ", + "VWJ|IS_NEQ", + "VWJ|IS_LE", + /* 16 */ + "VWJ|IS_GE", + "VVJ|IS_EQF", + "VVJ|IS_NEQF", + "VVJ|IS_LEF", + /* 20 */ + "VVJ|IS_GEF", + NULL, + NULL, + "WJ|CHANCE", + /* 24 */ + NULL, + "IJ|IS_ROOM", + "IJ|IS_OBJECT", + "IWJ|ITEM_STATE_IS", + /* 28 */ + "IBJ|OBJECT_HAS_FLAG", + NULL, + NULL, + "I|SET_NO_PARENT", + /* 32 */ + NULL, + "II|SET_PARENT", + NULL, + NULL, + /* 36 */ + "VV|MOVE", + NULL, + NULL, + NULL, + /* 40 */ + NULL, + "V|ZERO", + "VW|SET", + "VW|ADD", + /* 44 */ + "VW|SUB", + "VV|ADDF", + "VV|SUBF", + "VW|MUL", + /* 48 */ + "VW|DIV", + "VV|MULF", + "VV|DIVF", + "VW|MOD", + /* 52 */ + "VV|MODF", + "VW|RANDOM", + NULL, + "I|SET_A_PARENT", + /* 56 */ + "IB|SET_CHILD2_BIT", + "IB|CLEAR_CHILD2_BIT", + "II|MAKE_SIBLING", + "I|INC_STATE", + /* 60 */ + "I|DEC_STATE", + "IW|SET_STATE", + "V|SHOW_INT", + "T|SHOW_STRING_NL", + /* 64 */ + "T|SHOW_STRING", + "WWWWWB|ADD_TEXT_BOX", + "BT|SET_SHORT_TEXT", + "BT|SET_LONG_TEXT", + /* 68 */ + "x|END", + "x|DONE", + "V|SHOW_STRING_AR3", + "W|START_SUB", + /* 72 */ + NULL, + NULL, + NULL, + NULL, + /* 76 */ + "WW|ADD_TIMEOUT", + "J|IS_M1_EMPTY", + "J|IS_M3_EMPTY", + "ITJ|CHILD_FR2_IS", + /* 80 */ + "IIJ|IS_ITEM_EQ", + NULL, + "B|DEBUG", + "|RESCAN", + /* 84 */ + NULL, + "IBB|WHERE_TO", + NULL, + "W|COMMENT", + /* 88 */ + "|STOP_ANIMATION", + "|RESTART_ANIMATION", + "IB|GET_PARENT", + "IB|GET_NEXT", + /* 92 */ + "IB|GET_CHILDREN", + NULL, + NULL, + NULL, + /* 96 */ + "WB|PICTURE", + "W|LOAD_ZONE", + "WBWWW|ANIMATE", + "W|STOP_ANIMATE", + /* 100 */ + "|KILL_ANIMATE", + "BWWWWWW|DEFINE_WINDOW", + "B|CHANGE_WINDOW", + "|CLS", + /* 104 */ + "B|CLOSE_WINDOW", + "B|MENU", + "BB|TEXT_MENU", + "WWWWWIW|ADD_BOX", + /* 108 */ + "W|DEL_BOX", + "W|ENABLE_BOX", + "W|DISABLE_BOX", + "WWW|MOVE_BOX", + /* 112 */ + NULL, + NULL, + "IB|DO_ICONS", + "IBJ|IS_CLASS", + /* 116 */ + "IB|SET_CLASS", + "IB|UNSET_CLASS", + NULL, + "W|WAIT_SYNC", + /* 120 */ + "W|SYNC", + "BI|DEF_OBJ", + NULL, + NULL, + /* 124 */ + NULL, + "IJ|IS_SIBLING_WITH_A", + "IBB|DO_CLASS_ICONS", + "WW|PLAY_TUNE", + /* 128 */ + "W|WAIT_END_TUNE", + "W|IF_END_TUNE", + "Bww|SET_ADJ_NOUN", + NULL, + /* 132 */ + "|SAVE_GAME", + "|LOAD_GAME", + "|DUMMYPROC_134", + "|QUIT_IF_USER_PRESSES_Y", + /* 136 */ + "IV|COPY_SF", + "B|RESTORE_ICONS", + "|FREEZE_ZONES", + "II|SET_PARENT_SPECIAL", + /* 140 */ + "|CLEAR_TIMERS", + "BI|SET_M1_OR_M3", + "WJ|IS_HITAREA_0x40_CLEAR", + "I|START_ITEM_SUB", + /* 144 */ + NULL, + NULL, + NULL, + NULL, + /* 148 */ + "IB|IF_DOOR_OPEN", + NULL, + NULL, + "BI|SET_ARRAY6_TO", + /* 152 */ + "BB|SET_M1_M3_TO_ARRAY6", + "B|SET_BIT", + "B|CLEAR_BIT", + "BJ|IS_BIT_CLEAR", + /* 156 */ + "BJ|IS_BIT_SET", + "IBB|GET_ITEM_PROP", + "IBW|SET_ITEM_PROP", + NULL, + /* 160 */ + "B|SET_INK", + "BWBW|SETUP_TEXT", + "BBT|PRINT_STR", + "W|PLAY_EFFECT", + /* 164 */ + "|getDollar2", + "IWWJ|IS_ADJ_NOUN", + "B|SET_BIT2", + "B|CLEAR_BIT2", + /* 168 */ + "BJ|IS_BIT2_CLEAR", + "BJ|IS_BIT2_SET", + NULL, + NULL, + /* 172 */ + NULL, + NULL, + NULL, + "|LOCK_ZONES", + /* 176 */ + "|UNLOCK_ZONES", + "BBI|SCREEN_TEXT_POBJ", + "WWBB|GETPATHPOSN", + "IWWJ|IS_ADJ_NOUN", + /* 180 */ + "B|SET_BIT2", + "B|CLEAR_BIT2", + "BJ|IS_BIT2_CLEAR", + "BJ|IS_BIT2_SET", + /* 184 */ + "W|UNLOAD_ZONE", + "W|LOAD_SOUND_FILES", + "|UNFREEZE_ZONES", + "|FADE_TO_BLACK", +}; + static const char *const simon1dos_opcode_name_table[256] = { /* 0 */ "|NOT", @@ -1239,6 +1477,89 @@ static const char *const feeblefiles_opcode_name_table[256] = { "B|B3_NOT_ZERO", }; +const char *const ww_video_opcode_name_table[] = { + /* 0 */ + "x|RET", + "ddd|FADEOUT", + "d|CALL", + "ddddd|NEW_SPRITE", + /* 4 */ + "ddd|FADEIN", + "vd|SKIP_IF_NEQ", + "d|SKIP_IFN_SIB_WITH_A", + "d|SKIP_IF_SIB_WITH_A", + /* 8 */ + "dd|SKIP_IF_PARENT_IS", + "dd|SKIP_IF_UNK3_IS", + "dddd|DRAW", + "d|VC_11", + /* 12 */ + "d|DELAY", + "d|SET_SPRITE_OFFSET_X", + "d|SET_SPRITE_OFFSET_Y", + "d|IDENT_WAKEUP", + /* 16 */ + "d|IDENT_SLEEP", + "d|VC_17", + "i|JUMP_REL", + "|CHAIN_TO", + /* 20 */ + "dd|SET_REPEAT", + "i|END_REPEAT", + "d|SET_PALETTE", + "d|SET_PRIORITY", + /* 24 */ + "diid|SET_SPRITE_XY", + "x|HALT_SPRITE", + "ddddd|SET_WINDOW", + "|RESET", + /* 28 */ + "dddd|PLAY_SOUND", + "|STOP_ALL_SOUNDS", + "d|SET_FRAME_RATE", + "d|SET_WINDOW", + /* 32 */ + "|VC_32", + "|MOUSE_ON", + "|MOUSE_OFF", + "dd|CLEAR_WINDOW", + /* 36 */ + "dd|SAVELOAD_THING", + "dd|VC_37", + "v|SKIP_IF_VAR_ZERO", + "vd|SET_VAR", + /* 40 */ + "vd|ADD_VAR", + "vd|SUB_VAR", + "vd|DELAY_IF_NOT_EQ", + "d|SKIP_IF_BIT_CLEAR", + /* 44 */ + "d|SKIP_IF_BIT_SET", + "dd|VC_45", + "v|SET_SPRITE_Y", + "d|VC_47", + /* 48 */ + "d|VC_48", + "d|SET_BIT", + "d|CLEAR_BIT", + "d|ENABLE_BOX", + /* 52 */ + "d|PLAY_EFFECT", + "dd|DUMMY_53", + "ddd|DUMMY_54", + "ddd|MOVE_BOX", + /* 56 */ + "|FULL_SCREEN", + "|BLACK_PALETTE", + "|SET_PRIORITIES", + "|SKIP_IF_NOT_EGA", + /* 60 */ + "d|STOP_ANIMATE", + "d|VC_61", + "|FASTFADEOUT", + "|FASTFADEIN", +}; + const char *const simon1_video_opcode_name_table[] = { /* 0 */ "x|RET", diff --git a/engines/simon/draw.cpp b/engines/simon/draw.cpp index 746b25c471..a684093d4d 100644 --- a/engines/simon/draw.cpp +++ b/engines/simon/draw.cpp @@ -85,14 +85,20 @@ void SimonEngine::animateSprites() { _vgaCurSpritePriority = vsp->priority; params[0] = readUint16Wrapper(&vsp->image); - params[1] = readUint16Wrapper(&vsp->palette); - params[2] = readUint16Wrapper(&vsp->x); - params[3] = readUint16Wrapper(&vsp->y); - - if (getGameType() == GType_SIMON1) { - params[4] = READ_BE_UINT16(&vsp->flags); + if (getGameType() == GType_WW) { + params[1] = readUint16Wrapper(&vsp->x); + params[2] = readUint16Wrapper(&vsp->y); + params[3] = READ_BE_UINT16(&vsp->flags); } else { - *(byte *)(¶ms[4]) = (byte)vsp->flags; + params[1] = readUint16Wrapper(&vsp->palette); + params[2] = readUint16Wrapper(&vsp->x); + params[3] = readUint16Wrapper(&vsp->y); + + if (getGameType() == GType_SIMON1) { + params[4] = READ_BE_UINT16(&vsp->flags); + } else { + *(byte *)(¶ms[4]) = (byte)vsp->flags; + } } _vcPtr = (const byte *)params; @@ -132,10 +138,22 @@ void SimonEngine::animateSpritesDebug() { printf("id:%5d image:%3d base-color:%3d x:%3d y:%3d flags:%x\n", vsp->id, vsp->image, vsp->palette, vsp->x, vsp->y, vsp->flags); params[0] = readUint16Wrapper(&vsp->image); - params[1] = readUint16Wrapper(&vsp->palette); - params[2] = readUint16Wrapper(&vsp->x); - params[3] = readUint16Wrapper(&vsp->y); - params[4] = readUint16Wrapper(&vsp->flags); + if (getGameType() == GType_WW) { + params[1] = readUint16Wrapper(&vsp->x); + params[2] = readUint16Wrapper(&vsp->y); + params[3] = READ_BE_UINT16(&vsp->flags); + } else { + params[1] = readUint16Wrapper(&vsp->palette); + params[2] = readUint16Wrapper(&vsp->x); + params[3] = readUint16Wrapper(&vsp->y); + + if (getGameType() == GType_SIMON1) { + params[4] = READ_BE_UINT16(&vsp->flags); + } else { + *(byte *)(¶ms[4]) = (byte)vsp->flags; + } + } + _vcPtr = (const byte *)params; vc10_draw(); diff --git a/engines/simon/game.cpp b/engines/simon/game.cpp index 2d749a43cb..cde814605b 100644 --- a/engines/simon/game.cpp +++ b/engines/simon/game.cpp @@ -70,6 +70,7 @@ static const PlainGameDescriptor simonGames[] = { {"feeble", "The Feeble Files"}, {"simon1", "Simon the Sorcerer 1"}, {"simon2", "Simon the Sorcerer 2"}, + {"waxworks", "Waxworks"}, {NULL, NULL} }; @@ -88,7 +89,7 @@ GameDescriptor Engine_SIMON_findGameID(const char *gameid) { // First search the list of supported game IDs. const PlainGameDescriptor *g = simonGames; while (g->gameid) { - if (0 == scumm_stricmp(gameid, g->gameid)) + if (!scumm_stricmp(gameid, g->gameid)) return *g; g++; } @@ -586,7 +587,28 @@ static GameFileDescription FEEBLEFILES_ES_GameFiles[] = { { "tbllist", GAME_TBLFILE, "0bbfee8e69739111eb36b0d138da8ddf"}, }; +static GameFileDescription WAXWORKS_GameFiles[] = { + { "gamepc", GAME_BASEFILE, "7751e9358e894e32ef40ef3b3bae0f2a"}, + { "icon.dat", GAME_ICONFILE, "ef1b8ad3494cf103dc10a99fe152ef9a"}, + { "stripped.txt", GAME_STRFILE, "f259e3e07a1cde8d0404a767d815e12c"}, + { "tbllist", GAME_TBLFILE, "95c44bfc380770a6b6dd0dfcc69e80a0"}, + { "xtbllist", GAME_XTBLFILE, "6c7b3db345d46349a5226f695c03e20f"}, +}; + static GameDescription gameDescriptions[] = { + // Waxworks - English Floopy + { + "waxworks", + GType_WW, + GID_WAXWORKS, + "Floppy", + ARRAYSIZE(WAXWORKS_GameFiles), + WAXWORKS_GameFiles, + GF_OLD_BUNDLE, + Common::EN_ANY, + Common::kPlatformPC, + }, + // Simon the Sorcerer 1 - English Acorn CD Demo { "simon1", diff --git a/engines/simon/intern.h b/engines/simon/intern.h index 65a99ce077..52deded6a5 100644 --- a/engines/simon/intern.h +++ b/engines/simon/intern.h @@ -43,7 +43,18 @@ struct SubObject : Child { int16 objectFlagValue[1]; }; +struct SubUserChain : Child { + uint16 subroutine_id; + uint16 chChained; +}; + +struct SubUserInherit : Child { + uint16 subroutine_id; + uint16 inMaster; +}; + struct SubUserFlag : Child { + uint16 subroutine_id; uint16 userFlags[4]; }; @@ -166,11 +177,16 @@ enum GameFileTypes { GAME_GMEFILE = 1 << 2, GAME_STRFILE = 1 << 3, GAME_TBLFILE = 1 << 4, + GAME_XTBLFILE = 1 << 5, - GAME_GFXIDXFILE = 1 << 5 + GAME_GFXIDXFILE = 1 << 6 }; enum GameIds { + GID_ELVIRA, + GID_ELVIRA2, + GID_WAXWORKS, + GID_SIMON1DOS, GID_SIMON1DOS_RU, GID_SIMON1DOS_INF, diff --git a/engines/simon/items.cpp b/engines/simon/items.cpp index 210b85dab1..be3b39cd68 100644 --- a/engines/simon/items.cpp +++ b/engines/simon/items.cpp @@ -288,6 +288,50 @@ void SimonEngine::setupOpcodes() { _numOpcodes = ARRAYSIZE(opcode_table); switch (getGameType()) { + case GType_WW: + // Confirmed + 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_SIMON1: opcode_table[70] = &SimonEngine::o1_printLongText; opcode_table[83] = &SimonEngine::o1_rescan; @@ -376,7 +420,7 @@ int SimonEngine::getScriptReturn() { } // ----------------------------------------------------------------------- -// Simon 1 Opcodes +// Common Opcodes // ----------------------------------------------------------------------- void SimonEngine::o_at() { @@ -1495,6 +1539,76 @@ void SimonEngine::o_unfreezeZones() { } // ----------------------------------------------------------------------- +// Waxworks 1 Opcodes +// ----------------------------------------------------------------------- + +uint16 SimonEngine::getDoorState(Item *item, uint16 d) { + uint16 mask = 3; + uint16 n; + + SubRoom *subRoom = (SubRoom *)findChildOfType(item, 1); + if (subRoom == NULL) + return 0; + + d <<= 1; + mask <<= d; + n = subRoom->roomExitStates & mask; + n >>= d; + + return n; +} + +uint16 SimonEngine::getExitOf(Item *item, uint16 d) { + uint16 x; + uint16 y = 0; + + SubRoom *subRoom = (SubRoom *)findChildOfType(item, 1); + if (subRoom == NULL) + return 0; + x = d; + while (x > y) { + if (getDoorState(item, y) == 0) + d--; + y++; + } + return subRoom->roomExit[d]; +} + +void SimonEngine::oww_whereTo() { + // 85: where to + Item *i = getNextItemPtr(); + int16 d = getVarOrByte(); + int16 f = getVarOrByte(); + + if (f == 1) + _subjectItem = _itemArrayPtr[getExitOf(i, d)]; + else + _objectItem = _itemArrayPtr[getExitOf(i, d)]; +} + +void SimonEngine::oww_menu() { + // 105: menu + getVarOrByte(); +} + +void SimonEngine::oww_textMenu() { + // 106: text menu + + /* byte tmp = getVarOrByte(); + TextMenu[tmp] = getVarOrByte(); */ + + getVarOrByte(); + getVarOrByte(); +} + +void SimonEngine::oww_ifDoorOpen() { + // 148: if door open + Item *item = getNextItemPtr(); + uint16 d = getVarOrByte(); + setScriptCondition(getDoorState(item, d) != 0); +} + +// ----------------------------------------------------------------------- // Simon 1 Opcodes // ----------------------------------------------------------------------- diff --git a/engines/simon/midiparser_s1d.cpp b/engines/simon/midiparser_s1d.cpp index 92e4146a9b..80755044f8 100644 --- a/engines/simon/midiparser_s1d.cpp +++ b/engines/simon/midiparser_s1d.cpp @@ -115,7 +115,8 @@ void MidiParser_S1D::parseNextEvent(EventInfo &info) { // OTherwise fall through to default. default: - error("MidiParser_S1D: Unexpected byte 0x%02X found!\n", (int) info.event); + //warning("MidiParser_S1D: Unexpected byte 0x%02X found!\n", (int) info.command()); + break; } } diff --git a/engines/simon/res.cpp b/engines/simon/res.cpp index 914f62134d..28f1e23946 100644 --- a/engines/simon/res.cpp +++ b/engines/simon/res.cpp @@ -40,6 +40,23 @@ using Common::File; namespace Simon { // Script opcodes to load into memory +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 ", + "II ", "I ", "I ", "II ", "II ", "IBB ", "BIB ", "BB ", "B ", "BI ", "IB ", "B ", "B ", "BN ", + "BN ", "BN ", "BB ", "BB ", "BN ", "BN ", "BB ", "BB ", "BN ", "BB ", "BN ", "B ", "I ", "IB ", + "IB ", "II ", "I ", "I ", "IN ", "B ", "T ", "T ", "NNNNNB ", "BT ", "BT ", "T ", " ", "B ", + "N ", "IBN ", "I ", "I ", "I ", "NN ", " ", " ", "IT ", "II ", "I ", "B ", " ", "IB ", "IBB ", + "IIB ", "T ", "T ", "T ", "IB ", "IB ", "IB ", "B ", "BB ", "IBB ", "NB ", "N ", "NBNNN ", "N ", + " ", "BNNNNNN ", "B ", " ", "B ", "B ", "BB ", "NNNNNIN ", "N ", "N ", "N ", "NNN ", "NBNN ", + "IBNN ", "IB ", "IB ", "IB ", "IB ", "N ", "N ", "N ", "BI ", " ", " ", "N ", "I ", "IBB ", + "NN ", "N ", "N ", "Ban ", "BB ", " ", " ", " ", " ", "IB ", "B ", " ", "II ", " ", "BI ", "N ", + "I ", "IB ", "IB ", "IB ", "IB ", "IB ", "IB ", "IB ", "BI ", "BB ", "B ", "B ", "B ", "B ", + "IBB ", "IBN ", "IB ", "B ", " ", "TB ", "TB ", "I ", "N ", "B ", "INB ", "INB ", "INB ", "INB ", + "INB ", "INB ", "INB ", "N ", " ", "INBB ", "B ", "B ", "Ian ", "B ", "B ", "B ", "B ", "T ", + "T ", "B ", " ", "I ", " ", " " +}; + static const char *const opcode_arg_table_simon1win[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 ", @@ -252,6 +269,27 @@ void SimonEngine::loadGamePcFile() { in.close(); + if (getGameType() == GType_WW) { + /* Read list of TABLE resources */ + in.open(getFileName(GAME_XTBLFILE)); + if (in.isOpen() == false) { + error("loadGamePcFile: Can't load table resources file '%s'", getFileName(GAME_XTBLFILE)); + } + + file_size = in.size(); + + _xtblList = (byte *)malloc(file_size); + if (_xtblList == NULL) + error("loadGamePcFile: Out of memory for strip table list"); + in.read(_xtblList, file_size); + in.close(); + + /* Remember the current state */ + _xsubroutineListOrg = _subroutineList; + _xtablesHeapPtrOrg = _tablesHeapPtr; + _xtablesHeapCurPosOrg = _tablesHeapCurPos; + } + /* Read list of TABLE resources */ in.open(getFileName(GAME_TBLFILE)); if (in.isOpen() == false) { @@ -361,6 +399,17 @@ void SimonEngine::readItemChildren(Common::File *in, Item *item, uint type) { subObject->objectFlagValue[k++] = in->readUint16BE(); subObject->objectName = (uint16)in->readUint32BE(); + } else if (type == 8) { + SubUserChain *chain = (SubUserChain *)allocateChildBlock(item, 8, sizeof(SubUserChain)); + chain->chChained = (uint16)fileReadItemID(in); + } else if (type == 9) { + setUserFlag(item, 0, in->readUint16BE()); + setUserFlag(item, 1, in->readUint16BE()); + setUserFlag(item, 2, in->readUint16BE()); + setUserFlag(item, 3, in->readUint16BE()); + } else if (type == 255) { + SubUserInherit *inherit = (SubUserInherit *)allocateChildBlock(item, 255, sizeof(SubUserInherit)); + inherit->inMaster = (uint16)fileReadItemID(in); } else { error("readItemChildren: invalid type %d", type); } @@ -380,16 +429,18 @@ byte *SimonEngine::readSingleOpcode(Common::File *in, byte *ptr) { const char *const *table; - if (getGameType() == GType_FF) { + if (getGameType() == GType_FF) table = opcode_arg_table_feeblefiles; - } else if ((getGameType() == GType_SIMON2) && (getFeatures() & GF_TALKIE)) + else if (getGameType() == GType_SIMON2 && (getFeatures() & GF_TALKIE)) table = opcode_arg_table_simon2win; else if (getGameType() == GType_SIMON2) table = opcode_arg_table_simon2dos; - else if (getFeatures() & GF_TALKIE) + else if (getGameType() == GType_SIMON1 && (getFeatures() & GF_TALKIE)) table = opcode_arg_table_simon1win; - else + else if (getGameType() == GType_SIMON1) table = opcode_arg_table_simon1dos; + else /* if (getGameType() == GType_WW) */ + table = opcode_arg_table_waxworks; i = 0; @@ -690,10 +741,14 @@ byte *SimonEngine::loadVGAFile(uint id, uint type, uint32 &dstSize) { if (getPlatform() == Common::kPlatformAmiga) { if (getFeatures() & GF_TALKIE) sprintf(filename, "%.3d%d.out", id / 2, type); - else + else sprintf(filename, "%.3d%d.pkd", id / 2, type); } else { - sprintf(filename, "%.3d%d.VGA", id / 2, type); + if (getGameType() == GType_WW) { + sprintf(filename, "%.2d%d.VGA", id / 2, type); + } else { + sprintf(filename, "%.3d%d.VGA", id / 2, type); + } } in.open(filename); diff --git a/engines/simon/simon.cpp b/engines/simon/simon.cpp index 74ed56eb03..9a254c28ce 100644 --- a/engines/simon/simon.cpp +++ b/engines/simon/simon.cpp @@ -99,14 +99,18 @@ SimonEngine::SimonEngine(OSystem *syst) _iconFilePtr = 0; - _tblList = 0; - _codePtr = 0; _localStringtable = 0; _stringIdLocalMin = 0; _stringIdLocalMax = 0; + _xtblList = 0; + _xtablesHeapPtrOrg = 0; + _xtablesHeapCurPosOrg = 0; + _xsubroutineListOrg = 0; + + _tblList = 0; _tablesHeapPtr = 0; _tablesHeapPtrOrg = 0; _tablesheapPtrNew = 0; @@ -114,9 +118,9 @@ SimonEngine::SimonEngine(OSystem *syst) _tablesHeapCurPos = 0; _tablesHeapCurPosOrg = 0; _tablesHeapCurPosNew = 0; + _subroutineListOrg = 0; _subroutineList = 0; - _subroutineListOrg = 0; _subroutine = 0; _dxSurfacePitch = 0; @@ -707,9 +711,9 @@ Child *SimonEngine::allocateChildBlock(Item *i, uint type, uint size) { } void SimonEngine::allocItemHeap() { - _itemHeapSize = 20000; + _itemHeapSize = 32000; _itemHeapCurPos = 0; - _itemHeapPtr = (byte *)calloc(20000, 1); + _itemHeapPtr = (byte *)calloc(32000, 1); } void SimonEngine::allocTablesHeap() { @@ -754,6 +758,7 @@ uint SimonEngine::getVarOrWord() { Item *SimonEngine::getNextItemPtr() { int a = getNextWord(); + switch (a) { case -1: return _subjectItem; @@ -764,6 +769,7 @@ Item *SimonEngine::getNextItemPtr() { case -7: return actor(); case -9: + assert (derefItem(me()->parent) != NULL); return derefItem(me()->parent); default: return derefItem(a); @@ -1163,7 +1169,11 @@ startOver: void SimonEngine::hitarea_stuff_helper() { time_t cur_time; - if (getGameType() == GType_SIMON1) { + if (getGameType() == GType_SIMON2 || getGameType() == GType_FF) { + if (_variableArray[254] || _variableArray[249]) { + hitarea_stuff_helper_2(); + } + } else { uint subr_id = (uint16)_variableArray[254]; if (subr_id != 0) { Subroutine *sub = getSubroutineByID(subr_id); @@ -1174,10 +1184,6 @@ void SimonEngine::hitarea_stuff_helper() { _variableArray[254] = 0; _runScriptReturn1 = false; } - } else { - if (_variableArray[254] || _variableArray[249]) { - hitarea_stuff_helper_2(); - } } time(&cur_time); @@ -1265,11 +1271,8 @@ void SimonEngine::loadZone(uint vga_res) { vpe->vgaFile2 = loadVGAFile(vga_res * 2 + 1, 2, size); vpe->vgaFile2End = vpe->vgaFile2 + size; - vpe->sfxFile = NULL; - if (getGameType() == GType_FF && getPlatform() == Common::kPlatformWindows) { - vpe->sfxFile = loadVGAFile(vga_res * 2, 3, size); - vpe->sfxFileEnd = vpe->sfxFile + size; - } + vpe->sfxFile = loadVGAFile(vga_res * 2, 3, size); + vpe->sfxFileEnd = vpe->sfxFile + size; } void SimonEngine::setZoneBuffers() { @@ -1343,8 +1346,7 @@ void SimonEngine::checkNoOverWrite(byte *end) { void SimonEngine::checkRunningAnims(byte *end) { VgaSprite *vsp; - if ((getGameType() == GType_SIMON1 || getGameType() == GType_SIMON2) && - (_lockWord & 0x20)) { + if (getGameType() != GType_FF && (_lockWord & 0x20)) { return; } @@ -1451,7 +1453,21 @@ void SimonEngine::set_video_mode_internal(uint16 mode, uint16 vga_res_id) { bb = _curVgaFile1; - if (getGameType() == GType_FF) { + 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) { 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); @@ -1499,7 +1515,9 @@ void SimonEngine::set_video_mode_internal(uint16 mode, uint16 vga_res_id) { vc_ptr_org = _vcPtr; - if (getGameType() == GType_FF) { + if (getGameType() == GType_WW) { + _vcPtr = _curVgaFile1 + READ_BE_UINT16(&((ImageHeader_WW *) b)->scriptOffs); + } else if (getGameType() == GType_FF) { _vcPtr = _curVgaFile1 + READ_LE_UINT16(&((ImageHeader_Feeble *) b)->scriptOffs); } else { _vcPtr = _curVgaFile1 + READ_BE_UINT16(&((ImageHeader_Simon *) b)->scriptOffs); @@ -1566,6 +1584,7 @@ void SimonEngine::waitForSync(uint a) { _syncCount = 0; _exitCutscene = false; _rightButtonDown = false; + while (_vgaWaitFor != 0) { if (_rightButtonDown) { if (_vgaWaitFor == 200 && (getGameType() == GType_FF || !getBitFlag(14))) { @@ -1631,7 +1650,7 @@ uint SimonEngine::itemPtrToID(Item *id) { bool SimonEngine::isSpriteLoaded(uint16 id, uint16 zoneNum) { VgaSprite *vsp = _vgaSprites; while (vsp->id) { - if (getGameType() == GType_SIMON1) { + if (getGameType() == GType_SIMON1 || getGameType() == GType_WW) { if (vsp->id == id) return true; } else { @@ -1791,9 +1810,12 @@ void SimonEngine::loadSprite(uint windowNum, uint zoneNum, uint vgaSpriteId, uin vsp->y = y; vsp->x = x; vsp->image = 0; - vsp->palette = palette; + if (getGameType() == GType_WW) + vsp->palette = 0; + else + vsp->palette = palette; vsp->id = vgaSpriteId; - if (getGameType() == GType_SIMON1) + if (getGameType() == GType_SIMON1 || getGameType() == GType_WW) vsp->zoneNum = zoneNum = vgaSpriteId / 100; else vsp->zoneNum = zoneNum; @@ -1809,7 +1831,13 @@ void SimonEngine::loadSprite(uint windowNum, uint zoneNum, uint vgaSpriteId, uin } pp = _curVgaFile1; - if (getGameType() == GType_FF) { + 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) { 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); @@ -1820,7 +1848,16 @@ void SimonEngine::loadSprite(uint windowNum, uint zoneNum, uint vgaSpriteId, uin } for (;;) { - if (getGameType() == GType_FF) { + 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 (READ_LE_UINT16(&((AnimationHeader_Feeble *) p)->id) == vgaSpriteId) { if (_startVgaScript) dump_vga_script(pp + READ_LE_UINT16(&((AnimationHeader_Feeble*)p)->scriptOffs), zoneNum, vgaSpriteId); @@ -2126,6 +2163,19 @@ void SimonEngine::loadMusic(uint music) { } midi.startTrack (0); + } else { + midi.stop(); + midi.setLoop (true); // Must do this BEFORE loading music. (GMF may have its own override.) + + char filename[15]; + File f; + sprintf(filename, "MOD%d.MUS", music); + f.open(filename); + if (f.isOpen() == false) + error("loadMusic: Can't load music from '%s'", filename); + + midi.loadS1D (&f); + midi.startTrack (0); } } diff --git a/engines/simon/simon.h b/engines/simon/simon.h index 49c35ba386..cc1d49764f 100644 --- a/engines/simon/simon.h +++ b/engines/simon/simon.h @@ -112,7 +112,8 @@ struct VgaTimerEntry { enum SIMONGameType { GType_FF = 0, GType_SIMON1 = 1, - GType_SIMON2 = 2 + GType_SIMON2 = 2, + GType_WW = 3 }; struct GameFileDescription { @@ -216,18 +217,23 @@ protected: byte *_iconFilePtr; - byte *_tblList; - const byte *_codePtr; byte **_localStringtable; uint _stringIdLocalMin, _stringIdLocalMax; + byte *_xtblList; + byte *_xtablesHeapPtrOrg; + uint _xtablesHeapCurPosOrg; + Subroutine *_xsubroutineListOrg; + + byte *_tblList; byte *_tablesHeapPtr, *_tablesHeapPtrOrg, *_tablesheapPtrNew; uint _tablesHeapSize, _tablesHeapCurPos, _tablesHeapCurPosOrg; uint _tablesHeapCurPosNew; + Subroutine *_subroutineListOrg; - Subroutine *_subroutineList, *_subroutineListOrg; + Subroutine *_subroutineList; uint _subroutine; uint _dxSurfacePitch; @@ -622,7 +628,8 @@ protected: void mouseOn(); void loadTextIntoMem(uint stringId); - void loadTablesIntoMem(uint subr_id); + bool loadTablesIntoMem(uint subr_id); + bool loadXTablesIntoMem(uint subr_id); uint loadTextFile(const char *filename, byte *dst); Common::File *openTablesFile(const char *filename); @@ -784,7 +791,7 @@ public: void vc54_no_op(); void vc55_moveBox(); void vc56_delay(); - void vc57_no_op(); + void vc57_blackPalette(); void vc58(); void vc59(); void vc60_killSprite(); @@ -949,6 +956,15 @@ public: void o_unloadZone(); void o_unfreezeZones(); + uint16 getDoorState(Item *item, uint16 d); + uint16 getExitOf(Item *item, uint16 d); + + // Opcodes, Waxworks only + void oww_whereTo(); + void oww_menu(); + void oww_textMenu(); + void oww_ifDoorOpen(); + // Opcodes, Simon 1 only void o1_printLongText(); void o1_rescan(); diff --git a/engines/simon/subroutine.cpp b/engines/simon/subroutine.cpp index 3587fa4a0b..2b9ed04432 100644 --- a/engines/simon/subroutine.cpp +++ b/engines/simon/subroutine.cpp @@ -40,11 +40,18 @@ Subroutine *SimonEngine::getSubroutineByID(uint subroutine_id) { return cur; } - loadTablesIntoMem(subroutine_id); + if (loadXTablesIntoMem(subroutine_id)) { + for (cur = _subroutineList; cur; cur = cur->next) { + if (cur->id == subroutine_id) + return cur; + } + } - for (cur = _subroutineList; cur; cur = cur->next) { - if (cur->id == subroutine_id) - return cur; + if (loadTablesIntoMem(subroutine_id)) { + for (cur = _subroutineList; cur; cur = cur->next) { + if (cur->id == subroutine_id) + return cur; + } } if (subroutine_id != 160) @@ -99,7 +106,7 @@ File *SimonEngine::openTablesFile_gme(const char *filename) { return _gameFile; } -void SimonEngine::loadTablesIntoMem(uint subr_id) { +bool SimonEngine::loadTablesIntoMem(uint subr_id) { byte *p; int i; uint min_num, max_num; @@ -108,7 +115,7 @@ void SimonEngine::loadTablesIntoMem(uint subr_id) { p = _tblList; if (p == NULL) - return; + return 0; while (*p) { for (i = 0; *p; p++, i++) @@ -151,12 +158,71 @@ void SimonEngine::loadTablesIntoMem(uint subr_id) { if (_tablesHeapCurPos > _tablesHeapSize) error("loadTablesIntoMem: Out of table memory"); - return; + return 1; } } } debug(1,"loadTablesIntoMem: 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; + char filename[30]; + File *in; + + p = _xtblList; + if (p == NULL) + return 0; + + while (*p) { + for (i = 0; *p; p++, i++) + filename[i] = *p; + filename[i] = 0; + p++; + + for (;;) { + min_num = (p[0] * 256) | p[1]; + p += 2; + + if (min_num == 0) + break; + + max_num = (p[0] * 256) | p[1]; + p += 2; + + if (subr_id >= min_num && subr_id <= max_num) { + _subroutineList = _xsubroutineListOrg; + _tablesHeapPtr = _xtablesHeapPtrOrg; + _tablesHeapCurPos = _xtablesHeapCurPosOrg; + _stringIdLocalMin = 1; + _stringIdLocalMax = 0; + + in = openTablesFile(filename); + readSubroutineBlock(in); + closeTablesFile(in); + + alignTableMem(); + + _subroutineListOrg = _subroutineList; + _tablesHeapPtrOrg = _tablesHeapPtr; + _tablesHeapCurPosOrg = _tablesHeapCurPos; + _tablesheapPtrNew = _tablesHeapPtr; + _tablesHeapCurPosNew = _tablesHeapCurPos; + + return 1; + } + } + } + + debug(1,"loadXTablesIntoMem: didn't find %d", subr_id); + return 0; } void SimonEngine::closeTablesFile(File *in) { diff --git a/engines/simon/vga.cpp b/engines/simon/vga.cpp index d9fcddb36c..8a7008dd05 100644 --- a/engines/simon/vga.cpp +++ b/engines/simon/vga.cpp @@ -92,7 +92,7 @@ void SimonEngine::setupVgaOpcodes() { &SimonEngine::vc54_no_op, &SimonEngine::vc55_moveBox, &SimonEngine::vc56_delay, - &SimonEngine::vc57_no_op, + &SimonEngine::vc57_blackPalette, &SimonEngine::vc58, &SimonEngine::vc59, &SimonEngine::vc60_killSprite, @@ -137,7 +137,7 @@ void SimonEngine::runVgaScript() { } } - if (getGameType() == GType_SIMON1) { + if (getGameType() == GType_SIMON1 || getGameType() == GType_WW) { opcode = READ_BE_UINT16(_vcPtr); _vcPtr += 2; } else { @@ -195,7 +195,7 @@ bool SimonEngine::vc_maybe_skip_proc_1(uint16 a, int16 b) { VgaSprite *SimonEngine::findCurSprite() { VgaSprite *vsp = _vgaSprites; while (vsp->id) { - if (getGameType() == GType_SIMON1) { + if (getGameType() == GType_SIMON1 || getGameType() == GType_WW) { if (vsp->id == _vgaCurSpriteId) break; } else { @@ -236,6 +236,17 @@ void SimonEngine::vcWriteVar(uint var, int16 value) { } void SimonEngine::vcSkipNextInstruction() { + static const byte opcodeParamLenWW[] = { + 0, 6, 2, 10, 6, 4, 2, 2, + 4, 4, 8, 2, 2, 2, 2, 2, + 2, 2, 2, 0, 4, 2, 2, 2, + 8, 0, 10, 0, 8, 0, 2, 2, + 0, 0, 0, 4, 4, 4, 2, 4, + 4, 4, 4, 2, 2, 4, 2, 2, + 2, 2, 2, 2, 2, 4, 6, 6, + 0, 0, 0, 0, 2, 2, 0, 0, + }; + static const byte opcodeParamLenSimon1[] = { 0, 6, 2, 10, 6, 4, 2, 2, 4, 4, 10, 0, 2, 2, 2, 2, @@ -281,9 +292,12 @@ void SimonEngine::vcSkipNextInstruction() { } else if (getGameType() == GType_SIMON2) { opcode = vcReadNextByte(); _vcPtr += opcodeParamLenSimon2[opcode]; - } else { + } else if (getGameType() == GType_SIMON1) { opcode = vcReadNextWord(); _vcPtr += opcodeParamLenSimon1[opcode]; + } else { + opcode = vcReadNextWord(); + _vcPtr += opcodeParamLenWW[opcode]; } if (_continousVgaScript) @@ -325,7 +339,21 @@ void SimonEngine::vc2_call() { bb = _curVgaFile1; - if (getGameType() == GType_FF) { + 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) { 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); @@ -351,7 +379,9 @@ void SimonEngine::vc2_call() { vcPtrOrg = _vcPtr; - if (getGameType() == GType_FF) { + if (getGameType() == GType_WW) { + _vcPtr = _curVgaFile1 + READ_BE_UINT16(&((ImageHeader_WW *) b)->scriptOffs); + } else if (getGameType() == GType_FF) { _vcPtr = _curVgaFile1 + READ_LE_UINT16(&((ImageHeader_Feeble *) b)->scriptOffs); } else { _vcPtr = _curVgaFile1 + READ_BE_UINT16(&((ImageHeader_Simon *) b)->scriptOffs); @@ -376,7 +406,7 @@ void SimonEngine::vc3_loadSprite() { windowNum = vcReadNextWord(); /* 0 */ - if (getGameType() == GType_SIMON1) { + if (getGameType() == GType_SIMON1 || getGameType() == GType_WW) { vgaSpriteId = vcReadNextWord(); /* 2 */ zoneNum = vgaSpriteId / 100; } else { @@ -395,7 +425,10 @@ void SimonEngine::vc3_loadSprite() { while (vsp->id) vsp++; - vsp->palette = palette; + if (getGameType() == GType_WW) + vsp->palette = 0; + else + vsp->palette = palette; vsp->windowNum = windowNum; vsp->priority = 0; vsp->flags = 0; @@ -420,7 +453,20 @@ void SimonEngine::vc3_loadSprite() { } pp = _curVgaFile1; - if (getGameType() == GType_FF) { + 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) { 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); @@ -465,7 +511,9 @@ void SimonEngine::vc3_loadSprite() { #endif if (_startVgaScript) { - if (getGameType() == GType_FF) { + if (getGameType() == GType_WW) { + dump_vga_script(_curVgaFile1 + READ_BE_UINT16(&((AnimationHeader_WW*)p)->scriptOffs), res, vgaSpriteId); + } else if (getGameType() == GType_FF) { dump_vga_script(_curVgaFile1 + READ_LE_UINT16(&((AnimationHeader_Feeble*)p)->scriptOffs), res, vgaSpriteId); } else { dump_vga_script(_curVgaFile1 + READ_BE_UINT16(&((AnimationHeader_Simon*)p)->scriptOffs), res, vgaSpriteId); @@ -473,7 +521,9 @@ void SimonEngine::vc3_loadSprite() { } } - if (getGameType() == GType_FF) { + if (getGameType() == GType_WW) { + addVgaEvent(_vgaBaseDelay, _curVgaFile1 + READ_BE_UINT16(&((AnimationHeader_WW *) p)->scriptOffs), vgaSpriteId, res); + } else if (getGameType() == GType_FF) { addVgaEvent(_vgaBaseDelay, _curVgaFile1 + READ_LE_UINT16(&((AnimationHeader_Feeble *) p)->scriptOffs), vgaSpriteId, res); } else { addVgaEvent(_vgaBaseDelay, _curVgaFile1 + READ_BE_UINT16(&((AnimationHeader_Simon *) p)->scriptOffs), vgaSpriteId, res); @@ -771,17 +821,21 @@ void SimonEngine::vc10_draw() { if (getGameType() == GType_FF) { state.palette = (_vcPtr[0] * 16); - } else { + _vcPtr += 2; + } else if (getGameType() == GType_SIMON1 || getGameType() == GType_SIMON2) { state.palette = (_vcPtr[1] * 16); + _vcPtr += 2; + } else { + state.palette = 0; } - _vcPtr += 2; + state.x = (int16)vcReadNextWord(); state.x -= _scrollX; state.y = (int16)vcReadNextWord(); state.y -= _scrollY; - if (getGameType() == GType_SIMON1) { + if (getGameType() == GType_SIMON1 || getGameType() == GType_WW) { state.flags = vcReadNextWord(); } else { state.flags = vcReadNextByte(); @@ -842,7 +896,7 @@ void SimonEngine::vc10_draw() { return; } - if (getGameType() == GType_SIMON1 || getGameType() == GType_SIMON2) { + if (getGameType() == GType_SIMON1 || getGameType() == GType_SIMON2 || getGameType() == GType_WW) { if (state.flags & kDFCompressedFlip) { state.depack_src = vc10_uncompressFlip(state.depack_src, width, height); } else if (state.flags & kDFFlip) { @@ -870,7 +924,7 @@ bool SimonEngine::drawImages_clip(VC10_state *state) { vlut = &_video_windows[_windowNum * 4]; - if (getGameType() == GType_SIMON1 || getGameType() == GType_SIMON2) { + if (getGameType() == GType_SIMON1 || getGameType() == GType_SIMON2 || getGameType() == GType_WW) { state->draw_width = state->width * 2; } @@ -914,7 +968,7 @@ bool SimonEngine::drawImages_clip(VC10_state *state) { assert(state->draw_width != 0 && state->draw_height != 0); - if (getGameType() == GType_SIMON1 || getGameType() == GType_SIMON2) { + if (getGameType() == GType_SIMON1 || getGameType() == GType_SIMON2 || getGameType() == GType_WW) { state->draw_width *= 4; } @@ -1152,7 +1206,8 @@ void SimonEngine::drawImages(VC10_state *state) { } while (++w != state->draw_width); /* vc10_helper_5 */ - } else if (((_lockWord & 0x20) && state->palette == 0) || state->palette == 0xC0) { + } else if ((((_lockWord & 0x20) && state->palette == 0) || state->palette == 0xC0) && + getGameType() != GType_WW) { const byte *src; byte *dst; uint h, i; @@ -1413,7 +1468,12 @@ void SimonEngine::scaleClip(int16 h, int16 w, int16 y, int16 x, int16 scrollY) { } void SimonEngine::vc11_clearPathFinder() { - memset(&_pathFindArray, 0, sizeof(_pathFindArray)); + if (getGameType() == GType_WW) { + // FIXME + vcReadNextWord(); + } else { + memset(&_pathFindArray, 0, sizeof(_pathFindArray)); + } } void SimonEngine::vc12_delay() { @@ -1487,13 +1547,18 @@ void SimonEngine::vc16_waitSync() { } void SimonEngine::vc17_setPathfinderItem() { - uint16 a = vcReadNextWord(); - _pathFindArray[a - 1] = (const uint16 *)_vcPtr; + if (getGameType() == GType_WW) { + // FIXME + vcReadNextWord(); + } else { + uint16 a = vcReadNextWord(); + _pathFindArray[a - 1] = (const uint16 *)_vcPtr; - int end = (getGameType() == GType_FF) ? 9999 : 999; - while (readUint16Wrapper(_vcPtr) != end) - _vcPtr += 4; - _vcPtr += 2; + int end = (getGameType() == GType_FF) ? 9999 : 999; + while (readUint16Wrapper(_vcPtr) != end) + _vcPtr += 4; + _vcPtr += 2; + } } void SimonEngine::vc18_jump() { @@ -1522,7 +1587,7 @@ void SimonEngine::vc20_setRepeat() { void SimonEngine::vc21_endRepeat() { int16 a = vcReadNextWord(); const byte *tmp = _vcPtr + a; - if (getGameType() == GType_SIMON1) + if (getGameType() == GType_SIMON1 || getGameType() == GType_WW) tmp += 4; else tmp += 3; @@ -1536,29 +1601,48 @@ void SimonEngine::vc21_endRepeat() { } void SimonEngine::vc22_setSpritePalette() { - uint16 a = vcReadNextWord(); - uint16 b = vcReadNextWord(); - uint num = a == 0 ? 32 : 16; - uint palSize = 96; - byte *palptr, *src; - - if (getGameType() == GType_FF) { - a = 0; + byte *offs, *palptr, *src; + uint16 a, b, num, palSize; + + if (getGameType() != GType_WW) + 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) { num = 256; palSize = 768; - } - palptr = &_displayPalette[(a * 64)]; - src = _curVgaFile1 + 6 + b * palSize; + palptr = _displayPalette; + offs = _curVgaFile1 + 6; + } else { + num = a == 0 ? 32 : 16; + palSize = 96; + + palptr = &_displayPalette[(a * 64)]; + offs = _curVgaFile1 + 6; + } + src = offs + b * palSize; do { - palptr[0] = src[0] * 4; - palptr[1] = src[1] * 4; - palptr[2] = src[2] * 4; + if (getGameType() == GType_WW) { + uint16 color = READ_BE_UINT16(src); + palptr[2] = ((color & 0x00f) >> 0) * 32; + palptr[1] = ((color & 0x0f0) >> 4) * 32; + palptr[0] = ((color & 0xf00) >> 8) * 32; + } else { + palptr[0] = src[0] * 4; + palptr[1] = src[1] * 4; + palptr[2] = src[2] * 4; + } palptr[3] = 0; palptr += 4; - src += 3; + src += (getGameType() == GType_WW) ? 2 : 3; } while (--num); _paletteFlag = 2; @@ -1607,7 +1691,7 @@ void SimonEngine::vc24_setSpriteXY() { vsp->x += (int16)vcReadNextWord(); vsp->y += (int16)vcReadNextWord(); - if (getGameType() == GType_SIMON1) { + if (getGameType() == GType_SIMON1 || getGameType() == GType_WW) { vsp->flags = vcReadNextWord(); } else { vsp->flags = vcReadNextByte(); @@ -1702,8 +1786,12 @@ void SimonEngine::vc31_setWindow() { } void SimonEngine::vc32_copyVar() { - uint16 a = vcReadVar(vcReadNextWord()); - vcWriteVar(vcReadNextWord(), a); + if (getGameType() == GType_WW) { + // FIXME + } else { + uint16 a = vcReadVar(vcReadNextWord()); + vcWriteVar(vcReadNextWord(), a); + } } void SimonEngine::vc33_setMouseOn() { @@ -1744,9 +1832,15 @@ void SimonEngine::vc36_setWindowImage() { } void SimonEngine::vc37_addToSpriteY() { - VgaSprite *vsp = findCurSprite(); - vsp->y += vcReadVar(vcReadNextWord()); - _vgaSpriteChanged++; + if (getGameType() == GType_WW) { + // FIXME + vcReadNextWord(); + vcReadNextWord(); + } else { + VgaSprite *vsp = findCurSprite(); + vsp->y += vcReadVar(vcReadNextWord()); + _vgaSpriteChanged++; + } } void SimonEngine::vc38_skipIfVarZero() { @@ -1838,9 +1932,15 @@ void SimonEngine::vc44_skipIfBitSet() { } void SimonEngine::vc45_setSpriteX() { - VgaSprite *vsp = findCurSprite(); - vsp->x = vcReadVar(vcReadNextWord()); - _vgaSpriteChanged++; + if (getGameType() == GType_WW) { + //FIXME + vcReadNextWord(); + vcReadNextWord(); + } else { + VgaSprite *vsp = findCurSprite(); + vsp->x = vcReadVar(vcReadNextWord()); + _vgaSpriteChanged++; + } } void SimonEngine::vc46_setSpriteY() { @@ -1850,15 +1950,23 @@ void SimonEngine::vc46_setSpriteY() { } void SimonEngine::vc47_addToVar() { - uint16 var = vcReadNextWord(); - vcWriteVar(var, vcReadVar(var) + vcReadVar(vcReadNextWord())); + if (getGameType() == GType_WW) { + //FIXME + vcReadNextWord(); + } else { + uint16 var = vcReadNextWord(); + vcWriteVar(var, vcReadVar(var) + vcReadVar(vcReadNextWord())); + } } void SimonEngine::vc48_setPathFinder() { uint16 a = (uint16)_variableArrayPtr[12]; const uint16 *p = _pathFindArray[a - 1]; - if (getGameType() == GType_FF) { + if (getGameType() == GType_WW) { + //FIXME + vcReadNextWord(); + } else if (getGameType() == GType_FF) { VgaSprite *vsp = findCurSprite(); int16 x, y, ydiff; int16 x1, y1, x2, y2; @@ -2036,14 +2144,34 @@ void SimonEngine::vc55_moveBox() { } void SimonEngine::vc56_delay() { - uint16 num = vcReadVarOrWord() * _frameRate; + if (getGameType() == GType_SIMON2) { + uint16 num = vcReadVarOrWord() * _frameRate; - addVgaEvent(num + _vgaBaseDelay, _vcPtr, _vgaCurSpriteId, _vgaCurZoneNum); - _vcPtr = (byte *)&_vc_get_out_of_code; + addVgaEvent(num + _vgaBaseDelay, _vcPtr, _vgaCurSpriteId, _vgaCurZoneNum); + _vcPtr = (byte *)&_vc_get_out_of_code; + } else if (getGameType() == GType_WW) { + byte *src = _curVgaFile2 + 32; + byte *dst = getBackBuf(); + + uint8 palette[1024]; + for (int i = 0; i < 256; i++) { + palette[i * 4 + 0] = *src++ * 4; + palette[i * 4 + 1] = *src++ * 4; + palette[i * 4 + 2] = *src++ * 4; + palette[i * 4 + 3] = 0; + } + + _system->setPalette(palette, 0, 256); + memcpy(dst, src, _screenHeight * _screenWidth); + } } -void SimonEngine::vc57_no_op() { - /* unused */ +void SimonEngine::vc57_blackPalette() { + if (getGameType() == GType_WW) { + //uint8 palette[1024]; + //memset(palette, 0, sizeof(palette)); + //_system->setPalette(palette, 0, 256); + } } void SimonEngine::vc58() { @@ -2067,10 +2195,7 @@ void SimonEngine::vc58() { } void SimonEngine::vc59() { - if (getGameType() == GType_SIMON1) { - if (!_sound->isVoiceActive()) - vcSkipNextInstruction(); - } else { + if (getGameType() == GType_SIMON2 || getGameType() == GType_FF) { uint16 file = vcReadNextWord(); uint16 start = vcReadNextWord(); uint16 end = vcReadNextWord() + 1; @@ -2078,6 +2203,12 @@ void SimonEngine::vc59() { do { vc_kill_sprite(file, start); } while (++start != end); + } else if (getGameType() == GType_SIMON1) { + if (!_sound->isVoiceActive()) + vcSkipNextInstruction(); + } else { + // Skip if not EGA + vcSkipNextInstruction(); } } @@ -2139,10 +2270,15 @@ void SimonEngine::vc60_killSprite() { } void SimonEngine::vc61_setMaskImage() { + if (getGameType() == GType_WW) { + // FIXME + vcReadVarOrWord(); + return; + } + VgaSprite *vsp = findCurSprite(); vsp->image = vcReadVarOrWord(); - vsp->x += vcReadNextWord(); vsp->y += vcReadNextWord(); vsp->flags = kDFMasked | kDFUseFrontBuf; @@ -2156,7 +2292,8 @@ void SimonEngine::vc62_fastFadeOut() { if (!_fastFadeOutFlag) { uint i, fadeSize, fadeCount; - _fastFadeOutFlag = true; + if (getGameType() != GType_WW) + _fastFadeOutFlag = true; _fastFadeCount = 256; if (getGameType() == GType_SIMON1 || getGameType() == GType_SIMON2) { diff --git a/engines/simon/vga.h b/engines/simon/vga.h index 29731c29c3..fece63bf3a 100644 --- a/engines/simon/vga.h +++ b/engines/simon/vga.h @@ -92,6 +92,34 @@ struct AnimationHeader_Simon { }; +// Waxworks +struct VgaFileHeader2_WW { + uint16 x_1; + uint16 imageCount; + uint16 x_2; + uint16 animationCount; + uint16 x_3; + uint16 imageTable; + uint16 x_4; + uint16 animationTable; + uint16 x_5; +}; + +struct ImageHeader_WW { + uint16 id; + uint16 x_1; + uint16 x_2; + uint16 scriptOffs; +}; + +struct AnimationHeader_WW { + uint16 id; + uint16 x_1; + uint16 x_2; + uint16 scriptOffs; +}; + + #include "common/pack-end.h" // END STRUCT PACKING enum DrawFlags { |