Logo Search packages:      
Sourcecode: scummvm version File versions

inter.cpp

/* ScummVM - Scumm Interpreter
 * Copyright (C) 2004 Ivan Dubrov
 * Copyright (C) 2004-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/tags/release-0-9-1/engines/gob/inter.cpp $
 * $Id: inter.cpp 22790 2006-05-31 08:44:14Z drmccoy $
 *
 */

#include "common/stdafx.h"
#include "common/endian.h"

#include "gob/gob.h"
#include "gob/global.h"
#include "gob/inter.h"
#include "gob/util.h"
#include "gob/scenery.h"
#include "gob/parse.h"
#include "gob/game.h"
#include "gob/draw.h"
#include "gob/mult.h"
#include "gob/goblin.h"
#include "gob/cdrom.h"
#include "gob/map.h"

namespace Gob {

Inter::Inter(GobEngine *vm) : _vm(vm) {
      int i;

      _terminate = false;
      _breakFlag = false;
      
      for (i = 0; i < 8; i++)
      {
            _animPalLowIndex[i] = 0;
            _animPalHighIndex[i] = 0;
            _animPalDir[i] = 0;
      }

      _soundEndTimeKey = 0;
      _soundStopVal = 0;
      _breakFromLevel = 0;
      _nestLevel = 0;
}

int16 Inter::load16(void) {
      int16 tmp = (int16)READ_LE_UINT16(_vm->_global->_inter_execPtr);
      _vm->_global->_inter_execPtr += 2;
      return tmp;
}

char Inter::evalExpr(int16 *pRes) {
      byte token;

//
      _vm->_parse->printExpr(99);

      _vm->_parse->parseExpr(99, &token);
      if (pRes == 0)
            return token;

      switch (token) {
      case 20:
            *pRes = _vm->_global->_inter_resVal;
            break;

      case 22:
      case 23:
            *pRes = 0;
            break;

      case 24:
            *pRes = 1;
            break;
      }
      return token;
}

char Inter::evalBoolResult() {
      byte token;

      _vm->_parse->printExpr(99);

      _vm->_parse->parseExpr(99, &token);
      if (token == 24 || (token == 20 && _vm->_global->_inter_resVal != 0))
            return 1;
      else
            return 0;
}

void Inter::funcBlock(int16 retFlag) {
      char cmdCount;
      int16 counter;
      byte cmd;
      byte cmd2;

      if (_vm->_global->_inter_execPtr == 0)
            return;

      _breakFlag = false;
      _vm->_global->_inter_execPtr++;
      cmdCount = *_vm->_global->_inter_execPtr++;
      _vm->_global->_inter_execPtr += 2;

      if (cmdCount == 0) {
            _vm->_global->_inter_execPtr = 0;
            return;
      }

      int startaddr = _vm->_global->_inter_execPtr-_vm->_game->_totFileData;

      counter = 0;
      do {
            if (_terminate)
                  break;

            // WORKAROUND:
            // The EGA version of gob1 doesn't add a delay after showing
            // images between levels. We manually add it here.
            if ((_vm->_features & GF_GOB1) && (_vm->_features & GF_EGA)) {
                  int addr = _vm->_global->_inter_execPtr-_vm->_game->_totFileData;
                  if ((startaddr == 0x18B4 && addr == 0x1A7F && // Zombie
                         !strncmp(_vm->_game->_curTotFile, "avt005.tot", 10)) ||
                        (startaddr == 0x1299 && addr == 0x139A && // Dungeon
                         !strncmp(_vm->_game->_curTotFile, "avt006.tot", 10)) ||
                        (startaddr == 0x11C0 && addr == 0x12C9 && // Cauldron
                         !strncmp(_vm->_game->_curTotFile, "avt012.tot", 10)) ||
                        (startaddr == 0x09F2 && addr == 0x0AF3 && // Statue
                         !strncmp(_vm->_game->_curTotFile, "avt016.tot", 10)) ||
                        (startaddr == 0x0B92 && addr == 0x0C93 && // Castle
                         !strncmp(_vm->_game->_curTotFile, "avt019.tot", 10)) ||
                        (startaddr == 0x17D9 && addr == 0x18DA && // Finale
                         !strncmp(_vm->_game->_curTotFile, "avt022.tot", 10)))
                  {
                        _vm->_util->longDelay(5000);
                  }
            }
            // (end workaround)

            cmd = (byte)*_vm->_global->_inter_execPtr;
            if ((cmd >> 4) >= 12) {
                  cmd2 = 16 - (cmd >> 4);
                  cmd &= 0xf;
            } else
                  cmd2 = 0;

            _vm->_global->_inter_execPtr++;
            counter++;

            if (cmd2 == 0)
                  cmd >>= 4;

            if (executeFuncOpcode(cmd2, cmd, cmdCount, counter, retFlag))
                  return;

            if (_vm->_quitRequested)
                  break;

            if (_breakFlag) {
                  if (retFlag != 2)
                        break;

                  if (*_breakFromLevel == -1)
                        _breakFlag = false;
                  break;
            }
      } while (counter != cmdCount);

      _vm->_global->_inter_execPtr = 0;
      return;
}

void Inter::storeKey(int16 key) {
      WRITE_VAR(12, _vm->_util->getTimeKey() - _vm->_game->_startTimeKey);

      storeMouse();
      WRITE_VAR(1, _vm->_snd->_playingSound);

      if (key == 0x4800)
            key = 0x0b;
      else if (key == 0x5000)
            key = 0x0a;
      else if (key == 0x4d00)
            key = 0x09;
      else if (key == 0x4b00)
            key = 0x08;
      else if (key == 0x011b)
            key = 0x1b;
      else if ((key & 0xff) != 0)
            key &= 0xff;

      WRITE_VAR(0, key);

      if (key != 0)
            _vm->_util->waitKey();
}

void Inter::checkSwitchTable(char **ppExec) {
      int16 i;
      int16 len;
      char found;
      int32 value;
      char notFound;
      char defFlag;

      found = 0;
      notFound = 1;
      *ppExec = 0;
      value = _vm->_parse->parseVarIndex();
      value = VAR_OFFSET(value);

      do {
            len = *(int8*)_vm->_global->_inter_execPtr++; // must be a signed char typ and char is not default signed on all platforms.

            if (len == -5)
                  break;

            for (i = 0; i < len; i++) {
                  evalExpr(0);

                  if (_terminate)
                        return;

                  if (_vm->_global->_inter_resVal == value) {
                        found = 1;
                        notFound = 0;
                  }
            }

            if (found != 0)
                  *ppExec = _vm->_global->_inter_execPtr;

            _vm->_global->_inter_execPtr += READ_LE_UINT16(_vm->_global->_inter_execPtr + 2) + 2;
            found = 0;
      } while (len != -5);

      if (len != -5)
            _vm->_global->_inter_execPtr++;

      defFlag = *_vm->_global->_inter_execPtr;
      defFlag >>= 4;
      if (defFlag != 4)
            return;
      _vm->_global->_inter_execPtr++;

      if (notFound)
            *ppExec = _vm->_global->_inter_execPtr;

      _vm->_global->_inter_execPtr += READ_LE_UINT16(_vm->_global->_inter_execPtr + 2) + 2;
}

void Inter::callSub(int16 retFlag) {
      int16 block;
      while (!_vm->_quitRequested && _vm->_global->_inter_execPtr != 0 && (char *)_vm->_global->_inter_execPtr != _vm->_game->_totFileData) {
            block = *_vm->_global->_inter_execPtr;
            if (block == 1) {
                  funcBlock(retFlag);
            } else if (block == 2) {
                  _vm->_game->collisionsBlock();
            }
      }

      if ((char *)_vm->_global->_inter_execPtr == _vm->_game->_totFileData)
            _terminate = true;
}

void Inter::initControlVars(void) {
      *_nestLevel = 0;
      *_breakFromLevel = -1;

      *_vm->_scenery->_pCaptureCounter = 0;

      _breakFlag = false;
      _terminate = false;
      _animPalDir[0] = 0;
      _soundEndTimeKey = 0;
}

void Inter::renewTimeInVars(void) {
      struct tm *t;
      time_t now = time(NULL);

      t = localtime(&now);

      WRITE_VAR(5, 1900 + t->tm_year);
      WRITE_VAR(6, t->tm_mon);
      WRITE_VAR(7, 0);
      WRITE_VAR(8, t->tm_mday);
      WRITE_VAR(9, t->tm_hour);
      WRITE_VAR(10, t->tm_min);
      WRITE_VAR(11, t->tm_sec);
}

void Inter::manipulateMap(int16 xPos, int16 yPos, int16 item) {
      for (int16 y = 0; y < _vm->_map->_mapHeight; y++) {
            for (int16 x = 0; x < _vm->_map->_mapWidth; x++) {
                  if ((_vm->_map->_itemsMap[y][x] & 0xff) == item) {
                        _vm->_map->_itemsMap[y][x] &= 0xff00;
                  } else if (((_vm->_map->_itemsMap[y][x] & 0xff00) >> 8)
                              == item) {
                        _vm->_map->_itemsMap[y][x] &= 0xff;
                  }
            }
      }

      if (xPos < _vm->_map->_mapWidth - 1) {
            if (yPos > 0) {
                  if ((_vm->_map->_itemsMap[yPos][xPos] & 0xff00) != 0 ||
                              (_vm->_map->_itemsMap[yPos - 1][xPos] & 0xff00) !=
                              0
                              || (_vm->_map->_itemsMap[yPos][xPos +
                                    1] & 0xff00) != 0
                              || (_vm->_map->_itemsMap[yPos - 1][xPos +
                                    1] & 0xff00) != 0) {

                        _vm->_map->_itemsMap[yPos][xPos] =
                                    (_vm->_map->_itemsMap[yPos][xPos] & 0xff00)
                                    + item;

                        _vm->_map->_itemsMap[yPos - 1][xPos] =
                                    (_vm->_map->_itemsMap[yPos -
                              1][xPos] & 0xff00) + item;

                        _vm->_map->_itemsMap[yPos][xPos + 1] =
                                    (_vm->_map->_itemsMap[yPos][xPos +
                              1] & 0xff00) + item;

                        _vm->_map->_itemsMap[yPos - 1][xPos + 1] =
                                    (_vm->_map->_itemsMap[yPos - 1][xPos +
                              1] & 0xff00) + item;
                  } else {
                        _vm->_map->_itemsMap[yPos][xPos] =
                                    (_vm->_map->_itemsMap[yPos][xPos] & 0xff) +
                                    (item << 8);

                        _vm->_map->_itemsMap[yPos - 1][xPos] =
                                    (_vm->_map->_itemsMap[yPos -
                              1][xPos] & 0xff) + (item << 8);

                        _vm->_map->_itemsMap[yPos][xPos + 1] =
                                    (_vm->_map->_itemsMap[yPos][xPos +
                              1] & 0xff) + (item << 8);

                        _vm->_map->_itemsMap[yPos - 1][xPos + 1] =
                                    (_vm->_map->_itemsMap[yPos - 1][xPos +
                              1] & 0xff) + (item << 8);
                  }
            } else {
                  if ((_vm->_map->_itemsMap[yPos][xPos] & 0xff00) != 0 ||
                              (_vm->_map->_itemsMap[yPos][xPos + 1] & 0xff00) !=
                              0) {
                        _vm->_map->_itemsMap[yPos][xPos] =
                                    (_vm->_map->_itemsMap[yPos][xPos] & 0xff00)
                                    + item;

                        _vm->_map->_itemsMap[yPos][xPos + 1] =
                                    (_vm->_map->_itemsMap[yPos][xPos +
                              1] & 0xff00) + item;
                  } else {
                        _vm->_map->_itemsMap[yPos][xPos] =
                                    (_vm->_map->_itemsMap[yPos][xPos] & 0xff) +
                                    (item << 8);

                        _vm->_map->_itemsMap[yPos][xPos + 1] =
                                    (_vm->_map->_itemsMap[yPos][xPos +
                              1] & 0xff) + (item << 8);
                  }
            }
      } else {
            if (yPos > 0) {
                  if ((_vm->_map->_itemsMap[yPos][xPos] & 0xff00) != 0 ||
                              (_vm->_map->_itemsMap[yPos - 1][xPos] & 0xff00) !=
                              0) {
                        _vm->_map->_itemsMap[yPos][xPos] =
                                    (_vm->_map->_itemsMap[yPos][xPos] & 0xff00)
                                    + item;

                        _vm->_map->_itemsMap[yPos - 1][xPos] =
                                    (_vm->_map->_itemsMap[yPos -
                              1][xPos] & 0xff00) + item;
                  } else {
                        _vm->_map->_itemsMap[yPos][xPos] =
                                    (_vm->_map->_itemsMap[yPos][xPos] & 0xff) +
                                    (item << 8);

                        _vm->_map->_itemsMap[yPos - 1][xPos] =
                                    (_vm->_map->_itemsMap[yPos -
                              1][xPos] & 0xff) + (item << 8);
                  }
            } else {
                  if ((_vm->_map->_itemsMap[yPos][xPos] & 0xff00) != 0) {
                        _vm->_map->_itemsMap[yPos][xPos] =
                                    (_vm->_map->_itemsMap[yPos][xPos] & 0xff00)
                                    + item;
                  } else {
                        _vm->_map->_itemsMap[yPos][xPos] =
                                    (_vm->_map->_itemsMap[yPos][xPos] & 0xff) +
                                    (item << 8);
                  }
            }
      }

      if (item < 0 || item >= 20)
            return;

      if (xPos > 1 && _vm->_map->getPass(xPos - 2, yPos) == 1) {
            _vm->_map->_itemPoses[item].x = xPos - 2;
            _vm->_map->_itemPoses[item].y = yPos;
            _vm->_map->_itemPoses[item].orient = 4;
            return;
      }

      if (xPos < _vm->_map->_mapWidth - 2 && _vm->_map->getPass(xPos + 2, yPos) == 1) {
            _vm->_map->_itemPoses[item].x = xPos + 2;
            _vm->_map->_itemPoses[item].y = yPos;
            _vm->_map->_itemPoses[item].orient = 0;
            return;
      }

      if (xPos < _vm->_map->_mapWidth - 1 && _vm->_map->getPass(xPos + 1, yPos) == 1) {
            _vm->_map->_itemPoses[item].x = xPos + 1;
            _vm->_map->_itemPoses[item].y = yPos;
            _vm->_map->_itemPoses[item].orient = 0;
            return;
      }

      if (xPos > 0 && _vm->_map->getPass(xPos - 1, yPos) == 1) {
            _vm->_map->_itemPoses[item].x = xPos - 1;
            _vm->_map->_itemPoses[item].y = yPos;
            _vm->_map->_itemPoses[item].orient = 4;
            return;
      }
}

} // End of namespace Gob

Generated by  Doxygen 1.6.0   Back to index