mirror of
https://github.com/libretro/scummvm.git
synced 2024-12-17 07:07:10 +00:00
dd9e62e31e
svn-id: r41752
845 lines
21 KiB
C++
845 lines
21 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.
|
|
*
|
|
* $URL$
|
|
* $Id$
|
|
*
|
|
*/
|
|
|
|
#include "common/endian.h"
|
|
|
|
#include "gob/gob.h"
|
|
#include "gob/game.h"
|
|
#include "gob/helper.h"
|
|
#include "gob/global.h"
|
|
#include "gob/util.h"
|
|
#include "gob/dataio.h"
|
|
#include "gob/inter.h"
|
|
#include "gob/parse.h"
|
|
#include "gob/draw.h"
|
|
#include "gob/mult.h"
|
|
#include "gob/videoplayer.h"
|
|
#include "gob/sound/sound.h"
|
|
|
|
namespace Gob {
|
|
|
|
Game::Game(GobEngine *vm) : _vm(vm) {
|
|
_extTable = 0;
|
|
_totFileData = 0;
|
|
_totResourceTable = 0;
|
|
_imFileData = 0;
|
|
_extHandle = 0;
|
|
_lomHandle = -1;
|
|
_collisionAreas = 0;
|
|
_shouldPushColls = 0;
|
|
|
|
_captureCount = 0;
|
|
|
|
_foundTotLoc = false;
|
|
_totTextData = 0;
|
|
|
|
_collStackSize = 0;
|
|
|
|
for (int i = 0; i < 5; i++) {
|
|
_collStack[i] = 0;
|
|
_collStackElemSizes[i] = 0;
|
|
}
|
|
|
|
_curTotFile[0] = 0;
|
|
_curExtFile[0] = 0;
|
|
_totToLoad[0] = 0;
|
|
|
|
_startTimeKey = 0;
|
|
_mouseButtons = 0;
|
|
|
|
_lastCollKey = 0;
|
|
_lastCollAreaIndex = 0;
|
|
_lastCollId = 0;
|
|
|
|
_activeCollResId = 0;
|
|
_activeCollIndex = 0;
|
|
_handleMouse = 0;
|
|
_forceHandleMouse = 0;
|
|
_menuLevel = 0;
|
|
_noScroll = true;
|
|
_preventScroll = false;
|
|
_scrollHandleMouse = false;
|
|
|
|
_noCd = false;
|
|
|
|
_tempStr[0] = 0;
|
|
_curImaFile[0] = 0;
|
|
_collStr[0] = 0;
|
|
|
|
_backupedCount = 0;
|
|
_curBackupPos = 0;
|
|
|
|
for (int i = 0; i < 5; i++) {
|
|
_cursorHotspotXArray[i] = 0;
|
|
_cursorHotspotYArray[i] = 0;
|
|
_totTextDataArray[i] = 0;
|
|
_totFileDataArray[i] = 0;
|
|
_totResourceTableArray[i] = 0;
|
|
_extTableArray[i] = 0;
|
|
_extHandleArray[i] = 0;
|
|
_imFileDataArray[i] = 0;
|
|
_variablesArray[i] = 0;
|
|
_curTotFileArray[i][0] = 0;
|
|
}
|
|
}
|
|
|
|
Game::~Game() {
|
|
delete[] _vm->_game->_totFileData;
|
|
if (_vm->_game->_totTextData) {
|
|
if (_vm->_game->_totTextData->items)
|
|
delete[] _vm->_game->_totTextData->items;
|
|
delete _vm->_game->_totTextData;
|
|
}
|
|
if (_vm->_game->_totResourceTable) {
|
|
delete[] _vm->_game->_totResourceTable->items;
|
|
delete _vm->_game->_totResourceTable;
|
|
}
|
|
}
|
|
|
|
byte *Game::loadExtData(int16 itemId, int16 *pResWidth,
|
|
int16 *pResHeight, uint32 *dataSize) {
|
|
int16 commonHandle;
|
|
int16 itemsCount;
|
|
int32 offset;
|
|
uint32 size;
|
|
uint32 realSize;
|
|
ExtItem *item;
|
|
bool isPacked;
|
|
int16 handle;
|
|
int32 tableSize;
|
|
char path[20];
|
|
byte *dataBuf;
|
|
byte *packedBuf;
|
|
byte *dataPtr;
|
|
|
|
itemId -= 30000;
|
|
if (_extTable == 0)
|
|
return 0;
|
|
|
|
commonHandle = -1;
|
|
itemsCount = _extTable->itemsCount;
|
|
item = &_extTable->items[itemId];
|
|
tableSize = szGame_ExtTable + szGame_ExtItem * itemsCount;
|
|
|
|
offset = item->offset;
|
|
size = item->size;
|
|
isPacked = (item->width & 0x8000) != 0;
|
|
|
|
if ((pResWidth != 0) && (pResHeight != 0)) {
|
|
*pResWidth = item->width & 0x7FFF;
|
|
|
|
if (*pResWidth & 0x4000)
|
|
size += 1 << 16;
|
|
if (*pResWidth & 0x2000)
|
|
size += 2 << 16;
|
|
if (*pResWidth & 0x1000)
|
|
size += 4 << 16;
|
|
|
|
*pResWidth &= 0xFFF;
|
|
|
|
*pResHeight = item->height;
|
|
debugC(7, kDebugFileIO, "loadExtData(%d, %d, %d)",
|
|
itemId, *pResWidth, *pResHeight);
|
|
}
|
|
|
|
debugC(7, kDebugFileIO, "loadExtData(%d, 0, 0)", itemId);
|
|
|
|
if (item->height == 0)
|
|
size += (item->width & 0x7FFF) << 16;
|
|
|
|
debugC(7, kDebugFileIO, "size: %d off: %d", size, offset);
|
|
if (offset < 0) {
|
|
offset = -(offset + 1);
|
|
tableSize = 0;
|
|
_vm->_dataIO->closeData(_extHandle);
|
|
strcpy(path, "commun.ex1");
|
|
path[strlen(path) - 1] = *(_totFileData + 0x3C) + '0';
|
|
commonHandle = _vm->_dataIO->openData(path);
|
|
handle = commonHandle;
|
|
} else
|
|
handle = _extHandle;
|
|
|
|
DataStream *stream = _vm->_dataIO->openAsStream(handle);
|
|
|
|
debugC(7, kDebugFileIO, "off: %d size: %d", offset, tableSize);
|
|
stream->seek(offset + tableSize);
|
|
realSize = size;
|
|
if (isPacked)
|
|
dataBuf = new byte[size + 2];
|
|
else
|
|
dataBuf = new byte[size];
|
|
|
|
dataPtr = dataBuf;
|
|
while (size > 32000) {
|
|
// BUG: huge->far conversion. Need normalization?
|
|
stream->read(dataPtr, 32000);
|
|
size -= 32000;
|
|
dataPtr += 32000;
|
|
}
|
|
stream->read(dataPtr, size);
|
|
|
|
delete stream;
|
|
if (commonHandle != -1) {
|
|
_vm->_dataIO->closeData(commonHandle);
|
|
_extHandle = _vm->_dataIO->openData(_curExtFile);
|
|
}
|
|
|
|
if (isPacked) {
|
|
packedBuf = dataBuf;
|
|
realSize = READ_LE_UINT32(packedBuf);
|
|
dataBuf = new byte[realSize];
|
|
_vm->_dataIO->unpackData(packedBuf, dataBuf);
|
|
delete[] packedBuf;
|
|
}
|
|
|
|
if (dataSize)
|
|
*dataSize = realSize;
|
|
return dataBuf;
|
|
}
|
|
|
|
void Game::freeCollision(int16 id) {
|
|
for (int i = 0; i < 250; i++) {
|
|
if (_collisionAreas[i].id == id)
|
|
_collisionAreas[i].left = 0xFFFF;
|
|
}
|
|
}
|
|
|
|
void Game::capturePush(int16 left, int16 top, int16 width, int16 height) {
|
|
int16 right;
|
|
|
|
if (_captureCount == 20)
|
|
error("Game::capturePush(): Capture stack overflow");
|
|
|
|
_captureStack[_captureCount].left = left;
|
|
_captureStack[_captureCount].top = top;
|
|
_captureStack[_captureCount].right = left + width;
|
|
_captureStack[_captureCount].bottom = top + height;
|
|
|
|
_vm->_draw->_spriteTop = top;
|
|
_vm->_draw->_spriteBottom = height;
|
|
|
|
right = left + width - 1;
|
|
left &= 0xFFF0;
|
|
right |= 0xF;
|
|
|
|
_vm->_draw->initSpriteSurf(30 + _captureCount, right - left + 1, height, 0);
|
|
|
|
_vm->_draw->_sourceSurface = 21;
|
|
_vm->_draw->_destSurface = 30 + _captureCount;
|
|
|
|
_vm->_draw->_spriteLeft = left;
|
|
_vm->_draw->_spriteRight = right - left + 1;
|
|
_vm->_draw->_destSpriteX = 0;
|
|
_vm->_draw->_destSpriteY = 0;
|
|
_vm->_draw->_transparency = 0;
|
|
_vm->_draw->spriteOperation(0);
|
|
_captureCount++;
|
|
}
|
|
|
|
void Game::capturePop(char doDraw) {
|
|
if (_captureCount <= 0)
|
|
return;
|
|
|
|
_captureCount--;
|
|
if (doDraw) {
|
|
_vm->_draw->_destSpriteX = _captureStack[_captureCount].left;
|
|
_vm->_draw->_destSpriteY = _captureStack[_captureCount].top;
|
|
_vm->_draw->_spriteRight =
|
|
_captureStack[_captureCount].width();
|
|
_vm->_draw->_spriteBottom =
|
|
_captureStack[_captureCount].height();
|
|
|
|
_vm->_draw->_transparency = 0;
|
|
_vm->_draw->_sourceSurface = 30 + _captureCount;
|
|
_vm->_draw->_destSurface = 21;
|
|
_vm->_draw->_spriteLeft = _vm->_draw->_destSpriteX & 0xF;
|
|
_vm->_draw->_spriteTop = 0;
|
|
_vm->_draw->spriteOperation(0);
|
|
}
|
|
_vm->_draw->freeSprite(30 + _captureCount);
|
|
}
|
|
|
|
byte *Game::loadTotResource(int16 id,
|
|
int16 *dataSize, int16 *width, int16 *height) {
|
|
|
|
TotResItem *itemPtr;
|
|
int32 offset;
|
|
|
|
if (id >= _vm->_game->_totResourceTable->itemsCount) {
|
|
warning("Trying to load non-existent TOT resource (%s, %d/%d)",
|
|
_curTotFile, id, _totResourceTable->itemsCount - 1);
|
|
return 0;
|
|
}
|
|
|
|
itemPtr = &_totResourceTable->items[id];
|
|
offset = itemPtr->offset;
|
|
|
|
if (dataSize)
|
|
*dataSize = itemPtr->size;
|
|
if (width)
|
|
*width = itemPtr->width;
|
|
if (height)
|
|
*height = itemPtr->height;
|
|
|
|
if (offset < 0) {
|
|
offset = (-offset - 1) * 4;
|
|
return _imFileData + (int32) READ_LE_UINT32(_imFileData + offset);
|
|
} else
|
|
return _totResourceTable->dataPtr + szGame_TotResTable +
|
|
szGame_TotResItem * _totResourceTable->itemsCount + offset;
|
|
}
|
|
|
|
void Game::freeSoundSlot(int16 slot) {
|
|
if (slot == -1)
|
|
slot = _vm->_parse->parseValExpr();
|
|
|
|
_vm->_sound->sampleFree(_vm->_sound->sampleGetBySlot(slot));
|
|
}
|
|
|
|
void Game::evaluateScroll(int16 x, int16 y) {
|
|
if (_preventScroll || !_scrollHandleMouse || (_menuLevel > 0))
|
|
return;
|
|
|
|
if (_noScroll ||
|
|
((_vm->_global->_videoMode != 0x14) && (_vm->_global->_videoMode != 0x18)))
|
|
return;
|
|
|
|
if ((x == 0) && (_vm->_draw->_scrollOffsetX > 0)) {
|
|
uint16 off;
|
|
|
|
off = MIN(_vm->_draw->_cursorWidth, _vm->_draw->_scrollOffsetX);
|
|
off = MAX(off / 2, 1);
|
|
_vm->_draw->_scrollOffsetX -= off;
|
|
_vm->_video->dirtyRectsAll();
|
|
} else if ((y == 0) && (_vm->_draw->_scrollOffsetY > 0)) {
|
|
uint16 off;
|
|
|
|
off = MIN(_vm->_draw->_cursorHeight, _vm->_draw->_scrollOffsetY);
|
|
off = MAX(off / 2, 1);
|
|
_vm->_draw->_scrollOffsetY -= off;
|
|
_vm->_video->dirtyRectsAll();
|
|
}
|
|
|
|
int16 cursorRight = x + _vm->_draw->_cursorWidth;
|
|
int16 screenRight = _vm->_draw->_scrollOffsetX + _vm->_width;
|
|
int16 cursorBottom = y + _vm->_draw->_cursorHeight;
|
|
int16 screenBottom = _vm->_draw->_scrollOffsetY + _vm->_height;
|
|
|
|
if ((cursorRight >= _vm->_width) &&
|
|
(screenRight < _vm->_video->_surfWidth)) {
|
|
uint16 off;
|
|
|
|
off = MIN(_vm->_draw->_cursorWidth,
|
|
(int16) (_vm->_video->_surfWidth - screenRight));
|
|
off = MAX(off / 2, 1);
|
|
|
|
_vm->_draw->_scrollOffsetX += off;
|
|
_vm->_video->dirtyRectsAll();
|
|
|
|
_vm->_util->setMousePos(_vm->_width - _vm->_draw->_cursorWidth, y);
|
|
} else if ((cursorBottom >= (_vm->_height - _vm->_video->_splitHeight2)) &&
|
|
(screenBottom < _vm->_video->_surfHeight)) {
|
|
uint16 off;
|
|
|
|
off = MIN(_vm->_draw->_cursorHeight,
|
|
(int16) (_vm->_video->_surfHeight - screenBottom));
|
|
off = MAX(off / 2, 1);
|
|
|
|
_vm->_draw->_scrollOffsetY += off;
|
|
_vm->_video->dirtyRectsAll();
|
|
|
|
_vm->_util->setMousePos(x, _vm->_height - _vm->_video->_splitHeight2 -
|
|
_vm->_draw->_cursorHeight);
|
|
}
|
|
|
|
_vm->_util->setScrollOffset();
|
|
}
|
|
|
|
int16 Game::checkKeys(int16 *pMouseX, int16 *pMouseY,
|
|
int16 *pButtons, char handleMouse) {
|
|
|
|
_vm->_util->processInput(true);
|
|
|
|
if (_vm->_mult->_multData && _vm->_inter->_variables &&
|
|
(VAR(58) != 0)) {
|
|
if (_vm->_mult->_multData->frameStart != (int) VAR(58) - 1)
|
|
_vm->_mult->_multData->frameStart++;
|
|
else
|
|
_vm->_mult->_multData->frameStart = 0;
|
|
|
|
_vm->_mult->playMult(_vm->_mult->_multData->frameStart + VAR(57),
|
|
_vm->_mult->_multData->frameStart + VAR(57), 1, handleMouse);
|
|
}
|
|
|
|
if ((_vm->_inter->_soundEndTimeKey != 0) &&
|
|
(_vm->_util->getTimeKey() >= _vm->_inter->_soundEndTimeKey)) {
|
|
_vm->_sound->blasterStop(_vm->_inter->_soundStopVal);
|
|
_vm->_inter->_soundEndTimeKey = 0;
|
|
}
|
|
|
|
if (pMouseX && pMouseY && pButtons) {
|
|
_vm->_util->getMouseState(pMouseX, pMouseY, pButtons);
|
|
|
|
if (*pButtons == 3)
|
|
*pButtons = 0;
|
|
}
|
|
|
|
return _vm->_util->checkKey();
|
|
}
|
|
|
|
int16 Game::adjustKey(int16 key) {
|
|
if (key <= 0x60 || key >= 0x7B)
|
|
return key;
|
|
|
|
return key - 0x20;
|
|
}
|
|
|
|
int32 Game::loadTotFile(const char *path) {
|
|
int32 size;
|
|
|
|
_lomHandle = -1;
|
|
|
|
size = -1;
|
|
if (_vm->_dataIO->existData(path)) {
|
|
if (!scumm_stricmp(path + strlen(path) - 3, "LOM")) {
|
|
warning("Urban Stub: loadTotFile %s", path);
|
|
|
|
_lomHandle = _vm->_dataIO->openData(path);
|
|
|
|
DataStream *stream = _vm->_dataIO->openAsStream(_lomHandle);
|
|
|
|
stream->seek(48);
|
|
size = stream->readUint32LE();
|
|
stream->seek(0);
|
|
|
|
_totFileData = new byte[size];
|
|
stream->read(_totFileData, size);
|
|
|
|
delete stream;
|
|
} else {
|
|
size = _vm->_dataIO->getDataSize(path);
|
|
_totFileData = _vm->_dataIO->getData(path);
|
|
}
|
|
|
|
} else {
|
|
Common::MemoryReadStream *videoExtraData = _vm->_vidPlayer->getExtraData(path);
|
|
|
|
if (videoExtraData) {
|
|
warning("Found \"%s\" in video file", path);
|
|
|
|
size = videoExtraData->size();
|
|
_totFileData = new byte[size];
|
|
videoExtraData->read(_totFileData, size);
|
|
delete videoExtraData;
|
|
} else
|
|
_totFileData = 0;
|
|
}
|
|
|
|
return size;
|
|
}
|
|
|
|
void Game::loadExtTable(void) {
|
|
int16 count;
|
|
|
|
// Function is correct. [sev]
|
|
|
|
_extHandle = _vm->_dataIO->openData(_curExtFile);
|
|
if (_extHandle < 0)
|
|
return;
|
|
|
|
DataStream *stream = _vm->_dataIO->openAsStream(_extHandle);
|
|
count = stream->readUint16LE();
|
|
|
|
stream->seek(0);
|
|
_extTable = new ExtTable;
|
|
_extTable->items = 0;
|
|
if (count)
|
|
_extTable->items = new ExtItem[count];
|
|
|
|
_extTable->itemsCount = stream->readUint16LE();
|
|
_extTable->unknown = stream->readByte();
|
|
|
|
for (int i = 0; i < count; i++) {
|
|
_extTable->items[i].offset = stream->readUint32LE();
|
|
_extTable->items[i].size = stream->readUint16LE();
|
|
_extTable->items[i].width = stream->readUint16LE();
|
|
_extTable->items[i].height = stream->readUint16LE();
|
|
}
|
|
|
|
delete stream;
|
|
}
|
|
|
|
void Game::loadImFile(void) {
|
|
char path[20];
|
|
|
|
if ((_totFileData[0x3D] != 0) && (_totFileData[0x3B] == 0))
|
|
return;
|
|
|
|
strcpy(path, "commun.im1");
|
|
if (_totFileData[0x3B] != 0)
|
|
path[strlen(path) - 1] = '0' + _totFileData[0x3B];
|
|
|
|
if (!_vm->_dataIO->existData(path))
|
|
return;
|
|
|
|
_imFileData = _vm->_dataIO->getData(path);
|
|
}
|
|
|
|
void Game::start(void) {
|
|
_collisionAreas = new Collision[250];
|
|
memset(_collisionAreas, 0, 250 * sizeof(Collision));
|
|
|
|
prepareStart();
|
|
playTot(-2);
|
|
|
|
delete[] _collisionAreas;
|
|
_vm->_draw->closeScreen();
|
|
|
|
for (int i = 0; i < SPRITES_COUNT; i++)
|
|
_vm->_draw->freeSprite(i);
|
|
_vm->_draw->_scummvmCursor.reset();
|
|
}
|
|
|
|
// flagbits: 0 = freeInterVariables, 1 = skipPlay
|
|
void Game::totSub(int8 flags, const char *newTotFile) {
|
|
int8 curBackupPos;
|
|
|
|
if (_backupedCount >= 5)
|
|
return;
|
|
|
|
_cursorHotspotXArray[_backupedCount] = _vm->_draw->_cursorHotspotXVar;
|
|
_cursorHotspotYArray[_backupedCount] = _vm->_draw->_cursorHotspotYVar;
|
|
_totTextDataArray[_backupedCount] = _totTextData;
|
|
_totFileDataArray[_backupedCount] = _totFileData;
|
|
_totResourceTableArray[_backupedCount] = _totResourceTable;
|
|
_extTableArray[_backupedCount] = _extTable;
|
|
_extHandleArray[_backupedCount] = _extHandle;
|
|
_imFileDataArray[_backupedCount] = _imFileData;
|
|
_variablesArray[_backupedCount] = _vm->_inter->_variables;
|
|
strcpy(_curTotFileArray[_backupedCount], _curTotFile);
|
|
|
|
curBackupPos = _curBackupPos;
|
|
_backupedCount++;
|
|
_curBackupPos = _backupedCount;
|
|
|
|
_totTextData = 0;
|
|
_totFileData = 0;
|
|
_totResourceTable = 0;
|
|
if (flags & 1)
|
|
_vm->_inter->_variables = 0;
|
|
|
|
strncpy0(_curTotFile, newTotFile, 9);
|
|
// if (_vm->getGameType() == kGameTypeGeisha)
|
|
// strcat(_curTotFile, ".0OT");
|
|
// else
|
|
strcat(_curTotFile, ".TOT");
|
|
|
|
if (_vm->_inter->_terminate != 0)
|
|
return;
|
|
|
|
pushCollisions(0);
|
|
|
|
if (flags & 2)
|
|
playTot(-1);
|
|
else
|
|
playTot(0);
|
|
|
|
if (_vm->_inter->_terminate != 2)
|
|
_vm->_inter->_terminate = 0;
|
|
|
|
popCollisions();
|
|
|
|
if ((flags & 1) && _vm->_inter->_variables) {
|
|
_vm->_inter->delocateVars();
|
|
}
|
|
|
|
_backupedCount--;
|
|
_curBackupPos = curBackupPos;
|
|
|
|
_vm->_draw->_cursorHotspotXVar = _cursorHotspotXArray[_backupedCount];
|
|
_vm->_draw->_cursorHotspotYVar = _cursorHotspotYArray[_backupedCount];
|
|
_totTextData = _totTextDataArray[_backupedCount];
|
|
_totFileData = _totFileDataArray[_backupedCount];
|
|
_totResourceTable = _totResourceTableArray[_backupedCount];
|
|
_extTable = _extTableArray[_backupedCount];
|
|
_extHandle = _extHandleArray[_backupedCount];
|
|
_imFileData = _imFileDataArray[_backupedCount];
|
|
_vm->_inter->_variables = _variablesArray[_backupedCount];
|
|
strcpy(_curTotFile, _curTotFileArray[_backupedCount]);
|
|
strcpy(_curExtFile, _curTotFile);
|
|
_curExtFile[strlen(_curExtFile) - 4] = '\0';
|
|
strcat(_curExtFile, ".EXT");
|
|
}
|
|
|
|
void Game::switchTotSub(int16 index, int16 skipPlay) {
|
|
int16 backupedCount;
|
|
int16 curBackupPos;
|
|
|
|
if ((_backupedCount - index) < 1)
|
|
return;
|
|
|
|
int16 newPos = _curBackupPos - index - ((index >= 0) ? 1 : 0);
|
|
// WORKAROUND: Some versions don't make the MOVEMENT menu item unselectable
|
|
// in the dreamland screen, resulting in a crash when it's clicked.
|
|
if ((_vm->getGameType() == kGameTypeGob2) && (index == -1) && (skipPlay == 7) &&
|
|
!scumm_stricmp(_curTotFileArray[newPos], "gob06.tot"))
|
|
return;
|
|
|
|
curBackupPos = _curBackupPos;
|
|
backupedCount = _backupedCount;
|
|
if (_curBackupPos == _backupedCount) {
|
|
_cursorHotspotXArray[_backupedCount] = _vm->_draw->_cursorHotspotXVar;
|
|
_cursorHotspotYArray[_backupedCount] = _vm->_draw->_cursorHotspotYVar;
|
|
_totTextDataArray[_backupedCount] = _totTextData;
|
|
_totFileDataArray[_backupedCount] = _totFileData;
|
|
_totResourceTableArray[_backupedCount] = _totResourceTable;
|
|
_extTableArray[_backupedCount] = _extTable;
|
|
_extHandleArray[_backupedCount] = _extHandle;
|
|
_imFileDataArray[_backupedCount] = _imFileData;
|
|
_variablesArray[_backupedCount] = _vm->_inter->_variables;
|
|
strcpy(_curTotFileArray[_backupedCount], _curTotFile);
|
|
_backupedCount++;
|
|
}
|
|
_curBackupPos -= index;
|
|
if (index >= 0)
|
|
_curBackupPos--;
|
|
|
|
_vm->_draw->_cursorHotspotXVar = _cursorHotspotXArray[_curBackupPos];
|
|
_vm->_draw->_cursorHotspotYVar = _cursorHotspotYArray[_curBackupPos];
|
|
_totTextData = _totTextDataArray[_curBackupPos];
|
|
_totFileData = _totFileDataArray[_curBackupPos];
|
|
_totResourceTable = _totResourceTableArray[_curBackupPos];
|
|
_imFileData = _imFileDataArray[_curBackupPos];
|
|
_extTable = _extTableArray[_curBackupPos];
|
|
_extHandle = _extHandleArray[_curBackupPos];
|
|
_vm->_inter->_variables = _variablesArray[_curBackupPos];
|
|
strcpy(_curTotFile, _curTotFileArray[_curBackupPos]);
|
|
strcpy(_curExtFile, _curTotFile);
|
|
_curExtFile[strlen(_curExtFile) - 4] = '\0';
|
|
strcat(_curExtFile, ".EXT");
|
|
|
|
if (_vm->_inter->_terminate != 0)
|
|
return;
|
|
|
|
_vm->_game->pushCollisions(0);
|
|
_vm->_game->playTot(skipPlay);
|
|
|
|
if (_vm->_inter->_terminate != 2)
|
|
_vm->_inter->_terminate = 0;
|
|
|
|
_vm->_game->popCollisions();
|
|
|
|
_curBackupPos = curBackupPos;
|
|
_backupedCount = backupedCount;
|
|
_vm->_draw->_cursorHotspotXVar = _cursorHotspotXArray[_curBackupPos];
|
|
_vm->_draw->_cursorHotspotYVar = _cursorHotspotYArray[_curBackupPos];
|
|
_totTextData = _totTextDataArray[_curBackupPos];
|
|
_totFileData = _totFileDataArray[_curBackupPos];
|
|
_totResourceTable = _totResourceTableArray[_curBackupPos];
|
|
_extTable = _extTableArray[_curBackupPos];
|
|
_extHandle = _extHandleArray[_curBackupPos];
|
|
_imFileData = _imFileDataArray[_curBackupPos];
|
|
_vm->_inter->_variables = _variablesArray[_curBackupPos];
|
|
strcpy(_curTotFile, _curTotFileArray[_curBackupPos]);
|
|
strcpy(_curExtFile, _curTotFile);
|
|
_curExtFile[strlen(_curExtFile) - 4] = '\0';
|
|
strcat(_curExtFile, ".EXT");
|
|
}
|
|
|
|
bool Game::getLocTextFile(char *locTextFile, int language) {
|
|
int n = strlen(locTextFile);
|
|
if (n < 4)
|
|
return false;
|
|
|
|
locTextFile[n - 4] = 0;
|
|
switch (language) {
|
|
case 0:
|
|
strcat(locTextFile, ".dat");
|
|
break;
|
|
case 1:
|
|
strcat(locTextFile, ".all");
|
|
break;
|
|
case 3:
|
|
strcat(locTextFile, ".esp");
|
|
break;
|
|
case 4:
|
|
strcat(locTextFile, ".ita");
|
|
break;
|
|
case 5:
|
|
strcat(locTextFile, ".usa");
|
|
break;
|
|
case 6:
|
|
strcat(locTextFile, ".ndl");
|
|
break;
|
|
case 7:
|
|
strcat(locTextFile, ".kor");
|
|
break;
|
|
case 8:
|
|
strcat(locTextFile, ".isr");
|
|
break;
|
|
default:
|
|
strcat(locTextFile, ".ang");
|
|
break;
|
|
}
|
|
|
|
return _vm->_dataIO->existData(locTextFile);
|
|
}
|
|
|
|
byte *Game::loadLocTexts(int32 *dataSize) {
|
|
char locTextFile[20];
|
|
|
|
strcpy(locTextFile, _curTotFile);
|
|
|
|
bool found = getLocTextFile(locTextFile, _vm->_global->_languageWanted);
|
|
if (found) {
|
|
|
|
_foundTotLoc = true;
|
|
_vm->_global->_language = _vm->_global->_languageWanted;
|
|
|
|
} else if (!_foundTotLoc) {
|
|
// Trying US for GB and vice versa
|
|
if (_vm->_global->_languageWanted == 2) {
|
|
found = getLocTextFile(locTextFile, 5);
|
|
if (found) {
|
|
_vm->_global->_language = 5;
|
|
found = true;
|
|
}
|
|
} else if (_vm->_global->_languageWanted == 5) {
|
|
found = getLocTextFile(locTextFile, 2);
|
|
if (found) {
|
|
_vm->_global->_language = 2;
|
|
found = true;
|
|
}
|
|
}
|
|
|
|
if (!found) {
|
|
// Looking for the first existing language
|
|
for (int i = 0; i < 10; i++) {
|
|
found = getLocTextFile(locTextFile, i);
|
|
if (found) {
|
|
_vm->_global->_language = i;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
debugC(1, kDebugFileIO, "Using language %d for %s",
|
|
_vm->_global->_language, _curTotFile);
|
|
|
|
if (found) {
|
|
if (dataSize)
|
|
*dataSize = _vm->_dataIO->getDataSize(locTextFile);
|
|
|
|
return _vm->_dataIO->getData(locTextFile);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
void Game::setCollisions(byte arg_0) {
|
|
byte *savedIP;
|
|
uint16 left;
|
|
uint16 top;
|
|
uint16 width;
|
|
uint16 height;
|
|
Collision *collArea;
|
|
|
|
for (collArea = _collisionAreas; collArea->left != 0xFFFF; collArea++) {
|
|
if (((collArea->id & 0xC000) != 0x8000) || (collArea->funcSub == 0))
|
|
continue;
|
|
|
|
savedIP = _vm->_global->_inter_execPtr;
|
|
_vm->_global->_inter_execPtr = _totFileData + collArea->funcSub;
|
|
left = _vm->_parse->parseValExpr();
|
|
top = _vm->_parse->parseValExpr();
|
|
width = _vm->_parse->parseValExpr();
|
|
height = _vm->_parse->parseValExpr();
|
|
if ((_vm->_draw->_renderFlags & RENDERFLAG_CAPTUREPOP) &&
|
|
(left != 0xFFFF)) {
|
|
left += _vm->_draw->_backDeltaX;
|
|
top += _vm->_draw->_backDeltaY;
|
|
}
|
|
if (_vm->_draw->_needAdjust != 2) {
|
|
_vm->_draw->adjustCoords(0, &left, &top);
|
|
if ((collArea->flags & 0x0F) < 3)
|
|
_vm->_draw->adjustCoords(2, &width, &height);
|
|
else {
|
|
height &= 0xFFFE;
|
|
_vm->_draw->adjustCoords(2, 0, &height);
|
|
}
|
|
}
|
|
collArea->left = left;
|
|
collArea->top = top;
|
|
collArea->right = left + width - 1;
|
|
collArea->bottom = top + height - 1;
|
|
_vm->_global->_inter_execPtr = savedIP;
|
|
}
|
|
}
|
|
|
|
void Game::collSub(uint16 offset) {
|
|
byte *savedIP;
|
|
int16 collStackSize;
|
|
|
|
savedIP = _vm->_global->_inter_execPtr;
|
|
_vm->_global->_inter_execPtr = _totFileData + offset;
|
|
|
|
_shouldPushColls = 1;
|
|
collStackSize = _collStackSize;
|
|
|
|
_vm->_inter->funcBlock(0);
|
|
|
|
if (collStackSize != _collStackSize)
|
|
popCollisions();
|
|
|
|
_shouldPushColls = 0;
|
|
_vm->_global->_inter_execPtr = savedIP;
|
|
setCollisions();
|
|
}
|
|
|
|
void Game::collAreaSub(int16 index, int8 enter) {
|
|
uint16 collId;
|
|
|
|
collId = _collisionAreas[index].id & 0xF000;
|
|
|
|
if ((collId == 0xA000) || (collId == 0x9000)) {
|
|
if (enter == 0)
|
|
WRITE_VAR(17, _collisionAreas[index].id & 0x0FFF);
|
|
else
|
|
WRITE_VAR(17, -(_collisionAreas[index].id & 0x0FFF));
|
|
}
|
|
|
|
if (enter != 0) {
|
|
if (_collisionAreas[index].funcEnter != 0)
|
|
collSub(_collisionAreas[index].funcEnter);
|
|
} else {
|
|
if (_collisionAreas[index].funcLeave != 0)
|
|
collSub(_collisionAreas[index].funcLeave);
|
|
}
|
|
}
|
|
|
|
} // End of namespace Gob
|