scummvm/engines/agos/script_pn.cpp
2011-08-06 11:28:40 +01:00

1119 lines
23 KiB
C++

/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* 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.
*
*/
#include "agos/agos.h"
#include "agos/vga.h"
#include "common/endian.h"
#include "common/textconsole.h"
namespace AGOS {
enum {
kJmpClassNum = -1
};
#define OPCODE(x) _OPCODE(AGOSEngine_PN, x)
void AGOSEngine_PN::setupOpcodes() {
static const OpcodeEntryPN opcodes[] = {
/* 00 */
OPCODE(opn_opcode00),
OPCODE(opn_add),
OPCODE(opn_sub),
OPCODE(opn_mul),
/* 04 */
OPCODE(opn_div),
OPCODE(opn_opcode05),
OPCODE(opn_opcode06),
OPCODE(opn_opcode07),
/* 08 */
OPCODE(opn_opcode08),
OPCODE(opn_opcode09),
OPCODE(opn_opcode10),
OPCODE(opn_opcode11),
/* 12 */
OPCODE(opn_opcode12),
OPCODE(opn_opcode13),
OPCODE(opn_opcode14),
OPCODE(opn_opcode15),
/* 16 */
OPCODE(opn_opcode16),
OPCODE(opn_lt),
OPCODE(opn_gt),
OPCODE(opn_eq),
/* 20 */
OPCODE(opn_neq),
OPCODE(opn_opcode21),
OPCODE(opn_opcode22),
OPCODE(opn_opcode23),
/* 24 */
OPCODE(opn_opcode24),
OPCODE(opn_opcode25),
OPCODE(opn_opcode26),
OPCODE(opn_opcode27),
/* 28 */
OPCODE(opn_opcode28),
OPCODE(opn_opcode29),
OPCODE(opn_opcode30),
OPCODE(opn_opcode31),
/* 32 */
OPCODE(opn_opcode32),
OPCODE(opn_opcode33),
OPCODE(opn_opcode34),
OPCODE(opn_opcode35),
/* 36 */
OPCODE(opn_opcode36),
OPCODE(opn_opcode37),
OPCODE(opn_opcode38),
OPCODE(opn_opcode39),
/* 40 */
OPCODE(opn_opcode40),
OPCODE(opn_opcode41),
OPCODE(opn_opcode42),
OPCODE(opn_opcode43),
/* 44 */
OPCODE(opn_opcode44),
OPCODE(opn_opcode45),
OPCODE(opn_opcode46),
OPCODE(opn_opcode47),
/* 48 */
OPCODE(opn_opcode48),
OPCODE(opn_opcode49),
OPCODE(opn_opcode50),
OPCODE(opn_opcode51),
/* 52 */
OPCODE(opn_opcode52),
OPCODE(opn_opcode53),
OPCODE(opn_opcode54),
OPCODE(opn_opcode55),
/* 56 */
OPCODE(opn_opcode56),
OPCODE(opn_opcode57),
OPCODE(o_invalid),
OPCODE(o_invalid),
/* 60 */
OPCODE(o_invalid),
OPCODE(o_invalid),
OPCODE(opn_opcode62),
OPCODE(opn_opcode63),
};
_opcodesPN = opcodes;
_numOpcodes = 64;
}
void AGOSEngine_PN::executeOpcode(int opcode) {
OpcodeProcPN op = _opcodesPN[opcode].proc;
(this->*op)();
}
int AGOSEngine_PN::readfromline() {
if (!_linct)
error("readfromline: Internal Error - Line Over-run");
_linct--;
return *_workptr++;
}
// -----------------------------------------------------------------------
// Personal Nightmare Opcodes
// -----------------------------------------------------------------------
void AGOSEngine_PN::opn_opcode00() {
uint8 *str = _workptr;
varval();
writeval(str, varval());
setScriptReturn(true);
}
void AGOSEngine_PN::opn_add() {
uint8 *str = _workptr;
int32 sp = varval() + varval();
_variableArray[12] = sp % 65536;
_variableArray[13] = sp / 65536;
if (sp > 65535)
sp = 65535;
writeval(str, (int)sp);
setScriptReturn(true);
}
void AGOSEngine_PN::opn_sub() {
uint8 *str = _workptr;
int32 sp = varval();
sp -= varval();
_variableArray[12] = sp % 65536;
_variableArray[13] = sp / 65536;
if (sp < 0)
sp = 0;
writeval(str, (int)sp);
setScriptReturn(true);
}
void AGOSEngine_PN::opn_mul() {
uint8 *str = _workptr;
int32 sp = varval() * varval();
_variableArray[12] = sp % 65536;
_variableArray[13] = sp / 65536;
if (sp > 65535)
sp = 65535;
writeval(str, (int)sp);
setScriptReturn(true);
}
void AGOSEngine_PN::opn_div() {
uint8 *str = _workptr;
int32 sp = varval();
int32 sp2 = varval();
if (sp2 == 0)
error("opn_div: Division by 0");
sp = sp / sp2;
_variableArray[12] = sp % 65536;
_variableArray[13] = sp / 65536;
writeval(str, (int)sp);
setScriptReturn(true);
}
void AGOSEngine_PN::opn_opcode05() {
pcf((uint8)'\n');
setScriptReturn(true);
}
void AGOSEngine_PN::opn_opcode06() {
pmesd(varval());
setScriptReturn(true);
}
void AGOSEngine_PN::opn_opcode07() {
int32 sp = varval();
plocd((int)sp, varval());
setScriptReturn(true);
}
void AGOSEngine_PN::opn_opcode08() {
int32 sp = varval();
pobjd((int)sp, varval());
setScriptReturn(true);
}
void AGOSEngine_PN::opn_opcode09() {
pmesd(varval());
pcf((uint8)'\n');
setScriptReturn(true);
}
void AGOSEngine_PN::opn_opcode10() {
int32 sp = varval();
plocd((int)sp, varval());
pcf((uint8)'\n');
setScriptReturn(true);
}
void AGOSEngine_PN::opn_opcode11() {
int32 sp = varval();
pobjd((int)sp, varval());
setScriptReturn(true);
}
void AGOSEngine_PN::opn_opcode12() {
char bf[8];
int a = 0;
sprintf(bf,"%d", varval());
while (bf[a])
pcf(bf[a++]);
setScriptReturn(true);
}
void AGOSEngine_PN::opn_opcode13() {
char bf[8];
int a = 0;
sprintf(bf,"%d", varval());
while (bf[a])
pcf(bf[a++]);
pcf((uint8)'\n');
setScriptReturn(true);
}
void AGOSEngine_PN::opn_opcode14() {
clearWindow(_windowArray[_curWindow]);
pcf((uint8)255);
setScriptReturn(true);
}
void AGOSEngine_PN::opn_opcode15() {
int32 x = varval();
if ((x < 0) || (x > 4))
x = 0;
pcf((unsigned char)254);
_curWindow = x;
_xofs = (8 * _windowArray[_curWindow]->textLength) / 6 + 1;
setScriptReturn(true);
}
void AGOSEngine_PN::opn_opcode16() {
int32 sp = varval();
setScriptReturn((sp >= 0 && sp <= 4));
}
void AGOSEngine_PN::opn_lt() {
int16 v1 = varval();
int16 v2 = varval();
setScriptReturn(v1 < v2);
}
void AGOSEngine_PN::opn_gt() {
int16 v1 = varval();
int16 v2 = varval();
setScriptReturn(v1 > v2);
}
void AGOSEngine_PN::opn_eq() {
int16 v1 = varval();
int16 v2 = varval();
setScriptReturn(v1 == v2);
}
void AGOSEngine_PN::opn_neq() {
int16 v1 = varval();
int16 v2 = varval();
setScriptReturn(v1 != v2);
}
void AGOSEngine_PN::opn_opcode21() {
setposition(_procnum, varval());
setScriptReturn(true);
}
void AGOSEngine_PN::opn_opcode22() {
int pf[8];
int n = varval();
funcentry(pf, n);
funccpy(pf);
setposition(n, 0);
setScriptReturn(true);
}
void AGOSEngine_PN::opn_opcode23() {
setScriptReturn(actCallD(varval()));
}
void AGOSEngine_PN::opn_opcode24() {
popstack(kJmpClassNum);
// Jump back to the last doline, which will return 2-1=1.
// That value then is returned to actCallD, which once again
// returns it. In the end, this amounts to a setScriptReturn(true)
// (but possibly in a different level than the current one).
_dolineReturnVal = 2;
_tagOfActiveDoline = _stackbase->tagOfParentDoline;
}
void AGOSEngine_PN::opn_opcode25() {
popstack(kJmpClassNum);
// Jump back to the last doline, which will return 1-1=0.
// That value then is returned to actCallD, which once again
// returns it. In the end, this amounts to a setScriptReturn(false)
// (but possibly in a different level than the current one).
_dolineReturnVal = 1;
_tagOfActiveDoline = _stackbase->tagOfParentDoline;
}
void AGOSEngine_PN::opn_opcode26() {
while ((_stackbase != NULL) && (_stackbase->classnum != kJmpClassNum))
dumpstack();
dumpstack();
setScriptReturn(true);
}
void AGOSEngine_PN::opn_opcode27() {
quitGame();
// Make sure the quit event is processed immediately.
delay(0);
}
void AGOSEngine_PN::opn_opcode28() {
addstack(varval());
_stackbase->tagOfParentDoline = _tagOfActiveDoline;
setScriptReturn(false);
}
void AGOSEngine_PN::opn_opcode29() {
popstack(varval());
// Jump back to the last doline indicated by the top stackframe.
// The -1 tells it to simply go on with its business.
_dolineReturnVal = -1;
_tagOfActiveDoline = _stackbase->tagOfParentDoline;
}
void AGOSEngine_PN::opn_opcode30() {
_variableArray[1] = varval();
setScriptReturn(true);
}
void AGOSEngine_PN::opn_opcode31() {
int a, slot = 0;
char bf[60];
if ((a = varval()) > 2) {
setScriptReturn(false);
return;
}
switch (a) {
case 0:
getFilename();
slot = matchSaveGame(_saveFile, countSaveGames());
strcpy(bf, genSaveName(slot));
break;
case 1:
strcpy(bf, "pn.sav");
break;
case 2:
// NOTE: Is this case ever used?
error("opn_opcode31: case 2");
break;
}
if (slot == -1) {
setScriptReturn(false);
} else {
a = loadFile(bf);
if (a)
setScriptReturn(badload(a));
else
setScriptReturn(true);
}
}
void AGOSEngine_PN::opn_opcode32() {
char bf[60];
int a, slot;
a = varval();
if (a > 2) {
setScriptReturn(true);
return;
}
uint16 curSlot = countSaveGames();
switch (a) {
case 0:
getFilename();
slot = matchSaveGame(_saveFile, curSlot);
if (slot != -1)
strcpy(bf, genSaveName(slot));
else
strcpy(bf, genSaveName(curSlot));
break;
case 1:
strcpy(bf, "pn.sav");
break;
case 2:
// NOTE: Is this case ever used?
error("opn_opcode32: case 2");
break;
}
a = saveFile(bf);
setScriptReturn(a);
}
void AGOSEngine_PN::opn_opcode33() {
setScriptReturn((varval() < 3) ? 1 : 0);
}
void AGOSEngine_PN::opn_opcode34() {
uint16 msgNum1, msgNum2;
varval();
getResponse((int)_variableArray[166], (int)_variableArray[167], msgNum1, msgNum2);
_variableArray[168]= msgNum1;
_variableArray[169]= msgNum2;
setScriptReturn(true);
}
void AGOSEngine_PN::opn_opcode35() {
int a;
uint8 *sav = _workptr;
varval();
a = varval();
if ((a = gvwrd((uint8 *)_wordcp, a)) == -1) {
setScriptReturn(false);
return;
}
writeval(sav, a);
setScriptReturn(true);
}
void AGOSEngine_PN::opn_opcode36() {
for (int i = 0; i < _dataBase[57] + 1; ++i)
_wordcp[i] = 0;
if (isspace(static_cast<unsigned char>(*_inpp)))
while ((*_inpp) && (isspace(static_cast<unsigned char>(*_inpp))))
_inpp++;
if (*_inpp == 0) {
setScriptReturn(false);
return;
}
_curwrdptr = _inpp;
_wordcp[0] = *_inpp++;
if ((_wordcp[0] == '.') || (_wordcp[0] == ',') || (_wordcp[0] == '"')) {
setScriptReturn(true);
return;
}
int ct = 1;
while ((*_inpp != '.') && (*_inpp != ',') && (!isspace(static_cast<unsigned char>(*_inpp))) && (*_inpp != '\0') &&
(*_inpp!='"')) {
if (ct < _dataBase[57])
_wordcp[ct++] = *_inpp;
_inpp++;
}
setScriptReturn(true);
}
void AGOSEngine_PN::opn_opcode37() {
_curwrdptr = NULL;
_inputReady = true;
interact(_inputline, 49);
if ((_inpp = strchr(_inputline,'\n')) != NULL)
*_inpp = '\0';
_inpp = _inputline;
setScriptReturn(true);
}
void AGOSEngine_PN::opn_opcode38() {
_noScanFlag = 1;
clearInputLine();
writeval(_workptr, _keyPressed.ascii);
_keyPressed.reset();
_noScanFlag = 0;
varval();
setScriptReturn(true);
}
void AGOSEngine_PN::opn_opcode39() {
pcf((uint8)varval());
setScriptReturn(true);
}
void AGOSEngine_PN::opn_opcode40() {
int a = doaction();
if (_dolineReturnVal != 0)
return;
int b = doaction();
setScriptReturn(a | b);
}
void AGOSEngine_PN::opn_opcode41() {
int a = doaction();
if (_dolineReturnVal != 0)
return;
int b = doaction();
setScriptReturn(a & b);
}
void AGOSEngine_PN::opn_opcode42() {
int a = doaction();
if (_dolineReturnVal != 0)
return;
int b = doaction();
setScriptReturn(a ^ b);
}
void AGOSEngine_PN::opn_opcode43() {
int a = doaction();
setScriptReturn(!a);
}
void AGOSEngine_PN::opn_opcode44() {
pcf((uint8)254);
setScriptReturn(true);
}
void AGOSEngine_PN::opn_opcode45() {
uint8 *myptr;
int x;
if (_havinit == 0) {
_seed = (int16)getTime();
_havinit = 1;
}
_seed = 1 + (75 * (_seed + 1) - 1) % 65537;
myptr = _workptr;
varval();
x = varval();
if (x == 0)
error("Illegal range specified for RANDOM");
writeval(myptr, (_seed % x));
setScriptReturn(true);
}
void AGOSEngine_PN::opn_opcode46() {
char *x = _curwrdptr;
if (x == NULL) {
setScriptReturn(true);
return;
}
pcf(*x);
if ((*x == '.') || (*x == '"') || (*x == ',')) {
setScriptReturn(true);
return;
}
x++;
while ((*x != '.') && (*x != ',') && (*x != '"') && (!isspace(static_cast<unsigned char>(*x))) && (*x != '\0'))
pcf(*x++);
setScriptReturn(true);
}
void AGOSEngine_PN::opn_opcode47() {
pmesd(varval() * 256 + varval());
setScriptReturn(true);
}
void AGOSEngine_PN::opn_opcode48() {
pmesd(varval() * 256 + varval());
pcf((uint8)'\n');
setScriptReturn(true);
}
void AGOSEngine_PN::opn_opcode49() {
setScriptReturn(findentry());
}
void AGOSEngine_PN::opn_opcode50() {
_fnst = 0;
setScriptReturn(findset());
}
void AGOSEngine_PN::opn_opcode51() {
_fnst = varval();
setScriptReturn(findset());
}
void AGOSEngine_PN::opn_opcode52() {
int32 mode = varval();
if (mode == 1) {
setWindowImage(mode, varval(), true);
} else {
setWindowImageEx(mode, varval());
}
setScriptReturn(true);
}
void AGOSEngine_PN::opn_opcode53() {
vc27_resetSprite();
setScriptReturn(true);
}
void AGOSEngine_PN::opn_opcode54() {
stopAnimate(varval());
setScriptReturn(true);
}
void AGOSEngine_PN::opn_opcode55() {
varval();
varval();
varval();
setScriptReturn(true);
}
void AGOSEngine_PN::opn_opcode56() {
varval();
varval();
varval();
setScriptReturn(true);
}
void AGOSEngine_PN::opn_opcode57() {
uint16 windowNum = varval();
uint16 vgaSpriteId = varval();
int16 x = varval();
int16 y = varval();
uint16 palette = varval();
_videoLockOut |= 0x40;
animate(windowNum, 0, vgaSpriteId, x, y, palette);
_videoLockOut &= ~0x40;
setScriptReturn(true);
}
void AGOSEngine_PN::opn_opcode62() {
int32 zoneNum = varval();
_videoLockOut |= 0x80;
vc29_stopAllSounds();
_hitCalled = 0;
_oneClick = 0;
loadZone(zoneNum);
setWindowImage(2, 2);
_copyScnFlag = 0;
_vgaSpriteChanged = 0;
_videoLockOut &= ~0x80;
setScriptReturn(true);
}
void AGOSEngine_PN::opn_opcode63() {
int a = readfromline();
switch (a) {
case 65:
setScriptReturn(inventoryOn(varval()));
break;
case 64:
setScriptReturn((_videoLockOut & 0x10) != 0);
break;
case 63:
setScriptReturn(inventoryOff());
break;
default:
error("opn_opcode63: unknown code %d", a);
}
}
int AGOSEngine_PN::inventoryOn(int val) {
writeVariable(210, val);
if (_videoLockOut & 0x10) {
iconPage();
} else {
_videoLockOut |= 0x10;
_hitAreaList = _invHitAreas;
_windowArray[2]->textColor = 0;
windowPutChar(_windowArray[2], 13);
clearVideoWindow(4, 0);
drawIconHitBar();
_objects = _variableArray[211];
_objectCountS = -1;
iconPage();
}
return 1;
}
int AGOSEngine_PN::inventoryOff() {
if (_videoLockOut & 0x10) {
_windowArray[2]->textColor = 15;
restoreBlock(48, 2, 272, 130);
_hitAreaList = _hitAreas;
_videoLockOut &= ~0x10;
_vgaSpriteChanged++;
}
return 1;
}
// -----------------------------------------------------------------------
// Personal Nightmare Script Code
// -----------------------------------------------------------------------
int AGOSEngine_PN::bitextract(uint32 ptr, int offs) {
const byte mask = 0x80 >> (offs % 8);
return ((mask & _dataBase[ptr + offs / 8]) != 0);
}
uint16 AGOSEngine_PN::getptr(uint32 pos) {
if (pos > _dataBaseSize)
error("getptr: Read beyond EOF (%d)", pos);
return (int)READ_LE_UINT16(_dataBase + pos);
}
uint32 AGOSEngine_PN::getlong(uint32 pos) {
// Only actually reads 24bit though
if (pos > _dataBaseSize)
error("getlong: Read beyond EOF (%d)", pos);
return (uint32)READ_LE_UINT24(_dataBase + pos);
}
int AGOSEngine_PN::varval() {
int a;
int b;
a = readfromline();
if (a < 247) {
return a;
}
switch (a) {
case 249:
b = readfromline();
return (int)(b + 256 * readfromline());
case 250:
return readfromline();
case 251:
return (int)_variableArray[varval()];
case 252:
b = varval();
return (int)_dataBase[_quickptr[0] + b * _quickshort[0] + varval()];
case 254:
b = varval();
return (int)_dataBase[_quickptr[3] + b * _quickshort[2] + varval()];
case 247:
b = varval();
return (int)getptr(_quickptr[11] + (b * _quickshort[4]) + (2 * varval()));
case 248:
b = varval();
return (int)getptr(_quickptr[12] + (b * _quickshort[5]) + (2 * varval()));
case 253:
b = varval();
return bitextract((int32)_quickptr[1] + b * _quickshort[1], varval());
case 255:
b = varval();
return bitextract((int32)_quickptr[4] + b * _quickshort[3], varval());
default:
error("VARVAL : Illegal code %d encountered", a);
}
}
void AGOSEngine_PN::writeval(uint8 *ptr, int val) {
uint8 *savpt = _workptr;
int lsav = _linct, a, b, x;
_workptr = ptr;
_linct = 255;
if ((a = readfromline()) < 247)
error("writeval: Write to constant (%d)", a);
switch (a) {
case 249:
error("writeval: Write to constant (%d)", a);
break;
case 250:
error("writeval: Write to constant (%d)", a);
break;
case 251:
_variableArray[varval()] = val;
break;
case 252:
b = varval();
_dataBase[_quickptr[0] + b * _quickshort[0] + varval()] = val;
break;
case 254:
b = varval();
_dataBase[_quickptr[3] + b * _quickshort[2] + varval()] = val;
break;
case 247:
b = varval();
x = _quickptr[11] + b * _quickshort[4] + varval() * 2;
WRITE_LE_UINT16(_dataBase + x, val);
break;
case 248:
b = varval();
x = _quickptr[12] + b * _quickshort[5] + varval() * 2;
WRITE_LE_UINT16(_dataBase + x, val);
break;
case 253:
b = varval();
setbitf((uint32)_quickptr[1] + b * _quickshort[1], varval(), val);
break;
case 255:
b = varval();
setbitf((uint32)_quickptr[4] + b * _quickshort[3], varval(), val);
break;
default:
error("WRITEVAL : undefined evaluation %d", a);
}
_linct = lsav;
_workptr = savpt;
}
void AGOSEngine_PN::setbitf(uint32 ptr, int offs, int val) {
ptr += offs / 8;
const byte mask = 0x80 >> (offs % 8);
if (val != 0)
_dataBase[ptr] |= mask;
else
_dataBase[ptr] &= ~mask;
}
int AGOSEngine_PN::actCallD(int n) {
int pf[8];
funcentry(pf, n);
addstack(kJmpClassNum);
funccpy(pf);
setposition(n, 0);
return doline(1);
}
int AGOSEngine_PN::doaction() {
if (_linct == 0)
return 0;
_opcode = readfromline();
if (_opcode > 63) {
return (actCallD(_opcode - 64));
}
setScriptReturn(0);
executeOpcode(_opcode);
delay(0);
return getScriptReturn();
}
int AGOSEngine_PN::doline(int needsave) {
assert(!_stackbase == !needsave);
int x;
int myTag = ++_tagOfActiveDoline; // Obtain a unique tag for this doline invocation
_dolineReturnVal = 0;
if (_stackbase && needsave)
_stackbase->tagOfParentDoline = myTag;
do {
_linct = ((*_linebase) & 127) - 1;
_workptr = _linebase + 1;
if (*_linebase > 127) {
x = varval();
if (x != (int)_variableArray[1])
goto skipln;
}
do {
x = doaction();
if (_dolineReturnVal != 0) {
if (_tagOfActiveDoline != myTag)
return 0;
x = _dolineReturnVal;
_dolineReturnVal = 0;
if (x > 0) {
if (x != 3)
dumpstack();
// Restore the active jmpbuf to its previous value,
// then return _dolineReturnVal-1 (will be 2-1=1 or 1-1=0).
_tagOfActiveDoline = myTag - 1;
return (x - 1);
}
}
} while (x && !shouldQuit());
skipln:
_linebase += 127 & *_linebase;
_linembr++;
} while (!shouldQuit());
return 0;
}
int AGOSEngine_PN::findentry() {
int stepmt;
int curObj = 0;
uint32 ofs = _quickptr[11];
int c1, c2;
c1 = varval();
c2 = varval();
stepmt = _quickshort[4];
while (curObj < _quickshort[6]) {
if (((c1 == 255) || (c1 == getptr(ofs))) &&
(c2 == getptr(ofs + 2))) {
_variableArray[23] = curObj;
return 1;
}
curObj++;
ofs += stepmt;
}
return 0;
}
int AGOSEngine_PN::findset() {
int curObj = _fnst;
int c1, c2, c3, c4;
int stepmt = _quickshort[4];
uint32 ofs = _quickptr[11] + stepmt * curObj;
c1 = varval();
c2 = varval();
c3 = varval();
c4 = varval();
while (curObj < _quickshort[6]) {
if (((c1 ==255) || (c1 == getptr(ofs))) &&
((c2 == 255) || (c2 == getptr(ofs + 2))) &&
((c3 == 255) || (c3 == getptr(ofs + 4))) &&
((c4 == 255) || (c4 == getptr(ofs + 6)))) {
_variableArray[23] = curObj;
_fnst = curObj + 1;
return 1;
}
curObj++;
ofs += stepmt;
}
return 0;
}
void AGOSEngine_PN::funccpy(int *store) {
for (int i = 24; i < 32; ++i) {
_variableArray[i] = *store++;
}
}
void AGOSEngine_PN::funcentry(int *store, int procn) {
int numParams = _dataBase[getlong(_quickptr[6] + 3 * procn)];
for (int i = 0; i < numParams; ++i) {
*store++ = varval();
}
}
int AGOSEngine_PN::gvwrd(uint8 *wptr, int mask) {
int val = 0, code = 0, q = _dataBase[57];
uint8 *vocbase = _dataBase + getlong(15);
while (*vocbase != 255) {
if (*vocbase < 0x80) {
val = vocbase[q] + 256 * vocbase[q + 1];
code = vocbase[q + 2];
}
if (wrdmatch(vocbase, mask, wptr, code))
return val;
vocbase += (*vocbase > 127) ? q : q + 3;
}
return -1;
}
int AGOSEngine_PN::setposition(int process, int line) {
uint8 *ourptr;
int np;
int ct;
ourptr = _dataBase + getlong(_quickptr[6] + 3 * process);
np = *ourptr++;
for (ct = 0; ct < line; ++ct) {
ourptr += (127 & *ourptr);
}
while (true) {
_linebase = ourptr;
_linct = (127 & *ourptr) - 1;
if (*ourptr++ <= 127)
break;
ct = varval();
if (ct == (int)_variableArray[1])
break;
ourptr += _linct - 1;
line++;
}
_linembr = line;
_procnum = process;
_variableArray[0] = process;
_workptr = ourptr;
return np;
}
int AGOSEngine_PN::wrdmatch(uint8 *word1, int mask1, uint8 *word2, int mask2) {
uint8 sv;
if ((mask1 & mask2) == 0)
return 0;
sv = *word1;
*word1 &= 127;
if (scumm_strnicmp((const char *)word1, (const char *)word2, _dataBase[57])) {
*word1 = sv;
return 0;
}
*word1 = sv;
return 1;
}
// -----------------------------------------------------------------------
// Personal Nightmare Stack Code
// -----------------------------------------------------------------------
void AGOSEngine_PN::addstack(int type) {
StackFrame *a;
int i;
a = (StackFrame *)calloc(1, sizeof(StackFrame));
if (a == NULL)
error("addstack: Out of memory - stack overflow");
a->nextframe = _stackbase;
_stackbase = a;
for (i = 0; i < 6; ++i)
a->flag[i] = _variableArray[i];
for (i = 0; i < 8; ++i)
a->param[i] = _variableArray[24 + i];
a->classnum = type;
a->ll = _linct;
a->linenum = _linembr;
a->linpos = _workptr;
a->lbase = _linebase;
a->process = _procnum;
}
void AGOSEngine_PN::dumpstack() {
StackFrame *a;
if (_stackbase == NULL)
error("dumpstack: Stack underflow or unknown longjmp");
a = _stackbase->nextframe;
free((char *)_stackbase);
_stackbase = a;
}
void AGOSEngine_PN::popstack(int type) {
int i = 0;
while ((_stackbase != NULL) && (_stackbase->classnum != type)) {
dumpstack();
++i;
}
if (_stackbase == NULL)
error("popstack: Stack underflow or unknown longjmp");
_linct = _stackbase->ll;
_linebase = _stackbase->lbase;
_workptr = _stackbase->linpos;
_procnum = _stackbase->process;
_linembr = _stackbase->linenum;
for (i = 0; i < 6; ++i)
_variableArray[i] = _stackbase->flag[i];
for (i = 0; i < 8; ++i)
_variableArray[24 + i] = _stackbase->param[i];
}
} // End of namespace AGOS