aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--engines/simon/event.cpp290
-rw-r--r--engines/simon/items.cpp69
-rw-r--r--engines/simon/module.mk3
-rw-r--r--engines/simon/simon.cpp755
-rw-r--r--engines/simon/string.cpp144
-rw-r--r--engines/simon/subroutine.cpp319
-rw-r--r--engines/simon/window.cpp165
7 files changed, 921 insertions, 824 deletions
diff --git a/engines/simon/event.cpp b/engines/simon/event.cpp
new file mode 100644
index 0000000000..15105e7f61
--- /dev/null
+++ b/engines/simon/event.cpp
@@ -0,0 +1,290 @@
+/* ScummVM - Scumm Interpreter
+ * Copyright (C) 2001-2006 The ScummVM project
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "common/stdafx.h"
+
+#include "simon/simon.h"
+#include "simon/intern.h"
+
+namespace Simon {
+
+void SimonEngine::addTimeEvent(uint timeout, uint subroutine_id) {
+ TimeEvent *te = (TimeEvent *)malloc(sizeof(TimeEvent)), *first, *last = NULL;
+ time_t cur_time;
+
+ time(&cur_time);
+
+ te->time = cur_time + timeout - _gameStoppedClock;
+ if (_clockStopped)
+ te->time -= ((uint32)time(NULL) - _clockStopped);
+ te->subroutine_id = subroutine_id;
+
+ first = _firstTimeStruct;
+ while (first) {
+ if (te->time <= first->time) {
+ if (last) {
+ last->next = te;
+ te->next = first;
+ return;
+ }
+ te->next = _firstTimeStruct;
+ _firstTimeStruct = te;
+ return;
+ }
+
+ last = first;
+ first = first->next;
+ }
+
+ if (last) {
+ last->next = te;
+ te->next = NULL;
+ } else {
+ _firstTimeStruct = te;
+ te->next = NULL;
+ }
+}
+
+void SimonEngine::delTimeEvent(TimeEvent *te) {
+ TimeEvent *cur;
+
+ if (te == _pendingDeleteTimeEvent)
+ _pendingDeleteTimeEvent = NULL;
+
+ if (te == _firstTimeStruct) {
+ _firstTimeStruct = te->next;
+ free(te);
+ return;
+ }
+
+ cur = _firstTimeStruct;
+ if (cur == NULL)
+ error("delTimeEvent: none available");
+
+ for (;;) {
+ if (cur->next == NULL)
+ error("delTimeEvent: no such te");
+ if (te == cur->next) {
+ cur->next = te->next;
+ free(te);
+ return;
+ }
+ cur = cur->next;
+ }
+}
+
+void SimonEngine::invokeTimeEvent(TimeEvent *te) {
+ Subroutine *sub;
+
+ _scriptVerb = 0;
+
+ if (_runScriptReturn1)
+ return;
+
+ sub = getSubroutineByID(te->subroutine_id);
+ if (sub != NULL)
+ startSubroutineEx(sub);
+
+ _runScriptReturn1 = false;
+}
+
+void SimonEngine::killAllTimers() {
+ TimeEvent *cur, *next;
+
+ for (cur = _firstTimeStruct; cur; cur = next) {
+ next = cur->next;
+ delTimeEvent(cur);
+ }
+}
+
+bool SimonEngine::kickoffTimeEvents() {
+ time_t cur_time;
+ TimeEvent *te;
+ bool result = false;
+
+ if (_clockStopped)
+ return result;
+
+ time(&cur_time);
+ cur_time -= _gameStoppedClock;
+
+ while ((te = _firstTimeStruct) != NULL && te->time <= (uint32)cur_time) {
+ result = true;
+ _pendingDeleteTimeEvent = te;
+ invokeTimeEvent(te);
+ if (_pendingDeleteTimeEvent) {
+ _pendingDeleteTimeEvent = NULL;
+ delTimeEvent(te);
+ }
+ }
+
+ return result;
+}
+
+void SimonEngine::addVgaEvent(uint16 num, const byte *code_ptr, uint16 cur_sprite, uint16 curZoneNum, int32 param) {
+ VgaTimerEntry *vte;
+
+ // When Simon talks to the Golum about stew in French version of
+ // Simon the Sorcerer 1 the code_ptr is at wrong location for
+ // sprite 200. This was a bug in the original game, which
+ // caused several glitches in this scene.
+ // We work around the problem by correcting the code_ptr for sprite
+ // 200 in this scene, if it is wrong.
+ if (getGameType() == GType_SIMON1 && _language == Common::FR_FRA &&
+ (code_ptr - _vgaBufferPointers[curZoneNum].vgaFile1 == 4) && (cur_sprite == 200) && (curZoneNum == 2))
+ code_ptr += 0x66;
+
+ _lockWord |= 1;
+
+ for (vte = _vgaTimerList; vte->delay; vte++) {
+ }
+
+ vte->delay = num;
+ vte->script_pointer = code_ptr;
+ vte->sprite_id = cur_sprite;
+ vte->cur_vga_file = curZoneNum;
+ vte->param = param;
+
+ _lockWord &= ~1;
+}
+
+void SimonEngine::deleteVgaEvent(VgaTimerEntry * vte) {
+ _lockWord |= 1;
+
+ if (vte + 1 <= _nextVgaTimerToProcess) {
+ _nextVgaTimerToProcess--;
+ }
+
+ do {
+ memcpy(vte, vte + 1, sizeof(VgaTimerEntry));
+ vte++;
+ } while (vte->delay);
+
+ _lockWord &= ~1;
+}
+
+void SimonEngine::processVgaEvents() {
+ VgaTimerEntry *vte = _vgaTimerList;
+ uint timer = (getGameType() == GType_FF) ? 5 : 1;
+
+ _vgaTickCounter++;
+
+ while (vte->delay) {
+ vte->delay -= timer;
+ if (vte->delay <= 0) {
+ uint16 curZoneNum = vte->cur_vga_file;
+ uint16 cur_sprite = vte->sprite_id;
+ const byte *script_ptr = vte->script_pointer;
+ int32 param = vte->param;
+
+ _nextVgaTimerToProcess = vte + 1;
+ deleteVgaEvent(vte);
+
+ if (getGameType() == GType_FF && script_ptr == NULL) {
+ panEvent(curZoneNum, cur_sprite, param);
+ } else if (getGameType() == GType_SIMON2 && script_ptr == NULL) {
+ scrollEvent();
+ } else {
+ animateEvent(script_ptr, curZoneNum, cur_sprite);
+ }
+ vte = _nextVgaTimerToProcess;
+ } else {
+ vte++;
+ }
+ }
+}
+
+void SimonEngine::animateEvent(const byte *code_ptr, uint16 curZoneNum, uint16 cur_sprite) {
+ VgaPointersEntry *vpe;
+
+ _vgaCurSpriteId = cur_sprite;
+
+ _vgaCurZoneNum = curZoneNum;
+ _zoneNumber = curZoneNum;
+ vpe = &_vgaBufferPointers[curZoneNum];
+
+ _curVgaFile1 = vpe->vgaFile1;
+ _curVgaFile2 = vpe->vgaFile2;
+ _curSfxFile = vpe->sfxFile;
+
+ _vcPtr = code_ptr;
+
+ runVgaScript();
+}
+
+void SimonEngine::panEvent(uint16 curZoneNum, uint16 cur_sprite, int32 param) {
+ _vgaCurSpriteId = cur_sprite;
+ _vgaCurZoneNum = curZoneNum;
+
+ VgaSprite *vsp = findCurSprite();
+
+ param &= 0x10;
+
+ int32 pan = (vsp->x - _scrollX + param) * 8 - 2560;
+ if (pan < -10000)
+ pan = -10000;
+ if (pan > 10000)
+ pan = 10000;
+
+ //setSfxPan(param, pan);
+
+ if (pan != 0)
+ addVgaEvent(10, NULL, _vgaCurSpriteId, _vgaCurZoneNum); /* pan event */
+ debug(0, "panEvent: param %d pan %d", param, pan);
+}
+
+void SimonEngine::scrollEvent() {
+ if (_scrollCount == 0)
+ return;
+
+ if (getGameType() == GType_FF) {
+ if (_scrollCount < 0) {
+ if (_scrollFlag != -8) {
+ _scrollFlag = -8;
+ _scrollCount += 8;
+ }
+ } else {
+ if (_scrollFlag != 8) {
+ _scrollFlag = 8;
+ _scrollCount -= 8;
+ }
+ }
+ } else {
+ if (_scrollCount < 0) {
+ if (_scrollFlag != -1) {
+ _scrollFlag = -1;
+ if (++_scrollCount == 0)
+ return;
+ }
+ } else {
+ if (_scrollFlag != 1) {
+ _scrollFlag = 1;
+ if (--_scrollCount == 0)
+ return;
+ }
+ }
+
+ addVgaEvent(6, NULL, 0, 0); /* scroll event */
+ }
+}
+
+} // End of namespace Simon
diff --git a/engines/simon/items.cpp b/engines/simon/items.cpp
index 1ff4907a6c..f00aef3ee9 100644
--- a/engines/simon/items.cpp
+++ b/engines/simon/items.cpp
@@ -2203,75 +2203,6 @@ int SimonEngine::runScript() {
return getScriptReturn();
}
-int SimonEngine::startSubroutine(Subroutine *sub) {
- int result = -1;
- SubroutineLine *sl;
- const byte *old_code_ptr;
-
- if (_startMainScript)
- dumpSubroutine(sub);
-
- old_code_ptr = _codePtr;
-
- if (++_recursionDepth > 40)
- error("Recursion error");
-
- sl = (SubroutineLine *)((byte *)sub + sub->first);
-
- while ((byte *)sl != (byte *)sub) {
- if (checkIfToRunSubroutineLine(sl, sub)) {
- result = 0;
- _codePtr = (byte *)sl;
- if (sub->id)
- _codePtr += 2;
- else
- _codePtr += 8;
-
- if (_continousMainScript)
- fprintf(_dumpFile, "; %d\n", sub->id);
- result = runScript();
- if (result != 0) {
- /* result -10 means restart subroutine */
- if (result == -10) {
- delay(0); /* maybe leave control to the VGA */
- sl = (SubroutineLine *)((byte *)sub + sub->first);
- continue;
- }
- break;
- }
- }
- sl = (SubroutineLine *)((byte *)sub + sl->next);
- }
-
- _codePtr = old_code_ptr;
-
- _recursionDepth--;
- return result;
-}
-
-int SimonEngine::startSubroutineEx(Subroutine *sub) {
- return startSubroutine(sub);
-}
-
-bool SimonEngine::checkIfToRunSubroutineLine(SubroutineLine *sl, Subroutine *sub) {
- if (sub->id)
- return true;
-
- if (sl->verb != -1 && sl->verb != _scriptVerb &&
- (sl->verb != -2 || _scriptVerb != -1))
- return false;
-
- if (sl->noun1 != -1 && sl->noun1 != _scriptNoun1 &&
- (sl->noun1 != -2 || _scriptNoun1 != -1))
- return false;
-
- if (sl->noun2 != -1 && sl->noun2 != _scriptNoun2 &&
- (sl->noun2 != -2 || _scriptNoun2 != -1))
- return false;
-
- return true;
-}
-
void SimonEngine::scriptMouseOn() {
if (getGameType() == GType_FF && _mouseCursor != 5) {
resetVerbs();
diff --git a/engines/simon/module.mk b/engines/simon/module.mk
index b0e88d9257..1e55c0f0d6 100644
--- a/engines/simon/module.mk
+++ b/engines/simon/module.mk
@@ -6,6 +6,7 @@ MODULE_OBJS := \
cursor.o \
debug.o \
debugger.o \
+ event.o \
game.o \
icons.o \
items.o \
@@ -17,8 +18,10 @@ MODULE_OBJS := \
simon.o \
sound.o \
string.o \
+ subroutine.o \
verb.o \
vga.o \
+ window.o \
MODULE_DIRS += \
engines/simon
diff --git a/engines/simon/simon.cpp b/engines/simon/simon.cpp
index 46de8a3a5d..a5fe75faf7 100644
--- a/engines/simon/simon.cpp
+++ b/engines/simon/simon.cpp
@@ -649,27 +649,6 @@ byte *SimonEngine::allocateItem(uint size) {
return org;
}
-void SimonEngine::alignTableMem() {
- if ((unsigned long)_tablesHeapPtr & 3) {
- _tablesHeapPtr += 2;
- _tablesHeapCurPos += 2;
- }
-}
-
-byte *SimonEngine::allocateTable(uint size) {
- byte *org = _tablesHeapPtr;
-
- size = (size + 1) & ~1;
-
- _tablesHeapPtr += size;
- _tablesHeapCurPos += size;
-
- if (_tablesHeapCurPos > _tablesHeapSize)
- error("Tablesheap overflow");
-
- return org;
-}
-
int SimonEngine::allocGamePcVars(File *in) {
uint item_array_size, item_array_inited, stringtable_num;
uint32 version;
@@ -730,117 +709,6 @@ void SimonEngine::createPlayer() {
setUserFlag(_currentPlayer, 0, 0);
}
-void SimonEngine::allocateStringTable(int num) {
- _stringTabPtr = (byte **)calloc(num, sizeof(byte *));
- _stringTabPos = 0;
- _stringtab_numalloc = num;
-}
-
-void SimonEngine::setupStringTable(byte *mem, int num) {
- int i = 0;
- for (;;) {
- _stringTabPtr[i++] = mem;
- if (--num == 0)
- break;
- for (; *mem; mem++);
- mem++;
- }
-
- _stringTabPos = i;
-}
-
-void SimonEngine::setupLocalStringTable(byte *mem, int num) {
- int i = 0;
- for (;;) {
- _localStringtable[i++] = mem;
- if (--num == 0)
- break;
- for (; *mem; mem++);
- mem++;
- }
-}
-
-void SimonEngine::readSubroutineLine(File *in, SubroutineLine *sl, Subroutine *sub) {
- byte line_buffer[1024], *q = line_buffer;
- int size;
-
- if (sub->id == 0) {
- sl->verb = in->readUint16BE();
- sl->noun1 = in->readUint16BE();
- sl->noun2 = in->readUint16BE();
- }
-
- while ((*q = in->readByte()) != 0xFF) {
- if (*q == 87) {
- in->readUint16BE();
- } else {
- q = readSingleOpcode(in, q);
- }
- }
-
- size = q - line_buffer + 1;
-
- memcpy(allocateTable(size), line_buffer, size);
-}
-
-SubroutineLine *SimonEngine::createSubroutineLine(Subroutine *sub, int where) {
- SubroutineLine *sl, *cur_sl = NULL, *last_sl = NULL;
-
- if (sub->id == 0)
- sl = (SubroutineLine *)allocateTable(SUBROUTINE_LINE_BIG_SIZE);
- else
- sl = (SubroutineLine *)allocateTable(SUBROUTINE_LINE_SMALL_SIZE);
-
- // where is what offset to insert the line at, locate the proper beginning line
- if (sub->first != 0) {
- cur_sl = (SubroutineLine *)((byte *)sub + sub->first);
- while (where) {
- last_sl = cur_sl;
- cur_sl = (SubroutineLine *)((byte *)sub + cur_sl->next);
- if ((byte *)cur_sl == (byte *)sub)
- break;
- where--;
- }
- }
-
- if (last_sl != NULL) {
- // Insert the subroutine line in the middle of the link
- last_sl->next = (byte *)sl - (byte *)sub;
- sl->next = (byte *)cur_sl - (byte *)sub;
- } else {
- // Insert the subroutine line at the head of the link
- sl->next = sub->first;
- sub->first = (byte *)sl - (byte *)sub;
- }
-
- return sl;
-}
-
-void SimonEngine::readSubroutine(File *in, Subroutine *sub) {
- while (in->readUint16BE() == 0) {
- readSubroutineLine(in, createSubroutineLine(sub, 0xFFFF), sub);
- }
-}
-
-Subroutine *SimonEngine::createSubroutine(uint id) {
- Subroutine *sub;
-
- alignTableMem();
-
- sub = (Subroutine *)allocateTable(sizeof(Subroutine));
- sub->id = id;
- sub->first = 0;
- sub->next = _subroutineList;
- _subroutineList = sub;
- return sub;
-}
-
-void SimonEngine::readSubroutineBlock(File *in) {
- while (in->readUint16BE() == 0) {
- readSubroutine(in, createSubroutine(in->readUint16BE()));
- }
-}
-
Child *SimonEngine::findChildOfType(Item *i, uint type) {
Child *child = i->children;
for (; child; child = child->next)
@@ -1108,141 +976,6 @@ void SimonEngine::linkItem(Item *item, Item *parent) {
}
}
-const byte *SimonEngine::getStringPtrByID(uint stringId) {
- const byte *string_ptr;
- byte *dst;
-
- _freeStringSlot ^= 1;
-
- if (stringId < 0x8000) {
- string_ptr = _stringTabPtr[stringId];
- } else {
- string_ptr = getLocalStringByID(stringId);
- }
-
- dst = _stringReturnBuffer[_freeStringSlot];
- strcpy((char *)dst, (const char *)string_ptr);
- return dst;
-}
-
-const byte *SimonEngine::getLocalStringByID(uint stringId) {
- if (stringId < _stringIdLocalMin || stringId >= _stringIdLocalMax) {
- loadTextIntoMem(stringId);
- }
- return _localStringtable[stringId - _stringIdLocalMin];
-}
-
-void SimonEngine::loadTextIntoMem(uint stringId) {
- byte *p;
- char filename[30];
- int i;
- uint base_min = 0x8000, base_max, size;
-
- _tablesHeapPtr = _tablesheapPtrNew;
- _tablesHeapCurPos = _tablesHeapCurPosNew;
-
- p = _strippedTxtMem;
-
- // get filename
- while (*p) {
- for (i = 0; *p; p++, i++)
- filename[i] = *p;
- filename[i] = 0;
- p++;
-
- base_max = (p[0] * 256) | p[1];
- p += 2;
-
- if (stringId < base_max) {
- _stringIdLocalMin = base_min;
- _stringIdLocalMax = base_max;
-
- _localStringtable = (byte **)_tablesHeapPtr;
-
- size = (base_max - base_min + 1) * sizeof(byte *);
- _tablesHeapPtr += size;
- _tablesHeapCurPos += size;
-
- size = loadTextFile(filename, _tablesHeapPtr);
-
- setupLocalStringTable(_tablesHeapPtr, base_max - base_min + 1);
-
- _tablesHeapPtr += size;
- _tablesHeapCurPos += size;
-
- if (_tablesHeapCurPos > _tablesHeapSize) {
- error("loadTextIntoMem: Out of table memory");
- }
- return;
- }
-
- base_min = base_max;
- }
-
- error("loadTextIntoMem: didn't find %d", stringId);
-}
-
-void SimonEngine::loadTablesIntoMem(uint subr_id) {
- byte *p;
- int i;
- uint min_num, max_num;
- char filename[30];
- File *in;
-
- p = _tblList;
- if (p == NULL)
- return;
-
- while (*p) {
- for (i = 0; *p; p++, i++)
- filename[i] = *p;
- filename[i] = 0;
- p++;
-
- for (;;) {
- min_num = (p[0] * 256) | p[1];
- p += 2;
-
- if (min_num == 0)
- break;
-
- max_num = (p[0] * 256) | p[1];
- p += 2;
-
- if (subr_id >= min_num && subr_id <= max_num) {
- _subroutineList = _subroutineListOrg;
- _tablesHeapPtr = _tablesHeapPtrOrg;
- _tablesHeapCurPos = _tablesHeapCurPosOrg;
- _stringIdLocalMin = 1;
- _stringIdLocalMax = 0;
-
- in = openTablesFile(filename);
- readSubroutineBlock(in);
- closeTablesFile(in);
- if (getGameType() == GType_FF) {
- // TODO
- } else if (getGameType() == GType_SIMON2) {
- _sound->loadSfxTable(_gameFile, _gameOffsetsPtr[atoi(filename + 6) - 1 + SOUND_INDEX_BASE]);
- } else if (getPlatform() == Common::kPlatformWindows) {
- memcpy(filename, "SFXXXX", 6);
- _sound->readSfxFile(filename);
- }
-
- alignTableMem();
-
- _tablesheapPtrNew = _tablesHeapPtr;
- _tablesHeapCurPosNew = _tablesHeapCurPos;
-
- if (_tablesHeapCurPos > _tablesHeapSize)
- error("loadTablesIntoMem: Out of table memory");
- return;
- }
- }
- }
-
- debug(1,"loadTablesIntoMem: didn't find %d", subr_id);
-}
-
void SimonEngine::playSting(uint a) {
if (!midi._enable_sfx)
return;
@@ -1269,212 +1002,6 @@ void SimonEngine::playSting(uint a) {
midi.startTrack(0);
}
-Subroutine *SimonEngine::getSubroutineByID(uint subroutine_id) {
- Subroutine *cur;
-
- _subroutine = subroutine_id;
-
- for (cur = _subroutineList; cur; cur = cur->next) {
- if (cur->id == subroutine_id)
- return cur;
- }
-
- loadTablesIntoMem(subroutine_id);
-
- for (cur = _subroutineList; cur; cur = cur->next) {
- if (cur->id == subroutine_id)
- return cur;
- }
-
- if (subroutine_id != 160)
- debug(0,"getSubroutineByID: subroutine %d not found", subroutine_id);
- return NULL;
-}
-
-uint SimonEngine::loadTextFile_gme(const char *filename, byte *dst) {
- uint res;
- uint32 offs;
- uint32 size;
-
- res = atoi(filename + 4) + TEXT_INDEX_BASE - 1;
- offs = _gameOffsetsPtr[res];
- size = _gameOffsetsPtr[res + 1] - offs;
-
- readGameFile(dst, offs, size);
-
- return size;
-}
-
-File *SimonEngine::openTablesFile_gme(const char *filename) {
- uint res;
- uint32 offs;
-
- res = atoi(filename + 6) + TABLE_INDEX_BASE - 1;
- offs = _gameOffsetsPtr[res];
-
- _gameFile->seek(offs, SEEK_SET);
- return _gameFile;
-}
-
-uint SimonEngine::loadTextFile_simon1(const char *filename, byte *dst) {
- File fo;
- fo.open(filename);
- uint32 size;
-
- if (fo.isOpen() == false)
- error("loadTextFile: Can't open '%s'", filename);
-
- size = fo.size();
-
- if (fo.read(dst, size) != size)
- error("loadTextFile: fread failed");
- fo.close();
-
- return size;
-}
-
-File *SimonEngine::openTablesFile_simon1(const char *filename) {
- File *fo = new File();
- fo->open(filename);
- if (fo->isOpen() == false)
- error("openTablesFile: Can't open '%s'", filename);
- return fo;
-}
-
-uint SimonEngine::loadTextFile(const char *filename, byte *dst) {
- if (getFeatures() & GF_OLD_BUNDLE)
- return loadTextFile_simon1(filename, dst);
- else
- return loadTextFile_gme(filename, dst);
-}
-
-File *SimonEngine::openTablesFile(const char *filename) {
- if (getFeatures() & GF_OLD_BUNDLE)
- return openTablesFile_simon1(filename);
- else
- return openTablesFile_gme(filename);
-}
-
-void SimonEngine::closeTablesFile(File *in) {
- if (getFeatures() & GF_OLD_BUNDLE) {
- in->close();
- delete in;
- }
-}
-
-void SimonEngine::addTimeEvent(uint timeout, uint subroutine_id) {
- TimeEvent *te = (TimeEvent *)malloc(sizeof(TimeEvent)), *first, *last = NULL;
- time_t cur_time;
-
- time(&cur_time);
-
- te->time = cur_time + timeout - _gameStoppedClock;
- if (_clockStopped)
- te->time -= ((uint32)time(NULL) - _clockStopped);
- te->subroutine_id = subroutine_id;
-
- first = _firstTimeStruct;
- while (first) {
- if (te->time <= first->time) {
- if (last) {
- last->next = te;
- te->next = first;
- return;
- }
- te->next = _firstTimeStruct;
- _firstTimeStruct = te;
- return;
- }
-
- last = first;
- first = first->next;
- }
-
- if (last) {
- last->next = te;
- te->next = NULL;
- } else {
- _firstTimeStruct = te;
- te->next = NULL;
- }
-}
-
-void SimonEngine::delTimeEvent(TimeEvent *te) {
- TimeEvent *cur;
-
- if (te == _pendingDeleteTimeEvent)
- _pendingDeleteTimeEvent = NULL;
-
- if (te == _firstTimeStruct) {
- _firstTimeStruct = te->next;
- free(te);
- return;
- }
-
- cur = _firstTimeStruct;
- if (cur == NULL)
- error("delTimeEvent: none available");
-
- for (;;) {
- if (cur->next == NULL)
- error("delTimeEvent: no such te");
- if (te == cur->next) {
- cur->next = te->next;
- free(te);
- return;
- }
- cur = cur->next;
- }
-}
-
-void SimonEngine::killAllTimers() {
- TimeEvent *cur, *next;
-
- for (cur = _firstTimeStruct; cur; cur = next) {
- next = cur->next;
- delTimeEvent(cur);
- }
-}
-
-bool SimonEngine::kickoffTimeEvents() {
- time_t cur_time;
- TimeEvent *te;
- bool result = false;
-
- if (_clockStopped)
- return result;
-
- time(&cur_time);
- cur_time -= _gameStoppedClock;
-
- while ((te = _firstTimeStruct) != NULL && te->time <= (uint32)cur_time) {
- result = true;
- _pendingDeleteTimeEvent = te;
- invokeTimeEvent(te);
- if (_pendingDeleteTimeEvent) {
- _pendingDeleteTimeEvent = NULL;
- delTimeEvent(te);
- }
- }
-
- return result;
-}
-
-void SimonEngine::invokeTimeEvent(TimeEvent *te) {
- Subroutine *sub;
-
- _scriptVerb = 0;
-
- if (_runScriptReturn1)
- return;
-
- sub = getSubroutineByID(te->subroutine_id);
- if (sub != NULL)
- startSubroutineEx(sub);
-
- _runScriptReturn1 = false;
-}
-
void SimonEngine::setup_cond_c_helper() {
HitArea *last;
uint id;
@@ -1600,17 +1127,6 @@ void SimonEngine::endCutscene() {
_runScriptReturn1 = true;
}
-uint SimonEngine::getWindowNum(WindowBlock *window) {
- uint i;
-
- for (i = 0; i != ARRAYSIZE(_windowArray); i++)
- if (_windowArray[i] == window)
- return i;
-
- error("getWindowNum: not found");
- return 0;
-}
-
void SimonEngine::mouseOff() {
_mouseHideCount++;
}
@@ -2337,153 +1853,6 @@ void SimonEngine::set_video_mode_internal(uint16 mode, uint16 vga_res_id) {
}
}
-void SimonEngine::addVgaEvent(uint16 num, const byte *code_ptr, uint16 cur_sprite, uint16 curZoneNum, int32 param) {
- VgaTimerEntry *vte;
-
- // When Simon talks to the Golum about stew in French version of
- // Simon the Sorcerer 1 the code_ptr is at wrong location for
- // sprite 200. This was a bug in the original game, which
- // caused several glitches in this scene.
- // We work around the problem by correcting the code_ptr for sprite
- // 200 in this scene, if it is wrong.
- if (getGameType() == GType_SIMON1 && _language == Common::FR_FRA &&
- (code_ptr - _vgaBufferPointers[curZoneNum].vgaFile1 == 4) && (cur_sprite == 200) && (curZoneNum == 2))
- code_ptr += 0x66;
-
- _lockWord |= 1;
-
- for (vte = _vgaTimerList; vte->delay; vte++) {
- }
-
- vte->delay = num;
- vte->script_pointer = code_ptr;
- vte->sprite_id = cur_sprite;
- vte->cur_vga_file = curZoneNum;
- vte->param = param;
-
- _lockWord &= ~1;
-}
-
-void SimonEngine::deleteVgaEvent(VgaTimerEntry * vte) {
- _lockWord |= 1;
-
- if (vte + 1 <= _nextVgaTimerToProcess) {
- _nextVgaTimerToProcess--;
- }
-
- do {
- memcpy(vte, vte + 1, sizeof(VgaTimerEntry));
- vte++;
- } while (vte->delay);
-
- _lockWord &= ~1;
-}
-
-void SimonEngine::processVgaEvents() {
- VgaTimerEntry *vte = _vgaTimerList;
- uint timer = (getGameType() == GType_FF) ? 5 : 1;
-
- _vgaTickCounter++;
-
- while (vte->delay) {
- vte->delay -= timer;
- if (vte->delay <= 0) {
- uint16 curZoneNum = vte->cur_vga_file;
- uint16 cur_sprite = vte->sprite_id;
- const byte *script_ptr = vte->script_pointer;
- int32 param = vte->param;
-
- _nextVgaTimerToProcess = vte + 1;
- deleteVgaEvent(vte);
-
- if (getGameType() == GType_FF && script_ptr == NULL) {
- panEvent(curZoneNum, cur_sprite, param);
- } else if (getGameType() == GType_SIMON2 && script_ptr == NULL) {
- scrollEvent();
- } else {
- animateEvent(script_ptr, curZoneNum, cur_sprite);
- }
- vte = _nextVgaTimerToProcess;
- } else {
- vte++;
- }
- }
-}
-
-void SimonEngine::animateEvent(const byte *code_ptr, uint16 curZoneNum, uint16 cur_sprite) {
- VgaPointersEntry *vpe;
-
- _vgaCurSpriteId = cur_sprite;
-
- _vgaCurZoneNum = curZoneNum;
- _zoneNumber = curZoneNum;
- vpe = &_vgaBufferPointers[curZoneNum];
-
- _curVgaFile1 = vpe->vgaFile1;
- _curVgaFile2 = vpe->vgaFile2;
- _curSfxFile = vpe->sfxFile;
-
- _vcPtr = code_ptr;
-
- runVgaScript();
-}
-
-void SimonEngine::panEvent(uint16 curZoneNum, uint16 cur_sprite, int32 param) {
- _vgaCurSpriteId = cur_sprite;
- _vgaCurZoneNum = curZoneNum;
-
- VgaSprite *vsp = findCurSprite();
-
- param &= 0x10;
-
- int32 pan = (vsp->x - _scrollX + param) * 8 - 2560;
- if (pan < -10000)
- pan = -10000;
- if (pan > 10000)
- pan = 10000;
-
- //setSfxPan(param, pan);
-
- if (pan != 0)
- addVgaEvent(10, NULL, _vgaCurSpriteId, _vgaCurZoneNum); /* pan event */
- debug(0, "panEvent: param %d pan %d", param, pan);
-}
-
-void SimonEngine::scrollEvent() {
- if (_scrollCount == 0)
- return;
-
- if (getGameType() == GType_FF) {
- if (_scrollCount < 0) {
- if (_scrollFlag != -8) {
- _scrollFlag = -8;
- _scrollCount += 8;
- }
- } else {
- if (_scrollFlag != 8) {
- _scrollFlag = 8;
- _scrollCount -= 8;
- }
- }
- } else {
- if (_scrollCount < 0) {
- if (_scrollFlag != -1) {
- _scrollFlag = -1;
- if (++_scrollCount == 0)
- return;
- }
- } else {
- if (_scrollFlag != 1) {
- _scrollFlag = 1;
- if (--_scrollCount == 0)
- return;
- }
- }
-
- addVgaEvent(6, NULL, 0, 0); /* scroll event */
- }
-}
-
void SimonEngine::waitForSync(uint a) {
const uint maxCount = (getGameType() == GType_SIMON1) ? 500 : 1000;
@@ -2842,57 +2211,6 @@ void SimonEngine::timer_callback() {
}
}
-void SimonEngine::closeWindow(uint a) {
- if (_windowArray[a] == NULL)
- return;
- removeIconArray(a);
- resetWindow(_windowArray[a]);
- _windowArray[a] = NULL;
- if (_curWindow == a) {
- _textWindow = NULL;
- changeWindow(0);
- }
-}
-
-void SimonEngine::changeWindow(uint a) {
- a &= 7;
-
- if (_windowArray[a] == NULL || _curWindow == a)
- return;
-
- _curWindow = a;
- showmessage_print_char(0);
- _textWindow = _windowArray[a];
-
- if (getGameType() == GType_FF)
- showmessage_helper_3(_textWindow->textColumn, _textWindow->width);
- else
- showmessage_helper_3(_textWindow->textLength, _textWindow->textMaxLength);
-}
-
-WindowBlock *SimonEngine::openWindow(uint x, uint y, uint w, uint h, uint flags, uint fill_color, uint text_color) {
- WindowBlock *window;
-
- window = _windowList;
- while (window->mode != 0)
- window++;
-
- window->mode = 2;
- window->x = x;
- window->y = y;
- window->width = w;
- window->height = h;
- window->flags = flags;
- window->fill_color = fill_color;
- window->text_color = text_color;
- window->textColumn = 0;
- window->textRow = 0;
- window->textColumnOffset = 0;
- window->textMaxLength = window->width * 8 / 6; // characters are 6 pixels
- window->scrollY = 0;
- return window;
-}
-
Item *SimonEngine::derefItem(uint item) {
if (item >= _itemArraySize)
error("derefItem: invalid item %d", item);
@@ -2913,73 +2231,6 @@ void SimonEngine::delete_hitarea_by_index(uint index) {
_hitAreas[index].flags = 0;
}
-void SimonEngine::windowPutChar(uint a) {
- if (_textWindow != _windowArray[0])
- windowPutChar(_textWindow, a);
-}
-
-void SimonEngine::clearWindow(WindowBlock *window) {
- if (window->flags & 0x10)
- restoreWindow(window);
- else
- colorWindow(window);
-
- window->textColumn = 0;
- window->textRow = 0;
- window->textColumnOffset = 0;
- window->textLength = 0;
- window->scrollY = 0;
-}
-
-void SimonEngine::restoreWindow(WindowBlock *window) {
- _lockWord |= 0x8000;
-
- if (getGameType() == GType_FF) {
- restoreBlock(window->y + window->height, window->x + window->width, window->y, window->x);
- } else if (getGameType() == GType_SIMON2) {
- if (_restoreWindow6 && _windowArray[2] == window) {
- window = _windowArray[6];
- _restoreWindow6 = 0;
- }
-
- restoreBlock(window->y + window->height * 8, (window->x + window->width) * 8, window->y, window->x * 8);
- } else {
- restoreBlock(window->y + window->height * 8 + ((window == _windowArray[2]) ? 1 : 0), (window->x + window->width) * 8, window->y, window->x * 8);
- }
-
- _lockWord &= ~0x8000;
-}
-
-void SimonEngine::colorWindow(WindowBlock *window) {
- byte *dst;
- uint h, w;
-
- _lockWord |= 0x8000;
-
- if (getGameType() == GType_FF) {
- dst = getFrontBuf() + _dxSurfacePitch * window->y + window->x;
-
- for (h = 0; h < window->height; h++) {
- for (w = 0; w < window->width; w++) {
- if (dst[w] == 113 || dst[w] == 116 || dst[w] == 252)
- dst[w] = window->fill_color;
- }
- dst += _screenWidth;
- }
- } else {
- dst = getFrontBuf() + _dxSurfacePitch * window->y + window->x * 8;
- h = window->height * 8;
- w = window->width * 8;
-
- do {
- memset(dst, window->fill_color, w);
- dst += _dxSurfacePitch;
- } while (--h);
- }
-
- _lockWord &= ~0x8000;
-}
-
VgaSprite *SimonEngine::findCurSprite() {
VgaSprite *vsp = _vgaSprites;
while (vsp->id) {
@@ -3167,12 +2418,6 @@ void SimonEngine::video_toggle_colors(HitArea * ha, byte a, byte b, byte c, byte
_lockWord &= ~0x8000;
}
-void SimonEngine::resetWindow(WindowBlock *window) {
- if (window->flags & 8)
- restoreWindow(window);
- window->mode = 0;
-}
-
void SimonEngine::loadSprite(uint windowNum, uint zoneNum, uint vgaSpriteId, uint x, uint y, uint palette) {
VgaSprite *vsp;
VgaPointersEntry *vpe;
diff --git a/engines/simon/string.cpp b/engines/simon/string.cpp
index ee709e88b2..ffda5629e8 100644
--- a/engines/simon/string.cpp
+++ b/engines/simon/string.cpp
@@ -25,8 +25,152 @@
#include "simon/simon.h"
#include "simon/intern.h"
+using Common::File;
+
namespace Simon {
+const byte *SimonEngine::getStringPtrByID(uint stringId) {
+ const byte *string_ptr;
+ byte *dst;
+
+ _freeStringSlot ^= 1;
+
+ if (stringId < 0x8000) {
+ string_ptr = _stringTabPtr[stringId];
+ } else {
+ string_ptr = getLocalStringByID(stringId);
+ }
+
+ dst = _stringReturnBuffer[_freeStringSlot];
+ strcpy((char *)dst, (const char *)string_ptr);
+ return dst;
+}
+
+const byte *SimonEngine::getLocalStringByID(uint stringId) {
+ if (stringId < _stringIdLocalMin || stringId >= _stringIdLocalMax) {
+ loadTextIntoMem(stringId);
+ }
+ return _localStringtable[stringId - _stringIdLocalMin];
+}
+
+void SimonEngine::allocateStringTable(int num) {
+ _stringTabPtr = (byte **)calloc(num, sizeof(byte *));
+ _stringTabPos = 0;
+ _stringtab_numalloc = num;
+}
+
+void SimonEngine::setupStringTable(byte *mem, int num) {
+ int i = 0;
+ for (;;) {
+ _stringTabPtr[i++] = mem;
+ if (--num == 0)
+ break;
+ for (; *mem; mem++);
+ mem++;
+ }
+
+ _stringTabPos = i;
+}
+
+void SimonEngine::setupLocalStringTable(byte *mem, int num) {
+ int i = 0;
+ for (;;) {
+ _localStringtable[i++] = mem;
+ if (--num == 0)
+ break;
+ for (; *mem; mem++);
+ mem++;
+ }
+}
+
+uint SimonEngine::loadTextFile(const char *filename, byte *dst) {
+ if (getFeatures() & GF_OLD_BUNDLE)
+ return loadTextFile_simon1(filename, dst);
+ else
+ return loadTextFile_gme(filename, dst);
+}
+
+uint SimonEngine::loadTextFile_simon1(const char *filename, byte *dst) {
+ File fo;
+ fo.open(filename);
+ uint32 size;
+
+ if (fo.isOpen() == false)
+ error("loadTextFile: Can't open '%s'", filename);
+
+ size = fo.size();
+
+ if (fo.read(dst, size) != size)
+ error("loadTextFile: fread failed");
+ fo.close();
+
+ return size;
+}
+
+uint SimonEngine::loadTextFile_gme(const char *filename, byte *dst) {
+ uint res;
+ uint32 offs;
+ uint32 size;
+
+ res = atoi(filename + 4) + TEXT_INDEX_BASE - 1;
+ offs = _gameOffsetsPtr[res];
+ size = _gameOffsetsPtr[res + 1] - offs;
+
+ readGameFile(dst, offs, size);
+
+ return size;
+}
+
+void SimonEngine::loadTextIntoMem(uint stringId) {
+ byte *p;
+ char filename[30];
+ int i;
+ uint base_min = 0x8000, base_max, size;
+
+ _tablesHeapPtr = _tablesheapPtrNew;
+ _tablesHeapCurPos = _tablesHeapCurPosNew;
+
+ p = _strippedTxtMem;
+
+ // get filename
+ while (*p) {
+ for (i = 0; *p; p++, i++)
+ filename[i] = *p;
+ filename[i] = 0;
+ p++;
+
+ base_max = (p[0] * 256) | p[1];
+ p += 2;
+
+ if (stringId < base_max) {
+ _stringIdLocalMin = base_min;
+ _stringIdLocalMax = base_max;
+
+ _localStringtable = (byte **)_tablesHeapPtr;
+
+ size = (base_max - base_min + 1) * sizeof(byte *);
+ _tablesHeapPtr += size;
+ _tablesHeapCurPos += size;
+
+ size = loadTextFile(filename, _tablesHeapPtr);
+
+ setupLocalStringTable(_tablesHeapPtr, base_max - base_min + 1);
+
+ _tablesHeapPtr += size;
+ _tablesHeapCurPos += size;
+
+ if (_tablesHeapCurPos > _tablesHeapSize) {
+ error("loadTextIntoMem: Out of table memory");
+ }
+ return;
+ }
+
+ base_min = base_max;
+ }
+
+ error("loadTextIntoMem: didn't find %d", stringId);
+}
+
static const byte charWidth[226] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
diff --git a/engines/simon/subroutine.cpp b/engines/simon/subroutine.cpp
new file mode 100644
index 0000000000..e700182899
--- /dev/null
+++ b/engines/simon/subroutine.cpp
@@ -0,0 +1,319 @@
+/* ScummVM - Scumm Interpreter
+ * Copyright (C) 2001-2006 The ScummVM project
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "common/stdafx.h"
+
+#include "simon/simon.h"
+#include "simon/intern.h"
+
+using Common::File;
+
+namespace Simon {
+
+Subroutine *SimonEngine::getSubroutineByID(uint subroutine_id) {
+ Subroutine *cur;
+
+ _subroutine = subroutine_id;
+
+ for (cur = _subroutineList; cur; cur = cur->next) {
+ if (cur->id == subroutine_id)
+ return cur;
+ }
+
+ loadTablesIntoMem(subroutine_id);
+
+ for (cur = _subroutineList; cur; cur = cur->next) {
+ if (cur->id == subroutine_id)
+ return cur;
+ }
+
+ if (subroutine_id != 160)
+ debug(0,"getSubroutineByID: subroutine %d not found", subroutine_id);
+ return NULL;
+}
+
+void SimonEngine::alignTableMem() {
+ if ((unsigned long)_tablesHeapPtr & 3) {
+ _tablesHeapPtr += 2;
+ _tablesHeapCurPos += 2;
+ }
+}
+
+byte *SimonEngine::allocateTable(uint size) {
+ byte *org = _tablesHeapPtr;
+
+ size = (size + 1) & ~1;
+
+ _tablesHeapPtr += size;
+ _tablesHeapCurPos += size;
+
+ if (_tablesHeapCurPos > _tablesHeapSize)
+ error("Tablesheap overflow");
+
+ return org;
+}
+
+File *SimonEngine::openTablesFile(const char *filename) {
+ if (getFeatures() & GF_OLD_BUNDLE)
+ return openTablesFile_simon1(filename);
+ else
+ return openTablesFile_gme(filename);
+}
+
+File *SimonEngine::openTablesFile_simon1(const char *filename) {
+ File *fo = new File();
+ fo->open(filename);
+ if (fo->isOpen() == false)
+ error("openTablesFile: Can't open '%s'", filename);
+ return fo;
+}
+
+File *SimonEngine::openTablesFile_gme(const char *filename) {
+ uint res;
+ uint32 offs;
+
+ res = atoi(filename + 6) + TABLE_INDEX_BASE - 1;
+ offs = _gameOffsetsPtr[res];
+
+ _gameFile->seek(offs, SEEK_SET);
+ return _gameFile;
+}
+
+void SimonEngine::loadTablesIntoMem(uint subr_id) {
+ byte *p;
+ int i;
+ uint min_num, max_num;
+ char filename[30];
+ File *in;
+
+ p = _tblList;
+ if (p == NULL)
+ return;
+
+ while (*p) {
+ for (i = 0; *p; p++, i++)
+ filename[i] = *p;
+ filename[i] = 0;
+ p++;
+
+ for (;;) {
+ min_num = (p[0] * 256) | p[1];
+ p += 2;
+
+ if (min_num == 0)
+ break;
+
+ max_num = (p[0] * 256) | p[1];
+ p += 2;
+
+ if (subr_id >= min_num && subr_id <= max_num) {
+ _subroutineList = _subroutineListOrg;
+ _tablesHeapPtr = _tablesHeapPtrOrg;
+ _tablesHeapCurPos = _tablesHeapCurPosOrg;
+ _stringIdLocalMin = 1;
+ _stringIdLocalMax = 0;
+
+ in = openTablesFile(filename);
+ readSubroutineBlock(in);
+ closeTablesFile(in);
+ if (getGameType() == GType_FF) {
+ // TODO
+ } else if (getGameType() == GType_SIMON2) {
+ _sound->loadSfxTable(_gameFile, _gameOffsetsPtr[atoi(filename + 6) - 1 + SOUND_INDEX_BASE]);
+ } else if (getPlatform() == Common::kPlatformWindows) {
+ memcpy(filename, "SFXXXX", 6);
+ _sound->readSfxFile(filename);
+ }
+
+ alignTableMem();
+
+ _tablesheapPtrNew = _tablesHeapPtr;
+ _tablesHeapCurPosNew = _tablesHeapCurPos;
+
+ if (_tablesHeapCurPos > _tablesHeapSize)
+ error("loadTablesIntoMem: Out of table memory");
+ return;
+ }
+ }
+ }
+
+ debug(1,"loadTablesIntoMem: didn't find %d", subr_id);
+}
+
+void SimonEngine::closeTablesFile(File *in) {
+ if (getFeatures() & GF_OLD_BUNDLE) {
+ in->close();
+ delete in;
+ }
+}
+
+Subroutine *SimonEngine::createSubroutine(uint id) {
+ Subroutine *sub;
+
+ alignTableMem();
+
+ sub = (Subroutine *)allocateTable(sizeof(Subroutine));
+ sub->id = id;
+ sub->first = 0;
+ sub->next = _subroutineList;
+ _subroutineList = sub;
+ return sub;
+}
+
+SubroutineLine *SimonEngine::createSubroutineLine(Subroutine *sub, int where) {
+ SubroutineLine *sl, *cur_sl = NULL, *last_sl = NULL;
+
+ if (sub->id == 0)
+ sl = (SubroutineLine *)allocateTable(SUBROUTINE_LINE_BIG_SIZE);
+ else
+ sl = (SubroutineLine *)allocateTable(SUBROUTINE_LINE_SMALL_SIZE);
+
+ // where is what offset to insert the line at, locate the proper beginning line
+ if (sub->first != 0) {
+ cur_sl = (SubroutineLine *)((byte *)sub + sub->first);
+ while (where) {
+ last_sl = cur_sl;
+ cur_sl = (SubroutineLine *)((byte *)sub + cur_sl->next);
+ if ((byte *)cur_sl == (byte *)sub)
+ break;
+ where--;
+ }
+ }
+
+ if (last_sl != NULL) {
+ // Insert the subroutine line in the middle of the link
+ last_sl->next = (byte *)sl - (byte *)sub;
+ sl->next = (byte *)cur_sl - (byte *)sub;
+ } else {
+ // Insert the subroutine line at the head of the link
+ sl->next = sub->first;
+ sub->first = (byte *)sl - (byte *)sub;
+ }
+
+ return sl;
+}
+
+int SimonEngine::startSubroutine(Subroutine *sub) {
+ int result = -1;
+ SubroutineLine *sl;
+ const byte *old_code_ptr;
+
+ if (_startMainScript)
+ dumpSubroutine(sub);
+
+ old_code_ptr = _codePtr;
+
+ if (++_recursionDepth > 40)
+ error("Recursion error");
+
+ sl = (SubroutineLine *)((byte *)sub + sub->first);
+
+ while ((byte *)sl != (byte *)sub) {
+ if (checkIfToRunSubroutineLine(sl, sub)) {
+ result = 0;
+ _codePtr = (byte *)sl;
+ if (sub->id)
+ _codePtr += 2;
+ else
+ _codePtr += 8;
+
+ if (_continousMainScript)
+ fprintf(_dumpFile, "; %d\n", sub->id);
+ result = runScript();
+ if (result != 0) {
+ /* result -10 means restart subroutine */
+ if (result == -10) {
+ delay(0); /* maybe leave control to the VGA */
+ sl = (SubroutineLine *)((byte *)sub + sub->first);
+ continue;
+ }
+ break;
+ }
+ }
+ sl = (SubroutineLine *)((byte *)sub + sl->next);
+ }
+
+ _codePtr = old_code_ptr;
+
+ _recursionDepth--;
+ return result;
+}
+
+int SimonEngine::startSubroutineEx(Subroutine *sub) {
+ return startSubroutine(sub);
+}
+
+bool SimonEngine::checkIfToRunSubroutineLine(SubroutineLine *sl, Subroutine *sub) {
+ if (sub->id)
+ return true;
+
+ if (sl->verb != -1 && sl->verb != _scriptVerb &&
+ (sl->verb != -2 || _scriptVerb != -1))
+ return false;
+
+ if (sl->noun1 != -1 && sl->noun1 != _scriptNoun1 &&
+ (sl->noun1 != -2 || _scriptNoun1 != -1))
+ return false;
+
+ if (sl->noun2 != -1 && sl->noun2 != _scriptNoun2 &&
+ (sl->noun2 != -2 || _scriptNoun2 != -1))
+ return false;
+
+ return true;
+}
+
+void SimonEngine::readSubroutine(File *in, Subroutine *sub) {
+ while (in->readUint16BE() == 0) {
+ readSubroutineLine(in, createSubroutineLine(sub, 0xFFFF), sub);
+ }
+}
+
+void SimonEngine::readSubroutineLine(File *in, SubroutineLine *sl, Subroutine *sub) {
+ byte line_buffer[1024], *q = line_buffer;
+ int size;
+
+ if (sub->id == 0) {
+ sl->verb = in->readUint16BE();
+ sl->noun1 = in->readUint16BE();
+ sl->noun2 = in->readUint16BE();
+ }
+
+ while ((*q = in->readByte()) != 0xFF) {
+ if (*q == 87) {
+ in->readUint16BE();
+ } else {
+ q = readSingleOpcode(in, q);
+ }
+ }
+
+ size = q - line_buffer + 1;
+
+ memcpy(allocateTable(size), line_buffer, size);
+}
+
+void SimonEngine::readSubroutineBlock(File *in) {
+ while (in->readUint16BE() == 0) {
+ readSubroutine(in, createSubroutine(in->readUint16BE()));
+ }
+}
+
+} // End of namespace Simon
diff --git a/engines/simon/window.cpp b/engines/simon/window.cpp
new file mode 100644
index 0000000000..ce4f989a6e
--- /dev/null
+++ b/engines/simon/window.cpp
@@ -0,0 +1,165 @@
+/* ScummVM - Scumm Interpreter
+ * Copyright (C) 2001-2006 The ScummVM project
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL: https://svn.sourceforge.net/svnroot/scummvm/scummvm/trunk/engines/simon/string.cpp $
+ * $Id: string.cpp 22062 2006-04-21 00:18:23Z kirben $
+ *
+ */
+
+#include "common/stdafx.h"
+
+#include "simon/simon.h"
+#include "simon/intern.h"
+
+namespace Simon {
+
+uint SimonEngine::getWindowNum(WindowBlock *window) {
+ uint i;
+
+ for (i = 0; i != ARRAYSIZE(_windowArray); i++)
+ if (_windowArray[i] == window)
+ return i;
+
+ error("getWindowNum: not found");
+ return 0;
+}
+
+WindowBlock *SimonEngine::openWindow(uint x, uint y, uint w, uint h, uint flags, uint fill_color, uint text_color) {
+ WindowBlock *window;
+
+ window = _windowList;
+ while (window->mode != 0)
+ window++;
+
+ window->mode = 2;
+ window->x = x;
+ window->y = y;
+ window->width = w;
+ window->height = h;
+ window->flags = flags;
+ window->fill_color = fill_color;
+ window->text_color = text_color;
+ window->textColumn = 0;
+ window->textRow = 0;
+ window->textColumnOffset = 0;
+ window->textMaxLength = window->width * 8 / 6; // characters are 6 pixels
+ window->scrollY = 0;
+ return window;
+}
+
+void SimonEngine::changeWindow(uint a) {
+ a &= 7;
+
+ if (_windowArray[a] == NULL || _curWindow == a)
+ return;
+
+ _curWindow = a;
+ showmessage_print_char(0);
+ _textWindow = _windowArray[a];
+
+ if (getGameType() == GType_FF)
+ showmessage_helper_3(_textWindow->textColumn, _textWindow->width);
+ else
+ showmessage_helper_3(_textWindow->textLength, _textWindow->textMaxLength);
+}
+
+void SimonEngine::closeWindow(uint a) {
+ if (_windowArray[a] == NULL)
+ return;
+ removeIconArray(a);
+ resetWindow(_windowArray[a]);
+ _windowArray[a] = NULL;
+ if (_curWindow == a) {
+ _textWindow = NULL;
+ changeWindow(0);
+ }
+}
+
+void SimonEngine::clearWindow(WindowBlock *window) {
+ if (window->flags & 0x10)
+ restoreWindow(window);
+ else
+ colorWindow(window);
+
+ window->textColumn = 0;
+ window->textRow = 0;
+ window->textColumnOffset = 0;
+ window->textLength = 0;
+ window->scrollY = 0;
+}
+
+void SimonEngine::colorWindow(WindowBlock *window) {
+ byte *dst;
+ uint h, w;
+
+ _lockWord |= 0x8000;
+
+ if (getGameType() == GType_FF) {
+ dst = getFrontBuf() + _dxSurfacePitch * window->y + window->x;
+
+ for (h = 0; h < window->height; h++) {
+ for (w = 0; w < window->width; w++) {
+ if (dst[w] == 113 || dst[w] == 116 || dst[w] == 252)
+ dst[w] = window->fill_color;
+ }
+ dst += _screenWidth;
+ }
+ } else {
+ dst = getFrontBuf() + _dxSurfacePitch * window->y + window->x * 8;
+ h = window->height * 8;
+ w = window->width * 8;
+
+ do {
+ memset(dst, window->fill_color, w);
+ dst += _dxSurfacePitch;
+ } while (--h);
+ }
+
+ _lockWord &= ~0x8000;
+}
+
+void SimonEngine::resetWindow(WindowBlock *window) {
+ if (window->flags & 8)
+ restoreWindow(window);
+ window->mode = 0;
+}
+
+void SimonEngine::restoreWindow(WindowBlock *window) {
+ _lockWord |= 0x8000;
+
+ if (getGameType() == GType_FF) {
+ restoreBlock(window->y + window->height, window->x + window->width, window->y, window->x);
+ } else if (getGameType() == GType_SIMON2) {
+ if (_restoreWindow6 && _windowArray[2] == window) {
+ window = _windowArray[6];
+ _restoreWindow6 = 0;
+ }
+
+ restoreBlock(window->y + window->height * 8, (window->x + window->width) * 8, window->y, window->x * 8);
+ } else {
+ restoreBlock(window->y + window->height * 8 + ((window == _windowArray[2]) ? 1 : 0), (window->x + window->width) * 8, window->y, window->x * 8);
+ }
+
+ _lockWord &= ~0x8000;
+}
+
+void SimonEngine::windowPutChar(uint a) {
+ if (_textWindow != _windowArray[0])
+ windowPutChar(_textWindow, a);
+}
+
+} // End of namespace Simon