mirror of
https://github.com/libretro/scummvm.git
synced 2024-12-17 15:18:11 +00:00
cb8378065d
- Changed Snd to be a permanent audiostream, to have better control over stopping, looping and compositions - Some clean-up svn-id: r25292
1646 lines
44 KiB
C++
1646 lines
44 KiB
C++
/* 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$
|
|
* $Id$
|
|
*
|
|
*/
|
|
|
|
#include "common/stdafx.h"
|
|
#include "common/endian.h"
|
|
|
|
#include "gob/gob.h"
|
|
#include "gob/global.h"
|
|
#include "gob/game.h"
|
|
#include "gob/video.h"
|
|
#include "gob/dataio.h"
|
|
#include "gob/pack.h"
|
|
#include "gob/scenery.h"
|
|
#include "gob/inter.h"
|
|
#include "gob/parse.h"
|
|
#include "gob/draw.h"
|
|
#include "gob/mult.h"
|
|
#include "gob/util.h"
|
|
#include "gob/goblin.h"
|
|
#include "gob/cdrom.h"
|
|
#include "gob/music.h"
|
|
#include "gob/palanim.h"
|
|
|
|
namespace Gob {
|
|
|
|
int16 Game::_captureCount = 0;
|
|
Common::Rect Game::_captureStack[20];
|
|
|
|
Game::Game(GobEngine *vm) : _vm(vm) {
|
|
_extTable = 0;
|
|
_totFileData = 0;
|
|
_totResourceTable = 0;
|
|
_imFileData = 0;
|
|
_extHandle = 0;
|
|
_collisionAreas = 0;
|
|
_shouldPushColls = 0;
|
|
_totTextData = 0;
|
|
|
|
// Collisions stack
|
|
_collStackSize = 0;
|
|
int i;
|
|
|
|
for (i = 0; i < 5; i++) {
|
|
_collStack[i] = 0;
|
|
_collStackElemSizes[i] = 0;
|
|
}
|
|
|
|
for (i = 0; i < 60; i++) {
|
|
_soundSamples[i] = 0;
|
|
_soundIds[i] = 0;
|
|
_soundTypes[i] = 0;
|
|
_soundFromExt[i] = 0;
|
|
_soundADL[i] = false;
|
|
}
|
|
_infIns = 0;
|
|
_infogrames = 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;
|
|
|
|
_tempStr[0] = 0;
|
|
_curImaFile[0] = 0;
|
|
_collStr[0] = 0;
|
|
|
|
_backupedCount = 0;
|
|
_curBackupPos = 0;
|
|
|
|
for (i = 0; i < 5; i++) {
|
|
_cursorXDeltaArray[i] = 0;
|
|
_cursorYDeltaArray[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;
|
|
}
|
|
|
|
_imdFile = 0;
|
|
_curImdFile[0] = 0;
|
|
_imdX = 0;
|
|
_imdY = 0;
|
|
_imdFrameDataSize = 0;
|
|
_imdVidBufferSize = 0;
|
|
_imdFrameData = 0;
|
|
_imdVidBuffer = 0;
|
|
|
|
warning("GOB2 Stub! _byte_2FC82, _byte_2FC83, _word_2FC80");
|
|
_byte_2FC82 = 0;
|
|
_byte_2FC83 = 0;
|
|
_word_2FC80 = 0;
|
|
|
|
warning("GOB2 Stub! _byte_2FC9B, _dword_2F2B6");
|
|
_byte_2FC9B = 0;
|
|
_dword_2F2B6 = 0;
|
|
}
|
|
|
|
Game::~Game() {
|
|
if (_imdFile) {
|
|
if (_imdFile->palette)
|
|
delete[] _imdFile->palette;
|
|
if (_imdFile->surfDesc &&
|
|
(_imdFile->surfDesc != _vm->_draw->_spritesArray[20]) &&
|
|
(_imdFile->surfDesc != _vm->_draw->_spritesArray[21]))
|
|
_vm->_video->freeSurfDesc(_imdFile->surfDesc);
|
|
if (_imdFile->framesPos)
|
|
delete[] _imdFile->framesPos;
|
|
if (_imdFile->frameCoords)
|
|
delete[] _imdFile->frameCoords;
|
|
delete _imdFile;
|
|
}
|
|
if (_imdFrameData)
|
|
delete[] _imdFrameData;
|
|
if (_imdVidBuffer)
|
|
delete[] _imdVidBuffer;
|
|
if (_word_2FC80)
|
|
delete[] _word_2FC80;
|
|
if (_infIns)
|
|
delete _infIns;
|
|
}
|
|
|
|
char *Game::loadExtData(int16 itemId, int16 *pResWidth, int16 *pResHeight, uint32 *dataSize) {
|
|
int16 commonHandle;
|
|
int16 itemsCount;
|
|
int32 offset;
|
|
uint32 size;
|
|
uint32 realSize;
|
|
ExtItem *item;
|
|
char isPacked;
|
|
int16 handle;
|
|
int32 tableSize;
|
|
char path[20];
|
|
char *dataBuf;
|
|
char *packedBuf;
|
|
char *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;
|
|
if (item->width & 0x8000)
|
|
isPacked = 1;
|
|
else
|
|
isPacked = 0;
|
|
|
|
if (pResWidth != 0) {
|
|
*pResWidth = item->width & 0x7fff;
|
|
*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) {
|
|
handle = _extHandle;
|
|
} else {
|
|
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;
|
|
}
|
|
|
|
debugC(7, kDebugFileIO, "off: %d size: %d", offset, tableSize);
|
|
_vm->_dataio->seekData(handle, offset + tableSize, SEEK_SET);
|
|
realSize = size;
|
|
// CHECKME: is the below correct?
|
|
if (isPacked)
|
|
dataBuf = new char[size];
|
|
else
|
|
dataBuf = new char[size];
|
|
|
|
dataPtr = dataBuf;
|
|
while (size > 32000) {
|
|
// BUG: huge->far conversion. Need normalization?
|
|
_vm->_dataio->readData(handle, (char *)dataPtr, 32000);
|
|
size -= 32000;
|
|
dataPtr += 32000;
|
|
}
|
|
_vm->_dataio->readData(handle, (char *)dataPtr, size);
|
|
if (commonHandle != -1) {
|
|
_vm->_dataio->closeData(commonHandle);
|
|
_extHandle = _vm->_dataio->openData(_curExtFile);
|
|
}
|
|
|
|
if (isPacked != 0) {
|
|
packedBuf = dataBuf;
|
|
realSize = READ_LE_UINT32(packedBuf);
|
|
dataBuf = new char[realSize];
|
|
_vm->_pack->unpackData(packedBuf, dataBuf);
|
|
delete[] packedBuf;
|
|
}
|
|
|
|
if (dataSize)
|
|
*dataSize = realSize;
|
|
return dataBuf;
|
|
}
|
|
|
|
void Game::freeCollision(int16 id) {
|
|
int16 i;
|
|
|
|
for (i = 0; i < 250; i++) {
|
|
if (_collisionAreas[i].id == id)
|
|
_collisionAreas[i].left = -1;
|
|
}
|
|
}
|
|
|
|
void Game::capturePush(int16 left, int16 top, int16 width, int16 height) {
|
|
int16 right;
|
|
|
|
if (_captureCount == 20)
|
|
error("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->_spritesArray[30 + _captureCount] =
|
|
_vm->_video->initSurfDesc(_vm->_global->_videoMode, 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->_video->freeSurfDesc(_vm->_draw->_spritesArray[30 + _captureCount]);
|
|
_vm->_draw->_spritesArray[30 + _captureCount] = 0;
|
|
}
|
|
|
|
char *Game::loadTotResource(int16 id, int16 *dataSize) {
|
|
TotResItem *itemPtr;
|
|
int32 offset;
|
|
|
|
itemPtr = &_totResourceTable->items[id];
|
|
offset = itemPtr->offset;
|
|
if (dataSize)
|
|
*dataSize = itemPtr->size;
|
|
if (offset >= 0) {
|
|
return _totResourceTable->dataPtr + szGame_TotResTable +
|
|
szGame_TotResItem * _totResourceTable->itemsCount + offset;
|
|
} else {
|
|
return (char *)(_imFileData + (int32)READ_LE_UINT32(&((int32 *)_imFileData)[-offset - 1]));
|
|
}
|
|
}
|
|
|
|
void Game::loadSound(int16 slot, char *dataPtr, uint32 dataSize) {
|
|
Snd::SoundDesc *soundDesc;
|
|
byte *data = (byte *) dataPtr;
|
|
|
|
soundDesc = new Snd::SoundDesc;
|
|
|
|
_soundSamples[slot] = soundDesc;
|
|
|
|
soundDesc->frequency = (data[4] << 8) + data[5];
|
|
// Somehow, one sound in one CD version has a wrong size, leading to statics and crashes
|
|
soundDesc->size = MIN((uint32) ((data[1] << 16) + (data[2] << 8) + data[3]), dataSize - 6);
|
|
soundDesc->data = dataPtr + 6;
|
|
soundDesc->timerTicks = (int32)1193180 / (int32)soundDesc->frequency;
|
|
soundDesc->inClocks = (soundDesc->frequency * 10) / 182;
|
|
soundDesc->flag = 0;
|
|
|
|
}
|
|
|
|
void Game::freeSoundSlot(int16 slot) {
|
|
if (slot == -1)
|
|
slot = _vm->_parse->parseValExpr();
|
|
|
|
if ((slot < 0) || (slot >= 60) || (_soundSamples[slot] == 0))
|
|
return;
|
|
|
|
if (slot == _vm->_snd->getCompositionSlot()) {
|
|
if (_vm->_quitRequested)
|
|
_vm->_snd->stopComposition();
|
|
else
|
|
_vm->_snd->waitEndPlay();
|
|
}
|
|
|
|
if (_soundADL[slot]) {
|
|
if (_vm->_adlib && (_vm->_adlib->getIndex() == slot))
|
|
_vm->_adlib->stopPlay();
|
|
|
|
if (_soundFromExt[slot] == 1) {
|
|
delete[] _soundSamples[slot]->data;
|
|
_soundFromExt[slot] = 0;
|
|
}
|
|
|
|
delete _soundSamples[slot];
|
|
} else {
|
|
char* data = _soundSamples[slot]->data;
|
|
|
|
_vm->_snd->freeSoundDesc(_soundSamples[slot], false);
|
|
|
|
if (_soundFromExt[slot] == 1) {
|
|
delete[] (data - 6);
|
|
_soundFromExt[slot] = 0;
|
|
}
|
|
}
|
|
_soundSamples[slot] = 0;
|
|
}
|
|
|
|
int16 Game::adjustKey(int16 key) {
|
|
if (key <= 0x60 || key >= 0x7b)
|
|
return key;
|
|
|
|
return key - 0x20;
|
|
}
|
|
|
|
int32 Game::loadTotFile(char *path) {
|
|
int16 handle;
|
|
int32 size;
|
|
|
|
size = -1;
|
|
handle = _vm->_dataio->openData(path);
|
|
if (handle >= 0) {
|
|
_vm->_dataio->closeData(handle);
|
|
size = _vm->_dataio->getDataSize(path);
|
|
_totFileData = _vm->_dataio->getData(path);
|
|
} else {
|
|
_totFileData = 0;
|
|
}
|
|
|
|
return size;
|
|
}
|
|
|
|
void Game::loadExtTable(void) {
|
|
int16 count, i;
|
|
|
|
// Function is correct. [sev]
|
|
|
|
_extHandle = _vm->_dataio->openData(_curExtFile);
|
|
if (_extHandle < 0)
|
|
return;
|
|
|
|
_vm->_dataio->readData(_extHandle, (char *)&count, 2);
|
|
count = FROM_LE_16(count);
|
|
|
|
_vm->_dataio->seekData(_extHandle, 0, 0);
|
|
_extTable = new ExtTable;
|
|
_extTable->items = 0;
|
|
if (count)
|
|
_extTable->items = new ExtItem[count];
|
|
|
|
_vm->_dataio->readData(_extHandle, (char *)&_extTable->itemsCount, 2);
|
|
_extTable->itemsCount = FROM_LE_16(_extTable->itemsCount);
|
|
_vm->_dataio->readData(_extHandle, (char *)&_extTable->unknown, 1);
|
|
|
|
for (i = 0; i < count; i++) {
|
|
_vm->_dataio->readData(_extHandle, (char *)&_extTable->items[i].offset, 4);
|
|
_extTable->items[i].offset = FROM_LE_32(_extTable->items[i].offset);
|
|
_vm->_dataio->readData(_extHandle, (char *)&_extTable->items[i].size, 2);
|
|
_extTable->items[i].size = FROM_LE_16(_extTable->items[i].size);
|
|
_vm->_dataio->readData(_extHandle, (char *)&_extTable->items[i].width, 2);
|
|
_extTable->items[i].width = FROM_LE_16(_extTable->items[i].width);
|
|
_vm->_dataio->readData(_extHandle, (char *)&_extTable->items[i].height, 2);
|
|
_extTable->items[i].height = FROM_LE_16(_extTable->items[i].height);
|
|
}
|
|
}
|
|
|
|
void Game::loadImFile(void) {
|
|
char path[20];
|
|
int16 handle;
|
|
|
|
if (_totFileData[0x3d] != 0 && _totFileData[0x3b] == 0)
|
|
return;
|
|
|
|
strcpy(path, "commun.im1");
|
|
if (_totFileData[0x3b] != 0)
|
|
path[strlen(path) - 1] = '0' + _totFileData[0x3b];
|
|
|
|
handle = _vm->_dataio->openData(path);
|
|
if (handle < 0)
|
|
return;
|
|
|
|
_vm->_dataio->closeData(handle);
|
|
_imFileData = _vm->_dataio->getData(path);
|
|
}
|
|
|
|
void Game::start(void) {
|
|
int i;
|
|
|
|
_collisionAreas = new Collision[250];
|
|
memset(_collisionAreas, 0, 250 * sizeof(Collision));
|
|
|
|
prepareStart();
|
|
playTot(-2);
|
|
|
|
delete[] _collisionAreas;
|
|
_vm->_draw->closeScreen();
|
|
|
|
_vm->_draw->_spritesArray[20] = 0;
|
|
for (i = 0; i < 50; i++) {
|
|
_vm->_video->freeSurfDesc(_vm->_draw->_spritesArray[i]);
|
|
_vm->_draw->_spritesArray[i] = 0;
|
|
}
|
|
_vm->_video->freeSurfDesc(_vm->_draw->_scummvmCursor);
|
|
}
|
|
|
|
// flagbits: 0 = freeInterVariables, 1 = skipPlay
|
|
void Game::totSub(int8 flags, char *newTotFile) {
|
|
int8 curBackupPos;
|
|
|
|
if (_backupedCount >= 5)
|
|
return;
|
|
|
|
_cursorXDeltaArray[_backupedCount] = _vm->_draw->_cursorXDeltaVar;
|
|
_cursorYDeltaArray[_backupedCount] = _vm->_draw->_cursorYDeltaVar;
|
|
_totTextDataArray[_backupedCount] = _totTextData;
|
|
_totFileDataArray[_backupedCount] = _totFileData;
|
|
_totResourceTableArray[_backupedCount] = _totResourceTable;
|
|
_extTableArray[_backupedCount] = _extTable;
|
|
_extHandleArray[_backupedCount] = _extHandle;
|
|
_imFileDataArray[_backupedCount] = _imFileData;
|
|
_variablesArray[_backupedCount] = _vm->_global->_inter_variables;
|
|
_variablesSizesArray[_backupedCount] = _vm->_global->_inter_variablesSizes;
|
|
strcpy(_curTotFileArray[_backupedCount], _curTotFile);
|
|
|
|
curBackupPos = _curBackupPos;
|
|
_backupedCount++;
|
|
_curBackupPos = _backupedCount;
|
|
|
|
_totTextData = 0;
|
|
_totFileData = 0;
|
|
_totResourceTable = 0;
|
|
if (flags & 1) {
|
|
_vm->_global->_inter_variables = 0;
|
|
_vm->_global->_inter_variablesSizes = 0;
|
|
}
|
|
|
|
strcpy(_curTotFile, newTotFile);
|
|
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->_global->_inter_variables != 0)) {
|
|
delete[] _vm->_global->_inter_variables;
|
|
delete[] _vm->_global->_inter_variablesSizes;
|
|
}
|
|
|
|
_backupedCount--;
|
|
_curBackupPos = curBackupPos;
|
|
|
|
_vm->_draw->_cursorXDeltaVar = _cursorXDeltaArray[_backupedCount];
|
|
_vm->_draw->_cursorYDeltaVar = _cursorYDeltaArray[_backupedCount];
|
|
_totTextData = _totTextDataArray[_backupedCount];
|
|
_totFileData = _totFileDataArray[_backupedCount];
|
|
_totResourceTable = _totResourceTableArray[_backupedCount];
|
|
_extTable = _extTableArray[_backupedCount];
|
|
_extHandle = _extHandleArray[_backupedCount];
|
|
_imFileData = _imFileDataArray[_backupedCount];
|
|
_vm->_global->_inter_variables = _variablesArray[_backupedCount];
|
|
_vm->_global->_inter_variablesSizes = _variablesSizesArray[_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;
|
|
|
|
curBackupPos = _curBackupPos;
|
|
backupedCount = _backupedCount;
|
|
if (_curBackupPos == _backupedCount) {
|
|
_cursorXDeltaArray[_backupedCount] = _vm->_draw->_cursorXDeltaVar;
|
|
_cursorYDeltaArray[_backupedCount] = _vm->_draw->_cursorYDeltaVar;
|
|
_totTextDataArray[_backupedCount] = _totTextData;
|
|
_totFileDataArray[_backupedCount] = _totFileData;
|
|
_totResourceTableArray[_backupedCount] = _totResourceTable;
|
|
_extTableArray[_backupedCount] = _extTable;
|
|
_extHandleArray[_backupedCount] = _extHandle;
|
|
_imFileDataArray[_backupedCount] = _imFileData;
|
|
_variablesArray[_backupedCount] = _vm->_global->_inter_variables;
|
|
_variablesSizesArray[_backupedCount] = _vm->_global->_inter_variablesSizes;
|
|
strcpy(_curTotFileArray[_backupedCount], _curTotFile);
|
|
_backupedCount++;
|
|
}
|
|
_curBackupPos -= index;
|
|
if (index >= 0)
|
|
_curBackupPos--;
|
|
|
|
_vm->_draw->_cursorXDeltaVar = _cursorXDeltaArray[_curBackupPos];
|
|
_vm->_draw->_cursorYDeltaVar = _cursorYDeltaArray[_curBackupPos];
|
|
_totTextData = _totTextDataArray[_curBackupPos];
|
|
_totFileData = _totFileDataArray[_curBackupPos];
|
|
_totResourceTable = _totResourceTableArray[_curBackupPos];
|
|
_imFileData = _imFileDataArray[_curBackupPos];
|
|
_extTable = _extTableArray[_curBackupPos];
|
|
_extHandle = _extHandleArray[_curBackupPos];
|
|
_vm->_global->_inter_variables = _variablesArray[_curBackupPos];
|
|
_vm->_global->_inter_variablesSizes = _variablesSizesArray[_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->_cursorXDeltaVar = _cursorXDeltaArray[_curBackupPos];
|
|
_vm->_draw->_cursorYDeltaVar = _cursorYDeltaArray[_curBackupPos];
|
|
_totTextData = _totTextDataArray[_curBackupPos];
|
|
_totFileData = _totFileDataArray[_curBackupPos];
|
|
_totResourceTable = _totResourceTableArray[_curBackupPos];
|
|
_extTable = _extTableArray[_curBackupPos];
|
|
_extHandle = _extHandleArray[_curBackupPos];
|
|
_imFileData = _imFileDataArray[_curBackupPos];
|
|
_vm->_global->_inter_variables = _variablesArray[_curBackupPos];
|
|
_vm->_global->_inter_variablesSizes = _variablesSizesArray[_curBackupPos];
|
|
strcpy(_curTotFile, _curTotFileArray[_curBackupPos]);
|
|
strcpy(_curExtFile, _curTotFile);
|
|
_curExtFile[strlen(_curExtFile)-4] = '\0';
|
|
strcat(_curExtFile, ".EXT");
|
|
}
|
|
|
|
int16 Game::openLocTextFile(char *locTextFile, int language) {
|
|
int n;
|
|
|
|
n = strlen(locTextFile);
|
|
if (n < 4)
|
|
return -1;
|
|
|
|
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->openData(locTextFile);
|
|
}
|
|
|
|
char *Game::loadLocTexts(void) {
|
|
char locTextFile[20];
|
|
int16 handle;
|
|
int i;
|
|
|
|
strcpy(locTextFile, _curTotFile);
|
|
|
|
handle = openLocTextFile(locTextFile, _vm->_global->_language);
|
|
if ((handle < 0) && !scumm_stricmp(_vm->_game->_curTotFile, _vm->_startTot0)) {
|
|
warning("Your game version doesn't support the requested language, using the first one available");
|
|
for (i = 0; i < 10; i++) {
|
|
handle = openLocTextFile(locTextFile, i);
|
|
if (handle >= 0) {
|
|
_vm->_global->_language = i;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (handle >= 0) {
|
|
_vm->_dataio->closeData(handle);
|
|
return _vm->_dataio->getData(locTextFile);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void Game::setCollisions(void) {
|
|
char *savedIP;
|
|
int16 left;
|
|
int16 top;
|
|
int16 width;
|
|
int16 height;
|
|
Collision *collArea;
|
|
|
|
for (collArea = _collisionAreas; collArea->left != -1; collArea++) {
|
|
if (((collArea->id & 0xC000) != 0x8000) || (collArea->field_12 == 0))
|
|
continue;
|
|
|
|
savedIP = _vm->_global->_inter_execPtr;
|
|
_vm->_global->_inter_execPtr = _totFileData + collArea->field_12;
|
|
left = _vm->_parse->parseValExpr();
|
|
top = _vm->_parse->parseValExpr();
|
|
width = _vm->_parse->parseValExpr();
|
|
height = _vm->_parse->parseValExpr();
|
|
if ((_vm->_draw->_renderFlags & 8) && (left != -1)) {
|
|
left += _vm->_draw->_backDeltaX;
|
|
top += _vm->_draw->_backDeltaY;
|
|
}
|
|
if (_vm->_draw->_word_2E8E2 != 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(int16 offset) {
|
|
char *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);
|
|
}
|
|
}
|
|
|
|
Snd::SoundDesc *Game::loadSND(const char *path, int8 arg_4) {
|
|
Snd::SoundDesc *soundDesc;
|
|
uint32 dsize;
|
|
char *data;
|
|
char *dataPtr;
|
|
|
|
soundDesc = new Snd::SoundDesc;
|
|
|
|
data = _vm->_dataio->getData(path);
|
|
if (data == 0) {
|
|
delete soundDesc;
|
|
return 0;
|
|
}
|
|
soundDesc->data = data;
|
|
soundDesc->flag = *data & 0x7F;
|
|
if (*data == 0)
|
|
soundDesc->flag = 8;
|
|
dataPtr = data + 4;
|
|
|
|
WRITE_LE_UINT16(dataPtr, READ_BE_UINT16(dataPtr));
|
|
|
|
WRITE_LE_UINT32(data, (READ_LE_UINT32(data) >> 24) + ((READ_LE_UINT16(data) & 0xFF00) << 8) + ((READ_LE_UINT16(data + 2) & 0xFF) >> 8));
|
|
|
|
soundDesc->size = READ_LE_UINT32(data);
|
|
dsize = _vm->_dataio->getDataSize(path) - 6;
|
|
if (dsize > soundDesc->size)
|
|
soundDesc->size = dsize;
|
|
|
|
soundDesc->frequency = READ_LE_UINT16(dataPtr);
|
|
soundDesc->data += 6;
|
|
soundDesc->timerTicks = 1193180 / READ_LE_UINT16(dataPtr);
|
|
|
|
if (arg_4 & 2)
|
|
arg_4 |= 1;
|
|
if ((soundDesc->frequency < 4700) && (arg_4 & 1))
|
|
arg_4 &= 0xFE;
|
|
|
|
if (arg_4 & 1) {
|
|
if ((_vm->_global->_soundFlags & BLASTER_FLAG) || (_vm->_global->_soundFlags & PROAUDIO_FLAG)) {
|
|
}
|
|
}
|
|
|
|
return soundDesc;
|
|
}
|
|
|
|
int8 Game::openImd(const char *path, int16 x, int16 y, int16 repeat, int16 flags) {
|
|
int i;
|
|
int j;
|
|
const char *src;
|
|
byte *vidMem;
|
|
Video::SurfaceDesc *surfDesc;
|
|
|
|
if (path[0] != 0) {
|
|
if (_imdFile == 0)
|
|
_curImdFile[0] = 0;
|
|
|
|
src = strrchr(path, '\\');
|
|
src = src == 0 ? path : src+1;
|
|
|
|
if (strcmp(_curImdFile, src) != 0) {
|
|
closeImd();
|
|
_imdFile = loadImdFile(path, 0, 2);
|
|
if (_imdFile == 0)
|
|
return 0;
|
|
|
|
_imdX = _imdFile->x;
|
|
_imdY = _imdFile->y;
|
|
strcpy(_curImdFile, src);
|
|
_imdFrameData = new byte[_imdFrameDataSize + 1000];
|
|
_imdVidBuffer = new byte[_imdVidBufferSize + 1000];
|
|
memset(_imdFrameData, 0, _imdFrameDataSize + 1000);
|
|
memset(_imdVidBuffer, 0, _imdVidBufferSize + 1000);
|
|
|
|
if (_vm->_global->_videoMode == 0x14) {
|
|
_byte_2FC83 = (flags & 0x80) ? 1 : 0;
|
|
if (!(_imdFile->field_E & 0x100) || (_imdFile->field_E & 0x2000)) {
|
|
setImdXY(_imdFile, 0, 0);
|
|
_imdFile->surfDesc =
|
|
_vm->_video->initSurfDesc(0x13, _imdFile->width, _imdFile->height, 0);
|
|
} else {
|
|
if (_byte_2FC82 == 0)
|
|
_imdFile->surfDesc = _vm->_draw->_spritesArray[21];
|
|
else
|
|
_imdFile->surfDesc = _vm->_draw->_spritesArray[20];
|
|
if ((x != -1) || (y != -1)) {
|
|
_imdX = x != -1 ? x : _imdX;
|
|
_imdY = y != -1 ? y : _imdY;
|
|
setImdXY(_imdFile, _imdX, _imdY);
|
|
}
|
|
}
|
|
if (flags & 0x40) {
|
|
_imdX = x != -1 ? x : _imdX;
|
|
_imdY = y != -1 ? y : _imdY;
|
|
if ((_imdFile->surfDesc->vidMode & 0x7F) == 0x14) {
|
|
surfDesc = _vm->_video->initSurfDesc(0x13, _imdFile->width, _imdFile->height, 0);
|
|
_vm->_video->drawSprite(_vm->_draw->_spritesArray[21], surfDesc, _imdX, _imdY,
|
|
_imdX + _imdFile->width - 1, _imdY + _imdFile->height - 1, 0, 0, 0);
|
|
vidMem = _imdFile->surfDesc->vidPtr;
|
|
for (i = 0; i < _imdFile->height; i++)
|
|
for (j = 0; j < _imdFile->width; j++, vidMem++) {
|
|
*(vidMem) = *(surfDesc->vidPtr
|
|
+ (j / 4)
|
|
+ (surfDesc->width / 4 * i)
|
|
+ (surfDesc->reserved2 * (j & 3)));
|
|
}
|
|
_vm->_video->freeSurfDesc(surfDesc);
|
|
}
|
|
}
|
|
} else {
|
|
if ((x != -1) || (y != -1)) {
|
|
_imdX = x != -1 ? x : _imdX;
|
|
_imdY = y != -1 ? y : _imdY;
|
|
setImdXY(_imdFile, _imdX, _imdY);
|
|
}
|
|
_byte_2FC83 = (flags & 0x80) ? 1 : 0;
|
|
if (_byte_2FC83 == 0)
|
|
_imdFile->surfDesc = _vm->_draw->_spritesArray[21];
|
|
else
|
|
_imdFile->surfDesc = _vm->_draw->_spritesArray[20];
|
|
}
|
|
}
|
|
}
|
|
|
|
if (_imdFile == 0)
|
|
return 0;
|
|
|
|
if (repeat == -1) {
|
|
closeImd();
|
|
return 0;
|
|
}
|
|
|
|
_imdX = x != -1 ? x : _imdX;
|
|
_imdY = y != -1 ? y : _imdY;
|
|
|
|
WRITE_VAR(7, _imdFile->framesCount);
|
|
|
|
return 1;
|
|
}
|
|
|
|
void Game::closeImd(void) {
|
|
if (_imdFile == 0)
|
|
return;
|
|
|
|
if ((_imdFile->surfDesc != _vm->_draw->_spritesArray[20]) &&
|
|
(_imdFile->surfDesc != _vm->_draw->_spritesArray[21]))
|
|
_vm->_video->freeSurfDesc(_imdFile->surfDesc);
|
|
|
|
finishImd(_imdFile);
|
|
|
|
delete[] _imdFrameData;
|
|
delete[] _imdVidBuffer;
|
|
_imdFrameData = 0;
|
|
_imdVidBuffer = 0;
|
|
|
|
_imdFile = 0;
|
|
}
|
|
|
|
void Game::finishImd(Game::Imd *imdPtr) {
|
|
if (imdPtr == 0)
|
|
return;
|
|
|
|
/*
|
|
if (dword_31345 != 0) {
|
|
_vm->_sound->stopSound(0);
|
|
dword_31345 = 0;
|
|
delete off_31461;
|
|
byte_31344 = 0;
|
|
}
|
|
*/
|
|
|
|
_vm->_dataio->closeData(imdPtr->fileHandle);
|
|
|
|
if (imdPtr->frameCoords != 0)
|
|
delete[] imdPtr->frameCoords;
|
|
if (imdPtr->palette != 0)
|
|
delete[] imdPtr->palette;
|
|
if (imdPtr->framesPos != 0)
|
|
delete[] imdPtr->framesPos;
|
|
|
|
delete imdPtr;
|
|
imdPtr = 0;
|
|
}
|
|
|
|
// flagsBit: 0 = read and set palette
|
|
// 1 = read palette
|
|
Game::Imd *Game::loadImdFile(const char *path, Video::SurfaceDesc *surfDesc, int8 flags) {
|
|
int i;
|
|
Imd *imdPtr;
|
|
int16 handle;
|
|
int16 setAllPalBak;
|
|
char buf[18];
|
|
Video::Color *palBak;
|
|
|
|
int32 byte_31449 = 0;
|
|
int32 byte_3144D = 0;
|
|
|
|
buf[0] = 0;
|
|
strcpy(buf, path);
|
|
strcat(buf, ".IMD");
|
|
|
|
handle = _vm->_dataio->openData(buf);
|
|
|
|
if (handle < 0) {
|
|
warning("Can't open IMD \"%s\"", buf);
|
|
return 0;
|
|
}
|
|
|
|
imdPtr = new Imd;
|
|
memset(imdPtr, 0, sizeof(Imd));
|
|
|
|
imdPtr->palette = 0;
|
|
|
|
_vm->_dataio->readData(handle, buf, 18);
|
|
|
|
// "fileHandle" holds the major version while loading
|
|
imdPtr->fileHandle = READ_LE_UINT16(buf);
|
|
imdPtr->verMin = READ_LE_UINT16(buf + 2);
|
|
imdPtr->framesCount = READ_LE_UINT16(buf + 4);
|
|
imdPtr->x = READ_LE_UINT16(buf + 6);
|
|
imdPtr->y = READ_LE_UINT16(buf + 8);
|
|
imdPtr->width = READ_LE_UINT16(buf + 10);
|
|
imdPtr->height = READ_LE_UINT16(buf + 12);
|
|
imdPtr->field_E = READ_LE_UINT16(buf + 14);
|
|
imdPtr->curFrame = READ_LE_UINT16(buf + 16);
|
|
|
|
if (imdPtr->fileHandle != 0)
|
|
imdPtr->verMin = 0;
|
|
|
|
if ((imdPtr->verMin & 0xFF) < 2) {
|
|
warning("IMD version incorrect (%d,%d)", imdPtr->fileHandle, imdPtr->verMin);
|
|
_vm->_dataio->closeData(handle);
|
|
delete imdPtr;
|
|
return 0;
|
|
}
|
|
|
|
imdPtr->surfDesc = surfDesc;
|
|
imdPtr->framesPos = 0;
|
|
imdPtr->firstFramePos = imdPtr->curFrame;
|
|
|
|
if (flags & 3) {
|
|
imdPtr->palette = new Video::Color[256];
|
|
_vm->_dataio->readData(handle, (char *) imdPtr->palette, 768);
|
|
} else {
|
|
_vm->_dataio->seekData(handle, 768, 1);
|
|
imdPtr->palette = 0;
|
|
}
|
|
if ((flags & 3) == 1) {
|
|
palBak = _vm->_global->_pPaletteDesc->vgaPal;
|
|
setAllPalBak = _vm->_global->_setAllPalette;
|
|
_vm->_global->_pPaletteDesc->vgaPal = imdPtr->palette;
|
|
_vm->_global->_setAllPalette = 1;
|
|
_vm->_video->setFullPalette(_vm->_global->_pPaletteDesc);
|
|
_vm->_global->_setAllPalette = setAllPalBak;
|
|
_vm->_global->_pPaletteDesc->vgaPal = palBak;
|
|
}
|
|
|
|
if ((imdPtr->verMin & 0xFF) >= 3) {
|
|
_vm->_dataio->readData(handle, buf, 2);
|
|
imdPtr->stdX = READ_LE_UINT16(buf);
|
|
if (imdPtr->stdX > 1) {
|
|
warning("IMD ListI incorrect (%d)", imdPtr->stdX);
|
|
_vm->_dataio->closeData(handle);
|
|
delete imdPtr;
|
|
return 0;
|
|
}
|
|
if (imdPtr->stdX != 0) {
|
|
_vm->_dataio->readData(handle, buf, 8);
|
|
imdPtr->stdX = READ_LE_UINT16(buf);
|
|
imdPtr->stdY = READ_LE_UINT16(buf + 2);
|
|
imdPtr->stdWidth = READ_LE_UINT16(buf + 4);
|
|
imdPtr->stdHeight = READ_LE_UINT16(buf + 6);
|
|
} else
|
|
imdPtr->stdX = -1;
|
|
} else
|
|
imdPtr->stdX = -1;
|
|
|
|
if ((imdPtr->verMin & 0xFF) >= 4) {
|
|
_vm->_dataio->readData(handle, buf, 4);
|
|
byte_31449 = READ_LE_UINT32(buf);
|
|
imdPtr->framesPos = byte_31449 == 0 ? 0 : new int32[imdPtr->framesCount];
|
|
} else
|
|
imdPtr->framesPos = 0;
|
|
|
|
if (imdPtr->verMin & 0x8000) {
|
|
_vm->_dataio->readData(handle, buf, 4);
|
|
byte_3144D = READ_LE_UINT32(buf);
|
|
}
|
|
|
|
if (imdPtr->verMin & 0x4000) {
|
|
// loc_29C4F
|
|
error("GOB2 Stub! loadImdFile, imdPtr->verMin & 0x4000");
|
|
// Sound stuff, I presume...
|
|
}
|
|
|
|
if (imdPtr->verMin & 0x2000) {
|
|
_vm->_dataio->readData(handle, buf, 4);
|
|
imdPtr->frameDataSize = READ_LE_UINT16(buf);
|
|
imdPtr->vidBufferSize = READ_LE_UINT16(buf + 2);
|
|
} else {
|
|
imdPtr->frameDataSize = imdPtr->width * imdPtr->height + 1000;
|
|
imdPtr->vidBufferSize = imdPtr->width * imdPtr->height + 1000;
|
|
}
|
|
|
|
if (imdPtr->framesPos != 0) {
|
|
_vm->_dataio->seekData(handle, byte_31449, 0);
|
|
for (i = 0; i < imdPtr->framesCount; i++) {
|
|
_vm->_dataio->readData(handle, buf, 4);
|
|
imdPtr->framesPos[i] = READ_LE_UINT32(buf);
|
|
}
|
|
}
|
|
|
|
if (imdPtr->verMin & 0x8000) {
|
|
_vm->_dataio->seekData(handle, byte_3144D, 0);
|
|
imdPtr->frameCoords = new ImdCoord[imdPtr->framesCount];
|
|
for (i = 0; i < imdPtr->framesCount; i++) {
|
|
_vm->_dataio->readData(handle, buf, 8);
|
|
imdPtr->frameCoords[i].left = READ_LE_UINT16(buf);
|
|
imdPtr->frameCoords[i].top = READ_LE_UINT16(buf + 2);
|
|
imdPtr->frameCoords[i].right = READ_LE_UINT16(buf + 4);
|
|
imdPtr->frameCoords[i].bottom = READ_LE_UINT16(buf + 6);
|
|
}
|
|
} else
|
|
imdPtr->frameCoords = 0;
|
|
|
|
_vm->_dataio->seekData(handle, imdPtr->firstFramePos, 0);
|
|
imdPtr->curFrame = 0;
|
|
imdPtr->fileHandle = handle;
|
|
imdPtr->filePos = imdPtr->firstFramePos;
|
|
_imdFrameDataSize = imdPtr->frameDataSize;
|
|
_imdVidBufferSize = imdPtr->vidBufferSize;
|
|
if (flags & 0x80) {
|
|
imdPtr->verMin |= 0x1000;
|
|
warning("GOB2 Stub! loadImdFile(), flags & 0x80");
|
|
}
|
|
|
|
return imdPtr;
|
|
}
|
|
|
|
void Game::setImdXY(Game::Imd *imdPtr, int16 x, int16 y) {
|
|
int i;
|
|
|
|
if (imdPtr->stdX != -1) {
|
|
imdPtr->stdX = imdPtr->stdX - imdPtr->x + x;
|
|
imdPtr->stdY = imdPtr->stdY - imdPtr->y + y;
|
|
}
|
|
|
|
if (imdPtr->frameCoords != 0) {
|
|
for (i = 0; i < imdPtr->framesCount; i++) {
|
|
imdPtr->frameCoords[i].left -= imdPtr->frameCoords[i].left - imdPtr->x + x;
|
|
imdPtr->frameCoords[i].top -= imdPtr->frameCoords[i].top - imdPtr->y + y;
|
|
imdPtr->frameCoords[i].right -= imdPtr->frameCoords[i].right - imdPtr->x + x;
|
|
imdPtr->frameCoords[i].bottom -= imdPtr->frameCoords[i].bottom - imdPtr->y + y;
|
|
}
|
|
}
|
|
|
|
imdPtr->x = x;
|
|
imdPtr->y = y;
|
|
}
|
|
|
|
void Game::playImd(int16 frame, int16 arg_2, int16 arg_4, int16 arg_6, int16 arg_8, int16 lastFrame) {
|
|
int16 var_1;
|
|
int16 var_4 = 0;
|
|
byte *vidMemBak;
|
|
Video::SurfaceDesc *surfDescBak;
|
|
Video::SurfaceDesc frontSurfBak;
|
|
|
|
int8 byte_31344 = 0;
|
|
|
|
if ((frame < 0) || (frame > lastFrame))
|
|
return;
|
|
|
|
if ((frame == arg_8) || ((frame == lastFrame) && (arg_2 == 8))) { // loc_1C3F0
|
|
var_1 = 1;
|
|
_vm->_draw->_applyPal = 0;
|
|
if (arg_2 >= 4) {
|
|
if (arg_4 != -1)
|
|
memcpy( ((char *) (_vm->_global->_pPaletteDesc->vgaPal)) + arg_4 * 3,
|
|
((char *) (_imdFile->palette)) + arg_4 * 3, (arg_6 - arg_4 + 1) * 3);
|
|
else
|
|
memcpy((char *) _vm->_global->_pPaletteDesc->vgaPal, (char *) _imdFile->palette, 768);
|
|
}
|
|
} else
|
|
var_1 = 0;
|
|
|
|
if ((var_1 == 1) && (arg_2 == 8) && (_byte_2FC83 != 0))
|
|
_vm->_video->setFullPalette(_vm->_global->_pPaletteDesc);
|
|
|
|
if (_imdFile->surfDesc->vidMode == 0x14) {
|
|
if ((_byte_2FC82 != 0) && (_word_2FC80 == _vm->_draw->_spritesArray[20]->vidPtr)) {
|
|
vidMemBak = _vm->_draw->_spritesArray[20]->vidPtr;
|
|
_vm->_draw->_spritesArray[20]->vidPtr = _vm->_draw->_spritesArray[21]->vidPtr;
|
|
var_4 = viewImd(_imdFile, frame);
|
|
_vm->_draw->_spritesArray[20]->vidPtr = vidMemBak;
|
|
} else
|
|
var_4 = viewImd(_imdFile, frame);
|
|
if (_byte_2FC82 == 0) {
|
|
if ((_imdFile->frameCoords == 0) || (_imdFile->frameCoords[frame].left == -1))
|
|
_vm->_draw->invalidateRect(_imdX, _imdY,
|
|
_imdX + _imdFile->width - 1, _imdY + _imdFile->height - 1);
|
|
else
|
|
_vm->_draw->invalidateRect(_imdFile->frameCoords[frame].left,
|
|
_imdFile->frameCoords[frame].top, _imdFile->frameCoords[frame].right,
|
|
_imdFile->frameCoords[frame].bottom);
|
|
}
|
|
} else {
|
|
if ((_imdFile->field_E & 0x100) && (_vm->_global->_videoMode == 0x14) &&
|
|
(_byte_2FC82 != 0) && (sub_2C825(_imdFile) & 0x8000) && (_byte_2FC83 == 0)) {
|
|
surfDescBak = _imdFile->surfDesc;
|
|
if (_word_2FC80 == _vm->_draw->_spritesArray[20]->vidPtr)
|
|
_imdFile->surfDesc = _vm->_draw->_spritesArray[21];
|
|
else
|
|
_imdFile->surfDesc = _vm->_draw->_spritesArray[20];
|
|
setImdXY(_imdFile, _imdX, _imdY);
|
|
var_4 = viewImd(_imdFile, frame);
|
|
_imdFile->surfDesc = surfDescBak;
|
|
setImdXY(_imdFile, 0, 0);
|
|
} else {
|
|
var_4 = viewImd(_imdFile, frame);
|
|
if (!(var_4 & 0x800)) {
|
|
if (_byte_2FC83 == 0) {
|
|
if (_vm->_global->_videoMode == 0x14) {
|
|
if (_byte_2FC82 == 0) {
|
|
memcpy((char *) &frontSurfBak, (char *) &_vm->_draw->_frontSurface,
|
|
sizeof(Video::SurfaceDesc));
|
|
memcpy((char *) &_vm->_draw->_frontSurface, (char *) &_vm->_draw->_spritesArray[21],
|
|
sizeof(Video::SurfaceDesc));
|
|
imdDrawFrame(_imdFile, frame, _imdX, _imdY);
|
|
memcpy((char *) &_vm->_draw->_frontSurface, (char *) &frontSurfBak,
|
|
sizeof(Video::SurfaceDesc));
|
|
if ((_imdFile->frameCoords == 0) || (_imdFile->frameCoords[frame].left == -1))
|
|
_vm->_draw->invalidateRect(_imdX, _imdY, _imdX + _imdFile->width - 1,
|
|
_imdY + _imdFile->height - 1);
|
|
else
|
|
_vm->_draw->invalidateRect(_imdFile->frameCoords[frame].left,
|
|
_imdFile->frameCoords[frame].top, _imdFile->frameCoords[frame].right,
|
|
_imdFile->frameCoords[frame].bottom);
|
|
} else {
|
|
if (_word_2FC80 == _vm->_draw->_spritesArray[20]->vidPtr) { // loc_1C68D
|
|
memcpy((char *) &frontSurfBak, (char *) &_vm->_draw->_frontSurface,
|
|
sizeof(Video::SurfaceDesc));
|
|
memcpy((char *) &_vm->_draw->_frontSurface, (char *) &_vm->_draw->_spritesArray[21],
|
|
sizeof(Video::SurfaceDesc));
|
|
imdDrawFrame(_imdFile, frame, _imdX, _imdY);
|
|
memcpy((char *) &_vm->_draw->_frontSurface, (char *) &frontSurfBak,
|
|
sizeof(Video::SurfaceDesc));
|
|
} else
|
|
imdDrawFrame(_imdFile, frame, _imdX, _imdY);
|
|
}
|
|
} else {
|
|
if ((_imdFile->frameCoords == 0) || (_imdFile->frameCoords[frame].left == -1))
|
|
_vm->_draw->invalidateRect(_imdX, _imdY, _imdX + _imdFile->width - 1,
|
|
_imdY + _imdFile->height - 1);
|
|
else
|
|
_vm->_draw->invalidateRect(_imdFile->frameCoords[frame].left,
|
|
_imdFile->frameCoords[frame].top, _imdFile->frameCoords[frame].right,
|
|
_imdFile->frameCoords[frame].bottom);
|
|
}
|
|
} else
|
|
if (_vm->_global->_videoMode == 0x14)
|
|
imdDrawFrame(_imdFile, frame, _imdX, _imdY);
|
|
}
|
|
}
|
|
}
|
|
|
|
if ((var_1 != 0) && (arg_2 == 16)) {
|
|
if ((_vm->_draw->_spritesArray[20] != _vm->_draw->_spritesArray[21]) && (_byte_2FC83 == 0))
|
|
_vm->_video->drawSprite(_vm->_draw->_spritesArray[21],
|
|
_vm->_draw->_spritesArray[20], 0, 0,
|
|
_vm->_draw->_spritesArray[21]->width - 1,
|
|
_vm->_draw->_spritesArray[21]->height - 1, 0, 0, 0);
|
|
_vm->_palanim->fade(_vm->_global->_pPaletteDesc, -2, 0);
|
|
_vm->_draw->_noInvalidated = 1;
|
|
}
|
|
if ((var_1 != 0) && (arg_2 == 8) && (_byte_2FC83 == 0))
|
|
_vm->_video->setFullPalette(_vm->_global->_pPaletteDesc);
|
|
|
|
if (!(var_4 & 0x800)) {
|
|
if (_vm->_draw->_cursorIndex == -1) {
|
|
if (_byte_2FC82 != 0) {
|
|
if (_word_2FC80 == _vm->_draw->_spritesArray[20]->vidPtr)
|
|
_word_2FC80 = _vm->_draw->_spritesArray[21]->vidPtr;
|
|
else
|
|
_word_2FC80 = _vm->_draw->_spritesArray[20]->vidPtr;
|
|
warning("GOB2 Stub! sub_1BC3A(_word_2FC80);");
|
|
} else
|
|
_vm->_draw->blitInvalidated();
|
|
} else
|
|
_vm->_draw->animateCursor(-1);
|
|
}
|
|
|
|
if ((var_1 != 0) && ((arg_2 == 2) || (arg_2 == 4)))
|
|
_vm->_palanim->fade(_vm->_global->_pPaletteDesc, -2, 0);
|
|
|
|
// To allow quitting, etc. during IMDs
|
|
_vm->_util->processInput();
|
|
if (_vm->_quitRequested)
|
|
return;
|
|
|
|
if (byte_31344 != 2) {
|
|
if (var_4 & 0x800) {
|
|
if (_dword_2F2B6 == 0)
|
|
_vm->_util->delay(30);
|
|
else {
|
|
_dword_2F2B6 -= 30;
|
|
if (_dword_2F2B6 < 0)
|
|
_dword_2F2B6 = 0;
|
|
}
|
|
} else
|
|
_vm->_util->waitEndFrame();
|
|
}
|
|
_vm->_inter->animPalette();
|
|
}
|
|
|
|
int16 Game::viewImd(Game::Imd *imdPtr, int16 frame) {
|
|
int16 x;
|
|
int16 y;
|
|
int16 width;
|
|
int16 height;
|
|
int16 retVal;
|
|
uint32 tmp;
|
|
char buf[4];
|
|
|
|
int8 var_4;
|
|
int32 var_12 = 0;
|
|
|
|
// .---
|
|
int16 word_31451 = 0;
|
|
int8 byte_31344 = 0;
|
|
int8 byte_2DA60 = 0;
|
|
int16 word_2DA61 = -1;
|
|
// '---
|
|
|
|
word_31451 = 0;
|
|
|
|
if (imdPtr == 0)
|
|
return (int16)0x8000;
|
|
|
|
retVal = 0;
|
|
var_4 = 0;
|
|
|
|
if (frame != imdPtr->curFrame) {
|
|
retVal |= 0x2000;
|
|
if (frame == 0)
|
|
imdPtr->filePos = imdPtr->firstFramePos;
|
|
else if (frame == 1) {
|
|
imdPtr->filePos = imdPtr->firstFramePos;
|
|
_vm->_dataio->seekData(imdPtr->fileHandle, imdPtr->filePos, 0);
|
|
_vm->_dataio->readData(imdPtr->fileHandle, buf, 2);
|
|
tmp = READ_LE_UINT16(buf);
|
|
imdPtr->filePos += tmp + 4;
|
|
} else if (imdPtr->framesPos != 0)
|
|
imdPtr->filePos = imdPtr->framesPos[frame];
|
|
else
|
|
error("Image %d innaccessible in IMD", frame);
|
|
imdPtr->curFrame = frame;
|
|
_vm->_dataio->seekData(imdPtr->fileHandle, imdPtr->filePos, 0);
|
|
}
|
|
|
|
x = imdPtr->x;
|
|
y = imdPtr->y;
|
|
width = imdPtr->width;
|
|
height = imdPtr->height;
|
|
|
|
do {
|
|
if (frame != 0) {
|
|
if (imdPtr->stdX != -1) {
|
|
imdPtr->x = imdPtr->stdX;
|
|
imdPtr->y = imdPtr->stdY;
|
|
imdPtr->width = imdPtr->stdWidth;
|
|
imdPtr->height = imdPtr->stdHeight;
|
|
retVal |= 0x1000;
|
|
}
|
|
if ((imdPtr->frameCoords != 0) && (imdPtr->frameCoords[frame].left != -1)) {
|
|
var_4 |= 0x400;
|
|
imdPtr->x = imdPtr->frameCoords[frame].left;
|
|
imdPtr->y = imdPtr->frameCoords[frame].top;
|
|
imdPtr->width = imdPtr->frameCoords[frame].right - imdPtr->x + 1;
|
|
imdPtr->height = imdPtr->frameCoords[frame].bottom - imdPtr->y + 1;
|
|
}
|
|
}
|
|
|
|
_vm->_dataio->readData(imdPtr->fileHandle, buf, 2);
|
|
tmp = READ_LE_UINT16(buf);
|
|
|
|
imdPtr->filePos += 2;
|
|
|
|
if ((tmp & 0xFFF8) == 0xFFF0) {
|
|
if (tmp == 0xFFF0) {
|
|
_vm->_dataio->readData(imdPtr->fileHandle, buf, 2);
|
|
tmp = READ_LE_UINT16(buf);
|
|
if (var_4 == 0)
|
|
word_31451 = tmp;
|
|
_vm->_dataio->readData(imdPtr->fileHandle, buf, 2);
|
|
tmp = READ_LE_UINT16(buf);
|
|
imdPtr->filePos += 4;
|
|
} else if (tmp == 0xFFF1) {
|
|
retVal = (int16)0x8000;
|
|
continue;
|
|
} else if (tmp == 0xFFF2) {
|
|
_vm->_dataio->readData(imdPtr->fileHandle, buf, 2);
|
|
tmp = READ_LE_UINT16(buf);
|
|
imdPtr->filePos += 2;
|
|
_vm->_dataio->seekData(imdPtr->fileHandle, tmp, 1);
|
|
imdPtr->filePos += tmp;
|
|
retVal = (int16)0x8000;
|
|
continue;
|
|
} else if (tmp == 0xFFF3) {
|
|
_vm->_dataio->readData(imdPtr->fileHandle, buf, 4);
|
|
tmp = READ_LE_UINT32(buf);
|
|
imdPtr->filePos += 4;
|
|
_vm->_dataio->seekData(imdPtr->fileHandle, tmp, 1);
|
|
imdPtr->filePos += tmp;
|
|
retVal = (int16)0x8000;
|
|
continue;
|
|
}
|
|
}
|
|
if (byte_31344 != 0) {
|
|
if ((var_4 == 0) && (_vm->_global->_soundFlags & 0x14) && (byte_31344 == 2)) { // loc_2A503
|
|
var_12 = _vm->_util->getTimeKey();
|
|
warning("GOB2 Stub! viewImd, IMD sound stuff");
|
|
}
|
|
}
|
|
var_4 = 0;
|
|
if (tmp == 0xFFFD) {
|
|
_vm->_dataio->readData(imdPtr->fileHandle, buf, 2);
|
|
frame = READ_LE_UINT16(buf);
|
|
if ((imdPtr->framesPos != 0) && (byte_2DA60 == 0)) {
|
|
word_2DA61 = frame;
|
|
imdPtr->filePos = imdPtr->framesPos[frame];
|
|
_vm->_dataio->seekData(imdPtr->fileHandle, imdPtr->filePos, 0);
|
|
var_4 = 1;
|
|
retVal |= 0x200;
|
|
imdPtr->curFrame = frame;
|
|
} else
|
|
imdPtr->filePos += 2;
|
|
continue;
|
|
}
|
|
if (tmp != 0) {
|
|
imdPtr->filePos += tmp + 2;
|
|
if (byte_2DA60 != 0) {
|
|
_vm->_dataio->seekData(imdPtr->fileHandle, tmp + 2, 1);
|
|
} else {
|
|
_vm->_dataio->readData(imdPtr->fileHandle, (char *) _imdFrameData, tmp + 2);
|
|
retVal |= *_imdFrameData;
|
|
if (imdPtr->surfDesc == 0)
|
|
continue;
|
|
if (imdPtr->surfDesc->vidMode != 0x14)
|
|
imdRenderFrame(imdPtr);
|
|
else
|
|
warning("GOB2 Stub! viedImd, sub_2C69A(imdPtr);");
|
|
}
|
|
} else
|
|
retVal |= 0x800;
|
|
} while (var_4 != 0);
|
|
|
|
if (byte_2DA60 != 0) {
|
|
byte_2DA60 = 0;
|
|
retVal |= 0x100;
|
|
}
|
|
|
|
imdPtr->x = x;
|
|
imdPtr->y = y;
|
|
imdPtr->width = width;
|
|
imdPtr->height = height;
|
|
imdPtr->curFrame++;
|
|
|
|
return retVal;
|
|
}
|
|
|
|
void Game::imdDrawFrame(Imd *imdPtr, int16 frame, int16 x, int16 y) {
|
|
// In the original asm, "sub_2C348" is called instead of Video::drawSprite();
|
|
// it basically just blits.
|
|
|
|
if (frame == 0)
|
|
_vm->_video->drawSprite(imdPtr->surfDesc, _vm->_draw->_frontSurface, 0, 0,
|
|
imdPtr->width - 1, imdPtr->height - 1, x, y, 1);
|
|
else if ((imdPtr->frameCoords != 0) && (imdPtr->frameCoords[frame].left != -1))
|
|
_vm->_video->drawSprite(imdPtr->surfDesc, _vm->_draw->_frontSurface,
|
|
imdPtr->frameCoords[frame].left, imdPtr->frameCoords[frame].top,
|
|
imdPtr->frameCoords[frame].right, imdPtr->frameCoords[frame].bottom,
|
|
imdPtr->frameCoords[frame].left, imdPtr->frameCoords[frame].top, 1);
|
|
else if (imdPtr->stdX != -1)
|
|
_vm->_video->drawSprite(imdPtr->surfDesc, _vm->_draw->_frontSurface,
|
|
imdPtr->stdX, imdPtr->stdY, imdPtr->stdX + imdPtr->stdWidth - 1,
|
|
imdPtr->stdY + imdPtr->stdHeight - 1, x + imdPtr->stdX,
|
|
y + imdPtr->stdY, 1);
|
|
else
|
|
_vm->_video->drawSprite(imdPtr->surfDesc, _vm->_draw->_frontSurface, 0, 0,
|
|
imdPtr->width - 1, imdPtr->height - 1, x, y, 0);
|
|
}
|
|
|
|
void Game::imdRenderFrame(Imd *imdPtr) {
|
|
int i;
|
|
int16 imdX;
|
|
int16 imdY;
|
|
int16 imdW;
|
|
int16 imdH;
|
|
int16 sW;
|
|
uint16 pixCount, pixWritten;
|
|
uint8 type;
|
|
byte *imdVidMem;
|
|
byte *imdVidMemBak;
|
|
byte *dataPtr = 0;
|
|
byte *srcPtr = 0;
|
|
byte *srcPtrBak = 0;
|
|
|
|
dataPtr = (byte *) _imdFrameData;
|
|
imdX = imdPtr->x;
|
|
imdY = imdPtr->y;
|
|
imdW = imdPtr->width;
|
|
imdH = imdPtr->height;
|
|
sW = imdPtr->surfDesc->width;
|
|
imdVidMem = imdPtr->surfDesc->vidPtr + sW * imdY + imdX;
|
|
|
|
type = *dataPtr++;
|
|
srcPtr = dataPtr;
|
|
|
|
if (type & 0x10) {
|
|
type ^= 0x10;
|
|
dataPtr++; // => 0x3C8 |_ palette
|
|
dataPtr += 48; // => 0x3C9 | stuff
|
|
}
|
|
|
|
srcPtr = dataPtr;
|
|
if (type & 0x80) {
|
|
srcPtr = (byte *) _imdVidBuffer;
|
|
type &= 0x7F;
|
|
if ((type == 2) && (imdW == sW)) {
|
|
imdFrameUncompressor(imdVidMem, dataPtr);
|
|
return;
|
|
} else
|
|
imdFrameUncompressor(srcPtr, dataPtr);
|
|
}
|
|
|
|
if (type == 2) {
|
|
for (i = 0; i < imdH; i++) {
|
|
memcpy(imdVidMem, srcPtr, imdW);
|
|
srcPtr += imdW;
|
|
imdVidMem += sW;
|
|
}
|
|
} else if (type == 1) {
|
|
imdVidMemBak = imdVidMem;
|
|
for (i = 0; i < imdH; i++) {
|
|
pixWritten = 0;
|
|
while (pixWritten < imdW) {
|
|
pixCount = *srcPtr++;
|
|
if (pixCount & 0x80) {
|
|
pixCount = (pixCount & 0x7F) + 1;
|
|
// Just to be safe
|
|
pixCount = (pixWritten + pixCount) > imdW ? imdW - pixWritten : pixCount;
|
|
pixWritten += pixCount;
|
|
memcpy(imdVidMem, srcPtr, pixCount);
|
|
imdVidMem += pixCount;
|
|
srcPtr += pixCount;
|
|
} else {
|
|
pixCount = (pixCount + 1) % 256;
|
|
pixWritten += pixCount;
|
|
imdVidMem += pixCount;
|
|
}
|
|
}
|
|
imdVidMemBak += sW;
|
|
imdVidMem = imdVidMemBak;
|
|
}
|
|
} else if (type == 0x42) { // loc_2AFC4
|
|
warning("=> type == 0x42");
|
|
} else if ((type & 0xF) == 2) { // loc_2AFEC
|
|
warning("=> (type & 0xF) == 2");
|
|
} else { // loc_2B021
|
|
srcPtrBak = srcPtr;
|
|
for (i = 0; i < imdH; i += 2) {
|
|
pixWritten = 0;
|
|
while (pixWritten < imdW) {
|
|
pixCount = *srcPtr++;
|
|
if (pixCount & 0x80) {
|
|
pixCount = (pixCount & 0x7F) + 1;
|
|
// Just to be safe
|
|
pixCount = (pixWritten + pixCount) > imdW ? imdW - pixWritten : pixCount;
|
|
pixWritten += pixCount;
|
|
memcpy(imdVidMem, srcPtr, pixCount);
|
|
memcpy(imdVidMem + sW, srcPtr, pixCount);
|
|
imdVidMem += pixCount;
|
|
srcPtr += pixCount;
|
|
} else {
|
|
pixCount = (pixCount + 1) % 256;
|
|
pixWritten += pixCount;
|
|
imdVidMem += pixCount;
|
|
}
|
|
}
|
|
srcPtrBak += sW + sW;
|
|
srcPtr = srcPtrBak;
|
|
}
|
|
}
|
|
}
|
|
|
|
void Game::imdFrameUncompressor(byte *dest, byte *src) {
|
|
int i;
|
|
byte buf[4370];
|
|
int16 chunkLength;
|
|
int16 frameLength;
|
|
uint16 bufPos1;
|
|
uint16 bufPos2;
|
|
uint16 tmp;
|
|
uint8 chunkBitField;
|
|
uint8 chunkCount;
|
|
bool mode;
|
|
|
|
frameLength = READ_LE_UINT16(src);
|
|
src += 4;
|
|
bufPos1 = 4078;
|
|
mode = 0; // 275h (jnz +2)
|
|
if ((READ_LE_UINT16(src) == 0x1234) && (READ_LE_UINT16(src + 2) == 0x5678)) {
|
|
src += 4;
|
|
bufPos1 = 273;
|
|
mode = 1; // 123Ch (cmp al, 12h)
|
|
}
|
|
memset(buf, 32, bufPos1);
|
|
chunkCount = 1;
|
|
chunkBitField = 0;
|
|
|
|
while (frameLength > 0) {
|
|
chunkCount--;
|
|
if (chunkCount == 0) {
|
|
tmp = *src++;
|
|
chunkCount = 8;
|
|
chunkBitField = tmp;
|
|
}
|
|
if (chunkBitField % 2) {
|
|
chunkBitField >>= 1;
|
|
buf[bufPos1] = *src;
|
|
*dest++ = *src++;
|
|
bufPos1 = (bufPos1 + 1) % 4096;
|
|
frameLength--;
|
|
continue;
|
|
}
|
|
chunkBitField >>= 1;
|
|
|
|
tmp = READ_LE_UINT16(src);
|
|
src += 2;
|
|
chunkLength = ((tmp & 0xF00) >> 8) + 3;
|
|
|
|
if ((mode && ((chunkLength & 0xFF) == 0x12)) || (!mode && (chunkLength == 0)))
|
|
chunkLength = *src++ + 0x12;
|
|
|
|
bufPos2 = (tmp & 0xFF) + ((tmp >> 4) & 0x0F00);
|
|
if (((tmp + chunkLength) >= 4096) || ((chunkLength + bufPos1) >= 4096)) {
|
|
for (i = 0; i < chunkLength; i++, dest++) {
|
|
*dest = buf[bufPos2];
|
|
buf[bufPos1] = buf[bufPos2];
|
|
bufPos1 = (bufPos1 + 1) % 4096;
|
|
bufPos2 = (bufPos2 + 1) % 4096;
|
|
}
|
|
frameLength -= chunkLength;
|
|
} else if (((tmp + chunkLength) < bufPos1) || ((chunkLength + bufPos1) < bufPos2)) {
|
|
memcpy(dest, buf + bufPos2, chunkLength);
|
|
dest += chunkLength;
|
|
memmove(buf + bufPos1, buf + bufPos2, chunkLength);
|
|
bufPos1 += chunkLength;
|
|
bufPos2 += chunkLength;
|
|
frameLength -= chunkLength;
|
|
} else {
|
|
for (i = 0; i < chunkLength; i++, dest++, bufPos1++, bufPos2++) {
|
|
*dest = buf[bufPos2];
|
|
buf[bufPos1] = buf[bufPos2];
|
|
}
|
|
frameLength -= chunkLength;
|
|
}
|
|
}
|
|
}
|
|
|
|
int16 Game::sub_2C825(Imd *imdPtr) {
|
|
warning("GOB2 Stub! sub_2C825()");
|
|
return 0;
|
|
}
|
|
|
|
} // End of namespace Gob
|