[Scummvm-cvs-logs] SF.net SVN: scummvm: [23994] scummvm/trunk/engines/simon

kirben at users.sourceforge.net kirben at users.sourceforge.net
Fri Sep 29 01:22:19 CEST 2006


Revision: 23994
          http://svn.sourceforge.net/scummvm/?rev=23994&view=rev
Author:   kirben
Date:     2006-09-28 16:22:07 -0700 (Thu, 28 Sep 2006)

Log Message:
-----------
Expand Simon engine more

Modified Paths:
--------------
    scummvm/trunk/engines/simon/debug.cpp
    scummvm/trunk/engines/simon/game.cpp
    scummvm/trunk/engines/simon/intern.h
    scummvm/trunk/engines/simon/items.cpp
    scummvm/trunk/engines/simon/midiparser_s1d.cpp
    scummvm/trunk/engines/simon/res.cpp
    scummvm/trunk/engines/simon/simon.cpp
    scummvm/trunk/engines/simon/simon.h
    scummvm/trunk/engines/simon/sound.cpp
    scummvm/trunk/engines/simon/subroutine.cpp
    scummvm/trunk/engines/simon/vga.cpp

Modified: scummvm/trunk/engines/simon/debug.cpp
===================================================================
--- scummvm/trunk/engines/simon/debug.cpp	2006-09-28 13:01:13 UTC (rev 23993)
+++ scummvm/trunk/engines/simon/debug.cpp	2006-09-28 23:22:07 UTC (rev 23994)
@@ -37,10 +37,18 @@
 	byte opcode;
 	const char *s, *st;
 
