diff options
-rw-r--r-- | engines/simon/event.cpp | 290 | ||||
-rw-r--r-- | engines/simon/items.cpp | 69 | ||||
-rw-r--r-- | engines/simon/module.mk | 3 | ||||
-rw-r--r-- | engines/simon/simon.cpp | 755 | ||||
-rw-r--r-- | engines/simon/string.cpp | 144 | ||||
-rw-r--r-- | engines/simon/subroutine.cpp | 319 | ||||
-rw-r--r-- | engines/simon/window.cpp | 165 |
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 |