Expand Simon engine

svn-id: r23939
This commit is contained in:
Travis Howell 2006-09-19 11:59:13 +00:00
parent fd85c13d8f
commit ab2cb0b30a
13 changed files with 972 additions and 124 deletions

View File

@ -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 != '|')

View File

@ -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",

View File

@ -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();

View File

@ -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",

View File

@ -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,

View File

@ -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() {
@ -1494,6 +1538,76 @@ void SimonEngine::o_unfreezeZones() {
unfreezeBottom();
}
// -----------------------------------------------------------------------
// 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
// -----------------------------------------------------------------------

View File

@ -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;
}
}

View File

@ -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);

View File

@ -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);
@ -2125,6 +2162,19 @@ void SimonEngine::loadMusic(uint music) {
midi.loadSMF (&f, 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);
}
}

View File

@ -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();

View File

@ -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) {

View File

@ -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;
byte *offs, *palptr, *src;
uint16 a, b, num, palSize;
if (getGameType() == GType_FF) {
a = 0;
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) {

View File

@ -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 {