Split more functions of simon.cpp into separate files
svn-id: r22221
This commit is contained in:
parent
af280f967b
commit
daed55b789
7 changed files with 921 additions and 824 deletions
290
engines/simon/event.cpp
Normal file
290
engines/simon/event.cpp
Normal file
|
@ -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
|
|
@ -2203,75 +2203,6 @@ int SimonEngine::runScript() {
|
||||||
return getScriptReturn();
|
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() {
|
void SimonEngine::scriptMouseOn() {
|
||||||
if (getGameType() == GType_FF && _mouseCursor != 5) {
|
if (getGameType() == GType_FF && _mouseCursor != 5) {
|
||||||
resetVerbs();
|
resetVerbs();
|
||||||
|
|
|
@ -6,6 +6,7 @@ MODULE_OBJS := \
|
||||||
cursor.o \
|
cursor.o \
|
||||||
debug.o \
|
debug.o \
|
||||||
debugger.o \
|
debugger.o \
|
||||||
|
event.o \
|
||||||
game.o \
|
game.o \
|
||||||
icons.o \
|
icons.o \
|
||||||
items.o \
|
items.o \
|
||||||
|
@ -17,8 +18,10 @@ MODULE_OBJS := \
|
||||||
simon.o \
|
simon.o \
|
||||||
sound.o \
|
sound.o \
|
||||||
string.o \
|
string.o \
|
||||||
|
subroutine.o \
|
||||||
verb.o \
|
verb.o \
|
||||||
vga.o \
|
vga.o \
|
||||||
|
window.o \
|
||||||
|
|
||||||
MODULE_DIRS += \
|
MODULE_DIRS += \
|
||||||
engines/simon
|
engines/simon
|
||||||
|
|
|
@ -649,27 +649,6 @@ byte *SimonEngine::allocateItem(uint size) {
|
||||||
return org;
|
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) {
|
int SimonEngine::allocGamePcVars(File *in) {
|
||||||
uint item_array_size, item_array_inited, stringtable_num;
|
uint item_array_size, item_array_inited, stringtable_num;
|
||||||
uint32 version;
|
uint32 version;
|
||||||
|
@ -730,117 +709,6 @@ void SimonEngine::createPlayer() {
|
||||||
setUserFlag(_currentPlayer, 0, 0);
|
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 *SimonEngine::findChildOfType(Item *i, uint type) {
|
||||||
Child *child = i->children;
|
Child *child = i->children;
|
||||||
for (; child; child = child->next)
|
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) {
|
void SimonEngine::playSting(uint a) {
|
||||||
if (!midi._enable_sfx)
|
if (!midi._enable_sfx)
|
||||||
return;
|
return;
|
||||||
|
@ -1269,212 +1002,6 @@ void SimonEngine::playSting(uint a) {
|
||||||
midi.startTrack(0);
|
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() {
|
void SimonEngine::setup_cond_c_helper() {
|
||||||
HitArea *last;
|
HitArea *last;
|
||||||
uint id;
|
uint id;
|
||||||
|
@ -1600,17 +1127,6 @@ void SimonEngine::endCutscene() {
|
||||||
_runScriptReturn1 = true;
|
_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() {
|
void SimonEngine::mouseOff() {
|
||||||
_mouseHideCount++;
|
_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) {
|
void SimonEngine::waitForSync(uint a) {
|
||||||
const uint maxCount = (getGameType() == GType_SIMON1) ? 500 : 1000;
|
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) {
|
Item *SimonEngine::derefItem(uint item) {
|
||||||
if (item >= _itemArraySize)
|
if (item >= _itemArraySize)
|
||||||
error("derefItem: invalid item %d", item);
|
error("derefItem: invalid item %d", item);
|
||||||
|
@ -2913,73 +2231,6 @@ void SimonEngine::delete_hitarea_by_index(uint index) {
|
||||||
_hitAreas[index].flags = 0;
|
_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 *SimonEngine::findCurSprite() {
|
||||||
VgaSprite *vsp = _vgaSprites;
|
VgaSprite *vsp = _vgaSprites;
|
||||||
while (vsp->id) {
|
while (vsp->id) {
|
||||||
|
@ -3167,12 +2418,6 @@ void SimonEngine::video_toggle_colors(HitArea * ha, byte a, byte b, byte c, byte
|
||||||
_lockWord &= ~0x8000;
|
_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) {
|
void SimonEngine::loadSprite(uint windowNum, uint zoneNum, uint vgaSpriteId, uint x, uint y, uint palette) {
|
||||||
VgaSprite *vsp;
|
VgaSprite *vsp;
|
||||||
VgaPointersEntry *vpe;
|
VgaPointersEntry *vpe;
|
||||||
|
|
|
@ -25,8 +25,152 @@
|
||||||
#include "simon/simon.h"
|
#include "simon/simon.h"
|
||||||
#include "simon/intern.h"
|
#include "simon/intern.h"
|
||||||
|
|
||||||
|
using Common::File;
|
||||||
|
|
||||||
namespace Simon {
|
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] = {
|
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,
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
|
319
engines/simon/subroutine.cpp
Normal file
319
engines/simon/subroutine.cpp
Normal file
|
@ -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
|
165
engines/simon/window.cpp
Normal file
165
engines/simon/window.cpp
Normal file
|
@ -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
|
Loading…
Add table
Add a link
Reference in a new issue