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