Split more functions of simon.cpp into separate files

svn-id: r22221
This commit is contained in:
Travis Howell 2006-04-29 13:38:07 +00:00
parent af280f967b
commit daed55b789
7 changed files with 921 additions and 824 deletions

290
engines/simon/event.cpp Normal file
View 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

View file

@ -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();

View file

@ -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

View file

@ -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;

View file

@ -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,

View 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
View 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