From 853b6e28e9d1fcc45aa477978a44a45bbb4f22d0 Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Mon, 14 Apr 2008 20:20:51 +0000 Subject: Implemented some kyra3 code. svn-id: r31503 --- engines/kyra/animator_v3.cpp | 65 +++++++ engines/kyra/gui.cpp | 3 + engines/kyra/items_v3.cpp | 54 ++++++ engines/kyra/kyra_v3.cpp | 413 ++++++++++++++++++++++++++++++++--------- engines/kyra/kyra_v3.h | 184 +++++++++++++++--- engines/kyra/module.mk | 3 + engines/kyra/script_v3.cpp | 347 ++++++++++++++++++++++++++++++++++ engines/kyra/sound.h | 5 + engines/kyra/sound_digital.cpp | 7 + engines/kyra/staticres.cpp | 17 ++ 10 files changed, 976 insertions(+), 122 deletions(-) create mode 100644 engines/kyra/animator_v3.cpp create mode 100644 engines/kyra/items_v3.cpp create mode 100644 engines/kyra/script_v3.cpp diff --git a/engines/kyra/animator_v3.cpp b/engines/kyra/animator_v3.cpp new file mode 100644 index 0000000000..5278ec78c3 --- /dev/null +++ b/engines/kyra/animator_v3.cpp @@ -0,0 +1,65 @@ +/* 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 "kyra/kyra_v3.h" + +namespace Kyra { + +void KyraEngine_v3::clearAnimObjects() { + debugC(9, kDebugLevelAnimator, "KyraEngine_v3::clearAnimObjects()"); + + for (int i = 0; i < 67; ++i) + _animObjects[i].enabled = false; + + _animObjects[0].index = 0; + _animObjects[0].type = 0; + _animObjects[0].enabled = true; + _animObjects[0].unk8 = 1; + _animObjects[0].flags = 0x800; + _animObjects[0].width = 57; + _animObjects[0].height = 91; + _animObjects[0].width2 = 4; + _animObjects[0].height2 = 10; + + for (int i = 1; i < 17; ++i) { + _animObjects[i].type = 2; + _animObjects[i].flags = 0; + _animObjects[i].enabled = false; + _animObjects[i].needRefresh = 0; + _animObjects[i].unk8 = 1; + } + + for (int i = 17; i <= 66; ++i) { + _animObjects[i].type = 1; + _animObjects[i].unk8 = 1; + _animObjects[i].flags = 0x800; + _animObjects[i].width = 24; + _animObjects[i].height = 20; + _animObjects[i].width2 = 0; + _animObjects[i].height2 = 0; + } +} + +} // end of namespace Kyra diff --git a/engines/kyra/gui.cpp b/engines/kyra/gui.cpp index 170971bc90..5581f636b1 100644 --- a/engines/kyra/gui.cpp +++ b/engines/kyra/gui.cpp @@ -403,6 +403,9 @@ int MainMenu::handle(int dim) { _screen->_charWidth = -2; _screen->setScreenDim(dim); + while (!_screen->isMouseVisible()) + _screen->showMouse(); + int backUpX = _screen->_curDim->sx; int backUpY = _screen->_curDim->sy; int backUpWidth = _screen->_curDim->w; diff --git a/engines/kyra/items_v3.cpp b/engines/kyra/items_v3.cpp new file mode 100644 index 0000000000..303be84d66 --- /dev/null +++ b/engines/kyra/items_v3.cpp @@ -0,0 +1,54 @@ +/* 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 "kyra/kyra_v3.h" + +namespace Kyra { + +void KyraEngine_v3::resetItem(int index) { + debugC(9, kDebugLevelMain, "KyraEngine_v3::resetItem(%d)", index); + _itemList[index].id = 0xFFFF; + _itemList[index].sceneId = 0xFFFF; + _itemList[index].x = 0; + _itemList[index].y = 0; + _itemList[index].unk8 = 0; +} + +void KyraEngine_v3::resetItemList() { + debugC(9, kDebugLevelMain, "KyraEngine_v3::resetItemList()"); + for (int i = 0; i < 50; ++i) + resetItem(i); +} + +int KyraEngine_v3::findFreeItem() { + debugC(9, kDebugLevelMain, "KyraEngine_v3::findFreeItem()"); + for (int i = 0; i < 50; ++i) { + if (_itemList[i].id == 0xFFFF) + return i; + } + return -1; +} + +} // end of namespace Kyra diff --git a/engines/kyra/kyra_v3.cpp b/engines/kyra/kyra_v3.cpp index c2892e9ee6..ff00699d34 100644 --- a/engines/kyra/kyra_v3.cpp +++ b/engines/kyra/kyra_v3.cpp @@ -41,44 +41,65 @@ KyraEngine_v3::KyraEngine_v3(OSystem *system, const GameFlags &flags) : KyraEngi _musicSoundChannel = -1; _menuAudioFile = "TITLE1.AUD"; _curMusicTrack = -1; - _unkPage1 = _unkPage2 = 0; - _interfaceCPS1 = _interfaceCPS2 = 0; - memset(_gameShapes, 0, sizeof(_gameShapes)); _itemBuffer1 = _itemBuffer2 = 0; - _mouseSHPBuf = 0; - _unkBuffer5 = _unkBuffer6 = _unkBuffer7 = _unkBuffer9 = 0; - _costpalData = 0; - _unkWSAPtr = 0; - memset(_unkShapeTable, 0, sizeof(_unkShapeTable)); _scoreFile = 0; _cCodeFile = 0; - _scenesList = 0; + _scenesFile = 0; + _itemFile = 0; + _gamePlayBuffer = 0; + _interface = _interfaceCommandLine = 0; + _costPalBuffer = 0; + _animObjects = 0; + _sceneAnims = 0; + memset(_sceneShapes, 0, sizeof(_sceneShapes)); + memset(_sceneAnimMovie, 0, sizeof(_sceneAnimMovie)); + _gfxBackUpRect = 0; + _itemList = 0; + _malcolmShapes = 0; + _paletteOverlay = 0; + _sceneList = 0; + memset(&_mainCharacter, 0, sizeof(_mainCharacter)); + _mainCharacter.sceneId = 9; + _mainCharacter.dlgIndex = 0; + _mainCharacter.unk4 = 0x4C; + _mainCharacter.facing = 5; + _mainCharacter.walkspeed = 5; + memset(_mainCharacter.inventory, -1, sizeof(_mainCharacter.inventory)); } KyraEngine_v3::~KyraEngine_v3() { + delete _screen; delete _soundDigital; - delete [] _unkPage1; - delete [] _unkPage2; - delete [] _interfaceCPS1; - delete [] _interfaceCPS2; - delete [] _itemBuffer1; delete [] _itemBuffer2; - - delete [] _mouseSHPBuf; - - delete [] _unkBuffer5; - delete [] _unkBuffer6; - delete [] _unkBuffer7; - delete [] _unkBuffer9; - - delete [] _costpalData; - delete [] _unkWSAPtr; - delete [] _scoreFile; delete [] _cCodeFile; - delete [] _scenesList; + delete [] _scenesFile; + delete [] _itemFile; + delete [] _gamePlayBuffer; + delete [] _interface; + delete [] _interfaceCommandLine; + delete [] _costPalBuffer; + delete [] _animObjects; + delete [] _sceneAnims; + + for (uint i = 0; i < ARRAYSIZE(_sceneShapes); ++i) + delete _sceneShapes[i]; + + for (uint i = 0; i < ARRAYSIZE(_sceneAnimMovie); ++i) + delete _sceneAnimMovie[i]; + + delete [] _gfxBackUpRect; + delete [] _itemList; + delete [] _paletteOverlay; + delete [] _sceneList; + + for (ShapeMap::iterator i = _gameShapes.begin(); i != _gameShapes.end(); ++i) { + delete i->_value; + i->_value = 0; + } + _gameShapes.clear(); } int KyraEngine_v3::init() { @@ -97,28 +118,20 @@ int KyraEngine_v3::init() { _screen->loadFont(Screen::FID_6_FNT, "6.FNT"); _screen->loadFont(Screen::FID_8_FNT, "8FAT.FNT"); _screen->loadFont(Screen::FID_BOOKFONT_FNT, "BOOKFONT.FNT"); + _screen->setFont(Screen::FID_6_FNT); _screen->setAnimBlockPtr(3500); _screen->setScreenDim(0); - - _itemBuffer1 = new uint8[72]; - _itemBuffer2 = new uint8[144]; - assert(_itemBuffer1 && _itemBuffer2); - - _mouseSHPBuf = _res->fileData("MOUSE.SHP", 0); - assert(_mouseSHPBuf); - - for (int i = 0; i <= 6; ++i) - _gameShapes[i] = _screen->getPtrToShape(_mouseSHPBuf, i); - - initItems(); - - _screen->setMouseCursor(0, 0, *_gameShapes); + + _res->loadFileToBuf("PALETTE.COL", _screen->getPalette(0), 768); + _screen->setScreenPalette(_screen->getPalette(0)); return 0; } int KyraEngine_v3::go() { bool running = true; + preinit(); + _screen->hideMouse(); initMainMenu(); _screen->clearPage(0); @@ -154,16 +167,16 @@ int KyraEngine_v3::go() { case 0: uninitMainMenu(); - preinit(); - realInit(); + startup(); // XXX running = false; break; case 1: - memcpy(_screen->getPalette(1), _screen->getPalette(0), 768); + _soundDigital->beginFadeOut(_musicSoundChannel, 60); + _screen->fadeToBlack(60); playVQA("K3INTRO"); - memcpy(_screen->getPalette(0), _screen->getPalette(1), 768); + _screen->hideMouse(); break; case 2: @@ -222,7 +235,10 @@ void KyraEngine_v3::uninitMainMenu() { } void KyraEngine_v3::playVQA(const char *name) { - debugC(9, kDebugLevelMain, "KyraEngine::playVQA('%s')", name); + debugC(9, kDebugLevelMain, "KyraEngine_v3::playVQA('%s')", name); + + memcpy(_screen->getPalette(1), _screen->getPalette(0), 768); + VQAMovie vqa(this, _system); char filename[20]; @@ -249,12 +265,14 @@ void KyraEngine_v3::playVQA(const char *name) { _screen->copyRegion(0, 0, 0, 0, 320, 200, 3, 0); _screen->setScreenPalette(pal); } + + memcpy(_screen->getPalette(0), _screen->getPalette(1), 768); } #pragma mark - void KyraEngine_v3::playMenuAudioFile() { - debugC(9, kDebugLevelMain, "KyraEngine::playMenuAudioFile()"); + debugC(9, kDebugLevelMain, "KyraEngine_v3::playMenuAudioFile()"); if (_soundDigital->isPlaying(_musicSoundChannel)) return; @@ -264,9 +282,9 @@ void KyraEngine_v3::playMenuAudioFile() { } void KyraEngine_v3::playMusicTrack(int track, int force) { - debugC(9, kDebugLevelMain, "KyraEngine::playMusicTrack(%d, %d)", track, force); + debugC(9, kDebugLevelMain, "KyraEngine_v3::playMusicTrack(%d, %d)", track, force); - // XXX byte_2C87C compare + // XXX byte_3C87C compare if (_musicSoundChannel != -1 && !_soundDigital->isPlaying(_musicSoundChannel)) force = 1; @@ -290,6 +308,8 @@ void KyraEngine_v3::playMusicTrack(int track, int force) { } void KyraEngine_v3::stopMusicTrack() { + debugC(9, kDebugLevelMain, "KyraEngine_v3::stopMusicTrack()"); + if (_musicSoundChannel != -1 && _soundDigital->isPlaying(_musicSoundChannel)) _soundDigital->stopSound(_musicSoundChannel); @@ -298,23 +318,21 @@ void KyraEngine_v3::stopMusicTrack() { } int KyraEngine_v3::musicUpdate(int forceRestart) { - debugC(9, kDebugLevelMain, "KyraEngine::unkUpdate(%d)", forceRestart); + debugC(9, kDebugLevelMain, "KyraEngine_v3::musicUpdate(%d)", forceRestart); static uint32 mTimer = 0; static uint16 lock = 0; - if (ABS(_system->getMillis() - mTimer) > (int)(0x0F * _tickLength)) { + if (ABS(_system->getMillis() - mTimer) > (int)(0x0F * _tickLength)) mTimer = _system->getMillis(); - } - if (_system->getMillis() < mTimer && !forceRestart) { + if (_system->getMillis() < mTimer && !forceRestart) return 1; - } if (!lock) { lock = 1; if (_musicSoundChannel >= 0) { - // XXX sub_1C262 (sound specific. it seems to close some sound resource files in special cases) + _soundDigital->stopAllSounds(); if (!_soundDigital->isPlaying(_musicSoundChannel)) { if (_curMusicTrack != -1) playMusicTrack(_curMusicTrack, 1); @@ -330,75 +348,182 @@ int KyraEngine_v3::musicUpdate(int forceRestart) { #pragma mark - void KyraEngine_v3::preinit() { - debugC(9, kDebugLevelMain, "KyraEngine::preinit()"); + debugC(9, kDebugLevelMain, "KyraEngine_v3::preinit()"); + + _unkBuffer1040Bytes = new uint8[1040]; + _itemBuffer1 = new uint8[72]; + _itemBuffer2 = new uint8[144]; + initMouseShapes(); + initItems(); + + _screen->setMouseCursor(0, 0, _gameShapes[0]); +} + +void KyraEngine_v3::initMouseShapes() { + debugC(9, kDebugLevelMain, "KyraEngine_v3::initMouseShapes()"); + uint8 *data = _res->fileData("MOUSE.SHP", 0); + assert(data); + for (int i = 0; i <= 6; ++i) + _gameShapes[i] = _screen->makeShapeCopy(data, i); + delete [] data; +} +void KyraEngine_v3::startup() { + debugC(9, kDebugLevelMain, "KyraEngine_v3::startup()"); musicUpdate(0); - // XXX snd_allocateSoundBuffer? memset(_flagsTable, 0, sizeof(_flagsTable)); - - // XXX setGameFlag(0x216); - _unkPage1 = new uint8[64000]; - assert(_unkPage1); - + _gamePlayBuffer = new uint8[64000]; musicUpdate(0); musicUpdate(0); - _interfaceCPS1 = new uint8[17920]; - _interfaceCPS2 = new uint8[3840]; - assert(_interfaceCPS1 && _interfaceCPS2); + _interface = new uint8[17920]; + _interfaceCommandLine = new uint8[3840]; _screen->setFont(Screen::FID_6_FNT); -} - -void KyraEngine_v3::realInit() { - debugC(9, kDebugLevelMain, "KyraEngine::realInit()"); - - // XXX sound specific stuff - _unkBuffer5 = new uint8[500]; - _unkBuffer6 = new uint8[200]; - _unkBuffer7 = new uint8[600]; - _costpalData = new uint8[864]; - _unkBuffer9 = new uint8[3618]; - _unkWSAPtr = new uint8[624]; + //XXX + musicUpdate(0); + //XXX + _costPalBuffer = new uint8[864]; + //XXX + _animObjects = new AnimObj[67]; + _sceneAnims = new SceneAnim[16]; musicUpdate(0); - _unkPage2 = new uint8[64000]; + memset(_sceneShapes, 0, sizeof(_sceneShapes)); + _screenBuffer = new uint8[64000]; musicUpdate(0); musicUpdate(0); - if (!loadLanguageFile("ITEMS.", _itemList)) + if (!loadLanguageFile("ITEMS.", _itemFile)) error("couldn't load ITEMS"); if (!loadLanguageFile("C_CODE.", _cCodeFile)) error("couldn't load C_CODE"); - if (!loadLanguageFile("SCENES.", _scenesList)) + if (!loadLanguageFile("SCENES.", _scenesFile)) error("couldn't load SCENES"); - assert(_unkBuffer5 && _unkBuffer6 && _unkBuffer7 && _costpalData && _unkBuffer9 && - _unkWSAPtr && _unkPage2 && _itemList && _cCodeFile && _scenesList); + //XXX + + if ((_actorFileSize = loadLanguageFile("_ACTOR.", _actorFile)) == 0) + error("couldn't load _ACTOR"); + + musicUpdate(0); + //XXX + musicUpdate(0); + openTalkFile(0); + musicUpdate(0); + _currentTalkFile = 0; + openTalkFile(1); + //XXX + loadCostPal(); + musicUpdate(0); + + for (int i = 0; i < 16; ++i) { + _sceneAnims[i].flags = 0; + _sceneAnimMovie[i] = new WSAMovieV2(this, _screen); + assert(_sceneAnimMovie[i]); + } + + _screen->_curPage = 0; + + //XXX musicUpdate(0); + updateMalcolmShapes(); + _gfxBackUpRect = new uint8[_screen->getRectSize(32, 32)]; + _itemList = new Item[50]; + resetItemList(); + + loadShadowShape(); + //loadButtonShapes(); + musicUpdate(0); + loadExtrasShapes(); + musicUpdate(0); + loadMalcolmShapes(_malcolmShapes); + musicUpdate(0); + //initInventoryButtonList(1); + loadInterfaceShapes(); + + musicUpdate(0); + _res->loadFileToBuf("PALETTE.COL", _screen->getPalette(0), 768); + _paletteOverlay = new uint8[256]; + _screen->generateOverlay(_screen->getPalette(0), _paletteOverlay, 0xF0, 0x19); + + loadInterface(); + musicUpdate(0); + + clearAnimObjects(); + + //XXX + + musicUpdate(0); + memset(_hiddenItems, -1, sizeof(_hiddenItems)); + + //resetNewSceneDlgState(); + + _sceneList = new SceneDesc[98]; + musicUpdate(0); + runStartupScript(1, 0); + //openMoondomtrWsa(); + _soundDigital->beginFadeOut(_musicSoundChannel, 60); + delayUntil(_system->getMillis() + 60 * _tickLength); + //XXX enterNewScene(_mainCharacter.sceneId, _mainCharacter.facing, 0, 0, 1); + musicUpdate(0); + _screen->showMouse(); + //XXX +} + +void KyraEngine_v3::loadCostPal() { + debugC(9, kDebugLevelMain, "KyraEngine_v3::loadCostPal()"); + _costPalBuffer = _res->fileData("_COSTPAL.DAT", 0); +} + +void KyraEngine_v3::loadShadowShape() { + debugC(9, kDebugLevelMain, "KyraEngine_v3::loadShadowShape()"); + _screen->loadBitmap("SHADOW.CSH", 3, 3, 0); + addShapeToPool(_screen->getCPagePtr(3), 421, 0); +} + +void KyraEngine_v3::loadExtrasShapes() { + debugC(9, kDebugLevelMain, "KyraEngine_v3::loadExtrasShapes()"); + _screen->loadBitmap("EXTRAS.CSH", 3, 3, 0); + for (int i = 0; i < 20; ++i) + addShapeToPool(_screen->getCPagePtr(3), i+433, i); + addShapeToPool(_screen->getCPagePtr(3), 453, 20); + addShapeToPool(_screen->getCPagePtr(3), 454, 21); } -#pragma mark - items +void KyraEngine_v3::loadInterfaceShapes() { + debugC(9, kDebugLevelMain, "KyraEngine_v3::loadInterfaceShapes()"); + _screen->loadBitmap("INTRFACE.CSH", 3, 3, 0); + for (int i = 422; i <= 432; ++i) + addShapeToPool(_screen->getCPagePtr(3), i, i-422); +} + +void KyraEngine_v3::loadInterface() { + debugC(9, kDebugLevelMain, "KyraEngine_v3::loadInterface()"); + _screen->loadBitmap("INTRFACE.CPS", 3, 3, 0); + memcpy(_interface, _screen->getCPagePtr(3), 17920); + memcpy(_interfaceCommandLine, _screen->getCPagePtr(3), 3840); +} void KyraEngine_v3::initItems() { - debugC(9, kDebugLevelMain, "KyraEngine::initItems()"); + debugC(9, kDebugLevelMain, "KyraEngine_v3::initItems()"); _screen->loadBitmap("ITEMS.CSH", 3, 3, 0); - //for (int i = 248; i <= 319; ++i) - // addShapeToTable(_screen->getCPagePtr(3), i, i-248); + for (int i = 248; i <= 319; ++i) + addShapeToPool(_screen->getCPagePtr(3), i, i-248); _screen->loadBitmap("ITEMS2.CSH", 3, 3, 0); - //for (int i = 320; i <= 397; ++i) - // addShapeToTable(_screen->getCPagePtr(3), i, i-320); + for (int i = 320; i <= 397; ++i) + addShapeToPool(_screen->getCPagePtr(3), i, i-320); uint32 size = 0; uint8 *itemsDat = _res->fileData("_ITEMS.DAT", &size); @@ -413,10 +538,114 @@ void KyraEngine_v3::initItems() { _screen->_curPage = 0; } +void KyraEngine_v3::runStartupScript(int script, int unk1) { + debugC(9, kDebugLevelMain, "KyraEngine_v3::runStartupScript(%d, %d)", script, unk1); + ScriptState state; + ScriptData data; + memset(&state, 0, sizeof(state)); + memset(&data, 0, sizeof(data)); + char filename[13]; + strcpy(filename, "_START0X.EMC"); + filename[7] = (script % 10) + '0'; + + _scriptInterpreter->loadScript(filename, &data, &_opcodes); + _scriptInterpreter->initScript(&state, &data); + _scriptInterpreter->startScript(&state, 0); + state.regs[6] = unk1; + + while (_scriptInterpreter->validScript(&state)) + _scriptInterpreter->runScript(&state); +} + +void KyraEngine_v3::openTalkFile(int file) { + debugC(9, kDebugLevelMain, "KyraEngine_v3::openTalkFile(%d)", file); + char talkFilename[16]; + + if (file == 0) { + strcpy(talkFilename, "ANYTALK.TLK"); + } else { + if (_currentTalkFile > 0) + sprintf(talkFilename, "CH%dTALK.TLK", _currentTalkFile); + _res->unloadPakFile(talkFilename); + sprintf(talkFilename, "CH%dTALK.TLK", file); + } + + _currentTalkFile = file; + //TODO: support Kyra3 TLK files + //_res->loadPakFile(talkFilename); +} + +#pragma mark - + +void KyraEngine_v3::addShapeToPool(const uint8 *data, int realIndex, int shape) { + debugC(9, kDebugLevelMain, "KyraEngine_v3::addShapeToPool(%p, %d, %d)", data, realIndex, shape); + ShapeMap::iterator iter = _gameShapes.find(realIndex); + if (iter != _gameShapes.end()) { + delete [] iter->_value; + iter->_value = 0; + } + _gameShapes[realIndex] = _screen->makeShapeCopy(data, shape); + assert(_gameShapes[realIndex]); +} + +void KyraEngine_v3::loadMalcolmShapes(int newShapes) { + debugC(9, kDebugLevelMain, "KyraEngine_v3::loadMalcolmShapes(%d)", newShapes); + static const uint8 numberOffset[] = { 3, 3, 4, 4, 3, 3 }; + static const uint8 startShape[] = { 0x32, 0x58, 0x78, 0x98, 0xB8, 0xD8 }; + static const uint8 endShape[] = { 0x57, 0x77, 0x97, 0xB7, 0xD7, 0xF7 }; + static const char * const filenames[] = { + "MSW##.SHP", + "MTA##.SHP", + "MTFL##.SHP", + "MTFR##.SHP", + "MTL##.SHP", + "MTR#.SHP" + }; + + for (int i = 50; i <= 247; ++i) { + if (i == 87) + continue; + + ShapeMap::iterator iter = _gameShapes.find(i); + if (iter != _gameShapes.end()) { + delete iter->_value; + iter->_value = 0; + } + } + + const char lowNum = (newShapes % 10) + '0'; + const char highNum = (newShapes / 10) + '0'; + + for (int i = 0; i < 6; ++i) { + char filename[16]; + strcpy(filename, filenames[i]); + filename[numberOffset[i]+0] = highNum; + filename[numberOffset[i]+1] = lowNum; + _res->loadFileToBuf(filename, _screenBuffer, 64000); + for (int j = startShape[i]; j < endShape[i]; ++j) { + if (j == 87) + continue; + addShapeToPool(_screenBuffer, j, j-startShape[i]); + } + } + + _malcolmShapes = newShapes; + updateMalcolmShapes(); +} + +void KyraEngine_v3::updateMalcolmShapes() { + debugC(9, kDebugLevelMain, "KyraEngine_v3::updateMalcolmShapes()"); + assert(_malcolmShapes >= 0 && _malcolmShapes < _shapeDescsSize); + _malcolmShapeXOffset = _shapeDescs[_malcolmShapes].xOffset; + _malcolmShapeYOffset = _shapeDescs[_malcolmShapes].yOffset; + _animObjects[0].width = _shapeDescs[_malcolmShapes].width; + _animObjects[0].height = _shapeDescs[_malcolmShapes].height; +} + #pragma mark - int KyraEngine_v3::getMaxFileSize(const char *file) { - debugC(9, kDebugLevelMain, "KyraEngine::getMaxFileSize(%s)", file); + debugC(9, kDebugLevelMain, "KyraEngine_v3::getMaxFileSize(%s)", file); int size = 0; char buffer[32]; @@ -430,7 +659,7 @@ int KyraEngine_v3::getMaxFileSize(const char *file) { } char *KyraEngine_v3::appendLanguage(char *buf, int lang, int bufSize) { - debugC(9, kDebugLevelMain, "KyraEngine::appendLanguage([%p|'%s'], %d, %d)", (const void*)buf, buf, lang, bufSize); + debugC(9, kDebugLevelMain, "KyraEngine_v3::appendLanguage([%p|'%s'], %d, %d)", (const void*)buf, buf, lang, bufSize); assert(lang < _languageExtensionSize); int size = strlen(buf) + strlen(_languageExtension[lang]); @@ -448,15 +677,15 @@ char *KyraEngine_v3::appendLanguage(char *buf, int lang, int bufSize) { return buf; } -bool KyraEngine_v3::loadLanguageFile(const char *file, uint8 *&buffer) { - debugC(9, kDebugLevelMain, "KyraEngine::loadLanguageFile('%s', %p)", file, (const void*)buffer); +int KyraEngine_v3::loadLanguageFile(const char *file, uint8 *&buffer) { + debugC(9, kDebugLevelMain, "KyraEngine_v3::loadLanguageFile('%s', %p)", file, (const void*)buffer); uint32 size = 0; char nBuf[32]; strncpy(nBuf, file, 32); buffer = _res->fileData(appendLanguage(nBuf, _lang, sizeof(nBuf)), &size); - return size != 0 && buffer != 0; + return buffer ? size : 0 ; } Movie *KyraEngine_v3::createWSAMovie() { diff --git a/engines/kyra/kyra_v3.h b/engines/kyra/kyra_v3.h index 6d476a066a..f9b5ea22b3 100644 --- a/engines/kyra/kyra_v3.h +++ b/engines/kyra/kyra_v3.h @@ -28,12 +28,14 @@ #include "kyra/kyra.h" #include "kyra/screen_v3.h" +#include "common/hashmap.h" namespace Kyra { class SoundDigital; class Screen_v3; class MainMenu; +class WSAMovieV2; class KyraEngine_v3 : public KyraEngine { public: @@ -52,9 +54,11 @@ private: int init(); void preinit(); - void realInit(); + void startup(); - void setupOpcodeTable() {} + void runStartupScript(int script, int unk1); + + void setupOpcodeTable(); Screen_v3 *_screen; SoundDigital *_soundDigital; @@ -96,46 +100,166 @@ private: // pathfinder bool lineIsPassable(int, int) { return false; } - // unknown private: - uint8 *_unkPage1; - uint8 *_unkPage2; - - uint8 *_unkBuffer5; - uint8 *_unkBuffer6; - uint8 *_unkBuffer7; - uint8 *_unkBuffer9; - - uint8 *_costpalData; - - uint8 *_unkWSAPtr; - - uint8 *_unkShapeTable[20]; - // main menu static const char *_mainMenuStrings[]; + // animator + struct AnimObj { + uint16 index; + uint16 type; + bool enabled; + bool needRefresh; + uint16 unk8; + uint16 flags; + int16 xPos1, yPos1; + uint8 *shapePtr; + uint16 shapeIndex; + uint16 animNum; + uint16 shapeIndex3; + uint16 shapeIndex2; + int16 xPos2, yPos2; + int16 xPos3, yPos3; + int16 width, height; + int16 width2, height2; + AnimObj *nextObject; + }; + + AnimObj *_animObjects; + uint8 *_gamePlayBuffer; + + void clearAnimObjects(); + + // interface + uint8 *_interface; + uint8 *_interfaceCommandLine; + + void loadInterfaceShapes(); + void loadInterface(); + // translation stuff uint8 *_scoreFile; uint8 *_cCodeFile; - uint8 *_scenesList; - - // interface? - uint8 *_interfaceCPS1; - uint8 *_interfaceCPS2; - - // shapes - uint8 *_gameShapes[50]; - - uint8 *_mouseSHPBuf; + uint8 *_scenesFile; + uint8 *_itemFile; + uint8 *_actorFile; + uint32 _actorFileSize; // items uint8 *_itemBuffer1; uint8 *_itemBuffer2; + + void initItems(); - uint8 *_itemList; + // shapes + typedef Common::HashMap ShapeMap; + ShapeMap _gameShapes; + + void addShapeToPool(const uint8 *data, int realIndex, int shape); + + void initMouseShapes(); + + int _malcolmShapes; + void loadMalcolmShapes(int newShapes); + void updateMalcolmShapes(); + + int _malcolmShapeXOffset, _malcolmShapeYOffset; + + struct ShapeDesc { + uint8 width, height; + int8 xOffset, yOffset; + }; + static const ShapeDesc _shapeDescs[]; + static const int _shapeDescsSize; + + // scene animation + struct SceneAnim { + uint16 flags; + int16 x, y; + int16 x2, y2; + int16 width, height; + uint16 unk10; + uint16 specialSize; + uint16 unk14; + uint16 shapeIndex; + uint16 wsaFlag; + char filename[13]; + }; + + SceneAnim *_sceneAnims; + WSAMovieV2 *_sceneAnimMovie[16]; + uint8 *_sceneShapes[20]; + + // voice + int _currentTalkFile; + void openTalkFile(int file); + + // scene + struct SceneDesc { + char filename1[10]; + char filename2[10]; + uint16 exit1, exit2, exit3, exit4; + uint8 flags, sound; + }; + + SceneDesc *_sceneList; + uint16 _sceneExit1, _sceneExit2, _sceneExit3, _sceneExit4; - void initItems(); + // items + struct Item { + uint16 id; + uint16 sceneId; + int16 x, y; + uint16 unk8; + }; + + Item *_itemList; + uint16 _hiddenItems[100]; + + void resetItem(int index); + void resetItemList(); + + int findFreeItem(); + + // character + struct Character { + uint16 sceneId; + uint16 dlgIndex; + uint8 unk4; + uint8 facing; + uint16 animFrame; + //uint8 unk8, unk9; + uint32 walkspeed; + uint16 inventory[10]; + int16 x1, y1; + int16 x2, y2; + int16 x3, y3; + }; + + Character _mainCharacter; + + // unk + uint8 *_unkBuffer1040Bytes; + uint8 *_costPalBuffer; + uint8 *_screenBuffer; + uint8 *_gfxBackUpRect; + uint8 *_paletteOverlay; + + void loadCostPal(); + void loadShadowShape(); + void loadExtrasShapes(); + + // opcodes + int o3_defineItem(ScriptState *script); + int o3_queryGameFlag(ScriptState *script); + int o3_resetGameFlag(ScriptState *script); + int o3_setGameFlag(ScriptState *script); + int o3_setSceneFilename(ScriptState *script); + int o3_getRand(ScriptState *script); + int o3_defineScene(ScriptState *script); + int o3_setHiddenItemsEntry(ScriptState *script); + int o3_getHiddenItemsEntry(ScriptState *script); + int o3_dummy(ScriptState *script); // resource specific private: @@ -145,7 +269,7 @@ private: int getMaxFileSize(const char *file); char *appendLanguage(char *buf, int lang, int bufSize); - bool loadLanguageFile(const char *file, uint8 *&buffer); + int loadLanguageFile(const char *file, uint8 *&buffer); }; } // end of namespace Kyra diff --git a/engines/kyra/module.mk b/engines/kyra/module.mk index aa2eea7122..e598881ce5 100644 --- a/engines/kyra/module.mk +++ b/engines/kyra/module.mk @@ -3,6 +3,7 @@ MODULE := engines/kyra MODULE_OBJS := \ animator_v1.o \ animator_v2.o \ + animator_v3.o \ debugger.o \ detection.o \ gui.o \ @@ -10,6 +11,7 @@ MODULE_OBJS := \ gui_v2.o \ items_v1.o \ items_v2.o \ + items_v3.o \ kyra.o \ kyra_v1.o \ kyra_v2.o \ @@ -27,6 +29,7 @@ MODULE_OBJS := \ screen_v3.o \ script_v1.o \ script_v2.o \ + script_v3.o \ script.o \ seqplayer.o \ sequences_tim.o \ diff --git a/engines/kyra/script_v3.cpp b/engines/kyra/script_v3.cpp new file mode 100644 index 0000000000..de9ba6e843 --- /dev/null +++ b/engines/kyra/script_v3.cpp @@ -0,0 +1,347 @@ +/* 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 "kyra/kyra_v3.h" +#include "kyra/script.h" + +#include "common/endian.h" + +namespace Kyra { + +int KyraEngine_v3::o3_defineItem(ScriptState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v3::o3_defineItem(%p) (%d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3)); + int freeItem = findFreeItem(); + if (freeItem != -1) { + _itemList[freeItem].id = stackPos(0); + _itemList[freeItem].x = stackPos(1); + _itemList[freeItem].y = stackPos(2); + _itemList[freeItem].sceneId = stackPos(3); + } + return freeItem; +} + +int KyraEngine_v3::o3_queryGameFlag(ScriptState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v3::o3_queryGameFlag(%p) (%d)", (const void *)script, stackPos(0)); + return queryGameFlag(stackPos(0)); +} + +int KyraEngine_v3::o3_resetGameFlag(ScriptState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v3::o3_resetGameFlag(%p) (%d)", (const void *)script, stackPos(0)); + resetGameFlag(stackPos(0)); + return 0; +} + +int KyraEngine_v3::o3_setGameFlag(ScriptState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v3::o3_setGameFlag(%p) (%d)", (const void *)script, stackPos(0)); + setGameFlag(stackPos(0)); + return 1; +} + +int KyraEngine_v3::o3_setSceneFilename(ScriptState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v3::o3_setSceneFilename(%p) (%d, '%s')", (const void *)script, stackPos(0), stackPosString(1)); + strcpy(_sceneList[stackPos(0)].filename1, stackPosString(1)); + _sceneList[stackPos(0)].filename1[9] = 0; + return 0; +} + +int KyraEngine_v3::o3_getRand(ScriptState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v3::o3_getRand(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); + assert(stackPos(0) < stackPos(1)); + return _rnd.getRandomNumberRng(stackPos(0), stackPos(1)); +} + +int KyraEngine_v3::o3_defineScene(ScriptState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v3::o3_defineScene(%p) (%d, '%s', %d, %d, %d, %d, %d)", + (const void *)script, stackPos(0), stackPosString(1), stackPos(2), stackPos(3), stackPos(4), stackPos(5), stackPos(6), stackPos(7)); + const int scene = stackPos(0); + strcpy(_sceneList[scene].filename1, stackPosString(1)); + _sceneList[scene].filename1[9] = 0; + strcpy(_sceneList[scene].filename2, stackPosString(1)); + _sceneList[scene].filename2[9] = 0; + + _sceneList[scene].exit1 = stackPos(2); + _sceneList[scene].exit2 = stackPos(3); + _sceneList[scene].exit3 = stackPos(4); + _sceneList[scene].exit4 = stackPos(5); + _sceneList[scene].flags = stackPos(6); + _sceneList[scene].sound = stackPos(7); + + if (_mainCharacter.sceneId == scene) { + _sceneExit1 = _sceneList[scene].exit1; + _sceneExit2 = _sceneList[scene].exit2; + _sceneExit3 = _sceneList[scene].exit3; + _sceneExit4 = _sceneList[scene].exit4; + } + + return 0; +} + +int KyraEngine_v3::o3_setHiddenItemsEntry(ScriptState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v3::o3_setHiddenItemsEntry(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); + return (_hiddenItems[stackPos(0)] = (uint16)stackPos(1)); +} + +int KyraEngine_v3::o3_getHiddenItemsEntry(ScriptState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v3::o3_getHiddenItemsEntry(%p) (%d)", (const void *)script, stackPos(0)); + return (int16)_hiddenItems[stackPos(0)]; +} + +int KyraEngine_v3::o3_dummy(ScriptState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v3::o3_dummy(%p) ()", (const void *)script); + return 0; +} + +typedef Functor1Mem OpcodeV3; +#define Opcode(x) OpcodeV3(this, &KyraEngine_v3::x) +#define OpcodeUnImpl() OpcodeV3(this, 0) +void KyraEngine_v3::setupOpcodeTable() { + static const OpcodeV3 opcodeTable[] = { + // 0x00 + OpcodeUnImpl(), + OpcodeUnImpl(), + OpcodeUnImpl(), + OpcodeUnImpl(), + // 0x04 + OpcodeUnImpl(), + OpcodeUnImpl(), + OpcodeUnImpl(), + OpcodeUnImpl(), + // 0x08 + OpcodeUnImpl(), + Opcode(o3_dummy), + Opcode(o3_dummy), + OpcodeUnImpl(), + // 0x0c + OpcodeUnImpl(), + OpcodeUnImpl(), + OpcodeUnImpl(), + OpcodeUnImpl(), + // 0x10 + OpcodeUnImpl(), + OpcodeUnImpl(), + Opcode(o3_dummy), + Opcode(o3_dummy), + // 0x14 + OpcodeUnImpl(), + OpcodeUnImpl(), + Opcode(o3_dummy), + OpcodeUnImpl(), + // 0x18 + OpcodeUnImpl(), + OpcodeUnImpl(), + OpcodeUnImpl(), + OpcodeUnImpl(), + // 0x1c + OpcodeUnImpl(), + OpcodeUnImpl(), + OpcodeUnImpl(), + OpcodeUnImpl(), + // 0x20 + OpcodeUnImpl(), + Opcode(o3_dummy), + OpcodeUnImpl(), + Opcode(o3_defineItem), + // 0x24 + OpcodeUnImpl(), + OpcodeUnImpl(), + OpcodeUnImpl(), + Opcode(o3_queryGameFlag), + // 0x28 + Opcode(o3_resetGameFlag), + Opcode(o3_setGameFlag), + OpcodeUnImpl(), + OpcodeUnImpl(), + // 0x2c + OpcodeUnImpl(), + OpcodeUnImpl(), + OpcodeUnImpl(), + OpcodeUnImpl(), + // 0x30 + OpcodeUnImpl(), + OpcodeUnImpl(), + OpcodeUnImpl(), + Opcode(o3_dummy), + // 0x34 + OpcodeUnImpl(), + OpcodeUnImpl(), + Opcode(o3_dummy), + OpcodeUnImpl(), + // 0x38 + OpcodeUnImpl(), + OpcodeUnImpl(), + Opcode(o3_setSceneFilename), + OpcodeUnImpl(), + // 0x3c + OpcodeUnImpl(), + OpcodeUnImpl(), + OpcodeUnImpl(), + OpcodeUnImpl(), + // 0x40 + OpcodeUnImpl(), + OpcodeUnImpl(), + OpcodeUnImpl(), + Opcode(o3_dummy), + // 0x44 + Opcode(o3_dummy), + OpcodeUnImpl(), + OpcodeUnImpl(), + Opcode(o3_dummy), + // 0x48 + Opcode(o3_dummy), + Opcode(o3_dummy), + OpcodeUnImpl(), + OpcodeUnImpl(), + // 0x4c + OpcodeUnImpl(), + OpcodeUnImpl(), + OpcodeUnImpl(), + OpcodeUnImpl(), + // 0x50 + OpcodeUnImpl(), + OpcodeUnImpl(), + OpcodeUnImpl(), + Opcode(o3_dummy), + // 0x54 + Opcode(o3_dummy), + Opcode(o3_dummy), + OpcodeUnImpl(), + OpcodeUnImpl(), + // 0x58 + OpcodeUnImpl(), + OpcodeUnImpl(), + OpcodeUnImpl(), + OpcodeUnImpl(), + // 0x5c + OpcodeUnImpl(), + Opcode(o3_dummy), + OpcodeUnImpl(), + OpcodeUnImpl(), + // 0x60 + Opcode(o3_getRand), + Opcode(o3_dummy), + OpcodeUnImpl(), + OpcodeUnImpl(), + // 0x64 + OpcodeUnImpl(), + OpcodeUnImpl(), + Opcode(o3_dummy), + OpcodeUnImpl(), + // 0x68 + OpcodeUnImpl(), + OpcodeUnImpl(), + OpcodeUnImpl(), + OpcodeUnImpl(), + // 0x6c + Opcode(o3_dummy), + OpcodeUnImpl(), + OpcodeUnImpl(), + OpcodeUnImpl(), + // 0x70 + OpcodeUnImpl(), + Opcode(o3_dummy), + OpcodeUnImpl(), + Opcode(o3_dummy), + // 0x74 + OpcodeUnImpl(), + OpcodeUnImpl(), + OpcodeUnImpl(), + OpcodeUnImpl(), + // 0x78 + OpcodeUnImpl(), + Opcode(o3_defineScene), + OpcodeUnImpl(), + OpcodeUnImpl(), + // 0x7c + OpcodeUnImpl(), + OpcodeUnImpl(), + Opcode(o3_dummy), + Opcode(o3_dummy), + // 0x80 + Opcode(o3_dummy), + OpcodeUnImpl(), + Opcode(o3_dummy), + Opcode(o3_dummy), + // 0x84 + Opcode(o3_dummy), + Opcode(o3_dummy), + Opcode(o3_dummy), + Opcode(o3_dummy), + // 0x88 + OpcodeUnImpl(), + Opcode(o3_dummy), + OpcodeUnImpl(), + Opcode(o3_dummy), + // 0x8c + OpcodeUnImpl(), + Opcode(o3_dummy), + Opcode(o3_dummy), + OpcodeUnImpl(), + // 0x90 + OpcodeUnImpl(), + OpcodeUnImpl(), + Opcode(o3_dummy), + Opcode(o3_setHiddenItemsEntry), + // 0x94 + Opcode(o3_getHiddenItemsEntry), + Opcode(o3_dummy), + Opcode(o3_dummy), + OpcodeUnImpl(), + // 0x98 + OpcodeUnImpl(), + OpcodeUnImpl(), + OpcodeUnImpl(), + OpcodeUnImpl(), + // 0x9c + OpcodeUnImpl(), + OpcodeUnImpl(), + OpcodeUnImpl(), + OpcodeUnImpl(), + // 0xa0 + Opcode(o3_dummy), + Opcode(o3_dummy), + Opcode(o3_dummy), + Opcode(o3_dummy), + // 0xa4 + OpcodeUnImpl(), + OpcodeUnImpl(), + OpcodeUnImpl(), + OpcodeUnImpl(), + // 0xa8 + OpcodeUnImpl(), + OpcodeUnImpl(), + OpcodeUnImpl(), + OpcodeUnImpl(), + // 0xac + OpcodeUnImpl(), + Opcode(o3_dummy), + OpcodeUnImpl(), + Opcode(o3_dummy), + }; + + for (int i = 0; i < ARRAYSIZE(opcodeTable); ++i) + _opcodes.push_back(&opcodeTable[i]); +} + +} // end of namespace Kyra diff --git a/engines/kyra/sound.h b/engines/kyra/sound.h index 456a1096ac..ff61a4f907 100644 --- a/engines/kyra/sound.h +++ b/engines/kyra/sound.h @@ -536,6 +536,11 @@ public: */ void stopSound(int channel); + /** + * Stops playback of all sounds + */ + void stopAllSounds(); + /** * Makes the sound in a given channel * fading out. diff --git a/engines/kyra/sound_digital.cpp b/engines/kyra/sound_digital.cpp index ab36423df6..6ec57b64db 100644 --- a/engines/kyra/sound_digital.cpp +++ b/engines/kyra/sound_digital.cpp @@ -380,6 +380,13 @@ void SoundDigital::stopSound(int channel) { _sounds[channel].stream = 0; } +void SoundDigital::stopAllSounds() { + for (int i = 0; i < SOUND_STREAMS; ++i) { + if (isPlaying(i)) + stopSound(i); + } +} + void SoundDigital::beginFadeOut(int channel, int ticks) { if (isPlaying(channel)) _sounds[channel].stream->beginFadeOut(ticks * _vm->tickLength()); diff --git a/engines/kyra/staticres.cpp b/engines/kyra/staticres.cpp index f96ad9928c..1279a23709 100644 --- a/engines/kyra/staticres.cpp +++ b/engines/kyra/staticres.cpp @@ -1970,6 +1970,23 @@ const char *KyraEngine_v3::_languageExtension[] = { const int KyraEngine_v3::_languageExtensionSize = ARRAYSIZE(KyraEngine_v3::_languageExtension); +const KyraEngine_v3::ShapeDesc KyraEngine_v3::_shapeDescs[] = { + { 57, 91, -31, -82 }, + { 57, 91, -31, -82 }, + { 57, 91, -31, -82 }, + { 57, 91, -31, -82 }, + { 57, 91, -31, -82 }, + { 82, 96, -43, -86 }, + { 57, 91, -31, -82 }, + { 57, 91, -31, -82 }, + { 57, 91, -31, -82 }, + { 69, 91, -31, -82 }, + { 57, 91, -31, -82 }, + { 57, 91, -31, -82 } +}; + +const int KyraEngine_v3::_shapeDescsSize = ARRAYSIZE(KyraEngine_v3::_shapeDescs); + } // End of namespace Kyra -- cgit v1.2.3