aboutsummaryrefslogtreecommitdiff
path: root/engines/kyra
diff options
context:
space:
mode:
authorJohannes Schickel2007-04-15 13:44:49 +0000
committerJohannes Schickel2007-04-15 13:44:49 +0000
commit8c4e539a40f816400d89ba45e04f85869642318c (patch)
tree712d7366cc9e13060134df637dd32b66c1e04eba /engines/kyra
parent1b71599d86b66b53e601ec7c5781c63d4d07d595 (diff)
downloadscummvm-rg350-8c4e539a40f816400d89ba45e04f85869642318c.tar.gz
scummvm-rg350-8c4e539a40f816400d89ba45e04f85869642318c.tar.bz2
scummvm-rg350-8c4e539a40f816400d89ba45e04f85869642318c.zip
Readded lost files.
svn-id: r26496
Diffstat (limited to 'engines/kyra')
-rw-r--r--engines/kyra/kyra_v2.cpp129
-rw-r--r--engines/kyra/kyra_v2.h123
-rw-r--r--engines/kyra/kyra_v3.cpp705
-rw-r--r--engines/kyra/kyra_v3.h146
4 files changed, 1103 insertions, 0 deletions
diff --git a/engines/kyra/kyra_v2.cpp b/engines/kyra/kyra_v2.cpp
new file mode 100644
index 0000000000..9593817013
--- /dev/null
+++ b/engines/kyra/kyra_v2.cpp
@@ -0,0 +1,129 @@
+/* ScummVM - Scumm Interpreter
+ * Copyright (C) 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 "kyra/kyra.h"
+#include "kyra/kyra_v2.h"
+#include "kyra/screen.h"
+#include "kyra/resource.h"
+#include "kyra/wsamovie.h"
+#include "kyra/sound.h"
+
+#include "common/system.h"
+
+namespace Kyra {
+
+KyraEngine_v2::KyraEngine_v2(OSystem *system, const GameFlags &flags) : KyraEngine(system, flags) {
+ memset(_gameShapes, 0, sizeof(_gameShapes));
+ _mouseSHPBuf = 0;
+}
+
+KyraEngine_v2::~KyraEngine_v2() {
+ delete [] _mouseSHPBuf;
+}
+
+int KyraEngine_v2::init() {
+ KyraEngine::init();
+
+ if (_res->getFileSize("6.FNT")) {
+ _screen->loadFont(Screen::FID_6_FNT, "6.FNT");
+ }
+ if (_res->getFileSize("8FAT.FNT")) {
+ _screen->loadFont(Screen::FID_8_FNT, "8FAT.FNT");
+ }
+ _screen->loadFont(Screen::FID_GOLDFONT_FNT, "GOLDFONT.FNT");
+ _screen->setAnimBlockPtr(3500);
+ _screen->setScreenDim(0);
+
+ assert(_introStringsSize == 21);
+ for (int i = 0; i < 21; i++) {
+ _introStringsDuration[i] = strlen(_introStrings[i]) * 8;
+ }
+
+ // No mouse display in demo
+ if (_flags.isDemo)
+ return 0;
+
+ _mouseSHPBuf = _res->fileData("PWGMOUSE.SHP", 0);
+ assert(_mouseSHPBuf);
+
+ for (int i = 0; i < 2; i++) {
+ _gameShapes[i] = _screen->getPtrToShape(_mouseSHPBuf, i);
+ assert(_gameShapes[i]);
+ }
+
+ _screen->setMouseCursor(0, 0, _gameShapes[0]);
+ return 0;
+}
+
+int KyraEngine_v2::go() {
+ if (_flags.isDemo) {
+ static const char *soundFileList[] = {
+ "K2_DEMO",
+ "LOLSYSEX"
+ };
+ _sound->setSoundFileList(soundFileList, 2);
+ } else {
+ // TODO: move this to proper place
+ static const char *soundFileList[] = {
+ "K2INTRO"
+ };
+ _sound->setSoundFileList(soundFileList, 1);
+ }
+ _sound->loadSoundFile(0);
+
+ // Temporary measure to work around the fact that there's
+ // several WSA files with identical names in different PAK files.
+ _res->unloadPakFile("OUTFARM.PAK");
+ _res->unloadPakFile("FLYTRAP.PAK");
+
+ seq_playSequences(kSequenceVirgin, kSequenceWestwood);
+ mainMenu();
+
+ return 0;
+}
+
+void KyraEngine_v2::mainMenu() {
+ bool running = true;
+
+ while (running && !_quitFlag) {
+ seq_playSequences(kSequenceTitle);
+ _screen->showMouse();
+
+ switch (gui_handleMainMenu()) {
+ case 0:
+ break;
+ case 1:
+ seq_playSequences(kSequenceOverview, kSequenceLibrary);
+ break;
+ case 2:
+ break;
+ case 3:
+ running = false;
+ break;
+ default:
+ break;
+ }
+ _screen->hideMouse();
+ }
+}
+
+} // end of namespace Kyra
diff --git a/engines/kyra/kyra_v2.h b/engines/kyra/kyra_v2.h
new file mode 100644
index 0000000000..be3ef8f241
--- /dev/null
+++ b/engines/kyra/kyra_v2.h
@@ -0,0 +1,123 @@
+/* ScummVM - Scumm Interpreter
+ * Copyright (C) 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$
+ *
+ */
+
+#ifndef KYRA_KYRA_V2_H
+#define KYRA_KYRA_V2_H
+
+namespace Kyra {
+
+enum kSequences {
+ kSequenceVirgin = 0,
+ kSequenceWestwood = 1,
+ kSequenceTitle = 2,
+ kSequenceOverview = 3,
+ kSequenceLibrary = 4,
+ kSequenceHand = 5
+};
+
+class WSAMovieV2;
+class KyraEngine_v2;
+
+struct SequenceControl {
+ int8 frameIndex;
+ int8 frameDelay;
+};
+
+struct ActiveWSA {
+ WSAMovieV2 *movie;
+ uint16 currentFrame;
+ uint16 endFrame;
+ uint16 frameDelay;
+ uint32 nextFrame;
+ void (KyraEngine_v2::*callback)(int);
+ const SequenceControl *control;
+};
+
+struct ActiveChat {
+ uint16 strIndex;
+ uint16 x;
+ uint16 y;
+ int duration;
+ uint16 field_8;
+ uint16 startTime;
+ uint16 field_E;
+};
+
+struct Sequence {
+ uint8 type;
+ const char *filename;
+ int (KyraEngine_v2::*callback)(int);
+ uint8 frameDelay;
+ uint16 duration;
+ uint8 numFrames;
+ bool timeOut;
+ bool fadeOut;
+};
+
+class KyraEngine_v2 : public KyraEngine {
+public:
+ KyraEngine_v2(OSystem *system, const GameFlags &flags);
+ ~KyraEngine_v2();
+
+ int go();
+
+private:
+ void seq_playSequences(int startSeq, int endSeq = -1);
+ int seq_introWestwood(int seqNum);
+ int seq_introTitle(int seqNum);
+ int seq_introOverview(int seqNum);
+ int seq_introLibrary(int seqNum);
+ int seq_introHand(int seqNum);
+
+ void seq_introOverviewOver1(int currentFrame);
+ void seq_introOverviewForest(int currentFrame);
+ void seq_introOverviewDragon(int currentFrame);
+ void seq_loadWSA(int wsaNum, const char *filename, int frameDelay, void (KyraEngine_v2::*callback)(int) = 0,
+ const SequenceControl *control = 0 );
+ void seq_unloadWSA(int wsaNum);
+ void seq_playWSAs();
+ void seq_showChats();
+ void seq_playIntroChat(uint8 chatNum);
+ void seq_resetAllChatEntries();
+ void seq_waitForChatsToFinish();
+ void seq_setChatEntry(uint16 strIndex, uint16 posX, uint16 posY, int duration, uint16 unk1);
+
+ void mainMenu();
+ int init();
+
+ ActiveWSA *_activeWSA;
+ ActiveChat *_activeChat;
+ uint8 *_gameShapes[50];
+ uint8 *_mouseSHPBuf;
+
+ static const char *_introSoundList[];
+ static const int _introSoundListSize;
+ static const char *_introStrings[];
+ static const int _introStringsSize;
+
+ int _introStringsDuration[21];
+
+};
+
+} // end of namespace Kyra
+
+#endif
diff --git a/engines/kyra/kyra_v3.cpp b/engines/kyra/kyra_v3.cpp
new file mode 100644
index 0000000000..3c0bd0f140
--- /dev/null
+++ b/engines/kyra/kyra_v3.cpp
@@ -0,0 +1,705 @@
+/* ScummVM - Scumm Interpreter
+ * Copyright (C) 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 "kyra/kyra.h"
+#include "kyra/kyra_v3.h"
+#include "kyra/screen.h"
+#include "kyra/wsamovie.h"
+#include "kyra/sound.h"
+#include "kyra/text.h"
+#include "kyra/vqa.h"
+
+#include "common/system.h"
+#include "common/config-manager.h"
+
+// TODO: Temporary, to get the mouse cursor mock-up working
+#include "graphics/cursorman.h"
+
+namespace Kyra {
+KyraEngine_v3::KyraEngine_v3(OSystem *system, const GameFlags &flags) : KyraEngine(system, flags) {
+ _soundDigital = 0;
+ _musicSoundChannel = -1;
+ _menuAudioFile = "TITLE1.AUD";
+ _curMusicTrack = -1;
+ _unkPage1 = _unkPage2 = 0;
+ _interfaceCPS1 = _interfaceCPS2 = 0;
+ memset(_gameShapes, 0, sizeof(_gameShapes));
+ _shapePoolBuffer = 0;
+ _itemBuffer1 = _itemBuffer2 = 0;
+ _mouseSHPBuf = 0;
+ _tableBuffer1 = _tableBuffer2 = 0;
+ _unkBuffer5 = _unkBuffer6 = _unkBuffer7 = _unkBuffer9 = 0;
+ _costpalData = 0;
+ _unkWSAPtr = 0;
+ memset(_unkShapeTable, 0, sizeof(_unkShapeTable));
+ _scoreFile = 0;
+ _cCodeFile = 0;
+ _scenesList = 0;
+}
+
+KyraEngine_v3::~KyraEngine_v3() {
+ delete _soundDigital;
+
+ delete [] _unkPage1;
+ delete [] _unkPage2;
+ delete [] _interfaceCPS1;
+ delete [] _interfaceCPS2;
+
+ delete [] _itemBuffer1;
+ delete [] _itemBuffer2;
+
+ delete [] _shapePoolBuffer;
+
+ delete [] _mouseSHPBuf;
+
+ delete [] _unkBuffer5;
+ delete [] _unkBuffer6;
+ delete [] _unkBuffer7;
+ delete [] _unkBuffer9;
+
+ delete [] _costpalData;
+ delete [] _unkWSAPtr;
+
+ delete [] _scoreFile;
+ delete [] _cCodeFile;
+ delete [] _scenesList;
+}
+
+Movie *KyraEngine_v3::createWSAMovie() {
+ return new WSAMovieV2(this);
+}
+
+int KyraEngine_v3::init() {
+ KyraEngine::init();
+
+ gui_initMainMenu();
+
+ _soundDigital = new SoundDigital(this, _mixer);
+ assert(_soundDigital);
+ if (!_soundDigital->init())
+ error("_soundDigital->init() failed");
+
+ _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->setAnimBlockPtr(3500);
+ _screen->setScreenDim(0);
+
+ _shapePoolBuffer = new uint8[300000];
+ assert(_shapePoolBuffer);
+ memset(_shapePoolBuffer, 0, 300000);
+
+ initTableBuffer(_shapePoolBuffer, 300000);
+
+ _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);
+
+ return 0;
+}
+
+int KyraEngine_v3::go() {
+ uint8 *pal = _screen->getPalette(1);
+ assert(pal);
+
+ _mainMenuLogo = createWSAMovie();
+ assert(_mainMenuLogo);
+ _mainMenuLogo->open("REVENGE.WSA", 1, pal);
+ assert(_mainMenuLogo->opened());
+
+ bool running = true;
+ while (running && !_quitFlag) {
+ _screen->_curPage = 0;
+ _screen->clearPage(0);
+
+ pal[0] = pal[1] = pal[2] = 0;
+
+ _screen->setScreenPalette(pal);
+
+ // XXX
+ playMenuAudioFile();
+
+ _mainMenuLogo->setX(0); _mainMenuLogo->setY(0);
+ _mainMenuLogo->setDrawPage(0);
+
+ for (int i = 0; i < 64 && !_quitFlag; ++i) {
+ uint32 nextRun = _system->getMillis() + 3 * _tickLength;
+ _mainMenuLogo->displayFrame(i);
+ _screen->updateScreen();
+ delayUntil(nextRun);
+ }
+
+ for (int i = 64; i > 29 && !_quitFlag; --i) {
+ uint32 nextRun = _system->getMillis() + 3 * _tickLength;
+ _mainMenuLogo->displayFrame(i);
+ _screen->updateScreen();
+ delayUntil(nextRun);
+ }
+
+ switch (gui_handleMainMenu()) {
+ case 0:
+ delete _mainMenuLogo;
+ _mainMenuLogo = 0;
+ preinit();
+ realInit();
+ // XXX
+ running = false;
+ break;
+
+ case 1:
+ playVQA("K3INTRO");
+ break;
+
+ case 2:
+ //delete _mainMenuLogo;
+ //_mainMenuLogo = 0;
+ //show load dialog
+ //running = false;
+ break;
+
+ case 3:
+ _soundDigital->beginFadeOut(_musicSoundChannel);
+ _screen->fadeToBlack();
+ _soundDigital->stopSound(_musicSoundChannel);
+ _musicSoundChannel = -1;
+ running = false;
+ break;
+
+ default:
+ break;
+ }
+ }
+ delete _mainMenuLogo;
+
+ return 0;
+}
+
+void KyraEngine_v3::playVQA(const char *name) {
+ debugC(9, kDebugLevelMain, "KyraEngine::playVQA('%s')", name);
+ VQAMovie vqa(this, _system);
+
+ char filename[20];
+ int size = 0; // TODO: Movie size is 0, 1 or 2.
+
+ snprintf(filename, sizeof(filename), "%s%d.VQA", name, size);
+
+ if (vqa.open(filename)) {
+ uint8 pal[768];
+ memcpy(pal, _screen->getPalette(0), sizeof(pal));
+ if (_screen->_curPage == 0)
+ _screen->copyRegion(0, 0, 0, 0, 320, 200, 0, 3);
+
+ _screen->hideMouse();
+ _soundDigital->beginFadeOut(_musicSoundChannel);
+ _musicSoundChannel = -1;
+ _screen->fadeToBlack();
+ vqa.setDrawPage(0);
+ vqa.play();
+ vqa.close();
+ _screen->showMouse();
+
+ if (_screen->_curPage == 0)
+ _screen->copyRegion(0, 0, 0, 0, 320, 200, 3, 0);
+ _screen->setScreenPalette(pal);
+ }
+}
+
+#pragma mark -
+
+void KyraEngine_v3::playMenuAudioFile() {
+ debugC(9, kDebugLevelMain, "KyraEngine::playMenuAudioFile()");
+ if (_soundDigital->isPlaying(_musicSoundChannel))
+ return;
+
+ Common::File *handle = new Common::File();
+ uint32 temp = 0;
+ _res->getFileHandle(_menuAudioFile, &temp, *handle);
+ if (handle->isOpen()) {
+ _musicSoundChannel = _soundDigital->playSound(handle, true);
+ } else {
+ delete handle;
+ }
+}
+
+void KyraEngine_v3::playMusicTrack(int track, int force) {
+ debugC(9, kDebugLevelMain, "KyraEngine::playMusicTrack(%d, %d)", track, force);
+
+ // XXX byte_2C87C compare
+
+ if (_musicSoundChannel != -1 && !_soundDigital->isPlaying(_musicSoundChannel)) {
+ force = 1;
+ } else if (_musicSoundChannel == -1) {
+ force = 1;
+ }
+
+ if (track == _curMusicTrack && !force)
+ return;
+
+ stopMusicTrack();
+
+ if (_musicSoundChannel == -1) {
+ assert(track < _soundListSize && track >= 0);
+
+ Common::File *handle = new Common::File();
+ uint32 temp = 0;
+ _res->getFileHandle(_soundList[track], &temp, *handle);
+ if (handle->isOpen()) {
+ _musicSoundChannel = _soundDigital->playSound(handle);
+ } else {
+ delete handle;
+ }
+ }
+
+ _musicSoundChannel = track;
+}
+
+void KyraEngine_v3::stopMusicTrack() {
+ if (_musicSoundChannel != -1 && _soundDigital->isPlaying(_musicSoundChannel)) {
+ _soundDigital->stopSound(_musicSoundChannel);
+ }
+
+ _curMusicTrack = -1;
+ _musicSoundChannel = -1;
+}
+
+int KyraEngine_v3::musicUpdate(int forceRestart) {
+ debugC(9, kDebugLevelMain, "KyraEngine::unkUpdate(%d)", forceRestart);
+
+ static uint32 timer = 0;
+ static uint16 lock = 0;
+
+ if (ABS<int>(_system->getMillis() - timer) > (int)(0x0F * _tickLength)) {
+ timer = _system->getMillis();
+ }
+
+ if (_system->getMillis() < timer && !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)
+ if (!_soundDigital->isPlaying(_musicSoundChannel)) {
+ if (_curMusicTrack != -1)
+ playMusicTrack(_curMusicTrack, 1);
+ }
+ }
+ lock = 0;
+ timer = _system->getMillis() + 0x0F * _tickLength;
+ }
+
+ return 1;
+}
+
+#pragma mark -
+
+void KyraEngine_v3::gui_initMainMenu() {
+ KyraEngine::gui_initMainMenu();
+ _mainMenuFrame = 29;
+ _mainMenuFrameAdd = 1;
+}
+
+void KyraEngine_v3::gui_updateMainMenuAnimation() {
+ uint32 nextRun = 0;
+
+ uint32 now = _system->getMillis();
+ if (now < nextRun)
+ return;
+
+ // yes 2 * _tickLength here not 3 * like in the first draw
+ nextRun = now + 2 * _tickLength;
+
+ _mainMenuLogo->displayFrame(_mainMenuFrame);
+ _screen->updateScreen();
+
+ _mainMenuFrame += _mainMenuFrameAdd;
+ if (_mainMenuFrame < 29) {
+ _mainMenuFrame = 29;
+ _mainMenuFrameAdd = 1;
+ } else if (_mainMenuFrame > 63) {
+ _mainMenuFrame = 64;
+ _mainMenuFrameAdd = -1;
+ }
+
+ // XXX
+}
+
+#pragma mark -
+
+void KyraEngine_v3::preinit() {
+ debugC(9, kDebugLevelMain, "KyraEngine::preinit()");
+
+ musicUpdate(0);
+
+ // XXX snd_allocateSoundBuffer?
+ memset(_flagsTable, 0, sizeof(_flagsTable));
+
+ // XXX
+ setGameFlag(0x216);
+
+ _unkPage1 = new uint8[64000];
+ assert(_unkPage1);
+
+ musicUpdate(0);
+ musicUpdate(0);
+
+ _interfaceCPS1 = new uint8[17920];
+ _interfaceCPS2 = new uint8[3840];
+ assert(_interfaceCPS1 && _interfaceCPS2);
+
+ _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];
+
+ musicUpdate(0);
+
+ _unkPage2 = new uint8[64000];
+
+ musicUpdate(0);
+ musicUpdate(0);
+
+ if (!loadLanguageFile("ITEMS.", _itemList))
+ error("couldn't load ITEMS");
+ if (!loadLanguageFile("C_CODE.", _cCodeFile))
+ error("couldn't load C_CODE");
+ if (!loadLanguageFile("SCENES.", _scenesList))
+ error("couldn't load SCENES");
+
+ assert(_unkBuffer5 && _unkBuffer6 && _unkBuffer7 && _costpalData && _unkBuffer9 &&
+ _unkWSAPtr && _unkPage2 && _itemList && _cCodeFile && _scenesList);
+
+ musicUpdate(0);
+}
+
+#pragma mark -
+
+int KyraEngine_v3::initTableBuffer(uint8 *buf, int size) {
+ debugC(9, kDebugLevelMain, "KyraEngine::initTableBuffer(%p, %d)", (void *)buf, size);
+
+ if (!buf || size < 6320)
+ return 0;
+
+ if (_tableBuffer2 != _tableBuffer1 && _tableBuffer2 && _tableBuffer1) {
+ // no idea if this *should* be called
+ memmove(_tableBuffer2, _tableBuffer1, 6320);
+ }
+
+ _tableBuffer1 = buf;
+ size -= 6320;
+
+ *((uint16*)(_tableBuffer1)) = 0;
+ *((uint16*)(_tableBuffer1 + 2)) = 1;
+ *((uint16*)(_tableBuffer1 + 4)) = 1;
+ *((uint32*)(_tableBuffer1 + 6)) = size >> 4;
+ *((uint16*)(_tableBuffer1 + 10)) = 1;
+ *((uint32*)(_tableBuffer1 + 16)) = 6320;
+ *((uint32*)(_tableBuffer1 + 22)) = size >> 4;
+
+ _tableBuffer2 = buf;
+
+ return 1;
+}
+
+void KyraEngine_v3::updateTableBuffer(uint8 *buf) {
+ debugC(9, kDebugLevelMain, "KyraEngine::updateTableBuffer(%p)", (void *)buf);
+
+ if (_tableBuffer2 == buf)
+ return;
+
+ if (_tableBuffer1 != _tableBuffer2)
+ memmove(_tableBuffer2, _tableBuffer1, 6320);
+
+ _tableBuffer2 = _tableBuffer1 = buf;
+}
+
+int KyraEngine_v3::addShapeToTable(const uint8 *buf, int id, int shapeNum) {
+ debugC(9, kDebugLevelMain, "KyraEngine::addShapeToTable(%p, %d, %d)", (const void *)buf, id, shapeNum);
+
+ if (!buf)
+ return 0;
+
+ const uint8 *shapePtr = _screen->getPtrToShape(buf, shapeNum);
+ if (!shapePtr)
+ return 0;
+
+ int shapeSize = _screen->getShapeSize(shapePtr);
+
+ if (getTableSize(_shapePoolBuffer) < shapeSize) {
+ // XXX
+ error("[1] unimplemented table handling");
+ }
+
+ uint8 *ptr = allocTableSpace(_shapePoolBuffer, shapeSize, id);
+
+ if (!ptr) {
+ // XXX
+ error("[2] unimplemented table handling");
+ }
+
+ if (!ptr) {
+ warning("adding shape %d to _shapePoolBuffer not possible, not enough space left\n", id);
+ return shapeSize;
+ }
+
+ memcpy(ptr, shapePtr, shapeSize);
+ return shapeSize;
+}
+
+int KyraEngine_v3::getTableSize(uint8 *buf) {
+ debugC(9, kDebugLevelMain, "KyraEngine::getTableSize(%p)", (void *)buf);
+ updateTableBuffer(buf);
+
+ if (*((uint16*)(_tableBuffer1 + 4)) >= 450)
+ return 0;
+
+ return (*((uint32*)(_tableBuffer1 + 6)) << 4);
+}
+
+uint8 *KyraEngine_v3::allocTableSpace(uint8 *buf, int size, int id) {
+ debugC(9, kDebugLevelMain, "KyraEngine::allocTableSpace(%p, %d, %d)", (void *)buf, size, id);
+
+ if (!buf || !size)
+ return 0;
+
+ updateTableBuffer(buf);
+
+ int entries = *(uint16*)(_tableBuffer1 + 4);
+
+ if (entries >= 450)
+ return 0;
+
+ size += 0xF;
+ size &= 0xFFFFFFF0;
+
+ uint size2 = size >> 4;
+
+ if (*(uint32*)(_tableBuffer1 + 6) < size2)
+ return 0;
+
+ int unk1 = *(uint16*)(_tableBuffer1);
+ int usedEntry = unk1;
+ int ok = 0;
+
+ for (; usedEntry < entries; ++usedEntry) {
+ if (size2 <= *(uint32*)(_tableBuffer1 + usedEntry * 14 + 22)) {
+ ok = 1;
+ break;
+ }
+ }
+
+ if (!ok)
+ return 0;
+
+ ok = 0;
+ int unk3 = unk1 - 1;
+ while (ok <= unk3) {
+ int temp = (ok + unk3) >> 1;
+
+ if (*(uint32*)(_tableBuffer1 + temp * 14 + 12) >= (uint)id) {
+ if (*(uint32*)(_tableBuffer1 + temp * 14 + 12) <= (uint)id) {
+ return 0;
+ } else {
+ unk3 = temp - 1;
+ continue;
+ }
+ }
+
+ ok = temp + 1;
+ }
+
+ uint8 *buf2 = _tableBuffer1 + usedEntry * 14;
+
+ uint unkValue1 = *(uint32*)(buf2 + 16);
+ uint unkValue2 = *(uint32*)(buf2 + 22);
+
+ if (size2 < unkValue2) {
+ *(uint32*)(buf2 + 22) = unkValue2 - size2;
+ *(uint32*)(buf2 + 16) = unkValue1 + size;
+ memcpy(_tableBuffer1 + entries * 14 + 12, _tableBuffer1 + unk1 * 14 + 12, 14);
+ } else {
+ if (usedEntry > unk1) {
+ memcpy(buf2 + 12, _tableBuffer1 + unk1 * 14 + 12, 14);
+ }
+ int temp = *(uint16*)(_tableBuffer1 + 2) - 1;
+ *(uint16*)(_tableBuffer1 + 2) = temp;
+ temp = *(uint16*)(_tableBuffer1 + 4) - 1;
+ *(uint16*)(_tableBuffer1 + 4) = temp;
+ }
+
+ for (int i = unk1; i > ok; --i) {
+ memcpy(_tableBuffer1 + i * 14 + 12, _tableBuffer1 + (i-1) * 14 + 12, 14);
+ }
+
+ buf2 = _tableBuffer1 + ok * 14;
+
+ *(uint32*)(buf2 + 12) = id;
+ *(uint32*)(buf2 + 16) = unkValue1;
+ *(uint32*)(buf2 + 20) = (_system->getMillis() / 60) >> 4;
+ *(uint32*)(buf2 + 22) = size2;
+
+ int temp = *(uint16*)(_tableBuffer1) + 1;
+ *(uint16*)(_tableBuffer1) = temp;
+ temp = *(uint16*)(_tableBuffer1 + 4) + 1;
+ *(uint16*)(_tableBuffer1 + 4) = temp;
+
+ if (temp > *(uint16*)(_tableBuffer1 + 10)) {
+ *(uint16*)(_tableBuffer1 + 10) = temp;
+ if (temp > _unkTableValue)
+ _unkTableValue = temp;
+ }
+
+ temp = *(uint32*)(_tableBuffer1 + 6) - size2;
+ *(uint32*)(_tableBuffer1 + 6) = temp;
+
+ return _tableBuffer2 + unkValue1;
+}
+
+namespace {
+int tableIdCompare(const void *l, const void *r) {
+ int lV = *(const uint32*)(l);
+ int rV = *(const uint32*)(r);
+
+ return CLIP(lV - rV, -1, 1);
+}
+}
+
+uint8 *KyraEngine_v3::findIdInTable(uint8 *buf, int id) {
+ debugC(9, kDebugLevelMain, "KyraEngine::findIdInTable(%p, %d)", (void *)buf, id);
+
+ updateTableBuffer(buf);
+
+ uint32 idVal = id;
+ uint8 *ptr = (uint8*)bsearch(&idVal, _tableBuffer1 + 12, *(uint16*)(_tableBuffer1), 14, &tableIdCompare);
+
+ if (!ptr) {
+ return 0;
+ }
+
+ return _tableBuffer2 + *(uint32*)(ptr + 4);
+}
+
+uint8 *KyraEngine_v3::findShapeInTable(int id) {
+ debugC(9, kDebugLevelMain, "KyraEngine::findShapeInTable(%d)", id);
+
+ return findIdInTable(_shapePoolBuffer, id);
+}
+
+#pragma mark - items
+
+void KyraEngine_v3::initItems() {
+ debugC(9, kDebugLevelMain, "KyraEngine::initItems()");
+
+ _screen->loadBitmap("ITEMS.CSH", 3, 3, 0);
+
+ for (int i = 248; i <= 319; ++i) {
+ addShapeToTable(_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);
+ }
+
+ uint32 size = 0;
+ uint8 *itemsDat = _res->fileData("_ITEMS.DAT", &size);
+
+ assert(size >= 72+144);
+
+ memcpy(_itemBuffer1, itemsDat , 72);
+ memcpy(_itemBuffer2, itemsDat+72, 144);
+
+ delete [] itemsDat;
+
+ _screen->_curPage = 0;
+}
+
+#pragma mark -
+
+int KyraEngine_v3::getMaxFileSize(const char *file) {
+ debugC(9, kDebugLevelMain, "KyraEngine::getMaxFileSize(%s)", file);
+ int size = 0;
+
+ char buffer[32];
+
+ for (int i = 0; i < _languageExtensionSize; ++i) {
+ strncpy(buffer, file, 32);
+ size = MAX<uint32>(size, _res->getFileSize(appendLanguage(buffer, i, sizeof(buffer))));
+ }
+
+ return size + 20;
+}
+
+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);
+ assert(lang < _languageExtensionSize);
+
+ int size = strlen(buf) + strlen(_languageExtension[lang]);
+
+ if (size > bufSize) {
+ warning("buffer too small to append language extension");
+ return 0;
+ }
+
+ char *temp = buf + strlen(buf);
+ bufSize -= strlen(buf);
+
+ strncat(temp, _languageExtension[lang], bufSize);
+
+ return buf;
+}
+
+bool KyraEngine_v3::loadLanguageFile(const char *file, uint8 *&buffer) {
+ debugC(9, kDebugLevelMain, "KyraEngine::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;
+}
+
+} // end of namespace Kyra
diff --git a/engines/kyra/kyra_v3.h b/engines/kyra/kyra_v3.h
new file mode 100644
index 0000000000..7f3f476c15
--- /dev/null
+++ b/engines/kyra/kyra_v3.h
@@ -0,0 +1,146 @@
+/* ScummVM - Scumm Interpreter
+ * Copyright (C) 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$
+ *
+ */
+
+#ifndef KYRA_KYRA_V3_H
+#define KYRA_KYRA_V3_H
+
+#include "kyra/kyra.h"
+
+namespace Kyra {
+
+// maybe subclass KyraEngine_v2 later
+class WSAMovieV2;
+
+class KyraEngine_v3 : public KyraEngine {
+public:
+ KyraEngine_v3(OSystem *system, const GameFlags &flags);
+ ~KyraEngine_v3();
+
+ Movie *createWSAMovie();
+
+ SoundDigital *soundDigital() { return _soundDigital; }
+
+ int go();
+
+ void playVQA(const char *name);
+private:
+ int init();
+
+ void preinit();
+ void realInit();
+
+ SoundDigital *_soundDigital;
+
+ // sound specific
+private:
+ void playMenuAudioFile();
+
+ int _musicSoundChannel;
+ const char *_menuAudioFile;
+
+ static const char *_soundList[];
+ static const int _soundListSize;
+
+ int _curMusicTrack;
+
+ void playMusicTrack(int track, int force);
+ void stopMusicTrack();
+
+ int musicUpdate(int forceRestart);
+
+ virtual void gui_initMainMenu();
+ virtual void gui_updateMainMenuAnimation();
+
+ // unknown
+private:
+ uint8 *_unkPage1;
+ uint8 *_unkPage2;
+
+ uint8 *_unkBuffer5;
+ uint8 *_unkBuffer6;
+ uint8 *_unkBuffer7;
+ uint8 *_unkBuffer9;
+
+ uint8 *_costpalData;
+
+ uint8 *_unkWSAPtr;
+
+ uint8 *_unkShapeTable[20];
+
+ // main menu
+ Movie *_mainMenuLogo;
+ int _mainMenuFrame;
+ int _mainMenuFrameAdd;
+
+ // translation stuff
+ uint8 *_scoreFile;
+ uint8 *_cCodeFile;
+ uint8 *_scenesList;
+
+ // interface?
+ uint8 *_interfaceCPS1;
+ uint8 *_interfaceCPS2;
+
+ // shapes
+ uint8 *_gameShapes[50];
+ uint8 *_shapePoolBuffer;
+
+ uint8 *_mouseSHPBuf;
+
+ // items
+ uint8 *_itemBuffer1;
+ uint8 *_itemBuffer2;
+
+ uint8 *_itemList;
+
+ void initItems();
+
+ // used for CSH loading and some sound stuff (maybe voice files?)
+private:
+ uint8 *_tableBuffer1;
+ uint8 *_tableBuffer2;
+ int _unkTableValue;
+
+ // do not think of thouching the code belonging to these functions
+ int initTableBuffer(uint8 *buf, int size);
+ void updateTableBuffer(uint8 *buf);
+ int getTableSize(uint8 *buf);
+ uint8 *allocTableSpace(uint8 *buf, int size, int id);
+ uint8 *findIdInTable(uint8 *buf, int id);
+
+ int addShapeToTable(const uint8 *buf, int id, int shapeNum);
+ uint8 *findShapeInTable(int id);
+
+ // resource specific
+private:
+ static const char *_languageExtension[];
+ static const int _languageExtensionSize;
+
+ int getMaxFileSize(const char *file);
+ char *appendLanguage(char *buf, int lang, int bufSize);
+
+ bool loadLanguageFile(const char *file, uint8 *&buffer);
+};
+
+} // end of namespace Kyra
+
+#endif