Logo Search packages:      
Sourcecode: scummvm version File versions  Download package

script_pn.cpp

/* 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.
 *
 * $URL: https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/tags/release-1-0-0/engines/agos/script_pn.cpp $
 * $Id: script_pn.cpp 43296 2009-08-12 01:01:36Z Kirben $
 *
 */

#ifdef ENABLE_PN

#include "agos/agos.h"
#include "agos/vga.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(*_inpp))
            while ((*_inpp) && (isspace(*_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(*_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(*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());
                  break;
            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 (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

#endif // ENABLE_PN

Generated by  Doxygen 1.6.0   Back to index