aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTravis Howell2006-09-19 11:59:13 +0000
committerTravis Howell2006-09-19 11:59:13 +0000
commitab2cb0b30ad15c2cd33c82989461bdcf44644bd2 (patch)
treed8209b59ea5b444d2a7b7694c8b1cd13449d4ee3
parentfd85c13d8f5a8c58e056fe51658a5b83da323053 (diff)
downloadscummvm-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.cpp10
-rw-r--r--engines/simon/debug.h321
-rw-r--r--engines/simon/draw.cpp40
-rw-r--r--engines/simon/game.cpp24
-rw-r--r--engines/simon/intern.h18
-rw-r--r--engines/simon/items.cpp116
-rw-r--r--engines/simon/midiparser_s1d.cpp3
-rw-r--r--engines/simon/res.cpp67
-rw-r--r--engines/simon/simon.cpp98
-rw-r--r--engines/simon/simon.h28
-rw-r--r--engines/simon/subroutine.cpp80
-rw-r--r--engines/simon/vga.cpp265
-rw-r--r--engines/simon/vga.h28
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 *)(&params[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 *)(&params[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 *)(&params[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 {