-	opcode = *p++;
-	if (opcode == 255)
-		return NULL;
-	if (getGameType() == GType_FF) {
+	if (getGameType() == GType_ELVIRA || getGameType() == GType_ELVIRA2) {
+		opcode = READ_BE_UINT16(p);
+		p += 2;
+		if (opcode = 10000)
+			return NULL;
+	} else {
+		opcode = *p++;
+		if (opcode == 255)
+			return NULL;
+	}
+
+	if (getGameType() == GType_FF || getGameType() == GType_PP) {
 		st = s = feeblefiles_opcode_name_table[opcode];
 	} else if (getGameType() == GType_SIMON2 && getFeatures() & GF_TALKIE) {
 		st = s = simon2talkie_opcode_name_table[opcode];
@@ -192,7 +200,7 @@
 			return;
 		}
 
-		if (getGameType() == GType_FF) {
+		if (getGameType() == GType_FF || getGameType() == GType_PP) {
 			strn = str = feeblefiles_video_opcode_name_table[opcode];
 		} else if (getGameType() == GType_SIMON2) {
 			strn = str = simon2_video_opcode_name_table[opcode];
@@ -206,7 +214,7 @@
 			strn++;
 		printf("%.2d: %s ", opcode, strn + 1);
 
-		int end = (getGameType() == GType_FF) ? 9999 : 999;
+		int end = (getGameType() == GType_FF || getGameType() == GType_PP) ? 9999 : 999;
 		for (; *str != '|'; str++) {
 			switch (*str) {
 			case 'x':
@@ -344,7 +352,7 @@
 	state.dh = h;
 	state.y_skip = 0;
 
-	if (getGameType() == GType_FF) {
+	if (getGameType() == GType_FF || getGameType() == GType_PP) {
 		for (i = 0; i != w; i++) {
 			byte *c = vc10_depackColumn(&state);
 			for (j = 0; j != h; j++) {

Modified: scummvm/trunk/engines/simon/game.cpp
===================================================================
--- scummvm/trunk/engines/simon/game.cpp	2006-09-28 13:01:13 UTC (rev 23993)
+++ scummvm/trunk/engines/simon/game.cpp	2006-09-28 23:22:07 UTC (rev 23994)
@@ -67,10 +67,15 @@
 };
 
 static const PlainGameDescriptor simonGames[] = {
+	{"jumble", "Jumble"},
+	{"puzzle", "Puzzle"},
+	{"swampy", "Swampy Adventures"},
 	{"feeble", "The Feeble Files"},
 	{"simon1", "Simon the Sorcerer 1"},
 	{"simon2", "Simon the Sorcerer 2"},
 	{"waxworks", "Waxworks"},
+	{"elvira2", "Elvira 2"},
+	{"elvira", "Elvira"},
 	{NULL, NULL}
 };
 
@@ -596,9 +601,60 @@
 	{ "xtbllist",		GAME_XTBLFILE,	"6c7b3db345d46349a5226f695c03e20f"},
 };
 
+static GameFileDescription ELVIRA2_GameFiles[] = {
+	{ "gamepc",		GAME_BASEFILE,	"00000000000000000000000000000000"},
+	{ "icon.dat",		GAME_ICONFILE,	"00000000000000000000000000000000"},
+	{ "stripped.txt",	GAME_STRFILE,	"00000000000000000000000000000000"},
+	{ "tbllist",		GAME_TBLFILE,	"00000000000000000000000000000000"},
+};
+
+static GameFileDescription ELVIRA_GameFiles[] = {
+	{ "gamepc",		GAME_BASEFILE,	"9076d507d60cc454df662316438ec843"},
+	{ "icon.dat",		GAME_ICONFILE,	"fda48c9da7f3e72d0313e2f5f760fc45"},
+	{ "tbllist",		GAME_TBLFILE,	"319f6b227c7822a551f57d24e70f8149"},
+};
+
+static GameFileDescription JUMBLE_GameFiles[] = {
+	{ "Gjumble",		GAME_BASEFILE,	"d54cce46d339038d1a6b74ea213655bc"},
+};
+
+static GameFileDescription PUZZLE_GameFiles[] = {
+	{ "Gpuzzle",		GAME_BASEFILE,	"3f80dac8e0d85401a1058a560fe49ab6"},
+};
+
+static GameFileDescription SWAMPY_GameFiles[] = {
+	{ "Gswampy",		GAME_BASEFILE,	"3a6d4d7b2433e660f2483f9396cc87a2"},
+};
+
 static GameDescription gameDescriptions[] = {
-	// Waxworks - English Floopy
+	// Elvira - English Floppy
 	{
+		"elvira",
+		GType_ELVIRA,
+		GID_ELVIRA,
+		"Floppy",
+		ARRAYSIZE(ELVIRA_GameFiles),
+		ELVIRA_GameFiles,
+		GF_OLD_BUNDLE,
+		Common::EN_ANY,
+		Common::kPlatformPC,
+	},
+
+	// Elvira 2 - English Floppy
+	{
+		"elvira2",
+		GType_ELVIRA2,
+		GID_ELVIRA2,
+		"Floppy",
+		ARRAYSIZE(ELVIRA2_GameFiles),
+		ELVIRA2_GameFiles,
+		GF_OLD_BUNDLE,
+		Common::EN_ANY,
+		Common::kPlatformPC,
+	},
+
+	// Waxworks - English Floppy
+	{
 		"waxworks",
 		GType_WW,
 		GID_WAXWORKS,
@@ -1379,6 +1435,46 @@
 		Common::ES_ESP,
 		Common::kPlatformWindows,
 	},
+
+	// Jumble
+	{
+		"jumble",
+		GType_PP,
+		GID_JUMBLE,
+		"CD",
+		ARRAYSIZE(JUMBLE_GameFiles),
+		JUMBLE_GameFiles,
+		GF_OLD_BUNDLE | GF_TALKIE,
+		Common::EN_ANY,
+		Common::kPlatformWindows,
+	},
+
+	// Puzzle
+	{
+		"puzzle",
+		GType_PP,
+		GID_PUZZLE,
+		"CD",
+		ARRAYSIZE(PUZZLE_GameFiles),
+		PUZZLE_GameFiles,
+		GF_OLD_BUNDLE | GF_TALKIE,
+		Common::EN_ANY,
+		Common::kPlatformWindows,
+	},
+
+	// Swampy Adventures
+	{
+		"swampy",
+		GType_PP,
+		GID_SWAMPY,
+		"CD",
+		ARRAYSIZE(SWAMPY_GameFiles),
+		SWAMPY_GameFiles,
+		GF_OLD_BUNDLE | GF_TALKIE,
+		Common::EN_ANY,
+		Common::kPlatformWindows,
+	},
+
 };
 
 DetectedGame toDetectedGame(const GameDescription &g) {

Modified: scummvm/trunk/engines/simon/intern.h
===================================================================
--- scummvm/trunk/engines/simon/intern.h	2006-09-28 13:01:13 UTC (rev 23993)
+++ scummvm/trunk/engines/simon/intern.h	2006-09-28 23:22:07 UTC (rev 23994)
@@ -71,6 +71,7 @@
 	int16 adjective;
 	int16 state;										/* signed int */
 	uint16 classFlags;
+	uint16 itemName;
 	Child *children;
 
 	Item() { memset(this, 0, sizeof(*this)); }
@@ -248,7 +249,11 @@
 	GID_FEEBLEFILES_FR,
 	GID_FEEBLEFILES_DE,
 	GID_FEEBLEFILES_IT,
-	GID_FEEBLEFILES_ES
+	GID_FEEBLEFILES_ES,
+
+	GID_JUMBLE,
+	GID_PUZZLE,
+	GID_SWAMPY
 };
 
 } // End of namespace Simon

Modified: scummvm/trunk/engines/simon/items.cpp
===================================================================
--- scummvm/trunk/engines/simon/items.cpp	2006-09-28 13:01:13 UTC (rev 23993)
+++ scummvm/trunk/engines/simon/items.cpp	2006-09-28 23:22:07 UTC (rev 23994)
@@ -288,6 +288,55 @@
 	_numOpcodes = ARRAYSIZE(opcode_table);
 
 	switch (getGameType()) {
+	case GType_ELVIRA:
+	case GType_ELVIRA2:
+		// Confirmed
+		opcode_table[48] = &SimonEngine::o_destroy;
+		opcode_table[51] = &SimonEngine::o_place;
+		opcode_table[91] = &SimonEngine::o_message;
+
+		opcode_table[70] = &SimonEngine::o1_printLongText;
+		opcode_table[83] = &SimonEngine::o1_rescan;
+		opcode_table[98] = &SimonEngine::o1_animate;
+		opcode_table[99] = &SimonEngine::o1_stopAnimate;
+		opcode_table[85] = &SimonEngine::oww_whereTo;
+		opcode_table[105] = &SimonEngine::oww_menu;
+		opcode_table[106] = &SimonEngine::oww_textMenu;
+		opcode_table[127] = &SimonEngine::o1_playTune;
+		opcode_table[148] = &SimonEngine::oww_ifDoorOpen;
+		opcode_table[179] = &SimonEngine::o_isAdjNoun;
+		opcode_table[180] = &SimonEngine::o_b2Set;
+		opcode_table[181] = &SimonEngine::o_b2Clear;
+		opcode_table[182] = &SimonEngine::o_b2Zero;
+		opcode_table[183] = &SimonEngine::o_b2NotZero;
+
+		// Code difference, check if triggered
+		opcode_table[161] = NULL;
+		opcode_table[162] = NULL;
+		opcode_table[163] = NULL;
+		opcode_table[164] = NULL;
+		opcode_table[165] = NULL;
+		opcode_table[166] = NULL;
+		opcode_table[167] = NULL;
+		opcode_table[168] = NULL;
+		opcode_table[169] = NULL;
+		opcode_table[170] = NULL;
+		opcode_table[171] = NULL;
+		opcode_table[172] = NULL;
+		opcode_table[173] = NULL;
+		opcode_table[174] = NULL;
+		opcode_table[175] = NULL;
+		opcode_table[176] = NULL;
+		opcode_table[177] = NULL;
+		opcode_table[178] = NULL;
+		opcode_table[184] = NULL;
+		opcode_table[185] = NULL;
+		opcode_table[186] = NULL;
+		opcode_table[187] = NULL;
+		opcode_table[188] = NULL;
+		opcode_table[189] = NULL;
+		opcode_table[190] = NULL;
+		break;
 	case GType_WW:
 		// Confirmed
 		opcode_table[70] = &SimonEngine::o1_printLongText;
@@ -398,6 +447,50 @@
 		opcode_table[198] = &SimonEngine::o3_b3Zero;
 		opcode_table[199] = &SimonEngine::o3_b3NotZero;
 		break;
+	case GType_PP:
+		// Confirmed
+		opcode_table[30] = &SimonEngine::o4_opcode30;
+		opcode_table[38] = &SimonEngine::o4_opcode38;
+		opcode_table[105] = &SimonEngine::o4_loadHiScores;
+		opcode_table[106] = &SimonEngine::o4_checkHiScores;
+
+		// To check
+		opcode_table[23] = &SimonEngine::o3_chance;
+		opcode_table[37] = &SimonEngine::o3_jumpOut;
+		opcode_table[65] = &SimonEngine::o3_addTextBox;
+		opcode_table[70] = &SimonEngine::o3_printLongText;
+		opcode_table[83] = &SimonEngine::o2_rescan;
+		opcode_table[98] = &SimonEngine::o2_animate;
+		opcode_table[99] = &SimonEngine::o2_stopAnimate;
+		opcode_table[107] = &SimonEngine::o3_addBox;
+		opcode_table[122] = &SimonEngine::o3_oracleTextDown;
+		opcode_table[123] = &SimonEngine::o3_oracleTextUp;
+		opcode_table[124] = &SimonEngine::o3_ifTime;
+		opcode_table[127] = &SimonEngine::o3_playTune;
+		opcode_table[131] = &SimonEngine::o3_setTime;
+		opcode_table[132] = &SimonEngine::o3_saveUserGame,
+		opcode_table[133] = &SimonEngine::o3_loadUserGame;
+		opcode_table[134] = &SimonEngine::o3_listSaveGames;
+		opcode_table[135] = &SimonEngine::o3_checkCD;
+		opcode_table[161] = &SimonEngine::o3_screenTextBox;
+		opcode_table[165] = &SimonEngine::o3_isAdjNoun;
+		opcode_table[171] = &SimonEngine::o3_hyperLinkOn;
+		opcode_table[172] = &SimonEngine::o3_hyperLinkOff;
+		opcode_table[173] = &SimonEngine::o3_checkPaths;
+		opcode_table[177] = &SimonEngine::o3_screenTextPObj;
+		opcode_table[181] = &SimonEngine::o3_mouseOff;
+		opcode_table[182] = &SimonEngine::o3_loadVideo;
+		opcode_table[183] = &SimonEngine::o3_playVideo;
+		opcode_table[187] = &SimonEngine::o3_centreScroll;
+		opcode_table[188] = &SimonEngine::o2_isShortText;
+		opcode_table[189] = &SimonEngine::o2_clearMarks;
+		opcode_table[190] = &SimonEngine::o2_waitMark;
+		opcode_table[191] = &SimonEngine::o3_resetPVCount;
+		opcode_table[192] = &SimonEngine::o3_setPathValues;
+		opcode_table[193] = &SimonEngine::o3_stopClock;
+		opcode_table[194] = &SimonEngine::o3_restartClock;
+		opcode_table[195] = &SimonEngine::o3_setColour;
+		break;
 	default:
 		error("setupOpcodes: Unknown game");
 	}
@@ -588,7 +681,7 @@
 
 void SimonEngine::o_let() {
 	// 42: set var
-	uint var = getVarOrByte();
+	uint var = getVarWrapper();
 	writeVariable(var, getVarOrWord());
 }
 
@@ -600,31 +693,31 @@
 
 void SimonEngine::o_sub() {
 	// 44: sub
-	uint var = getVarOrByte();
+	uint var = getVarWrapper();
 	writeVariable(var, readVariable(var) - getVarOrWord());
 }
 
 void SimonEngine::o_addf() {
 	// 45: add f
-	uint var = getVarOrByte();
+	uint var = getVarWrapper();
 	writeVariable(var, readVariable(var) + getNextVarContents());
 }
 
 void SimonEngine::o_subf() {
 	// 46: sub f
-	uint var = getVarOrByte();
+	uint var = getVarWrapper();
 	writeVariable(var, readVariable(var) - getNextVarContents());
 }
 
 void SimonEngine::o_mul() {
 	// 47: mul
-	uint var = getVarOrByte();
+	uint var = getVarWrapper();
 	writeVariable(var, readVariable(var) * getVarOrWord());
 }
 
 void SimonEngine::o_div() {
 	// 48: div
-	uint var = getVarOrByte();
+	uint var = getVarWrapper();
 	int value = getVarOrWord();
 	if (value == 0)
 		error("o_div: Division by zero");
@@ -633,13 +726,13 @@
 
 void SimonEngine::o_mulf() {
 	// 49: mul f
-	uint var = getVarOrByte();
+	uint var = getVarWrapper();
 	writeVariable(var, readVariable(var) * getNextVarContents());
 }
 
 void SimonEngine::o_divf() {
 	// 50: div f
-	uint var = getVarOrByte();
+	uint var = getVarWrapper();
 	int value = getNextVarContents();
 	if (value == 0)
 		error("o_divf: Division by zero");
@@ -648,7 +741,7 @@
 
 void SimonEngine::o_mod() {
 	// 51: mod
-	uint var = getVarOrByte();
+	uint var = getVarWrapper();
 	int value = getVarOrWord();
 	if (value == 0)
 		error("o_mod: Division by zero");
@@ -657,7 +750,7 @@
 
 void SimonEngine::o_modf() {
 	// 52: mod f
-	uint var = getVarOrByte();
+	uint var = getVarWrapper();
 	int value = getNextVarContents();
 	if (value == 0)
 		error("o_modf: Division by zero");
@@ -666,7 +759,7 @@
 
 void SimonEngine::o_random() {
 	// 53: random
-	uint var = getVarOrByte();
+	uint var = getVarWrapper();
 	uint value = (uint16)getVarOrWord();
 
 	// Disable random in simon1amiga for now
@@ -765,8 +858,13 @@
 	// 66: set item name
 	uint var = getVarOrByte();
 	uint stringId = getNextStringID();
-	if (var < _numTextBoxes)
+	if (var < _numTextBoxes) {
 		_stringIdArray2[var] = stringId;
+		if (getGameType() == GType_PP) {
+			getVarOrWord();
+			getVarOrWord();
+		}
+	}
 }
 
 void SimonEngine::o_setLongText() {
@@ -1270,22 +1368,22 @@
 
 void SimonEngine::o_bSet() {
 	// 153: set bit
-	setBitFlag(getVarOrByte(), true);
+	setBitFlag(getVarWrapper(), true);
 }
 
 void SimonEngine::o_bClear() {
 	// 154: clear bit
-	setBitFlag(getVarOrByte(), false);
+	setBitFlag(getVarWrapper(), false);
 }
 
 void SimonEngine::o_bZero() {
 	// 155: is bit clear
-	setScriptCondition(!getBitFlag(getVarOrByte()));
+	setScriptCondition(!getBitFlag(getVarWrapper()));
 }
 
 void SimonEngine::o_bNotZero() {
 	// 156: is bit set
-	uint bit = getVarOrByte();
+	uint bit = getVarWrapper();
 
 	// WORKAROUND: Fix for glitch in some versions
 	if (getGameType() == GType_SIMON1 && _subroutine == 2962 && bit == 63) {
@@ -1355,7 +1453,7 @@
 			speechId = (uint16)getNextWord();
 	}
 
-	if (getGameType() == GType_FF)
+	if (getGameType() == GType_FF || getGameType() == GType_PP)
 		vgaSpriteId = 1;
 
 	tl = getTextLocation(vgaSpriteId);
@@ -2263,29 +2361,67 @@
 }
 
 // -----------------------------------------------------------------------
+// Puzzle Pack Opcodes
+// -----------------------------------------------------------------------
 
+void SimonEngine::o4_opcode30() {
+	getNextItemPtr();
+}
+
+void SimonEngine::o4_opcode38() {
+	getVarOrByte();
+	getNextItemPtr();
+}
+
+void SimonEngine::o4_loadHiScores() {
+	getVarOrByte();
+}
+
+void SimonEngine::o4_checkHiScores() {
+	getVarOrByte();
+	getVarOrByte();
+}
+
+// -----------------------------------------------------------------------
+
 int SimonEngine::runScript() {
-	byte opcode;
+	int opcode;
 	bool flag;
 
 	do {
 		if (_continousMainScript)
 			dumpOpcode(_codePtr);
 
-		opcode = getByte();
-		if (opcode == 0xFF)
-			return 0;
+		if (getGameType() == GType_ELVIRA || getGameType() == GType_ELVIRA2) {
+			opcode = getVarOrWord();
+			if (opcode == 10000)
+				return 0;
+		} else {
+			opcode = getByte();
+			if (opcode == 0xFF)
+				return 0;
+		}
+		debug(1, "runScript: opcode %d", opcode);
 
 		if (_runScriptReturn1)
 			return 1;
 
 		/* Invert condition? */
 		flag = false;
-		if (opcode == 0) {
-			flag = true;
-			opcode = getByte();
-			if (opcode == 0xFF)
-				return 0;
+		if (getGameType() == GType_ELVIRA || getGameType() == GType_ELVIRA2) {
+			if (opcode == 203) {
+				flag = true;
+				opcode = getVarOrWord();
+				if (opcode == 10000)
+					return 0;
+			}
+		} else {
+			if (opcode == 0) {
+				flag = true;
+				opcode = getByte();
+				if (opcode == 0xFF)
+					return 0;
+			}
 		}
 
 		setScriptCondition(true);

Modified: scummvm/trunk/engines/simon/midiparser_s1d.cpp
===================================================================
--- scummvm/trunk/engines/simon/midiparser_s1d.cpp	2006-09-28 13:01:13 UTC (rev 23993)
+++ scummvm/trunk/engines/simon/midiparser_s1d.cpp	2006-09-28 23:22:07 UTC (rev 23994)
@@ -115,7 +115,7 @@
 		// OTherwise fall through to default.
 
 	default:
-		warning("MidiParser_S1D: Unexpected byte 0x%02X found", (int) info.command());
+		debug(3, "MidiParser_S1D: Unexpected byte 0x%02X found", (int) info.command());
 		break;
 	}
 }

Modified: scummvm/trunk/engines/simon/res.cpp
===================================================================
--- scummvm/trunk/engines/simon/res.cpp	2006-09-28 13:01:13 UTC (rev 23993)
+++ scummvm/trunk/engines/simon/res.cpp	2006-09-28 23:22:07 UTC (rev 23994)
@@ -40,6 +40,30 @@
 namespace Simon {
 
 // Script opcodes to load into memory
+static const char *const opcode_arg_table_elvira[300] = {
+	"I ", "I ", "I ", "I ", "I ", "I ", "I ", "I ",	 "II ",	"II ", "II ", "II ", "F ", "F ", "FN ",	 /*  EQ",        */
+	"FN ", "FN ", "FN ", "FF ", "FF ", "FF ", "FF ", "II ", "II ", "a ", "a ", "n ", "n ", "p ",	 /*  PREP",      */
+	"N ", "I ", "I ", "I ",	 "I ",	"IN ",	"IB ", "IB ", "II ", "IB ", "N ", " ", " ", " ", "I ",	 /*  GET",       */
+	"I ","I ","I ", "I ","I ","I ",	"II ","II ","II ","II ","IBF ", "FIB ", "FF ", "N ", "NI ",
+	"IF ", "F ", "F ", "IB ", "IB ", "FN ",	"FN ", "FN ", "FF ", "FF ", "FN ", "FN ", "FF ", "FF ",	 /*  DIVF",      */
+	"FN ", "FF ", "FN ", "F ", "I ", "IN ", "IN ", "IB ", "IB ", "IB ", "IB ", "II ", "I ", "I ",	 /*  DEC",       */
+	"IN ", "T ", "F ", " ", "T ", "T ", "I ", "I ", " ", " ", "T ", " ", " ", " ", " ", " ", "T ",	 /*  PARSE",     */
+	" ", "N ", "INN ", "II ", "II ", "ITN ", "ITIN ", "ITIN ", "I3 ", "IN ", "I ",	 "I ", "Ivnn ",
+	"vnn ", "Ivnn ", "NN ",	"IT ", "INN ", " ", "N ", "N ", "N ", "T ", "v ", " ", " ", " ", " ",
+	"FN ", "I ", "TN ", "IT ", "II ", "I ", " ", "N ", "I ", " ", "I ", "NI ", "I ", "I ", "T ",	 /*  BECOME",    */
+	"I ", "I ", "N ", "N ", " ", "N ", "IF ", "IF ", "IF ", "IF ", "IF ", "IF ", "T ", "IB ",
+	"IB ", "IB ", "I ", " ", "vnnN ", "Ivnn ", "T ", "T ", "T ", "IF ", " ", " ", " ", "Ivnn ",
+	"IF ", "INI ", "INN ",  "IN ", "II ", "IFF ", "IIF ", "I ", "II ", "I ", "I ", "IN ", "IN ",	 /*  ROPENEXT",  */
+	"II ", "II ", "II ", "II ", "IIN ", "IIN ",  "IN ", "II ", "IN ", "IN ", "T ", "vanpan ",
+	"vIpI ", "T ", "T ", " ", " ",	"IN ", "IN ", "IN ", "IN ", "N ", "INTTT ",  "ITTT ",
+	"ITTT ", "I ", "I ", "IN ", "I ", " ", "F ", "NN ", "INN ", "INN ", "INNN ", "TF ", "NN ",	 /*  PICTURE",   */
+	"N ", "NNNNN ", "N ", " ", "NNNNNNN ", "N ", " ", "N ",	"NN ", "N ", "NNNNNIN ", "N ", "N ",	 /*  ENABLEBOX", */
+	"N ", "NNN ", "NNNN ", "INNN ", "IN ", "IN ", "TT ", "I ", "I ", "I ", "TTT ", "IN ", "IN ",	 /*  UNSETCLASS",*/
+	"FN ", "FN ", "FN ", "N ", "N ", "N ", "NI ", " ", " ",	 "N ", "I ", "INN ", "NN ", "N ",	 /*  WAITENDTUNE */
+	"N ", "Nan ", "NN ", " ", " ", " ", " ", " ", " ", " ", "IF ", "N ", " ", " ",	 " ", "II ",	 /*  PLACENOICONS*/
+	" ", "NI ","N ",
+};
+
 static const char *const opcode_arg_table_waxworks[256] = {
 	" ", "I ", "I ", "I ", "I ", "I ", "I ", "II ", "II ", "II ", "II ", "B ", "B ", "BN ", "BN ",
 	"BN ", "BN ", "BB ", "BB ", "BB ", "BB ", "II ", "II ", "N ", "I ", "I ", "I ", "IN ", "IB ",
@@ -142,22 +166,39 @@
 	" ", " ", "BT ", " ", "B ", " ", "BBBB ", " ", " ", "BBBB ", "B ", "B ", "B ", "B "
 };
 
+static const char *const opcode_arg_table_puzzlepack[256] = {
+	" ", "I ", "I ", "I ", "I ", "I ", "I ", "II ", "II ", "II ", "II ", "N ", "N ", "NN ", "NN ",
+	"NN ", "NN ", "NN ", "NN ", "NN ", "NN ", "II ", "II ", "N ", "I ", "I ", "I ", "IN ", "IB ",
+	"II ", "I ", "I ", "II ", "II ", "IBN ", "NIB ", "NN ", "B ", "BI ", "IN ", "N ", "N ", "NN ",
+	"NN ", "NN ", "NN ", "NN ", "NN ", "NN ", "NN ", "NN ", "NN ", "NN ", "NN ", "B ", "I ", "IB ",
+	"IB ", "II ", "I ", "I ", "IN ", "N ", "T ", "T ", "NNNNNB ", "BTNN ", "BTS ", "T ", " ", "B ",
+	"N ", "IBN ", "I ", "I ", "I ", "NN ", " ", " ", "IT ", "II ", "I ", "B ", " ", "IB ", "IBB ",
+	"IIB ", "T ", " ", " ", "IB ", "IB ", "IB ", "B ", "BB ", "IBB ", "NB ", "N ", "NNBNNN ", "NN ",
+	" ", "BNNNNNN ", "B ", " ", "B ", "B ", "BB ", "NNNNNIN ", "N ", "N ", "N ", "NNN ", "NBNN ",
+	"IBNN ", "IB ", "IB ", "IB ", "IB ", "N ", "N ", "N ", "BI ", " ", " ", "N ", "I ", "IBB ",
+	"NNB ", "N ", "N ", "Ban ", " ", " ", " ", " ", " ", "IN ", "B ", " ", "II ", " ", "BI ",
+	"N ", "I ", "IB ", "IB ", "IB ", "IB ", "IB ", "IB ", "IB ", "BI ", "BB ", "N ", "N ", "N ",
+	"N ", "IBN ", "IBN ", "IN ", "B ", "BNNN ", "BBTS ", "N ", " ", "Ian ", "B ", "B ", "B ", "B ",
+	"T ", "N ", " ", " ", "I ", " ", " ", "BBI ", "NNBB ", "BBB ", " ", " ", "T ", " ", "N ", "N ",
+	" ", " ", "BT ", " ", "B ", " ", "BBBB ", " ", " ", "BBBB ", "B ", "B ", "B ", "B "
+};
+
 uint16 SimonEngine::to16Wrapper(uint value) {
-	if (getGameType() == GType_FF)
+	if (getGameType() == GType_FF || getGameType() == GType_PP)
 		return TO_LE_16(value);
 	else
 		return TO_BE_16(value);
 }
 
 uint16 SimonEngine::readUint16Wrapper(const void *src) {
-	if (getGameType() == GType_FF)
+	if (getGameType() == GType_FF || getGameType() == GType_PP)
 		return READ_LE_UINT16(src);
 	else
 		return READ_BE_UINT16(src);
 }
 
 uint32 SimonEngine::readUint32Wrapper(const void *src) {
-	if (getGameType() == GType_FF)
+	if (getGameType() == GType_FF || getGameType() == GType_PP)
 		return READ_LE_UINT32(src);
 	else
 		return READ_BE_UINT32(src);
@@ -214,15 +255,21 @@
 int SimonEngine::allocGamePcVars(File *in) {
 	uint item_array_size, item_array_inited, stringtable_num;
 	uint32 version;
-	uint i;
+	uint i, start;
 
 	item_array_size = in->readUint32BE();
 	version = in->readUint32BE();
 	item_array_inited = in->readUint32BE();
 	stringtable_num = in->readUint32BE();
 
-	item_array_inited += 2;				// first two items are predefined
-	item_array_size += 2;
+	if (getGameType() == GType_ELVIRA || getGameType() == GType_ELVIRA2) {
+		item_array_inited = item_array_size;
+		start = 0;
+	} else {
+		item_array_inited += 2;				// first two items are predefined
+		item_array_size += 2;
+		start = 1;
+	}
 
 	if (version != 0x80)
 		error("allocGamePcVars: Not a runtime database");
@@ -234,7 +281,7 @@
 	_itemArraySize = item_array_size;
 	_itemArrayInited = item_array_inited;
 
-	for (i = 1; i < item_array_inited; i++) {
+	for (i = start; i < item_array_inited; i++) {
 		_itemArrayPtr[i] = (Item *)allocateItem(sizeof(Item));
 	}
 
@@ -261,7 +308,14 @@
 	createPlayer();
 	readGamePcText(&in);
 
-	for (i = 2; i < num_inited_objects; i++) {
+	int start;
+	if (getGameType() == GType_ELVIRA || getGameType() == GType_ELVIRA2) {
+		start = 0;
+	} else {
+		start = 2;
+	}
+
+	for (i = start; i < num_inited_objects; i++) {
 		readItemFromGamePc(&in, _itemArrayPtr[i]);
 	}
 
@@ -269,6 +323,9 @@
 
 	in.close();
 
+	if (getGameId() == GID_SWAMPY)
+		return;
+
 	/* Read list of TABLE resources */
 	in.open(getFileName(GAME_TBLFILE));
 	if (in.isOpen() == false) {
@@ -288,7 +345,7 @@
 	_tablesHeapPtrOrg = _tablesHeapPtr;
 	_tablesHeapCurPosOrg = _tablesHeapCurPos;
 
-	if (getGameType() == GType_FF)
+	if (getGameType() == GType_ELVIRA || getGameType() == GType_FF || getGameType() == GType_PP)
 		return;
 
 	/* Read list of TEXT resources */
@@ -355,16 +412,33 @@
 void SimonEngine::readItemFromGamePc(Common::File *in, Item *item) {
 	uint32 type;
 
-	item->adjective = in->readUint16BE();
-	item->noun = in->readUint16BE();
-	item->state = in->readUint16BE();
-	item->sibling = (uint16)fileReadItemID(in);
-	item->child = (uint16)fileReadItemID(in);
-	item->parent = (uint16)fileReadItemID(in);
-	in->readUint16BE();
-	item->classFlags = in->readUint16BE();
-	item->children = NULL;
+	if (getGameType() == GType_ELVIRA || getGameType() == GType_ELVIRA2) {
+		item->itemName = (uint16)in->readUint32BE();
+		item->adjective = in->readUint16BE();
+		item->noun = in->readUint16BE();
+		item->state = in->readUint16BE();
+		in->readUint16BE();
+		item->sibling = (uint16)fileReadItemID(in);
+		item->child = (uint16)fileReadItemID(in);
+		item->parent = (uint16)fileReadItemID(in);
+		in->readUint16BE();
+		in->readUint16BE();
+		in->readUint16BE();
+		item->classFlags = in->readUint16BE();
+		item->children = NULL;
+	} else {
+		item->adjective = in->readUint16BE();
+		item->noun = in->readUint16BE();
+		item->state = in->readUint16BE();
+		item->sibling = (uint16)fileReadItemID(in);
+		item->child = (uint16)fileReadItemID(in);
+		item->parent = (uint16)fileReadItemID(in);
+		in->readUint16BE();
+		item->classFlags = in->readUint16BE();
+		item->children = NULL;
+	}
 
+
 	type = in->readUint32BE();
 	while (type) {
 		type = in->readUint16BE();
@@ -375,24 +449,31 @@
 
 void SimonEngine::readItemChildren(Common::File *in, Item *item, uint type) {
 	if (type == 1) {
-		uint fr1 = in->readUint16BE();
-		uint fr2 = in->readUint16BE();
-		uint i, size;
-		uint j, k;
-		SubRoom *subRoom;
+		if (getGameType() == GType_ELVIRA || getGameType() == GType_ELVIRA2) {
+			// FIXME
+			in->readUint32BE();
+			in->readUint32BE();
+			in->readUint16BE();
+		} else {
+			uint fr1 = in->readUint16BE();
+			uint fr2 = in->readUint16BE();
+			uint i, size;
+			uint j, k;
+			SubRoom *subRoom;
 
-		size = SubRoom_SIZE;
-		for (i = 0, j = fr2; i != 6; i++, j >>= 2)
-			if (j & 3)
-				size += sizeof(subRoom->roomExit[0]);
+			size = SubRoom_SIZE;
+			for (i = 0, j = fr2; i != 6; i++, j >>= 2)
+				if (j & 3)
+					size += sizeof(subRoom->roomExit[0]);
 
-		subRoom = (SubRoom *)allocateChildBlock(item, 1, size);
-		subRoom->subroutine_id = fr1;
-		subRoom->roomExitStates = fr2;
+			subRoom = (SubRoom *)allocateChildBlock(item, 1, size);
+			subRoom->subroutine_id = fr1;
+			subRoom->roomExitStates = fr2;
 
-		for (i = k = 0, j = fr2; i != 6; i++, j >>= 2)
-			if (j & 3)
-				subRoom->roomExit[k++] = (uint16)fileReadItemID(in);
+			for (i = k = 0, j = fr2; i != 6; i++, j >>= 2)
+				if (j & 3)
+					subRoom->roomExit[k++] = (uint16)fileReadItemID(in);
+		}
 	} else if (type == 2) {
 		uint32 fr = in->readUint32BE();
 		uint i, k, size;
@@ -415,6 +496,24 @@
 				subObject->objectFlagValue[k++] = in->readUint16BE();
 
 		subObject->objectName = (uint16)in->readUint32BE();
+	} else if (type == 4) {
+		// FIXME
+		fileReadItemID(in);
+		fileReadItemID(in);
+		fileReadItemID(in);
+		fileReadItemID(in);
+		fileReadItemID(in);
+		fileReadItemID(in);
+		fileReadItemID(in);
+		fileReadItemID(in);
+		fileReadItemID(in);
+		fileReadItemID(in);
+		fileReadItemID(in);
+		fileReadItemID(in);
+	} else if (type == 7) {
+		// FIXME
+		in->readUint16BE();
+		in->readUint16BE();
 	} else if (type == 8) {
 		SubUserChain *chain = (SubUserChain *)allocateChildBlock(item, 8, sizeof(SubUserChain));
 		chain->chChained = (uint16)fileReadItemID(in);
@@ -423,6 +522,17 @@
 		setUserFlag(item, 1, in->readUint16BE());
 		setUserFlag(item, 2, in->readUint16BE());
 		setUserFlag(item, 3, in->readUint16BE());
+		if (getGameType() == GType_ELVIRA || getGameType() == GType_ELVIRA2) {
+			setUserFlag(item, 4, in->readUint16BE());
+			setUserFlag(item, 5, in->readUint16BE());
+			setUserFlag(item, 6, in->readUint16BE());
+			setUserFlag(item, 7, in->readUint16BE());
+			// FIXME
+			fileReadItemID(in); 
+			fileReadItemID(in);
+			fileReadItemID(in);
+			fileReadItemID(in);
+		}
 	} else if (type == 255) {
 		SubUserInherit *inherit = (SubUserInherit *)allocateChildBlock(item, 255, sizeof(SubUserInherit));
 		inherit->inMaster = (uint16)fileReadItemID(in);
@@ -441,11 +551,13 @@
 byte *SimonEngine::readSingleOpcode(Common::File *in, byte *ptr) {
 	int i, l;
 	const char *string_ptr;
-	uint val;
+	uint opcode, val;
 
 	const char *const *table;
 
-	if (getGameType() == GType_FF)
+	if (getGameType() == GType_PP)
+		table = opcode_arg_table_puzzlepack;
+	else if (getGameType() == GType_FF)
 		table = opcode_arg_table_feeblefiles;
 	else if (getGameType() == GType_SIMON2 && (getFeatures() & GF_TALKIE))
 		table = opcode_arg_table_simon2win;
@@ -455,12 +567,20 @@
 		table = opcode_arg_table_simon1win;
 	else if (getGameType() == GType_SIMON1)
 		table = opcode_arg_table_simon1dos;
-	else /* if (getGameType() == GType_WW) */
+	else if (getGameType() == GType_WW)
 		table = opcode_arg_table_waxworks;
+	else
+		table = opcode_arg_table_elvira;
 
 	i = 0;
+	if (getGameType() == GType_ELVIRA || getGameType() == GType_ELVIRA2) {
+		opcode = READ_BE_UINT16(ptr);
+		ptr += 2;
+	} else {
+		opcode = *ptr++;
+	}
 
-	string_ptr = table[*ptr++];
+	string_ptr = table[opcode];
 	if (!string_ptr)
 		error("Unable to locate opcode table. Perhaps you are using the wrong game target?");
 
@@ -469,22 +589,31 @@
 			return ptr;
 
 		l = string_ptr[i++];
+
 		switch (l) {
+		case 'F':
 		case 'N':
 		case 'S':
 		case 'a':
 		case 'n':
 		case 'p':
 		case 'v':
+		case '3':
 			val = in->readUint16BE();
 			*ptr++ = val >> 8;
 			*ptr++ = val & 255;
 			break;
 
 		case 'B':
-			*ptr++ = in->readByte();
-			if (ptr[-1] == 0xFF) {
+			if (getGameType() == GType_ELVIRA || getGameType() == GType_ELVIRA2) {
+				val = in->readUint16BE();
+				*ptr++ = val >> 8;
+				*ptr++ = val & 255;
+			} else {
 				*ptr++ = in->readByte();
+				if (ptr[-1] == 0xFF) {
+					*ptr++ = in->readByte();
+				}
 			}
 			break;
 

Modified: scummvm/trunk/engines/simon/simon.cpp
===================================================================
--- scummvm/trunk/engines/simon/simon.cpp	2006-09-28 13:01:13 UTC (rev 23993)
+++ scummvm/trunk/engines/simon/simon.cpp	2006-09-28 23:22:07 UTC (rev 23994)
@@ -317,8 +317,8 @@
 	memset(_bitArrayTwo, 0, sizeof(_bitArrayTwo));
 	memset(_bitArrayThree, 0, sizeof(_bitArrayThree));
 
-	memset(_variableArray, 0, sizeof(_variableArray));
-	memset(_variableArray2, 0, sizeof(_variableArray2));
+	_variableArray = 0;
+	_variableArray2 = 0;
 	_variableArrayPtr = 0;
 
 	memset(_windowArray, 0, sizeof(_windowArray));
@@ -415,9 +415,7 @@
 		return -1;
 	}
 
-	setupOpcodes();
-
-	if (getGameType() == GType_FF) {
+	if (getGameType() == GType_FF || getGameType() == GType_PP) {
 		_screenWidth = 640;
 		_screenHeight = 480;
 	} else {
@@ -426,7 +424,7 @@
 	}
 
 	_system->beginGFXTransaction();
-		initCommonGFX(getGameType() == GType_FF);
+		initCommonGFX(getGameType() == GType_FF || getGameType() == GType_PP);
 		_system->initSize(_screenWidth, _screenHeight);
 	_system->endGFXTransaction();
 
@@ -439,7 +437,7 @@
 
 	// Setup midi driver
 	MidiDriver *driver = 0;
-	if (getGameType() == GType_FF || getGameId() == GID_SIMON1CD32) {
+	if (getGameType() == GType_FF || getGameType() == GType_PP || getGameId() == GID_SIMON1CD32) {
 		driver = MidiDriver::createMidi(MD_NULL);
 		_native_mt32 = false;
 	} else {
@@ -462,21 +460,67 @@
 	if (ConfMan.hasKey("music_mute") && ConfMan.getBool("music_mute") == 1)
 		midi.pause(_musicPaused ^= 1);
 
-	_currentMouseCursor = 255;
-	_currentMouseAnim = 255;
+	// allocate buffers
+	_backGroundBuf = (byte *)calloc(_screenWidth * _screenHeight, 1);
+	_frontBuf = (byte *)calloc(_screenWidth * _screenHeight, 1);
+	_backBuf = (byte *)calloc(_screenWidth * _screenHeight, 1);
+	if (getGameType() == GType_FF || getGameType() == GType_PP)
+		_scaleBuf = (byte *)calloc(_screenWidth * _screenHeight, 1);
 
-	_frameRate = 1;
+	setupGame();
 
-	_lastMusicPlayed = -1;
-	_nextMusicToPlay = -1;
+	_debugger = new Debugger(this);
+	_moviePlay = new MoviePlayer(this, _mixer);
+	_sound = new Sound(this, gss, _mixer);
 
-	_noOverWrite = 0xFFFF;
+	if (ConfMan.hasKey("sfx_mute") && ConfMan.getBool("sfx_mute") == 1) {
+		if (getGameId() == GID_SIMON1DOS)
+			midi._enable_sfx ^= 1;
+		else
+			_sound->effectsPause(_effectsPaused ^= 1);
+	}
 
-	_stringIdLocalMin = 1;
+	_language = Common::parseLanguage(ConfMan.get("language"));
 
-	_variableArrayPtr = _variableArray;
+	if (getGameType() == GType_PP) {
+		_speech = false;
+		_subtitles = false;
+	} else if (getFeatures() & GF_TALKIE) {
+		_speech = !ConfMan.getBool("speech_mute");
+		_subtitles = ConfMan.getBool("subtitles");
 
-	if (getGameType() == GType_FF) {
+		if (getGameType() == GType_SIMON1) {
+			// English and German versions don't have full subtitles
+			 if (_language == Common::EN_ANY || _language == Common::DE_DEU)
+				_subtitles = false;
+			// Other versions require speech to be enabled
+			else
+				_speech = true;
+		}
+
+		// Default to speech only, if both speech and subtitles disabled
+		if (!_speech && !_subtitles)
+			_speech = true;
+	} else {
+		_speech = false;
+		_subtitles = true;
+	}
+
+	_debugMode = (gDebugLevel >= 0);
+	if (gDebugLevel == 2)
+		_continousMainScript = true;
+	if (gDebugLevel == 3)
+		_continousVgaScript = true;
+	if (gDebugLevel == 4)
+		_startMainScript = true;
+	if (gDebugLevel == 5)
+		_startVgaScript = true;
+
+	return 0;
+}
+
+void SimonEngine::setupGame() {
+	if (getGameType() == GType_PP) {
 		gss = PTR(feeblefiles_settings);
 		_numTextBoxes = 40;
 		_numVideoOpcodes = 85;
@@ -487,6 +531,19 @@
 #endif
 		_tableMemSize = 200000;
 		_vgaBaseDelay = 5;
+		_numVars = 2048;
+	} else if (getGameType() == GType_FF) {
+		gss = PTR(feeblefiles_settings);
+		_numTextBoxes = 40;
+		_numVideoOpcodes = 85;
+#ifndef PALMOS_68K
+		_vgaMemSize = 7000000;
+#else
+		_vgaMemSize = gVars->memory[kMemSimon2Games];
+#endif
+		_tableMemSize = 200000;
+		_vgaBaseDelay = 5;
+		_numVars = 256;
 	} else if (getGameType() == GType_SIMON2) {
 		gss = PTR(simon2_settings);
 		_tableIndexBase = 1580 / 4;
@@ -506,6 +563,7 @@
 			_musicIndexBase = 1128 / 4;
 		_soundIndexBase = 1660 / 4;
 		_vgaBaseDelay = 1;
+		_numVars = 256;
 	} else {
 		gss = PTR(simon1_settings);
 		_tableIndexBase = 1576 / 4;
@@ -517,69 +575,36 @@
 #else
 		_vgaMemSize = gVars->memory[kMemSimon1Games];
 #endif
-		_tableMemSize = 50000;
+		_tableMemSize = 150000;
 		_musicIndexBase = 1316 / 4;
 		_soundIndexBase = 0;
 		_vgaBaseDelay = 1;
+		_numVars = 256;
 	}
 
-	// allocate buffers
-	_backGroundBuf = (byte *)calloc(_screenWidth * _screenHeight, 1);
-	_frontBuf = (byte *)calloc(_screenWidth * _screenHeight, 1);
-	_backBuf = (byte *)calloc(_screenWidth * _screenHeight, 1);
-	if (getGameType() == GType_FF)
-		_scaleBuf = (byte *)calloc(_screenWidth * _screenHeight, 1);
-
 	allocItemHeap();
 	allocTablesHeap();
 
-	setZoneBuffers();
+	_variableArray = (int16 *)calloc(_numVars, sizeof(int16));
+	_variableArray2 = (int16 *)calloc(_numVars, sizeof(int16));
 
-	_debugger = new Debugger(this);
-	_moviePlay = new MoviePlayer(this, _mixer);
-	_sound = new Sound(this, gss, _mixer);
+	setupOpcodes();
 
-	if (ConfMan.hasKey("sfx_mute") && ConfMan.getBool("sfx_mute") == 1) {
-		if (getGameId() == GID_SIMON1DOS)
-			midi._enable_sfx ^= 1;
-		else
-			_sound->effectsPause(_effectsPaused ^= 1);
-	}
+	setZoneBuffers();
 
-	_language = Common::parseLanguage(ConfMan.get("language"));
+	_currentMouseCursor = 255;
+	_currentMouseAnim = 255;
 
-	if (getFeatures() & GF_TALKIE) {
-		_speech = !ConfMan.getBool("speech_mute");
-		_subtitles = ConfMan.getBool("subtitles");
+	_frameRate = 1;
 
-		if (getGameType() == GType_SIMON1) {
-			// English and German versions don't have full subtitles
-			 if (_language == Common::EN_ANY || _language == Common::DE_DEU)
-				_subtitles = false;
-			// Other versions require speech to be enabled
-			else
-				_speech = true;
-		}
+	_lastMusicPlayed = -1;
+	_nextMusicToPlay = -1;
 
-		// Default to speech only, if both speech and subtitles disabled
-		if (!_speech && !_subtitles)
-			_speech = true;
-	} else {
-		_speech = false;
-		_subtitles = true;
-	}
+	_noOverWrite = 0xFFFF;
 
-	_debugMode = (gDebugLevel >= 0);
-	if (gDebugLevel == 2)
-		_continousMainScript = true;
-	if (gDebugLevel == 3)
-		_continousVgaScript = true;
-	if (gDebugLevel == 4)
-		_startMainScript = true;
-	if (gDebugLevel == 5)
-		_startVgaScript = true;
+	_stringIdLocalMin = 1;
 
-	return 0;
+	_variableArrayPtr = _variableArray;
 }
 
 SimonEngine::~SimonEngine() {
@@ -713,9 +738,9 @@
 }
 
 void SimonEngine::allocItemHeap() {
-	_itemHeapSize = 32000;
+	_itemHeapSize = 64000;
 	_itemHeapCurPos = 0;
-	_itemHeapPtr = (byte *)calloc(32000, 1);
+	_itemHeapPtr = (byte *)calloc(64000, 1);
 }
 
 void SimonEngine::allocTablesHeap() {
@@ -758,6 +783,13 @@
 	return a;
 }
 
+uint SimonEngine::getVarWrapper() {
+	if (getGameId() == GID_SWAMPY)
+		return getVarOrWord();
+	else
+		return getVarOrByte();
+}
+
 Item *SimonEngine::getNextItemPtr() {
 	int a = getNextWord();
 
@@ -827,11 +859,11 @@
 }
 
 uint SimonEngine::getNextVarContents() {
-	return (uint16)readVariable(getVarOrByte());
+	return (uint16)readVariable(getVarWrapper());
 }
 
 uint SimonEngine::readVariable(uint variable) {
-	if (variable >= 255)
+	if (variable >= _numVars)
 		error("readVariable: Variable %d out of range", variable);
 
 	if (getGameType() == GType_FF) {
@@ -845,11 +877,11 @@
 }
 
 void SimonEngine::writeNextVarContents(uint16 contents) {
-	writeVariable(getVarOrByte(), contents);
+	writeVariable(getVarWrapper(), contents);
 }
 
 void SimonEngine::writeVariable(uint variable, uint16 contents) {
-	if (variable >= 256)
+	if (variable >= _numVars)
 		error("writeVariable: Variable %d out of range", variable);
 
 	if (getGameType() == GType_FF && getBitFlag(83))
@@ -918,8 +950,10 @@
 	for (;;) {
 		if (!first)
 			error("unlinkItem: parent empty");
-		if (first->sibling == 0)
-			error("unlinkItem: parent does not contain child");
+		if (first->sibling == 0) {
+			warning("unlinkItem: parent does not contain child");
+			return;
+		}
 
 		next = derefItem(first->sibling);
 		if (next == item) {
@@ -1170,7 +1204,7 @@
 void SimonEngine::hitarea_stuff_helper() {
 	time_t cur_time;
 
-	if (getGameType() == GType_SIMON2 || getGameType() == GType_FF) {
+	if (getGameType() == GType_SIMON2 || getGameType() == GType_FF || getGameType() == GType_PP) {
 		if (_variableArray[254] || _variableArray[249]) {
 			hitarea_stuff_helper_2();
 		}
@@ -1231,7 +1265,7 @@
 		_curWindow = 0;
 		if (_windowArray[0] != 0) {
 			_textWindow = _windowArray[0];
-			if (getGameType() == GType_FF)
+			if (getGameType() == GType_FF || getGameType() == GType_PP)
 				showmessage_helper_3(_textWindow->textColumn, _textWindow->width);
 			else
 				showmessage_helper_3(_textWindow->textLength, _textWindow->textMaxLength);
@@ -1273,8 +1307,7 @@
 	vpe->vgaFile2End = vpe->vgaFile2 + size;
 
 	vpe->sfxFile = NULL;
-	if ((getGameType() == GType_FF && getPlatform() == Common::kPlatformWindows) ||
-		getGameType() == GType_WW) {
+	if (!(getFeatures() & GF_ZLIBCOMP)) {
 		vpe->sfxFile = loadVGAFile(vga_res * 2, 3, size);
 		vpe->sfxFileEnd = vpe->sfxFile + size;
 	}
@@ -1325,7 +1358,7 @@
 
 	vpe = &_vgaBufferPointers[_noOverWrite];
 
-	if (getGameType() == GType_FF) {
+	if (getGameType() == GType_FF || getGameType() == GType_PP) {
 		if (vpe->vgaFile1 < end && vpe->vgaFile1End > _vgaMemPtr) {
 			_rejectBlock = true;
 			_vgaMemPtr = vpe->vgaFile1End;
@@ -1351,7 +1384,7 @@
 
 void SimonEngine::checkRunningAnims(byte *end) {
 	VgaSprite *vsp;
-	if (getGameType() != GType_FF && (_lockWord & 0x20)) {
+	if (getGameType() != GType_FF && getGameType() != GType_PP && (_lockWord & 0x20)) {
 		return;
 	}
 
@@ -1367,7 +1400,7 @@
 
 	vpe = &_vgaBufferPointers[a];
 
-	if (getGameType() == GType_FF) {
+	if (getGameType() == GType_FF || getGameType() == GType_PP) {
 		if (vpe->vgaFile1 < end && vpe->vgaFile1End > _vgaMemPtr) {
 			_rejectBlock = true;
 			_vgaMemPtr = vpe->vgaFile1End;
@@ -1395,7 +1428,7 @@
 	uint count = ARRAYSIZE(_vgaBufferPointers);
 	VgaPointersEntry *vpe = _vgaBufferPointers;
 	do {
-		if (getGameType() == GType_FF) {
+		if (getGameType() == GType_FF || getGameType() == GType_PP) {
 			if (vpe->vgaFile1 < end && vpe->vgaFile1End > _vgaMemPtr ||
 					vpe->vgaFile2 < end && vpe->vgaFile2End > _vgaMemPtr ||
 					vpe->sfxFile < end && vpe->sfxFileEnd > _vgaMemPtr) {
@@ -1426,7 +1459,7 @@
 	_windowNum = mode;
 	_lockWord |= 0x20;
 
-	if (getGameType() == GType_FF) {
+	if (getGameType() == GType_FF || getGameType() == GType_PP) {
 		vc27_resetSprite();
 	}
 
@@ -1458,21 +1491,7 @@
 
 	bb = _curVgaFile1;
 
-	if (getGameType() == GType_WW) {
-		b = bb + READ_BE_UINT16(bb + 10);
-		b += 20;
-
-		count = READ_BE_UINT16(&((VgaFileHeader2_WW *) b)->imageCount);
-		b = bb + READ_BE_UINT16(&((VgaFileHeader2_WW *) b)->imageTable);
-
-		while (count--) {
-			if (READ_BE_UINT16(&((ImageHeader_WW *) b)->id) == vga_res_id)
-				break;
-			b += sizeof(ImageHeader_WW);
-		}
-		assert(READ_BE_UINT16(&((ImageHeader_WW *) b)->id) == vga_res_id);
-
-	} else if (getGameType() == GType_FF) {
+	if (getGameType() == GType_FF || getGameType() == GType_PP) {
 		b = bb + READ_LE_UINT16(&((VgaFileHeader_Feeble *) bb)->hdr2_start);
 		count = READ_LE_UINT16(&((VgaFileHeader2_Feeble *) b)->imageCount);
 		b = bb + READ_LE_UINT16(&((VgaFileHeader2_Feeble *) b)->imageTable);
@@ -1484,7 +1503,7 @@
 		}
 		assert(READ_LE_UINT16(&((ImageHeader_Feeble *) b)->id) == vga_res_id);
 
-	} else {
+	} else if (getGameType() == GType_SIMON1 || getGameType() == GType_SIMON2) {
 		b = bb + READ_BE_UINT16(&((VgaFileHeader_Simon *) bb)->hdr2_start);
 		count = READ_BE_UINT16(&((VgaFileHeader2_Simon *) b)->imageCount);
 		b = bb + READ_BE_UINT16(&((VgaFileHeader2_Simon *) b)->imageTable);
@@ -1495,6 +1514,19 @@
 			b += sizeof(ImageHeader_Simon);
 		}
 		assert(READ_BE_UINT16(&((ImageHeader_Simon *) b)->id) == vga_res_id);
+	} else {
+		b = bb + READ_BE_UINT16(bb + 10);
+		b += 20;
+
+		count = READ_BE_UINT16(&((VgaFileHeader2_WW *) b)->imageCount);
+		b = bb + READ_BE_UINT16(&((VgaFileHeader2_WW *) b)->imageTable);
+
+		while (count--) {
+			if (READ_BE_UINT16(&((ImageHeader_WW *) b)->id) == vga_res_id)
+				break;
+			b += sizeof(ImageHeader_WW);
+		}
+		assert(READ_BE_UINT16(&((ImageHeader_WW *) b)->id) == vga_res_id);
 	}
 
 	if (getGameType() == GType_SIMON1) {
@@ -1520,12 +1552,12 @@
 
 	vc_ptr_org = _vcPtr;
 
-	if (getGameType() == GType_WW) {
-		_vcPtr = _curVgaFile1 + READ_BE_UINT16(&((ImageHeader_WW *) b)->scriptOffs);
-	} else if (getGameType() == GType_FF) {
+	if (getGameType() == GType_FF || getGameType() == GType_PP) {
 		_vcPtr = _curVgaFile1 + READ_LE_UINT16(&((ImageHeader_Feeble *) b)->scriptOffs);
+	} else if (getGameType() == GType_SIMON1 || getGameType() == GType_SIMON2) {
+		_vcPtr = _curVgaFile1 + READ_BE_UINT16(&((ImageHeader_Simon *) b)->scriptOffs);
 	} else {
-		_vcPtr = _curVgaFile1 + READ_BE_UINT16(&((ImageHeader_Simon *) b)->scriptOffs);
+		_vcPtr = _curVgaFile1 + READ_BE_UINT16(&((ImageHeader_WW *) b)->scriptOffs);
 	}
 
 	//dump_vga_script(_vcPtr, num, vga_res_id);
@@ -1533,7 +1565,7 @@
 	_vcPtr = vc_ptr_org;
 
 
-	if (getGameType() == GType_FF) {
+	if (getGameType() == GType_FF || getGameType() == GType_PP) {
 		fillFrontFromBack(0, 0, _screenWidth, _screenHeight);
 		fillBackGroundFromBack(_screenHeight);
 		_syncFlag2 = 1;
@@ -1836,33 +1868,24 @@
 	}
 
 	pp = _curVgaFile1;
-	if (getGameType() == GType_WW) {
-		p = pp + READ_BE_UINT16(pp + 10);
-		p += 20;
-
-		count = READ_BE_UINT16(&((VgaFileHeader2_WW *) p)->animationCount);
-		p = pp + READ_BE_UINT16(&((VgaFileHeader2_WW *) p)->animationTable);
-	} else if (getGameType() == GType_FF) {
+	if (getGameType() == GType_FF || getGameType() == GType_PP) {
 		p = pp + READ_LE_UINT16(&((VgaFileHeader_Feeble *) pp)->hdr2_start);
 		count = READ_LE_UINT16(&((VgaFileHeader2_Feeble *) p)->animationCount);
 		p = pp + READ_LE_UINT16(&((VgaFileHeader2_Feeble *) p)->animationTable);
-	} else {
+	} else if (getGameType() == GType_SIMON1 || getGameType() == GType_SIMON2) {
 		p = pp + READ_BE_UINT16(&((VgaFileHeader_Simon *) pp)->hdr2_start);
 		count = READ_BE_UINT16(&((VgaFileHeader2_Simon *) p)->animationCount);
 		p = pp + READ_BE_UINT16(&((VgaFileHeader2_Simon *) p)->animationTable);
+	} else {
+		p = pp + READ_BE_UINT16(pp + 10);
+		p += 20;
+
+		count = READ_BE_UINT16(&((VgaFileHeader2_WW *) p)->animationCount);
+		p = pp + READ_BE_UINT16(&((VgaFileHeader2_WW *) p)->animationTable);
 	}
 
 	for (;;) {
-		if (getGameType() == GType_WW) {
-			if (READ_BE_UINT16(&((AnimationHeader_WW *) p)->id) == vgaSpriteId) {
-				if (_startVgaScript)
-					dump_vga_script(pp + READ_BE_UINT16(&((AnimationHeader_WW *)p)->scriptOffs), zoneNum, vgaSpriteId);
-
-				addVgaEvent(_vgaBaseDelay, pp + READ_BE_UINT16(&((AnimationHeader_WW *) p)->scriptOffs), vgaSpriteId, zoneNum);
-				break;
-			}
-			p += sizeof(AnimationHeader_WW);
-		} else if (getGameType() == GType_FF) {
+		if (getGameType() == GType_FF || getGameType() == GType_PP) {
 			if (READ_LE_UINT16(&((AnimationHeader_Feeble *) p)->id) == vgaSpriteId) {
 				if (_startVgaScript)
 					dump_vga_script(pp + READ_LE_UINT16(&((AnimationHeader_Feeble*)p)->scriptOffs), zoneNum, vgaSpriteId);
@@ -1871,7 +1894,7 @@
 				break;
 			}
 			p += sizeof(AnimationHeader_Feeble);
-		} else {
+		} else if (getGameType() == GType_SIMON1 || getGameType() == GType_SIMON2) {
 			if (READ_BE_UINT16(&((AnimationHeader_Simon *) p)->id) == vgaSpriteId) {
 				if (_startVgaScript)
 					dump_vga_script(pp + READ_BE_UINT16(&((AnimationHeader_Simon*)p)->scriptOffs), zoneNum, vgaSpriteId);
@@ -1880,6 +1903,15 @@
 				break;
 			}
 			p += sizeof(AnimationHeader_Simon);
+		} else {
+			if (READ_BE_UINT16(&((AnimationHeader_WW *) p)->id) == vgaSpriteId) {
+				if (_startVgaScript)
+					dump_vga_script(pp + READ_BE_UINT16(&((AnimationHeader_WW *)p)->scriptOffs), zoneNum, vgaSpriteId);
+
+				addVgaEvent(_vgaBaseDelay, pp + READ_BE_UINT16(&((AnimationHeader_WW *) p)->scriptOffs), vgaSpriteId, zoneNum);
+				break;
+			}
+			p += sizeof(AnimationHeader_WW);
 		}
 
 		if (!--count) {
@@ -1952,7 +1984,7 @@
 
 	if (getGameType() == GType_FF)
 		loadIconData();
-	else
+	else if (getGameType() != GType_PP)
 		loadIconFile();
 
 	vc34_setMouseOff();

Modified: scummvm/trunk/engines/simon/simon.h
===================================================================
--- scummvm/trunk/engines/simon/simon.h	2006-09-28 13:01:13 UTC (rev 23993)
+++ scummvm/trunk/engines/simon/simon.h	2006-09-28 23:22:07 UTC (rev 23994)
@@ -110,10 +110,13 @@
 };
 
 enum SIMONGameType {
-	GType_FF = 0,
-	GType_SIMON1 = 1,
-	GType_SIMON2 = 2,
-	GType_WW = 3
+	GType_ELVIRA = 0,
+	GType_ELVIRA2 = 1,
+	GType_WW = 2,
+	GType_SIMON1 = 3,
+	GType_SIMON2 = 4,
+	GType_FF = 6,
+	GType_PP = 7
 };
 
 struct GameFileDescription {
@@ -157,6 +160,7 @@
 	GameDescription *_gameDescription;
 
 	bool initGame(void);
+	void setupGame();
 
 	int getGameId() const { return _gameDescription->gameId; }
 	int getGameType() const { return _gameDescription->gameType; }
@@ -188,6 +192,7 @@
 	uint _tableMemSize;
 	uint _musicIndexBase;
 	uint _soundIndexBase;
+	uint _numVars;
 	const GameSpecificSettings *gss;
 
 	byte _keyPressed;
@@ -403,11 +408,11 @@
 	uint16 _stringIdArray3[40];
 	uint16 _speechIdArray4[40];
 
-	uint16 _bitArray[16];
+	uint16 _bitArray[128];
 	uint16 _bitArrayTwo[16];
 	uint16 _bitArrayThree[16];
-	int16 _variableArray[256];
-	int16 _variableArray2[256];
+	int16 *_variableArray;
+	int16 *_variableArray2;
 	int16 *_variableArrayPtr;
 
 	WindowBlock *_windowArray[16];
@@ -552,6 +557,7 @@
 	int getNextWord();
 
 	uint getNextVarContents();
+	uint getVarWrapper();
 	uint getVarOrWord();
 	uint getVarOrByte();
 	uint readVariable(uint variable);
@@ -629,9 +635,11 @@
 	void mouseOff();
 	void mouseOn();
 
-	void loadTextIntoMem(uint stringId);
 	bool loadTablesIntoMem(uint subr_id);
+	bool loadTablesOldIntoMem(uint subr_id);
+	bool loadTablesNewIntoMem(uint subr_id);
 	bool loadXTablesIntoMem(uint subr_id);
+	void loadTextIntoMem(uint stringId);
 
 	bool loadRoomItems(uint item);
 
@@ -1029,6 +1037,12 @@
 	void o3_b3Zero();
 	void o3_b3NotZero();
 
+	// Opcodes, Puzzle Pack only
+	void o4_opcode30();
+	void o4_opcode38();
+	void o4_loadHiScores();
+	void o4_checkHiScores();
+
 protected:
 	void drawImages(VC10_state *state);
 	void drawImages_Feeble(VC10_state *state);

Modified: scummvm/trunk/engines/simon/sound.cpp
===================================================================
--- scummvm/trunk/engines/simon/sound.cpp	2006-09-28 13:01:13 UTC (rev 23993)
+++ scummvm/trunk/engines/simon/sound.cpp	2006-09-28 23:22:07 UTC (rev 23994)
@@ -288,7 +288,8 @@
 
 void Sound::loadVoiceFile(const GameSpecificSettings *gss) {
 	// Game versions which use separate voice files
-	if (_vm->getGameType() == GType_FF || _vm->getGameId() == GID_SIMON1CD32)
+	if (_vm->getGameType() == GType_FF || _vm->getGameType() == GType_PP ||
+		_vm->getGameId() == GID_SIMON1CD32)
 		return;
 
 	char filename[16];

Modified: scummvm/trunk/engines/simon/subroutine.cpp
===================================================================
--- scummvm/trunk/engines/simon/subroutine.cpp	2006-09-28 13:01:13 UTC (rev 23993)
+++ scummvm/trunk/engines/simon/subroutine.cpp	2006-09-28 23:22:07 UTC (rev 23994)
@@ -107,7 +107,64 @@
 }
 
 bool SimonEngine::loadTablesIntoMem(uint subr_id) {
+	if (getGameType() == GType_ELVIRA || getGameType() == GType_ELVIRA2)
+		return loadTablesOldIntoMem(subr_id);
+	else
+		return loadTablesNewIntoMem(subr_id);
+}
+
+
+bool SimonEngine::loadTablesOldIntoMem(uint subr_id) {
 	byte *p;
+	uint16 min_num, max_num, file_num;
+	File *in;
+	char filename[30];
+
+	if (_tblList == NULL)
+		return 0;
+
+	p = _tblList + 32;
+
+	min_num = READ_BE_UINT16(p);
+	max_num = READ_BE_UINT16(p + 2);
+	file_num = *(p + 4);
+	p += 6;
+
+	while (min_num) {
+		if ((subr_id >= min_num) && (subr_id <= max_num)) {
+			_subroutineList = _subroutineListOrg;
+			_tablesHeapPtr = _tablesHeapPtrOrg;
+			_tablesHeapCurPos = _tablesHeapCurPosOrg;
+			_stringIdLocalMin = 1;
+			_stringIdLocalMax = 0;
+
+			sprintf(filename, "TABLES%.2d", file_num);
+			in = openTablesFile(filename);
+			readSubroutineBlock(in);
+			closeTablesFile(in);
+
+			alignTableMem();
+
+			_tablesheapPtrNew = _tablesHeapPtr;
+			_tablesHeapCurPosNew = _tablesHeapCurPos;
+
+			if (_tablesHeapCurPos > _tablesHeapSize)
+				error("loadTablesOldIntoMem: Out of table memory");
+			return 1;
+		}
+
+		min_num = READ_BE_UINT16(p);
+		max_num = READ_BE_UINT16(p + 2);
+		file_num = *(p + 4);
+		p += 6;
+	}
+
+	debug(1,"loadTablesOldIntoMem: didn't find %d", subr_id);
+	return 0;
+}
+
+bool SimonEngine::loadTablesNewIntoMem(uint subr_id) {
+	byte *p;
 	int i;
 	uint min_num, max_num;
 	char filename[30];
@@ -124,14 +181,11 @@
 		p++;
 
 		for (;;) {
-			min_num = (p[0] * 256) | p[1];
-			p += 2;
-
+			min_num = READ_BE_UINT16(p); p += 2;
 			if (min_num == 0)
 				break;
 
-			max_num = (p[0] * 256) | p[1];
-			p += 2;
+			max_num = READ_BE_UINT16(p); p += 2;
 
 			if (subr_id >= min_num && subr_id <= max_num) {
 				_subroutineList = _subroutineListOrg;
@@ -157,20 +211,17 @@
 				_tablesHeapCurPosNew = _tablesHeapCurPos;
 
 				if (_tablesHeapCurPos > _tablesHeapSize)
-					error("loadTablesIntoMem: Out of table memory");
+					error("loadTablesNewIntoMem: Out of table memory");
 				return 1;
 			}
 		}
 	}
 
-	debug(1,"loadTablesIntoMem: didn't find %d", subr_id);
+	debug(1,"loadTablesNewIntoMem: didn't find %d", subr_id);
 	return 0;
 }
 
 bool SimonEngine::loadXTablesIntoMem(uint subr_id) {
-	if (getGameType() != GType_WW)
-		return 0;
-
 	byte *p;
 	int i;
 	uint min_num, max_num;
@@ -188,13 +239,13 @@
 		p++;
 
 		for (;;) {
-			min_num = (p[0] * 256) | p[1];
+			min_num = READ_BE_UINT16(p);
 			p += 2;
 
 			if (min_num == 0)
 				break;
 
-			max_num = (p[0] * 256) | p[1];
+			max_num = READ_BE_UINT16(p);
 			p += 2;
 
 			if (subr_id >= min_num && subr_id <= max_num) {
@@ -374,26 +425,49 @@
 }
 
 void SimonEngine::readSubroutineLine(File *in, SubroutineLine *sl, Subroutine *sub) {
-	byte line_buffer[1024], *q = line_buffer;
+	byte line_buffer[2048], *q = line_buffer;
 	int size;
 
 	if (sub->id == 0) {
 		sl->verb = in->readUint16BE();
 		sl->noun1 = in->readUint16BE();
 		sl->noun2 = in->readUint16BE();
+	} else if (getGameType() == GType_ELVIRA || getGameType() == GType_ELVIRA2) {
+		in->readUint16BE();
+		in->readUint16BE();
+		in->readUint16BE();
 	}
 
-	while ((*q = in->readByte()) != 0xFF) {
-		if (*q == 87) {
-			in->readUint16BE();
-		} else {
-			q = readSingleOpcode(in, q);
+	if (getGameType() == GType_ELVIRA || getGameType() == GType_ELVIRA2) {
+		int16 tmp;
+
+		tmp = in->readUint16BE();
+		WRITE_BE_UINT16(q, tmp);
+		while (tmp != 10000) {
+			if (READ_BE_UINT16(q) == 0xC6) {
+				in->readUint16BE();
+			} else {
+				q = readSingleOpcode(in, q);
+			}
+
+			tmp = in->readUint16BE();
+			WRITE_BE_UINT16(q, tmp);
 		}
-	}
 
-	size = q - line_buffer + 1;
+		size = (q - line_buffer + 1) * 2;
+		memcpy(allocateTable(size), line_buffer, size);
+	} else {
+		while ((*q = in->readByte()) != 0xFF) {
+			if (*q == 87) {
+				in->readUint16BE();
+			} else {
+				q = readSingleOpcode(in, q);
+			}
+		}
 
-	memcpy(allocateTable(size), line_buffer, size);
+		size = (q - line_buffer + 1);
+		memcpy(allocateTable(size), line_buffer, size);
+	}
 }
 
 void SimonEngine::readSubroutineBlock(File *in) {

Modified: scummvm/trunk/engines/simon/vga.cpp
===================================================================
--- scummvm/trunk/engines/simon/vga.cpp	2006-09-28 13:01:13 UTC (rev 23993)
+++ scummvm/trunk/engines/simon/vga.cpp	2006-09-28 23:22:07 UTC (rev 23994)
@@ -286,7 +286,7 @@
 	};
 
 	uint16 opcode;
-	if (getGameType() == GType_FF) {
+	if (getGameType() == GType_FF || getGameType() == GType_PP) {
 		opcode = vcReadNextByte();
 		_vcPtr += opcodeParamLenFeebleFiles[opcode];
 	} else if (getGameType() == GType_SIMON2) {
@@ -339,21 +339,7 @@
 
 
 	bb = _curVgaFile1;
-	if (getGameType() == GType_WW) {
-		b = bb + READ_BE_UINT16(bb + 10);
-		b += 20;
-
-		count = READ_BE_UINT16(&((VgaFileHeader2_WW *) b)->imageCount);
-		b = bb + READ_BE_UINT16(&((VgaFileHeader2_WW *) b)->imageTable);
-
-		while (count--) {
-			if (READ_BE_UINT16(&((ImageHeader_WW *) b)->id) == num)
-				break;
-			b += sizeof(ImageHeader_WW);
-		}
-		assert(READ_BE_UINT16(&((ImageHeader_WW *) b)->id) == num);
-
-	} else if (getGameType() == GType_FF) {
+	if (getGameType() == GType_FF || getGameType() == GType_PP) {
 		b = bb + READ_LE_UINT16(&((VgaFileHeader_Feeble *) bb)->hdr2_start);
 		count = READ_LE_UINT16(&((VgaFileHeader2_Feeble *) b)->imageCount);
 		b = bb + READ_LE_UINT16(&((VgaFileHeader2_Feeble *) b)->imageTable);
@@ -364,7 +350,7 @@
 			b += sizeof(ImageHeader_Feeble);
 		}
 		assert(READ_LE_UINT16(&((ImageHeader_Feeble *) b)->id) == num);
-	} else {
+	} else if (getGameType() == GType_SIMON1 || getGameType() == GType_SIMON2) {
 		b = bb + READ_BE_UINT16(&((VgaFileHeader_Simon *) bb)->hdr2_start);
 		count = READ_BE_UINT16(&((VgaFileHeader2_Simon *) b)->imageCount);
 		b = bb + READ_BE_UINT16(&((VgaFileHeader2_Simon *) b)->imageTable);
@@ -375,16 +361,29 @@
 			b += sizeof(ImageHeader_Simon);
 		}
 		assert(READ_BE_UINT16(&((ImageHeader_Simon *) b)->id) == num);
+	} else {
+		b = bb + READ_BE_UINT16(bb + 10);
+		b += 20;
+
+		count = READ_BE_UINT16(&((VgaFileHeader2_WW *) b)->imageCount);
+		b = bb + READ_BE_UINT16(&((VgaFileHeader2_WW *) b)->imageTable);
+
+		while (count--) {
+			if (READ_BE_UINT16(&((ImageHeader_WW *) b)->id) == num)
+				break;
+			b += sizeof(ImageHeader_WW);
+		}
+		assert(READ_BE_UINT16(&((ImageHeader_WW *) b)->id) == num);
 	}
 
 	vcPtrOrg = _vcPtr;
 
-	if (getGameType() == GType_WW) {
-		_vcPtr = _curVgaFile1 + READ_BE_UINT16(&((ImageHeader_WW *) b)->scriptOffs);
-	} else if (getGameType() == GType_FF) {
+	if (getGameType() == GType_FF || getGameType() == GType_PP) {
 		_vcPtr = _curVgaFile1 + READ_LE_UINT16(&((ImageHeader_Feeble *) b)->scriptOffs);
+	} else if (getGameType() == GType_SIMON1 || getGameType() == GType_SIMON2) {
+		_vcPtr = _curVgaFile1 + READ_BE_UINT16(&((ImageHeader_Simon *) b)->scriptOffs);
 	} else {
-		_vcPtr = _curVgaFile1 + READ_BE_UINT16(&((ImageHeader_Simon *) b)->scriptOffs);
+		_vcPtr = _curVgaFile1 + READ_BE_UINT16(&((ImageHeader_WW *) b)->scriptOffs);
 	}
 
 	//dump_vga_script(_vcPtr, res, num);
@@ -453,20 +452,7 @@
 	}
 
 	pp = _curVgaFile1;
-	if (getGameType() == GType_WW) {
-		p = pp + READ_BE_UINT16(pp + 10);
-		p += 20;
-
-		count = READ_BE_UINT16(&((VgaFileHeader2_WW *) p)->animationCount);
-		p = pp + READ_BE_UINT16(&((VgaFileHeader2_WW *) p)->animationTable);
-
-		while (count--) {
-			if (READ_BE_UINT16(&((AnimationHeader_WW *) p)->id) == vgaSpriteId)
-				break;
-			p += sizeof(AnimationHeader_WW);
-		}
-		assert(READ_BE_UINT16(&((AnimationHeader_WW *) p)->id) == vgaSpriteId);
-	} else if (getGameType() == GType_FF) {
+	if (getGameType() == GType_FF || getGameType() == GType_PP) {
 		p = pp + READ_LE_UINT16(&((VgaFileHeader_Feeble *) pp)->hdr2_start);
 		count = READ_LE_UINT16(&((VgaFileHeader2_Feeble *) p)->animationCount);
 		p = pp + READ_LE_UINT16(&((VgaFileHeader2_Feeble *) p)->animationTable);
@@ -477,7 +463,7 @@
 			p += sizeof(AnimationHeader_Feeble);
 		}
 		assert(READ_LE_UINT16(&((AnimationHeader_Feeble *) p)->id) == vgaSpriteId);
-	} else {
+	} else if (getGameType() == GType_SIMON1 || getGameType() == GType_SIMON2) {
 		p = pp + READ_BE_UINT16(&((VgaFileHeader_Simon *) pp)->hdr2_start);
 		count = READ_BE_UINT16(&((VgaFileHeader2_Simon *) p)->animationCount);
 		p = pp + READ_BE_UINT16(&((VgaFileHeader2_Simon *) p)->animationTable);
@@ -488,6 +474,19 @@
 			p += sizeof(AnimationHeader_Simon);
 		}
 		assert(READ_BE_UINT16(&((AnimationHeader_Simon *) p)->id) == vgaSpriteId);
+	} else {
+		p = pp + READ_BE_UINT16(pp + 10);
+		p += 20;
+
+		count = READ_BE_UINT16(&((VgaFileHeader2_WW *) p)->animationCount);
+		p = pp + READ_BE_UINT16(&((VgaFileHeader2_WW *) p)->animationTable);
+
+		while (count--) {
+			if (READ_BE_UINT16(&((AnimationHeader_WW *) p)->id) == vgaSpriteId)
+				break;
+			p += sizeof(AnimationHeader_WW);
+		}
+		assert(READ_BE_UINT16(&((AnimationHeader_WW *) p)->id) == vgaSpriteId);
 	}
 
 #ifdef DUMP_FILE_NR
@@ -511,22 +510,21 @@
 #endif
 
 	if (_startVgaScript) {
-		if (getGameType() == GType_WW) {
-			dump_vga_script(_curVgaFile1 + READ_BE_UINT16(&((AnimationHeader_WW*)p)->scriptOffs), res, vgaSpriteId);
-		} else if (getGameType() == GType_FF) {
+		if (getGameType() == GType_FF || getGameType() == GType_PP) {
 			dump_vga_script(_curVgaFile1 + READ_LE_UINT16(&((AnimationHeader_Feeble*)p)->scriptOffs), res, vgaSpriteId);
+		} else if (getGameType() == GType_SIMON1 || getGameType() == GType_SIMON2) {
+			dump_vga_script(_curVgaFile1 + READ_BE_UINT16(&((AnimationHeader_Simon*)p)->scriptOffs), res, vgaSpriteId);
 		} else {
-			dump_vga_script(_curVgaFile1 + READ_BE_UINT16(&((AnimationHeader_Simon*)p)->scriptOffs), res, vgaSpriteId);
-
+			dump_vga_script(_curVgaFile1 + READ_BE_UINT16(&((AnimationHeader_WW*)p)->scriptOffs), res, vgaSpriteId);
 		}
 	}
 
-	if (getGameType() == GType_WW) {
-		addVgaEvent(_vgaBaseDelay, _curVgaFile1 + READ_BE_UINT16(&((AnimationHeader_WW *) p)->scriptOffs), vgaSpriteId, res);
-	} else if (getGameType() == GType_FF) {
+	if (getGameType() == GType_FF || getGameType() == GType_PP) {
 		addVgaEvent(_vgaBaseDelay, _curVgaFile1 + READ_LE_UINT16(&((AnimationHeader_Feeble *) p)->scriptOffs), vgaSpriteId, res);
+	} else if (getGameType() == GType_SIMON1 || getGameType() == GType_SIMON2) {
+		addVgaEvent(_vgaBaseDelay, _curVgaFile1 + READ_BE_UINT16(&((AnimationHeader_Simon *) p)->scriptOffs), vgaSpriteId, res);
 	} else {
-		addVgaEvent(_vgaBaseDelay, _curVgaFile1 + READ_BE_UINT16(&((AnimationHeader_Simon *) p)->scriptOffs), vgaSpriteId, res);
+		addVgaEvent(_vgaBaseDelay, _curVgaFile1 + READ_BE_UINT16(&((AnimationHeader_WW *) p)->scriptOffs), vgaSpriteId, res);
 	}
 
 	_curVgaFile1 = old_file_1;
@@ -714,13 +712,23 @@
 
 /* must not be const */
 static uint16 _video_windows[128] = {
-	0, 0, 20, 200,
-	0, 0, 3, 136,
-	17, 0, 3, 136,
-	0, 0, 20, 200,
-	0, 0, 20, 134
+	0,  0, 20, 200,
+	0,  0,  3, 136,
+	17, 0,  3, 136,
+	0,  0, 20, 200,
+	0,  0, 20, 134
 };
 
+/* Elvira 1/2 & Waxworks
+static uint16 _video_windows[128] = {
+	 3, 0, 14, 136,
+	 0, 0,  3, 136,
+	17, 0,  3, 136,
+	 0, 0, 20, 200,
+	 3, 3, 14, 127,
+};
+ */
+
 void SimonEngine::decodeColumn(byte *dst, const byte *src, int height) {
 	const uint pitch = _dxSurfacePitch;
 	int8 reps = (int8)0x80;
@@ -819,7 +827,7 @@
 	if (state.image == 0)
 		return;
 
-	if (getGameType() == GType_FF) {
+	if (getGameType() == GType_FF || getGameType() == GType_PP) {
 		state.palette = (_vcPtr[0] * 16);
 		_vcPtr += 2;
 	} else if (getGameType() == GType_SIMON1 || getGameType() == GType_SIMON2) {
@@ -846,7 +854,7 @@
 
 	p2 = _curVgaFile2 + state.image * 8;
 	state.depack_src = _curVgaFile2 + readUint32Wrapper(p2);
-	if (getGameType() == GType_FF) {
+	if (getGameType() == GType_FF || getGameType() == GType_PP) {
 		width = READ_LE_UINT16(p2 + 6);
 		height = READ_LE_UINT16(p2 + 4) & 0x7FFF;
 		flags = p2[5];
@@ -863,7 +871,7 @@
 		dump_single_bitmap(_vgaCurZoneNum, state.image, state.depack_src, width, height,
 											 state.palette);
 	// Check if image is compressed
-	if (getGameType() == GType_FF) {
+	if (getGameType() == GType_FF || getGameType() == GType_PP) {
 		if (flags & 0x80) {
 			state.flags |= kDFCompressed;
 		}
@@ -886,7 +894,7 @@
 	state.x_skip = 0;				/* colums to skip = bh */
 	state.y_skip = 0;				/* rows to skip   = bl */
 
-	uint maxWidth = (getGameType() == GType_FF) ? 640 : 20;
+	uint maxWidth = (getGameType() == GType_FF || getGameType() == GType_PP) ? 640 : 20;
 	if ((getGameType() == GType_SIMON2 || getGameType() == GType_FF) && width > maxWidth) {
 		horizontalScroll(&state);
 		return;
@@ -910,7 +918,7 @@
 	state.surf_addr = getBackBuf();
 	state.surf_pitch = _dxSurfacePitch;
 
-	if (getGameType() == GType_FF) {
+	if (getGameType() == GType_FF || getGameType() == GType_PP) {
 		drawImages_Feeble(&state);
 	} else {
 		drawImages(&state);
@@ -938,7 +946,7 @@
 	}
 	state->x = cur;
 
-	maxWidth = (getGameType() == GType_FF) ? 640 : (vlut[2] * 2);
+	maxWidth = (getGameType() == GType_FF || getGameType() == GType_PP) ? 640 : (vlut[2] * 2);
 	cur += state->draw_width - maxWidth;
 	if (cur > 0) {
 		do {
@@ -957,7 +965,7 @@
 	}
 	state->y = cur;
 
-	maxHeight = (getGameType() == GType_FF) ? 480 : vlut[3];
+	maxHeight = (getGameType() == GType_FF || getGameType() == GType_PP) ? 480 : vlut[3];
 	cur += state->draw_height - maxHeight;
 	if (cur > 0) {
 		do {
@@ -1147,9 +1155,22 @@
 	uint offs, offs2;
 	// Allow one section of Simon the Sorcerer 1 introduction to be displayed
 	// in lower half of screen
-	if ((getGameType() == GType_SIMON1) && _subroutine == 2926) {
-		offs = ((vlut[0]) * 2 + state->x) * 8;
-		offs2 = (vlut[1] + state->y);
+	if (getGameType() == GType_WW) {
+		//if (_windowNum == 4 || _windowNum >= 10) {
+			offs = state->x * 8;
+			offs2 = state->y;
+		//} else {
+		//	offs = ((vlut[0] - _video_windows[16]) * 2 + state->x) * 8;
+		//	offs2 = (vlut[1] - _video_windows[17] + state->y);
+		//}
+	} else if (getGameType() == GType_SIMON1) {
+		if (_windowNum != 2 || _windowNum != 3) {
+			offs = ((vlut[0]) * 2 + state->x) * 8;
+			offs2 = (vlut[1] + state->y);
+		} else {
+			offs = ((vlut[0] - _video_windows[16]) * 2 + state->x) * 8;
+			offs2 = (vlut[1] - _video_windows[17] + state->y);
+		}
 	} else {
 		offs = ((vlut[0] - _video_windows[16]) * 2 + state->x) * 8;
 		offs2 = (vlut[1] - _video_windows[17] + state->y);
@@ -1480,7 +1501,7 @@
 	VgaSprite *vsp = findCurSprite();
 	uint16 num;
 
-	if (getGameType() == GType_FF) {
+	if (getGameType() == GType_FF || getGameType() == GType_PP) {
 		num = vcReadNextByte();
 	} else if (getGameType() == GType_SIMON2) {
 		num = vcReadNextByte() * _frameRate;
@@ -1554,7 +1575,7 @@
 		uint16 a = vcReadNextWord();
 		_pathFindArray[a - 1] = (const uint16 *)_vcPtr;
 
-		int end = (getGameType() == GType_FF) ? 9999 : 999;
+		int end = (getGameType() == GType_FF || getGameType() == GType_PP) ? 9999 : 999;
 		while (readUint16Wrapper(_vcPtr) != end)
 			_vcPtr += 4;
 		_vcPtr += 2;
@@ -1608,24 +1629,25 @@
 		a = vcReadNextWord();
 	b = vcReadNextWord();
 
-	if (getGameType() == GType_WW) {
-		num = 16;
-		palSize = 32;
-		palptr = _displayPalette;
-		offs = _curVgaFile1 + READ_BE_UINT16(_curVgaFile1 + 6);
-	} else if (getGameType() == GType_FF) {
+	if (getGameType() == GType_FF || getGameType() == GType_PP) {
 		num = 256;
 		palSize = 768;
 
 		palptr = _displayPalette;
 		offs = _curVgaFile1 + 6;
-	} else {
+	} else if (getGameType() == GType_SIMON1 || getGameType() == GType_SIMON2) {
 		num = a == 0 ? 32 : 16;
 		palSize = 96;
 
 		palptr = &_displayPalette[(a * 64)];
 		offs = _curVgaFile1 + 6;
+	} else {
+		num = 16;
+		palSize = 32;
+		palptr = _displayPalette;
+		offs = _curVgaFile1 + READ_BE_UINT16(_curVgaFile1 + 6);
 	}
+
 	src = offs + b * palSize;
 
 	do {
@@ -1818,7 +1840,7 @@
 	uint16 vga_res = vcReadNextWord();
 	uint16 windowNum = vcReadNextWord();
 
-	if (getGameType() == GType_FF) {
+	if (getGameType() == GType_FF || getGameType() == GType_PP) {
 		_copyPartialMode = 2;
 	} else if (getGameType() == GType_SIMON2) {
 		set_video_mode_internal(windowNum, vga_res);
@@ -1966,7 +1988,7 @@
 	if (getGameType() == GType_WW) {
 		//FIXME
 		vcReadNextWord();
-	} else if (getGameType() == GType_FF) {
+	} else if (getGameType() == GType_FF || getGameType() == GType_PP) {
 		VgaSprite *vsp = findCurSprite();
 		int16 x, y, ydiff;
 		int16 x1, y1, x2, y2;
@@ -2074,7 +2096,7 @@
 		sound = -sound;
 	}
 
-	if (getGameType() == GType_FF) {
+	if (getGameType() == GType_FF || getGameType() == GType_PP) {
 		int16 pan = vcReadNextWord();
 		int16 vol = vcReadNextWord();
 
@@ -2175,6 +2197,9 @@
 }
 
 void SimonEngine::vc58() {
+	if (getGameType() == GType_WW)
+		return;
+
 	uint16 sprite = _vgaCurSpriteId;
 	uint16 file = _vgaCurZoneNum;
 	const byte *vcPtrOrg;
@@ -2195,7 +2220,7 @@
 }
 
 void SimonEngine::vc59() {
-	if (getGameType() == GType_SIMON2 || getGameType() == GType_FF) {
+	if (getGameType() == GType_SIMON2 || getGameType() == GType_FF || getGameType() == GType_PP) {
 		uint16 file = vcReadNextWord();
 		uint16 start = vcReadNextWord();
 		uint16 end = vcReadNextWord() + 1;
@@ -2273,17 +2298,16 @@
 	if (getGameType() == GType_WW) {
 		// FIXME
 		vcReadVarOrWord();
-		return;
-	}
+	} else {
+		VgaSprite *vsp = findCurSprite();
 
-	VgaSprite *vsp = findCurSprite();
+		vsp->image = vcReadVarOrWord();
+		vsp->x += vcReadNextWord();
+		vsp->y += vcReadNextWord();
+		vsp->flags = kDFMasked | kDFUseFrontBuf;
 
-	vsp->image = vcReadVarOrWord();
-	vsp->x += vcReadNextWord();
-	vsp->y += vcReadNextWord();
-	vsp->flags = kDFMasked | kDFUseFrontBuf;
-
-	_vgaSpriteChanged++;
+		_vgaSpriteChanged++;
+	}
 }
 
 void SimonEngine::vc62_fastFadeOut() {
@@ -2303,7 +2327,7 @@
 
 		memcpy(_videoBuf1, _currentPalette, _fastFadeCount * 4);
 
-		if (getGameType() == GType_FF && !getBitFlag(75)) {
+		if ((getGameType() == GType_FF || getGameType() == GType_PP) && !getBitFlag(75)) {
 			fadeCount = 32;
 			fadeSize = 8;
 		} else {
@@ -2357,7 +2381,7 @@
 		// in lower half of screen
 		if ((getGameType() == GType_SIMON1) && (_subroutine == 2923 || _subroutine == 2926)) {
 			dx_clear_surfaces(200);
-		} else if (getGameType() == GType_FF) {
+		} else if (getGameType() == GType_FF || getGameType() == GType_PP) {
 			dx_clear_surfaces(480);
 		} else {
 			dx_clear_surfaces(_windowNum == 4 ? 134 : 200);
@@ -2370,7 +2394,7 @@
 }
 
 void SimonEngine::vc63_fastFadeIn() {
-	if (getGameType() == GType_FF) {
+	if (getGameType() == GType_FF || getGameType() == GType_PP) {
 		_fastFadeInFlag = 256;
 	} else {
 		_fastFadeInFlag = 208;


This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.




More information about the Scummvm-git-logs mailing list