aboutsummaryrefslogtreecommitdiff
path: root/engines/prince
diff options
context:
space:
mode:
Diffstat (limited to 'engines/prince')
-rw-r--r--engines/prince/animation.cpp155
-rw-r--r--engines/prince/animation.h66
-rw-r--r--engines/prince/archive.cpp146
-rw-r--r--engines/prince/archive.h63
-rw-r--r--engines/prince/common.h47
-rw-r--r--engines/prince/configure.engine3
-rw-r--r--engines/prince/cursor.cpp54
-rw-r--r--engines/prince/cursor.h50
-rw-r--r--engines/prince/debugger.cpp156
-rw-r--r--engines/prince/debugger.h57
-rw-r--r--engines/prince/decompress.cpp171
-rw-r--r--engines/prince/decompress.h44
-rw-r--r--engines/prince/detection.cpp147
-rw-r--r--engines/prince/flags.cpp406
-rw-r--r--engines/prince/flags.h416
-rw-r--r--engines/prince/font.cpp91
-rw-r--r--engines/prince/font.h70
-rw-r--r--engines/prince/graphics.cpp87
-rw-r--r--engines/prince/graphics.h61
-rw-r--r--engines/prince/hero.cpp333
-rw-r--r--engines/prince/hero.h160
-rw-r--r--engines/prince/hero_set.cpp243
-rw-r--r--engines/prince/hero_set.h30
-rw-r--r--engines/prince/mhwanh.cpp74
-rw-r--r--engines/prince/mhwanh.h67
-rw-r--r--engines/prince/mob.cpp101
-rw-r--r--engines/prince/mob.h86
-rw-r--r--engines/prince/module.mk29
-rw-r--r--engines/prince/musNum.h87
-rw-r--r--engines/prince/object.cpp84
-rw-r--r--engines/prince/object.h49
-rw-r--r--engines/prince/prince.cpp707
-rw-r--r--engines/prince/prince.h197
-rw-r--r--engines/prince/resource.h102
-rw-r--r--engines/prince/script.cpp1452
-rw-r--r--engines/prince/script.h321
-rw-r--r--engines/prince/sound.cpp222
-rw-r--r--engines/prince/sound.h74
-rw-r--r--engines/prince/variatxt.cpp59
-rw-r--r--engines/prince/variatxt.h44
40 files changed, 6811 insertions, 0 deletions
diff --git a/engines/prince/animation.cpp b/engines/prince/animation.cpp
new file mode 100644
index 0000000000..8edf9d04ee
--- /dev/null
+++ b/engines/prince/animation.cpp
@@ -0,0 +1,155 @@
+/* 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.
+ *
+ */
+
+#include "prince/animation.h"
+#include "prince/decompress.h"
+
+#include "common/debug.h"
+#include "common/endian.h"
+
+namespace Prince {
+
+bool Animation::loadFromStream(Common::SeekableReadStream &stream) {
+ _dataSize = stream.size();
+ _data = (byte*) malloc(_dataSize);
+
+ if (stream.read(_data, _dataSize) != _dataSize) {
+ free(_data);
+ return false;
+ }
+ return true;
+}
+/*
+const Graphics::Surface * Animation::getSurface(uint16 frameIndex) {
+ // bida kaszing
+ if (frameIndex >= _frameList.size()) {
+ _frameList.resize(frameIndex);
+ _frameList.push_back(_helper->getFrame(frameIndex));
+
+ }
+ return _frameList[frameIndex];
+}
+*/
+Animation::Animation(): _data(NULL) {
+
+}
+
+Animation::Animation(byte *data, uint32 dataSize)
+ : _data(data), _dataSize(dataSize) {
+}
+
+Animation::~Animation() {
+ free(_data);
+}
+
+void Animation::clear() {
+ if (_data != NULL) {
+ free(_data);
+ }
+}
+
+// TEMP
+/*
+int8 Animation::getZoom(uint16 offset) const {
+ return *(uint8*)(_data+offset);
+}
+*/
+int16 Animation::getZoom(uint16 offset) const {
+ return READ_LE_UINT16(_data + offset);
+}
+
+int16 Animation::getLoopCount() const {
+ return READ_LE_UINT16(_data + 2);
+}
+
+int16 Animation::getBaseX() const {
+ return READ_LE_UINT16(_data + 8);
+}
+
+int16 Animation::getBaseY() const {
+ return READ_LE_UINT16(_data + 10);
+}
+
+uint Animation::getPhaseCount() const {
+ return READ_LE_UINT16(_data + 4);
+}
+
+uint Animation::getFrameCount() const {
+ return READ_LE_UINT16(_data + 6);
+}
+
+int16 Animation::getPhaseOffsetX(uint phaseIndex) const {
+ return READ_LE_UINT16(getPhaseEntry(phaseIndex) + 0);
+}
+
+int16 Animation::getPhaseOffsetY(uint phaseIndex) const {
+ return READ_LE_UINT16(getPhaseEntry(phaseIndex) + 2);
+}
+
+int16 Animation::getPhaseFrameIndex(uint phaseIndex) const {
+ return READ_LE_UINT16(getPhaseEntry(phaseIndex) + 4);
+}
+
+int16 Animation::getFrameWidth(uint frameIndex) const {
+ byte *frameData = _data + READ_LE_UINT32(_data + 16 + frameIndex * 4);
+ return READ_LE_UINT16(frameData + 0);
+}
+
+int16 Animation::getFrameHeight(uint frameIndex) const {
+ byte *frameData = _data + READ_LE_UINT32(_data + 16 + frameIndex * 4);
+ return READ_LE_UINT16(frameData + 2);
+}
+
+Graphics::Surface *Animation::getFrame(uint frameIndex) {
+ byte *frameData = _data + READ_LE_UINT32(_data + 16 + frameIndex * 4);
+ int16 width = READ_LE_UINT16(frameData + 0);
+ int16 height = READ_LE_UINT16(frameData + 2);
+ debug("width = %d; height = %d", width, height);
+ Graphics::Surface *surf = new Graphics::Surface();
+ surf->create(width, height, Graphics::PixelFormat::createFormatCLUT8());
+ debug("frameData %p", frameData);
+ if (READ_BE_UINT32(frameData + 4) == 0x6D61736D) {
+ // Compressed
+ Decompressor dec;
+ uint32 ddataSize = READ_LE_UINT32(frameData + 8);
+ byte *ddata = new byte[ddataSize];
+ dec.decompress(frameData + 12, ddata, ddataSize);
+ for (uint16 i = 0; i < height; ++i) {
+ memcpy(surf->getBasePtr(0, i), ddata + width * i, width);
+ }
+ delete[] ddata;
+ } else {
+ // Uncompressed
+ for (uint16 i = 0; i < height; ++i) {
+ memcpy(surf->getBasePtr(0, i), frameData + 4 + width * i, width);
+ }
+ }
+ return surf;
+}
+
+byte *Animation::getPhaseEntry(uint phaseIndex) const {
+ return _data + READ_LE_UINT32(_data + 12) + phaseIndex * 8;
+}
+
+}
+
+/* vim: set tabstop=4 noexpandtab: */
diff --git a/engines/prince/animation.h b/engines/prince/animation.h
new file mode 100644
index 0000000000..710f8730cc
--- /dev/null
+++ b/engines/prince/animation.h
@@ -0,0 +1,66 @@
+/* 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.
+ *
+ */
+
+#ifndef PRINCE_ANIMATION_H
+#define PRINCE_ANIMATION_H
+
+#include "common/array.h"
+#include "common/stream.h"
+
+#include "graphics/surface.h"
+
+namespace Prince {
+
+class Animation {
+public:
+ bool loadFromStream(Common::SeekableReadStream &stream);
+ //const Graphics::Surface *getSurface(uint16 frameIndex);
+
+ Animation();
+ Animation(byte *data, uint32 dataSize);
+ ~Animation();
+ int16 getLoopCount() const;
+ int16 getBaseX() const;
+ int16 getBaseY() const;
+ uint getPhaseCount() const;
+ uint getFrameCount() const;
+ int16 getPhaseOffsetX(uint phaseIndex) const;
+ int16 getPhaseOffsetY(uint phaseIndex) const;
+ int16 getPhaseFrameIndex(uint phaseIndex) const;
+ Graphics::Surface *getFrame(uint frameIndex);
+ int16 getFrameWidth(uint frameIndex) const;
+ int16 getFrameHeight(uint frameIndex) const;
+ int16 getZoom(uint16 offset) const;
+ void clear();
+
+private:
+ Common::Array<Graphics::Surface *> _frameList;
+ byte *_data;
+ uint32 _dataSize;
+ byte *getPhaseEntry(uint phaseIndex) const;
+};
+
+}
+
+#endif
+
+/* vim: set tabstop=4 noexpandtab: */
diff --git a/engines/prince/archive.cpp b/engines/prince/archive.cpp
new file mode 100644
index 0000000000..d1b680c204
--- /dev/null
+++ b/engines/prince/archive.cpp
@@ -0,0 +1,146 @@
+/* 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.
+ *
+ */
+
+#include "prince/archive.h"
+#include "prince/decompress.h"
+
+#include "common/stream.h"
+#include "common/debug.h"
+#include "common/memstream.h"
+
+namespace Prince {
+
+PtcArchive::PtcArchive() : _stream(NULL) {
+}
+
+PtcArchive::~PtcArchive() {
+ close();
+}
+
+static void decrypt(byte *buffer, uint32 size) {
+ uint32 key = 0xDEADF00D;
+ while (size--) {
+ *buffer++ += key & 0xFF;
+ key ^= 0x2E84299A;
+ key += 0x424C4148;
+ key = ((key & 1) << 31) | (key >> 1);
+ }
+}
+
+bool PtcArchive::open(const Common::String &filename) {
+ _stream = SearchMan.createReadStreamForMember(filename);
+ if (!_stream)
+ return false;
+
+ uint32 magic = _stream->readUint32LE();
+ uint32 fileTableOffset = _stream->readUint32LE() ^ 0x4D4F4B2D; // MOK-
+ uint32 fileTableSize = _stream->readUint32LE() ^ 0x534F4654; // SOFT
+
+ //debug("fileTableOffset : %08X", fileTableOffset);
+ //debug("fileTableSize: %08X", fileTableSize);
+
+ _stream->seek(fileTableOffset);
+
+ byte *fileTable = new byte[fileTableSize];
+ byte *fileTableEnd = fileTable + fileTableSize;
+ _stream->read(fileTable, fileTableSize);
+ decrypt(fileTable, fileTableSize);
+
+ for (byte *fileItem = fileTable; fileItem < fileTableEnd; fileItem += 32) {
+ FileEntry item;
+ Common::String name = (const char*)fileItem;
+ item._offset = READ_LE_UINT32(fileItem + 24);
+ item._size = READ_LE_UINT32(fileItem + 28);
+ //debug("%12s %8X %d", name.c_str(), item._offset, item._size);
+ _items[name] = item;
+ }
+
+ delete[] fileTable;
+
+ return true;
+}
+
+void PtcArchive::close() {
+ delete _stream;
+ _stream = NULL;
+ _items.clear();
+}
+
+bool PtcArchive::hasFile(const Common::String &name) const {
+ // TODO: check if path matching should be added
+ return _items.contains(name);
+}
+
+int PtcArchive::listMembers(Common::ArchiveMemberList &list) const {
+ int matches = 0;
+
+ for (FileMap::const_iterator it = _items.begin(); it != _items.end(); ++it) {
+ list.push_back(Common::ArchiveMemberList::value_type(new Common::GenericArchiveMember(it->_key, this)));
+ matches++;
+ }
+
+ return matches;
+}
+
+const Common::ArchiveMemberPtr PtcArchive::getMember(const Common::String &name) const {
+ if (!_items.contains(name)) {
+ Common::ArchiveMemberPtr();
+ }
+ return Common::ArchiveMemberList::value_type(new Common::GenericArchiveMember(name, this));
+}
+
+Common::SeekableReadStream *PtcArchive::createReadStreamForMember(const Common::String &name) const {
+ if (!_items.contains(name)) {
+ return 0;
+ }
+
+ const FileEntry &entryHeader = _items[name];
+
+ if (entryHeader._size < 4)
+ return 0;
+
+ uint32 size = entryHeader._size;
+
+ _stream->seek(entryHeader._offset);
+
+ // This *HAS* to be malloc (not new[]) because MemoryReadStream uses free() to free the memory
+ byte* buffer = (byte *)malloc(size);
+ _stream->read(buffer, size);
+
+ if (READ_BE_UINT32(buffer) == 0x4D41534D) {
+ Decompressor dec;
+ uint32 decompLen = READ_BE_UINT32(buffer + 14);
+ byte *decompData = (byte*)malloc(decompLen);
+ dec.decompress(buffer + 18, decompData, decompLen);
+ free(buffer);
+ size = decompLen;
+ buffer = decompData;
+ }
+
+ //debug("PtcArchive::createReadStreamForMember name %s", name.c_str());
+
+ return new Common::MemoryReadStream(buffer, size, DisposeAfterUse::YES);
+}
+
+}
+
+/* vim: set tabstop=4 noexpandtab: */
diff --git a/engines/prince/archive.h b/engines/prince/archive.h
new file mode 100644
index 0000000000..29d3d58560
--- /dev/null
+++ b/engines/prince/archive.h
@@ -0,0 +1,63 @@
+/* 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.
+ *
+ */
+
+#ifndef PRINCE_ARCHIVE_H
+#define PRINCE_ARCHIVE_H
+
+#include "common/archive.h"
+#include "common/hashmap.h"
+#include "common/hash-str.h"
+
+namespace Prince {
+
+class PtcArchive : public Common::Archive {
+public:
+ PtcArchive();
+ ~PtcArchive();
+
+ bool open(const Common::String &filename);
+ void close();
+ bool isOpen() const { return _stream != 0; }
+
+ // Common::Archive API implementation
+ bool hasFile(const Common::String &name) const;
+ int listMembers(Common::ArchiveMemberList &list) const;
+ const Common::ArchiveMemberPtr getMember(const Common::String &name) const;
+ Common::SeekableReadStream *createReadStreamForMember(const Common::String &name) const;
+
+private:
+ struct FileEntry {
+ uint32 _offset;
+ uint32 _size;
+ };
+
+ Common::SeekableReadStream *_stream;
+
+ typedef Common::HashMap<Common::String, FileEntry, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> FileMap;
+ FileMap _items;
+};
+
+} // End of namespace Prince
+
+#endif
+
+/* vim: set tabstop=4 noexpandtab: */
diff --git a/engines/prince/common.h b/engines/prince/common.h
new file mode 100644
index 0000000000..6dc1bad6a8
--- /dev/null
+++ b/engines/prince/common.h
@@ -0,0 +1,47 @@
+/* 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.
+ *
+ */
+
+#ifndef PRINCE_COMMON_H
+#define PRINCE_COMMON_H
+
+namespace Prince {
+
+enum Direction {
+ LD = 0,
+ L = 1,
+ LG = 2,
+ PD = 3,
+ P = 4,
+ PG = 5,
+ GL = 6,
+ G = 7,
+ GP = 8,
+ DL = 9,
+ D = 10,
+ DP = 11
+};
+
+}
+
+#endif
+
+/* vim: set tabstop=4 noexpandtab: */
diff --git a/engines/prince/configure.engine b/engines/prince/configure.engine
new file mode 100644
index 0000000000..50740d9f41
--- /dev/null
+++ b/engines/prince/configure.engine
@@ -0,0 +1,3 @@
+# This file is included from the main "configure" script
+# add_engine [name] [desc] [build-by-default] [subengines] [base games] [deps]
+add_engine prince "The Prince and The Coward" no
diff --git a/engines/prince/cursor.cpp b/engines/prince/cursor.cpp
new file mode 100644
index 0000000000..865ae99cad
--- /dev/null
+++ b/engines/prince/cursor.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.
+ *
+ */
+
+#include "prince/cursor.h"
+
+#include "common/debug.h"
+#include "common/stream.h"
+
+namespace Prince {
+
+Cursor::Cursor() : _surface(NULL) {
+}
+
+Cursor::~Cursor() {
+ _surface->free();
+ delete _surface;
+ _surface = NULL;
+}
+
+bool Cursor::loadFromStream(Common::SeekableReadStream &stream) {
+ stream.skip(4);
+ uint16 w = stream.readUint16LE();
+ uint16 h = stream.readUint16LE();
+
+ _surface = new Graphics::Surface();
+ _surface->create(w, h, Graphics::PixelFormat::createFormatCLUT8());
+
+ for (int ih = 0; ih < h; ++ih)
+ stream.read(_surface->getBasePtr(0, ih), w);
+ return true;
+}
+
+}
+
+/* vim: set tabstop=4 noexpandtab: */
diff --git a/engines/prince/cursor.h b/engines/prince/cursor.h
new file mode 100644
index 0000000000..70516519e6
--- /dev/null
+++ b/engines/prince/cursor.h
@@ -0,0 +1,50 @@
+/* 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.
+ *
+ */
+
+#ifndef CURSOR_PRINCE_H
+#define CURSOR_PRINCE_H
+
+#include "graphics/surface.h"
+
+namespace Common {
+ class SeekableReadStream;
+}
+
+namespace Prince {
+
+class Cursor {
+public:
+ Cursor();
+ ~Cursor();
+
+ bool loadFromStream(Common::SeekableReadStream &stream);
+ const Graphics::Surface *getSurface() const { return _surface; }
+
+private:
+ Graphics::Surface *_surface;
+};
+
+}
+
+#endif
+
+/* vim: set tabstop=4 expandtab!: */
diff --git a/engines/prince/debugger.cpp b/engines/prince/debugger.cpp
new file mode 100644
index 0000000000..d9264cb02d
--- /dev/null
+++ b/engines/prince/debugger.cpp
@@ -0,0 +1,156 @@
+/* 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.
+ *
+ */
+
+#include "prince/debugger.h"
+#include "prince/prince.h"
+
+namespace Prince {
+
+Debugger::Debugger(PrinceEngine *vm) : GUI::Debugger(), _vm(vm), _locationNr(0) {
+ DCmd_Register("continue", WRAP_METHOD(Debugger, Cmd_Exit));
+ DCmd_Register("level", WRAP_METHOD(Debugger, Cmd_DebugLevel));
+ DCmd_Register("setflag", WRAP_METHOD(Debugger, Cmd_SetFlag));
+ DCmd_Register("getflag", WRAP_METHOD(Debugger, Cmd_GetFlag));
+ DCmd_Register("clearflag", WRAP_METHOD(Debugger, Cmd_ClearFlag));
+ DCmd_Register("viewflc", WRAP_METHOD(Debugger, Cmd_ViewFlc));
+ DCmd_Register("initroom", WRAP_METHOD(Debugger, Cmd_InitRoom));
+ DCmd_Register("changecursor", WRAP_METHOD(Debugger, Cmd_ChangeCursor));
+}
+
+static int strToInt(const char *s) {
+ if (!*s)
+ // No string at all
+ return 0;
+ else if (toupper(s[strlen(s) - 1]) != 'H')
+ // Standard decimal string
+ return atoi(s);
+
+ // Hexadecimal string
+ uint tmp = 0;
+ int read = sscanf(s, "%xh", &tmp);
+ if (read < 1)
+ error("strToInt failed on string \"%s\"", s);
+ return (int)tmp;
+}
+
+bool Debugger::Cmd_DebugLevel(int argc, const char **argv) {
+ if (argc == 1) {
+ DebugPrintf("Debugging is currently set at level %d\n", gDebugLevel);
+ } else { // set level
+ gDebugLevel = atoi(argv[1]);
+ if (0 <= gDebugLevel && gDebugLevel < 11) {
+ DebugPrintf("Debug level set to level %d\n", gDebugLevel);
+ } else if (gDebugLevel < 0) {
+ DebugPrintf("Debugging is now disabled\n");
+ } else
+ DebugPrintf("Not a valid debug level (0 - 10)\n");
+ }
+
+ return true;
+}
+
+/*
+ * This command sets a flag
+ */
+bool Debugger::Cmd_SetFlag(int argc, const char **argv) {
+ // Check for a flag to set
+ if (argc != 2) {
+ DebugPrintf("Usage: %s <flag number>\n", argv[0]);
+ return true;
+ }
+
+ int flagNum = strToInt(argv[1]);
+ //g_globals->setFlag(flagNum);
+ return true;
+}
+
+/*
+ * This command gets the value of a flag
+ */
+bool Debugger::Cmd_GetFlag(int argc, const char **argv) {
+ // Check for an flag to display
+ if (argc != 2) {
+ DebugPrintf("Usage: %s <flag number>\n", argv[0]);
+ return true;
+ }
+
+ int flagNum = strToInt(argv[1]);
+ //DebugPrintf("Value: %d\n", g_globals->getFlag(flagNum));
+ return true;
+}
+
+/*
+ * This command clears a flag
+ */
+bool Debugger::Cmd_ClearFlag(int argc, const char **argv) {
+ // Check for a flag to clear
+ if (argc != 2) {
+ DebugPrintf("Usage: %s <flag number>\n", argv[0]);
+ return true;
+ }
+
+ int flagNum = strToInt(argv[1]);
+ //g_globals->clearFlag(flagNum);
+ return true;
+}
+
+/*
+ * This command starts new flc anim
+ */
+bool Debugger::Cmd_ViewFlc(int argc, const char **argv) {
+ // Check for a flag to clear
+ if (argc != 2) {
+ DebugPrintf("Usage: %s <anim number>\n", argv[0]);
+ return true;
+ }
+
+ int flagNum = strToInt(argv[1]);
+ _vm->loadAnim(flagNum, false);
+ return true;
+}
+
+bool Debugger::Cmd_InitRoom(int argc, const char **argv) {
+ // Check for a flag to clear
+ if (argc != 2) {
+ DebugPrintf("Usage: %s <anim number>\n", argv[0]);
+ return true;
+ }
+
+ _locationNr = strToInt(argv[1]);
+ return true;
+}
+
+bool Debugger::Cmd_ChangeCursor(int argc, const char **argv) {
+ // Check for a flag to clear
+ if (argc != 2) {
+ DebugPrintf("Usage: %s <curId>\n", argv[0]);
+ return true;
+ }
+
+ _cursorNr = strToInt(argv[1]);
+
+ return true;
+}
+
+}
+
+/* vim: set tabstop=4 noexpandtab: */
diff --git a/engines/prince/debugger.h b/engines/prince/debugger.h
new file mode 100644
index 0000000000..f3608af81d
--- /dev/null
+++ b/engines/prince/debugger.h
@@ -0,0 +1,57 @@
+/* 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.
+ *
+ */
+
+#ifndef PRINCE_DEBUGGER_H
+#define PRINCE_DEBUGGER_H
+
+#include "common/scummsys.h"
+#include "gui/debugger.h"
+
+namespace Prince {
+
+class PrinceEngine;
+
+class Debugger : public GUI::Debugger {
+public:
+ Debugger(PrinceEngine *vm);
+ virtual ~Debugger() {} // we need this for __SYMBIAN32__ archaic gcc/UIQ
+
+ uint8 _locationNr;
+ uint8 _cursorNr;
+
+private:
+ bool Cmd_DebugLevel(int argc, const char **argv);
+ bool Cmd_SetFlag(int argc, const char **argv);
+ bool Cmd_GetFlag(int argc, const char **argv);
+ bool Cmd_ClearFlag(int argc, const char **argv);
+ bool Cmd_ViewFlc(int argc, const char **argv);
+ bool Cmd_InitRoom(int argc, const char **argv);
+ bool Cmd_ChangeCursor(int argc, const char **argv);
+
+ PrinceEngine *_vm;
+};
+
+}
+
+#endif
+
+/* vim: set tabstop=4 noexpandtab: */
diff --git a/engines/prince/decompress.cpp b/engines/prince/decompress.cpp
new file mode 100644
index 0000000000..7fba179541
--- /dev/null
+++ b/engines/prince/decompress.cpp
@@ -0,0 +1,171 @@
+/* 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.
+ *
+ */
+
+// John_Doe's implementation
+
+#include "prince/decompress.h"
+
+namespace Prince {
+
+static const uint16 table1[] = {
+ 0x8000, 0x0002,
+ 0x4000, 0x0004,
+ 0x2000, 0x0008,
+ 0x1000, 0x0010,
+ 0x0800, 0x0020,
+ 0x0400, 0x0040,
+ 0x0200, 0x0080,
+ 0x0100, 0x0100,
+ 0x0080, 0x0200,
+ 0x0040, 0x0400
+};
+
+static const uint32 table2[] = {
+ 0x0000F000,
+ 0x0020FC00,
+ 0x00A0FF00,
+ 0x02A0FF80,
+ 0x06A0FFC0,
+ 0x0EA0FFE0,
+ 0x1EA0FFF0,
+ 0x3EA0FFF8
+};
+
+static const uint16 table3[] = {
+ 0x8000, 0x0000,
+ 0x4000, 0x0002,
+ 0x2000, 0x0006,
+ 0x1000, 0x000E,
+ 0x0800, 0x001E,
+ 0x0400, 0x003E,
+ 0x0200, 0x007E,
+ 0x0100, 0x00FE,
+ 0x0080, 0x01FE,
+ 0x0040, 0x03FE,
+ 0x0020, 0x07FE,
+ 0x0010, 0x0FFE,
+ 0x0008, 0x1FFE,
+ 0x0004, 0x3FFE,
+ 0x0002, 0x7FFE,
+ 0x0001, 0xFFFE
+};
+
+void Decompressor::decompress(byte *source, byte *dest, uint32 destSize) {
+ byte *destEnd = dest + destSize;
+ int more;
+ _src = source;
+ _dst = dest;
+ _bitBuffer = 0x80;
+ while (_dst < destEnd) {
+ uint32 ebp;
+ uint16 offset, length;
+ if (getBit()) {
+ if (getBit()) {
+ if (getBit()) {
+ if (getBit()) {
+ if (getBit()) {
+ if (getBit()) {
+ uint32 tableIndex = 0;
+ while (getBit())
+ tableIndex++;
+ length = table3[tableIndex * 2 + 0];
+ do {
+ more = !(length & 0x8000);
+ length = (length << 1) | getBit();
+ } while (more);
+ length += table3[tableIndex * 2 + 1];
+ length++;
+ memcpy(_dst, _src, length);
+ _src += length;
+ _dst += length;
+ }
+ *_dst++ = *_src++;
+ }
+ *_dst++ = *_src++;
+ }
+ *_dst++ = *_src++;
+ }
+ *_dst++ = *_src++;
+ }
+ *_dst++ = *_src++;
+ }
+ if (!getBit()) {
+ if (getBit()) {
+ uint32 tableIndex = getBit();
+ tableIndex = (tableIndex << 1) | getBit();
+ tableIndex = (tableIndex << 1) | getBit();
+ ebp = table2[tableIndex];
+ length = 1;
+ } else {
+ ebp = 0x0000FF00;
+ length = 0;
+ }
+ } else {
+ uint32 tableIndex = 0;
+ while (getBit())
+ tableIndex++;
+ length = table1[tableIndex * 2 + 0];
+ do {
+ more = !(length & 0x8000);
+ length = (length << 1) | getBit();
+ } while (more);
+ length += table1[tableIndex * 2 + 1];
+ tableIndex = getBit();
+ tableIndex = (tableIndex << 1) | getBit();
+ tableIndex = (tableIndex << 1) | getBit();
+ ebp = table2[tableIndex];
+ }
+ offset = ebp & 0xFFFF;
+ do {
+ if (_bitBuffer == 0x80) {
+ if (offset >= 0xFF00) {
+ offset = (offset << 8) | *_src++;
+ }
+ }
+ more = offset & 0x8000;
+ offset = (offset << 1) | getBit();
+ } while (more);
+ offset += (ebp >> 16);
+ length += 2;
+ while (length--) {
+ if (_dst >= destEnd) {
+ return;
+ }
+ *_dst = *(_dst - offset);
+ _dst++;
+ }
+ }
+}
+
+int Decompressor::getBit() {
+ int bit = (_bitBuffer & 0x80) >> 7;
+ _bitBuffer <<= 1;
+ if (_bitBuffer == 0) {
+ _bitBuffer = *_src++;
+ bit = (_bitBuffer & 0x80) >> 7;
+ _bitBuffer <<= 1;
+ _bitBuffer |= 1;
+ }
+ return bit;
+}
+
+} // End of namespace Prince
diff --git a/engines/prince/decompress.h b/engines/prince/decompress.h
new file mode 100644
index 0000000000..ef495db65e
--- /dev/null
+++ b/engines/prince/decompress.h
@@ -0,0 +1,44 @@
+/* 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.
+ *
+ */
+
+// John_Doe's implementation
+
+#ifndef PRINCE_DECOMPRESS_H
+#define PRINCE_DECOMPRESS_H
+
+#include "engines/util.h"
+
+namespace Prince {
+
+class Decompressor {
+public:
+ void decompress(byte *source, byte *dest, uint32 destSize);
+protected:
+ byte *_src, *_dst;
+ byte _bitBuffer;
+ int _bitsLeft;
+ int getBit();
+};
+
+} // End of namespace Prince
+
+#endif
diff --git a/engines/prince/detection.cpp b/engines/prince/detection.cpp
new file mode 100644
index 0000000000..fa9df38c90
--- /dev/null
+++ b/engines/prince/detection.cpp
@@ -0,0 +1,147 @@
+/* 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.
+ *
+ */
+
+#include "base/plugins.h"
+#include "engines/advancedDetector.h"
+
+#include "prince/prince.h"
+
+namespace Prince {
+
+struct PrinceGameDescription {
+ ADGameDescription desc;
+
+ int gameType;
+};
+
+int PrinceEngine::getGameType() const {
+ return _gameDescription->gameType;
+}
+
+const char *PrinceEngine::getGameId() const {
+ return _gameDescription->desc.gameid;
+}
+
+uint32 PrinceEngine::getFeatures() const {
+ return _gameDescription->desc.flags;
+}
+
+Common::Language PrinceEngine::getLanguage() const {
+ return _gameDescription->desc.language;
+}
+
+}
+
+static const PlainGameDescriptor princeGames[] = {
+ {"prince", "Prince Game"},
+ {0, 0}
+};
+
+namespace Prince {
+
+static const PrinceGameDescription gameDescriptions[] = {
+
+ // German
+ {
+ {
+ "prince",
+ "Galador",
+ AD_ENTRY1s("databank.ptc", "5fa03833177331214ec1354761b1d2ee", 3565031),
+ Common::DE_DEU,
+ Common::kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO1(GUIO_NONE)
+ },
+ 0
+ },
+ // Polish
+ {
+ {
+ "prince",
+ "Ksiaze i Tchorz",
+ AD_ENTRY1s("databank.ptc", "48ec9806bda9d152acbea8ce31c93c49", 3435298),
+ Common::PL_POL,
+ Common::kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO1(GUIO_NONE)
+ },
+ 1
+ },
+
+
+ { AD_TABLE_END_MARKER, 0 }
+};
+
+} // End of namespace Prince
+
+using namespace Prince;
+
+// we match from data too, to stop detection from a non-top-level directory
+const static char *directoryGlobs[] = {
+ "all",
+ 0
+};
+
+class PrinceMetaEngine : public AdvancedMetaEngine {
+public:
+ PrinceMetaEngine() : AdvancedMetaEngine(Prince::gameDescriptions, sizeof(Prince::PrinceGameDescription), princeGames) {
+ _singleid = "prince";
+ _maxScanDepth = 2;
+ _directoryGlobs = directoryGlobs;
+ }
+
+ virtual const char *getName() const {
+ return "Prince Engine";
+ }
+
+ virtual const char *getOriginalCopyright() const {
+ return "Copyright (C)";
+ }
+
+ virtual bool createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const;
+ virtual bool hasFeature(MetaEngineFeature f) const;
+};
+
+bool PrinceMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {
+ using namespace Prince;
+ const PrinceGameDescription *gd = (const PrinceGameDescription *)desc;
+ if (gd) {
+ *engine = new PrinceEngine(syst, gd);
+ }
+ return gd != 0;
+}
+
+bool PrinceMetaEngine::hasFeature(MetaEngineFeature f) const {
+ return false;
+}
+
+bool Prince::PrinceEngine::hasFeature(EngineFeature f) const {
+ return false;//(f == kSupportsRTL);
+}
+
+#if PLUGIN_ENABLED_DYNAMIC(PRINCE)
+REGISTER_PLUGIN_DYNAMIC(PRINCE, PLUGIN_TYPE_ENGINE, PrinceMetaEngine);
+#else
+REGISTER_PLUGIN_STATIC(PRINCE, PLUGIN_TYPE_ENGINE, PrinceMetaEngine);
+#endif
+
+/* vim: set tabstop=4 noexpandtab: */
diff --git a/engines/prince/flags.cpp b/engines/prince/flags.cpp
new file mode 100644
index 0000000000..d6d577a575
--- /dev/null
+++ b/engines/prince/flags.cpp
@@ -0,0 +1,406 @@
+/* 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.
+ *
+ */
+
+#include "prince/flags.h"
+
+namespace Prince {
+
+const char * Flags::getFlagName(uint16 flagId)
+{
+ switch (flagId) {
+ default: return "unknown_flag";
+ case FLAGA1: return "FLAGA1";
+ case FLAGA2: return "FLAGA2";
+ case FLAGA3: return "FLAGA3";
+ case DESTX: return "DESTX";
+ case DESTY: return "DESTY";
+ case DESTD: return "DESTD";
+ case DwarfDone: return "DwarfDone";
+ case GRABARZCOUNTER: return "GRABARZCOUNTER";
+ case KIERUNEK: return "KIERUNEK";
+ case BACKFLAG1: return "BACKFLAG1";
+ case BACKFLAG2: return "BACKFLAG2";
+ case BACKFLAG3: return "BACKFLAG3";
+ case BACKFLAG4: return "BACKFLAG4";
+ case MACROFLAG1: return "MACROFLAG1";
+ case MACROFLAG2: return "MACROFLAG2";
+ case MACROFLAG3: return "MACROFLAG3";
+ case HEROLDDONE: return "HEROLDDONE";
+ case BRIDGESET: return "BRIDGESET";
+ case U_BT_1: return "U_BT_1";
+ case U_BT_2: return "U_BT_2";
+ case U_BT_3: return "U_BT_3";
+ case U_BT_4: return "U_BT_4";
+ case U_BT_5: return "U_BT_5";
+ case U_BT_6: return "U_BT_6";
+ case U_BT_7: return "U_BT_7";
+ case U_BT_8: return "U_BT_8";
+ case U_BT_9: return "U_BT_9";
+ case U_BT_COUNTER: return "U_BT_COUNTER";
+ case ARIVALDALIVE: return "ARIVALDALIVE";
+ case TALKCHAR1: return "TALKCHAR1";
+ case TalkType1: return "TalkType1";
+ case TALKROUT1: return "TALKROUT1";
+ case TALKROUT2: return "TALKROUT2";
+ case TALKROUT3: return "TALKROUT3";
+ case TALKROUT4: return "TALKROUT4";
+ case TALKANIM1: return "TALKANIM1";
+ case TALKANIM2: return "TALKANIM2";
+ case TALKCOLOR1: return "TALKCOLOR1";
+ case TALKCOLOR2: return "TALKCOLOR2";
+ case KapciuchTaken: return "KapciuchTaken";
+ case CurrentBeggarA: return "CurrentBeggarA";
+ case TempKapc: return "TempKapc";
+ case HomTaken: return "HomTaken";
+ case WizardTalk: return "WizardTalk";
+ case SunlordTalk: return "SunlordTalk";
+ case HermitTalk: return "HermitTalk";
+ case RunyMode: return "RunyMode";
+ case FatMerchantTalk: return "FatMerchantTalk";
+ case HotDogTalk: return "HotDogTalk";
+ case ThiefTalk: return "ThiefTalk";
+ case BeggarTalk: return "BeggarTalk";
+ case MonkTalk: return "MonkTalk";
+ case BardTalk: return "BardTalk";
+ case BarmanTalk: return "BarmanTalk";
+ case LeftPlayerTalk: return "LeftPlayerTalk";
+ case OczySowy: return "OczySowy";
+ case CzachySpeed1: return "CzachySpeed1";
+ case CzachySpeed2: return "CzachySpeed2";
+ case CzachySpeed3: return "CzachySpeed3";
+ case CzachySlowDown1: return "CzachySlowDown1";
+ case CzachySlowDown2: return "CzachySlowDown2";
+ case CzachySlowDown3: return "CzachySlowDown3";
+ case FjordDane: return "FjordDane";
+ case GKopany1: return "GKopany1";
+ case GKopany2: return "GKopany2";
+ case GKopany3: return "GKopany3";
+ case GKopany4: return "GKopany4";
+ case KnowGodWord: return "KnowGodWord";
+ case TALKROUT21: return "TALKROUT21";
+ case TALKROUT22: return "TALKROUT22";
+ case TALKROUT23: return "TALKROUT23";
+ case TALKROUT24: return "TALKROUT24";
+ case TalkType2: return "TalkType2";
+ case GrabarzTalk: return "GrabarzTalk";
+ case LastTalker: return "LastTalker";
+ case MapaPustelniaEnabled: return "MapaPustelniaEnabled";
+ case MapaTempleEnabled: return "MapaTempleEnabled";
+ case MapaFjordEnabled: return "MapaFjordEnabled";
+ case MapaSilmanionaEnabled: return "MapaSilmanionaEnabled";
+ case MapaKurhanEnabled: return "MapaKurhanEnabled";
+ case MapaDragonEnabled: return "MapaDragonEnabled";
+ case MapaMillEnabled: return "MapaMillEnabled";
+ case DwarfRunning: return "DwarfRunning";
+ case DwarfTalk: return "DwarfTalk";
+ case CurseLift: return "CurseLift";
+ case KosciSwapped: return "KosciSwapped";
+ case BookStolen: return "BookStolen";
+ case MapaUsable: return "MapaUsable";
+ case FjordBoss: return "FjordBoss";
+ case FjordHotDog: return "FjordHotDog";
+ case FjordLewy: return "FjordLewy";
+ case FjordPrawy: return "FjordPrawy";
+ case TalkArivald: return "TalkArivald";
+ case ShootDone: return "ShootDone";
+ case ShootRunning: return "ShootRunning";
+ case ShootKnow: return "ShootKnow";
+ case MirrorKnow: return "MirrorKnow";
+ case Gar1stTime: return "Gar1stTime";
+ case KosciTaken: return "KosciTaken";
+ case ArivGotSpell: return "ArivGotSpell";
+ case BookGiven: return "BookGiven";
+ case Wywieszka: return "Wywieszka";
+ case TalkSheila: return "TalkSheila";
+ case TalkSheila2: return "TalkSheila2";
+ case BackHuman: return "BackHuman";
+ case SkarbiecOpen: return "SkarbiecOpen";
+ case LustroTaken: return "LustroTaken";
+ case GargoyleHom: return "GargoyleHom";
+ case GargoyleBroken: return "GargoyleBroken";
+ case FjordDzien: return "FjordDzien";
+ case GargoyleHom2: return "GargoyleHom2";
+ case RunMonstersRunning: return "RunMonstersRunning";
+ case FoundPaperInCoffin: return "FoundPaperInCoffin";
+ case KnowSunlord: return "KnowSunlord";
+ case KnowSunlordTalk: return "KnowSunlordTalk";
+ case ArivaldCzyta: return "ArivaldCzyta";
+ case TelepX: return "TelepX";
+ case TelepY: return "TelepY";
+ case TelepDir: return "TelepDir";
+ case TelepRoom: return "TelepRoom";
+ case ListStolen: return "ListStolen";
+ case WifeInDoor: return "WifeInDoor";
+ case TalkWifeFlag: return "TalkWifeFlag";
+ case LetterGiven: return "LetterGiven";
+ case LutniaTaken: return "LutniaTaken";
+ case BardHomeOpen: return "BardHomeOpen";
+ case FjordNoMonsters: return "FjordNoMonsters";
+ case ShandriaWallTalking: return "ShandriaWallTalking";
+ case ShandriaWallCounter: return "ShandriaWallCounter";
+ case ShandriaWallDone: return "ShandriaWallDone";
+ case FutureDone: return "FutureDone";
+ case TalkButch: return "TalkButch";
+ case GotSzalik: return "GotSzalik";
+ case GotCzosnek: return "GotCzosnek";
+ case BearDone: return "BearDone";
+ case NekrVisited: return "NekrVisited";
+ case SunRiddle: return "SunRiddle";
+ case PtaszekAway: return "PtaszekAway";
+ case KotGadanie: return "KotGadanie";
+ case SzlafmycaTaken: return "SzlafmycaTaken";
+ case BabkaTalk: return "BabkaTalk";
+ case SellerTalk: return "SellerTalk";
+ case CzosnekDone: return "CzosnekDone";
+ case PriestCounter: return "PriestCounter";
+ case PriestGest1: return "PriestGest1";
+ case PriestGest2: return "PriestGest2";
+ case PriestGest3: return "PriestGest3";
+ case PriestGest4: return "PriestGest4";
+ case PriestAnim: return "PriestAnim";
+ case HolyWaterTaken: return "HolyWaterTaken";
+ case AxeTaken: return "AxeTaken";
+ case BadylTaken1: return "BadylTaken1";
+ case BadylTaken2: return "BadylTaken2";
+ case BadylSharpened: return "BadylSharpened";
+ case PorwanieSmoka: return "PorwanieSmoka";
+ case ShopReOpen: return "ShopReOpen";
+ case LuskaShown: return "LuskaShown";
+ case CudKnow: return "CudKnow";
+ case VampireDead: return "VampireDead";
+ case MapaVisible1: return "MapaVisible1";
+ case MapaVisible2: return "MapaVisible2";
+ case MapaVisible3: return "MapaVisible3";
+ case MapaVisible4: return "MapaVisible4";
+ case MapaVisible5: return "MapaVisible5";
+ case MapaVisible6: return "MapaVisible6";
+ case MapaVisible7: return "MapaVisible7";
+ case MapaVisible8: return "MapaVisible8";
+ case MapaVisible9: return "MapaVisible9";
+ case MapaX: return "MapaX";
+ case MapaY: return "MapaY";
+ case MapaD: return "MapaD";
+ case OldMapaX: return "OldMapaX";
+ case OldMapaY: return "OldMapaY";
+ case OldMapaD: return "OldMapaD";
+ case MovingBack: return "MovingBack";
+ case MapaCount: return "MapaCount";
+ case Pustelnia1st: return "Pustelnia1st";
+ case CzarnePole1st: return "CzarnePole1st";
+ case TalkArivNum: return "TalkArivNum";
+ case Pfui: return "Pfui";
+ case MapaSunlordEnabled:return "MapaSunlordEnabled";
+ case WebDone: return "WebDone";
+ case DragonDone: return "DragonDone";
+ case KanPlay: return "KanPlay";
+ case OldKanPlay: return "OldKanPlay";
+ case LapkiWait: return "LapkiWait";
+ case WebNoCheck: return "WebNoCheck";
+ case Perfumeria: return "Perfumeria";
+ case SmokNoCheck: return "SmokNoCheck";
+ case IluzjaBroken: return "IluzjaBroken";
+ case IluzjaWorking: return "IluzjaWorking";
+ case IluzjaCounter: return "IluzjaCounter";
+ case KurhanOpen1: return "KurhanOpen1";
+ case KastetTaken: return "KastetTaken";
+ case KastetDown: return "KastetDown";
+ case KurhanDone: return "KurhanDone";
+ case SkelCounter: return "SkelCounter";
+ case SkelDial1: return "SkelDial1";
+ case SkelDial2: return "SkelDial2";
+ case SkelDial3: return "SkelDial3";
+ case SkelDial4: return "SkelDial4";
+ case SameTalker: return "SameTalker";
+ case RunMonstersText: return "RunMonstersText";
+ case PiwnicaChecked: return "PiwnicaChecked";
+ case DragonTalked: return "DragonTalked";
+ case ToldAboutBook: return "ToldAboutBook";
+ case SilmanionaDone: return "SilmanionaDone";
+ case ToldBookCount: return "ToldBookCount";
+ case SmrodNoCheck: return "SmrodNoCheck";
+ case RopeTaken: return "RopeTaken";
+ case RopeTime: return "RopeTime";
+ case LaskaFree: return "LaskaFree";
+ case ShanSmokTalked: return "ShanSmokTalked";
+ case SwordTaken: return "SwordTaken";
+ case Mill1st: return "Mill1st";
+ case SawRat: return "SawRat";
+ case KnowRat: return "KnowRat";
+ case DziuraTimer: return "DziuraTimer";
+ case LaskaInside: return "LaskaInside";
+ case HoleBig: return "HoleBig";
+ case EnableWiedzmin: return "EnableWiedzmin";
+ case EnableTrucizna: return "EnableTrucizna";
+ case KnowPoison: return "KnowPoison";
+ case KufelTaken: return "KufelTaken";
+ case BojkaEnabled: return "BojkaEnabled";
+ case BitwaNot1st: return "BitwaNot1st";
+ case BojkaTimer: return "BojkaTimer";
+ case BojkaGirl: return "BojkaGirl";
+ case Look1st: return "Look1st";
+ case RatTaken: return "RatTaken";
+ case LaskaTalkedGr: return "LaskaTalkedGr";
+ case RatusGivus: return "RatusGivus";
+ case MamObole: return "MamObole";
+ case Speed1st: return "Speed1st";
+ case SpeedTimer: return "SpeedTimer";
+ case ProveIt: return "ProveIt";
+ case Proven: return "Proven";
+ case ShowWoalka: return "ShowWoalka";
+ case PoisonTaken: return "PoisonTaken";
+ case HellOpened: return "HellOpened";
+ case HellNoCheck: return "HellNoCheck";
+ case TalAn1: return "TalAn1";
+ case TalAn2: return "TalAn2";
+ case TalAn3: return "TalAn3";
+ case TalkDevilGuard: return "TalkDevilGuard";
+ case Sword1st: return "Sword1st";
+ case IluzjaNoCheck: return "IluzjaNoCheck";
+ case RozdzielniaNumber: return "RozdzielniaNumber";
+ case JailChecked: return "JailChecked";
+ case JailTalked: return "JailTalked";
+ case TrickFailed: return "TrickFailed";
+ case WegielVisible: return "WegielVisible";
+ case WegielTimer1: return "WegielTimer1";
+ case RandomSample: return "RandomSample";
+ case RandomSampleTimer: return "RandomSampleTimer";
+ case SampleTimer: return "SampleTimer";
+ case ZonaSample: return "ZonaSample";
+ case HoleTryAgain: return "HoleTryAgain";
+ case TeleportTimer: return "TeleportTimer";
+ case RozLezy: return "RozLezy";
+ case UdkoTimer: return "UdkoTimer";
+ case ZaworZatkany: return "ZaworZatkany";
+ case ZaworOpened: return "ZaworOpened";
+ case DoorExploded: return "DoorExploded";
+ case SkoraTaken: return "SkoraTaken";
+ case CiezkieByl: return "CiezkieByl";
+ case MamWegiel: return "MamWegiel";
+ case SwiecaAway: return "SwiecaAway";
+ case ITSAVE: return "ITSAVE";
+ case RozpadlSie: return "RozpadlSie";
+ case WegielFullTimer: return "WegielFullTimer";
+ case WegielDown: return "WegielDown";
+ case WegielDownTimer: return "WegielDownTimer";
+ case PaliSie: return "PaliSie";
+ case DiabGuardTalked: return "DiabGuardTalked";
+ case GuardsNoCheck: return "GuardsNoCheck";
+ case TalkedPowloka: return "TalkedPowloka";
+ case JailOpen: return "JailOpen";
+ case PrzytulTimer: return "PrzytulTimer";
+ case JailDone: return "JailDone";
+ case MamMonety: return "MamMonety";
+ case LotTimer: return "LotTimer";
+ case LotObj: return "LotObj";
+ case PtakTimer: return "PtakTimer";
+ case BookTimer: return "BookTimer";
+ case BookGiba: return "BookGiba";
+ case PtakLata: return "PtakLata";
+ case Podej: return "Podej";
+ case GotHint: return "GotHint";
+ case LawaLeci: return "LawaLeci";
+ case PowerKlik: return "PowerKlik";
+ case LucekBad: return "LucekBad";
+ case LucekBad1st: return "LucekBad1st";
+ case IntroDial1: return "IntroDial1";
+ case IntroDial2: return "IntroDial2";
+ case ItsOutro: return "ItsOutro";
+ case KamienComment: return "KamienComment";
+ case KamienSkip: return "KamienSkip";
+ case TesterFlag: return "TesterFlag";
+ case RememberLine: return "RememberLine";
+ case OpisLapek: return "OpisLapek";
+ case TalWait: return "TalWait";
+ case OpisKamienia: return "OpisKamienia";
+ case JumpBox: return "JumpBox";
+ case JumpBox1: return "JumpBox1";
+ case JumpBox2: return "JumpBox2";
+ case JumpBox3: return "JumpBox3";
+ case SpecPiesek: return "SpecPiesek";
+ case SpecPiesekCount: return "SpecPiesekCount";
+ case SpecPiesekGadanie: return "SpecPiesekGadanie";
+ case ZnikaFlag: return "ZnikaFlag";
+ case ZnikaTimer: return "ZnikaTimer";
+ case SowaTimer: return "SowaTimer";
+ case MamrotanieOff: return "MamrotanieOff";
+
+ case CURRMOB: return "CURRMOB";
+ case KOLOR: return "KOLOR";
+ case MBFLAG: return "MBFLAG";
+ case MXFLAG: return "MXFLAG";
+ case MYFLAG: return "MYFLAG";
+ case SCROLLTYPE: return "SCROLLTYPE";
+ case SCROLLVALUE: return "SCROLLVALUE";
+ case SCROLLVALUE2: return "SCROLLVALUE2";
+ case TALKEXITCODE: return "TALKEXITCODE";
+ case SPECROUTFLAG1: return "SPECROUTFLAG1";
+ case SPECROUTFLAG2: return "SPECROUTFLAG2";
+ case SPECROUTFLAG3: return "SPECROUTFLAG3";
+ case TALKFLAGCODE: return "TALKFLAGCODE";
+ case CURRROOM: return "CURRROOM";
+ case Talker1Init: return "Talker1Init";
+ case Talker2Init: return "Talker2Init";
+ case RESTOREROOM: return "RESTOREROOM";
+ case INVALLOWED: return "INVALLOWED";
+ case BOXSEL: return "BOXSEL";
+ case CURSEBLINK: return "CURSEBLINK";
+ case EXACTMOVE: return "EXACTMOVE";
+ case MOVEDESTX: return "MOVEDESTX";
+ case MOVEDESTY: return "MOVEDESTY";
+ case NOANTIALIAS: return "NOANTIALIAS";
+ case ESCAPED: return "ESCAPED";
+ case ALLOW1OPTION: return "ALLOW1OPTION";
+ case VOICE_H_LINE: return "VOICE_H_LINE";
+ case VOICE_A_LINE: return "VOICE_A_LINE";
+ case VOICE_B_LINE: return "VOICE_B_LINE";
+ case VOICE_C_LINE: return "VOICE_C_LINE";
+ case NOHEROATALL: return "NOHEROATALL";
+ case MOUSEENABLED: return "MOUSEENABLED";
+ case DIALINES: return "DIALINES";
+
+ case SHANWALK: return "SHANWALK";
+ case SHANDOG: return "SHANDOG";
+ case GETACTIONBACK: return "GETACTIONBACK";
+ case GETACTIONDATA: return "GETACTIONDATA";
+ case GETACTION: return "GETACTION";
+ case HEROFAST: return "HEROFAST";
+ case SELITEM: return "SELITEM";
+ case LMOUSE: return "LMOUSE";
+ case MINMX: return "MINMX";
+ case MAXMX: return "MAXMX";
+ case MINMY: return "MINMY";
+ case MAXMY: return "MAXMY";
+ case TORX1: return "TORX1";
+ case TORY1: return "TORY1";
+ case TORX2: return "TORX2";
+ case TORY2: return "TORY2";
+ case POWER: return "POWER";
+ case POWERENABLED: return "POWERENABLED";
+ case FLCRESTORE: return "FLCRESTORE";
+ case NOCLSTEXT: return "NOCLSTEXT";
+ case ESCAPED2: return "ESCAPED2";
+ }
+}
+
+}
+
+/* vim: set tabstop=4 noexpandtab: */
diff --git a/engines/prince/flags.h b/engines/prince/flags.h
new file mode 100644
index 0000000000..aa607a01fe
--- /dev/null
+++ b/engines/prince/flags.h
@@ -0,0 +1,416 @@
+/* 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.
+ *
+ */
+
+#ifndef PRINCE_FLAGS_H
+#define PRINCE_FLAGS_H
+
+#include "common/scummsys.h"
+
+namespace Prince {
+
+struct Flags {
+
+ // TODO: Remove from release build
+ // useful just for debugging
+ static const char * getFlagName(uint16 flagId);
+
+ enum Id {
+ FLAGA1 = 0x8000,
+ FLAGA2 = 0x8002,
+ FLAGA3 = 0x8004,
+ DESTX = 0x8006,
+ DESTY = 0x8008,
+ DESTD = 0x800A,
+ DwarfDone = 0x800C,
+ GRABARZCOUNTER = 0x800E,
+ KIERUNEK = 0x8010,
+ BACKFLAG1 = 0x8012,
+ BACKFLAG2 = 0x8014,
+ BACKFLAG3 = 0x8016,
+ BACKFLAG4 = 0x8018,
+ MACROFLAG1 = 0x801A,
+ MACROFLAG2 = 0x801C,
+ MACROFLAG3 = 0x801E,
+ HEROLDDONE = 0x8020,
+ BRIDGESET = 0x8022,
+ U_BT_1 = 0x8024,
+ U_BT_2 = 0x8026,
+ U_BT_3 = 0x8028,
+ U_BT_4 = 0x802A,
+ U_BT_5 = 0x802C,
+ U_BT_6 = 0x802E,
+ U_BT_7 = 0x8030,
+ U_BT_8 = 0x8032,
+ U_BT_9 = 0x8034,
+ U_BT_COUNTER = 0x8036,
+ ARIVALDALIVE = 0x8038,
+ TALKCHAR1 = 0x803A,
+ TalkType1 = 0x803C,
+ TALKROUT1 = 0x803E,
+ TALKROUT2 = 0x8042,
+ TALKROUT3 = 0x8046,
+ TALKROUT4 = 0x804A,
+ TALKANIM1 = 0x804E,
+ TALKANIM2 = 0x8050,
+ TALKCOLOR1 = 0x8052,
+ TALKCOLOR2 = 0x8054,
+ KapciuchTaken = 0x8056,
+ CurrentBeggarA = 0x8058,
+ TempKapc = 0x805A,
+ HomTaken = 0x805C,
+ WizardTalk = 0x805E,
+ SunlordTalk = 0x8060,
+ HermitTalk = 0x8062,
+ RunyMode = 0x8064,
+ FatMerchantTalk = 0x8066,
+ HotDogTalk = 0x8068,
+ ThiefTalk = 0x806A,
+ BeggarTalk = 0x806C,
+ // DwarfTalk = 0x806E, // Redefinition
+ MonkTalk = 0x8070,
+ BardTalk = 0x8072,
+ BarmanTalk = 0x8074,
+ LeftPlayerTalk = 0x8076,
+ OczySowy = 0x8078,
+ CzachySpeed1 = 0x807A,
+ CzachySpeed2 = 0x807C,
+ CzachySpeed3 = 0x807E,
+ CzachySlowDown1 = 0x8080,
+ CzachySlowDown2 = 0x8082,
+ CzachySlowDown3 = 0x8084,
+ FjordDane = 0x8086,
+ GKopany1 = 0x8088,
+ GKopany2 = 0x808A,
+ GKopany3 = 0x808C,
+ GKopany4 = 0x808E,
+ KnowGodWord = 0x8090,
+ TALKROUT21 = 0x8092,
+ TALKROUT22 = 0x8096,
+ TALKROUT23 = 0x809A,
+ TALKROUT24 = 0x809E,
+ TalkType2 = 0x80A2,
+ GrabarzTalk = 0x80A4,
+ LastTalker = 0x80A6,
+ MapaPustelniaEnabled = 0x80A8,
+ MapaTempleEnabled = 0x80AA,
+ MapaFjordEnabled = 0x80AC,
+ MapaSilmanionaEnabled = 0x80AE,
+ MapaKurhanEnabled = 0x80B0,
+ MapaDragonEnabled = 0x80B2,
+ MapaMillEnabled = 0x80B4,
+ DwarfRunning = 0x80B6,
+ DwarfTalk = 0x80B8,
+ CurseLift = 0x80BA,
+ KosciSwapped = 0x80BC,
+ BookStolen = 0x80BE,
+ MapaUsable = 0x80C0,
+ FjordBoss = 0x80C2,
+ FjordHotDog = 0x80C4,
+ FjordLewy = 0x80C6,
+ FjordPrawy = 0x80C8,
+ TalkArivald = 0x80CA,
+ ShootDone = 0x80CC,
+ ShootRunning = 0x80CE,
+ ShootKnow = 0x80D0,
+ MirrorKnow = 0x80D2,
+ Gar1stTime = 0x80D4,
+ KosciTaken = 0x80D6,
+ ArivGotSpell = 0x80D8,
+ BookGiven = 0x80DA,
+ Wywieszka = 0x80DC,
+ TalkSheila = 0x80DE,
+ TalkSheila2 = 0x80E0,
+ BackHuman = 0x80E2,
+ SkarbiecOpen = 0x80E4,
+ LustroTaken = 0x80E6,
+ GargoyleHom = 0x80E8,
+ GargoyleBroken = 0x80EA,
+ FjordDzien = 0x80EC,
+ GargoyleHom2 = 0x80EE,
+ RunMonstersRunning = 0x80F0,
+ FoundPaperInCoffin = 0x80F2,
+ KnowSunlord = 0x80F4,
+ KnowSunlordTalk = 0x80F6,
+ ArivaldCzyta = 0x80F8,
+ TelepX = 0x80FA,
+ TelepY = 0x80FC,
+ TelepDir = 0x80FE,
+ TelepRoom = 0x8100,
+ ListStolen = 0x8102,
+ WifeInDoor = 0x8104,
+ TalkWifeFlag = 0x8106,
+ LetterGiven = 0x8108,
+ LutniaTaken = 0x810A,
+ BardHomeOpen = 0x810C,
+ FjordNoMonsters = 0x810E,
+ ShandriaWallTalking = 0x8110,
+ ShandriaWallCounter = 0x8112,
+ ShandriaWallDone = 0x8114,
+ FutureDone = 0x8116,
+ TalkButch = 0x8118,
+ GotSzalik = 0x811A,
+ GotCzosnek = 0x811C,
+ BearDone = 0x811E,
+ NekrVisited = 0x8120,
+ SunRiddle = 0x8122,
+ PtaszekAway = 0x8124,
+ KotGadanie = 0x8126,
+ SzlafmycaTaken = 0x8128,
+ BabkaTalk = 0x812A,
+ SellerTalk = 0x812C,
+ CzosnekDone = 0x812E,
+ PriestCounter = 0x8130,
+ PriestGest1 = 0x8132,
+ PriestGest2 = 0x8134,
+ PriestGest3 = 0x8136,
+ PriestGest4 = 0x8138,
+ PriestAnim = 0x813A,
+ HolyWaterTaken = 0x813C,
+ AxeTaken = 0x813E,
+ BadylTaken1 = 0x8140,
+ BadylTaken2 = 0x8142,
+ BadylSharpened = 0x8144,
+ PorwanieSmoka = 0x8146,
+ ShopReOpen = 0x8148,
+ LuskaShown = 0x814A,
+ CudKnow = 0x814C,
+ VampireDead = 0x814E,
+ MapaVisible1 = 0x8150,
+ MapaVisible2 = 0x8152,
+ MapaVisible3 = 0x8154,
+ MapaVisible4 = 0x8156,
+ MapaVisible5 = 0x8158,
+ MapaVisible6 = 0x815A,
+ MapaVisible7 = 0x815C,
+ MapaVisible8 = 0x815E,
+ MapaVisible9 = 0x8160,
+ MapaX = 0x8162,
+ MapaY = 0x8164,
+ MapaD = 0x8166,
+ OldMapaX = 0x8168,
+ OldMapaY = 0x816A,
+ OldMapaD = 0x816C,
+ MovingBack = 0x816E,
+ MapaCount = 0x8170,
+ Pustelnia1st = 0x8172,
+ CzarnePole1st = 0x8174,
+ TalkArivNum = 0x8176,
+ Pfui = 0x8178,
+ MapaSunlordEnabled = 0x817A,
+ WebDone = 0x817C,
+ DragonDone = 0x817E,
+ KanPlay = 0x8180,
+ OldKanPlay = 0x8182,
+ LapkiWait = 0x8184,
+ WebNoCheck = 0x8186,
+ Perfumeria = 0x8188,
+ SmokNoCheck = 0x818A,
+ IluzjaBroken = 0x818C,
+ IluzjaWorking = 0x818E,
+ IluzjaCounter = 0x8190,
+ KurhanOpen1 = 0x8192,
+ KastetTaken = 0x8194,
+ KastetDown = 0x8196,
+ KurhanDone = 0x8198,
+ SkelCounter = 0x819A,
+ SkelDial1 = 0x819C,
+ SkelDial2 = 0x819E,
+ SkelDial3 = 0x81A0,
+ SkelDial4 = 0x81A2,
+ SameTalker = 0x81A4,
+ RunMonstersText = 0x81A6,
+ PiwnicaChecked = 0x81A8,
+ DragonTalked = 0x81AA,
+ ToldAboutBook = 0x81AC,
+ SilmanionaDone = 0x81AE,
+ ToldBookCount = 0x81B0,
+ SmrodNoCheck = 0x81B2,
+ RopeTaken = 0x81B4,
+ RopeTime = 0x81B6,
+ LaskaFree = 0x81B8,
+ ShanSmokTalked = 0x81BA,
+ SwordTaken = 0x81BC,
+ Mill1st = 0x81BE,
+ SawRat = 0x81C0,
+ KnowRat = 0x81C2,
+ DziuraTimer = 0x81C4,
+ LaskaInside = 0x81C6,
+ HoleBig = 0x81C8,
+ EnableWiedzmin = 0x81CA,
+ EnableTrucizna = 0x81CC,
+ KnowPoison = 0x81CE,
+ KufelTaken = 0x81D0,
+ BojkaEnabled = 0x81D2,
+ BitwaNot1st = 0x81D4,
+ BojkaTimer = 0x81D6,
+ BojkaGirl = 0x81D8,
+ Look1st = 0x81DA,
+ RatTaken = 0x81DC,
+ LaskaTalkedGr = 0x81DE,
+ RatusGivus = 0x81E0,
+ MamObole = 0x81E2,
+ Speed1st = 0x81E4,
+ SpeedTimer = 0x81E6,
+ ProveIt = 0x81E8,
+ Proven = 0x81EA,
+ ShowWoalka = 0x81EC,
+ PoisonTaken = 0x81EE,
+ HellOpened = 0x81F0,
+ HellNoCheck = 0x81F2,
+ TalAn1 = 0x81F4,
+ TalAn2 = 0x81F6,
+ TalAn3 = 0x81F8,
+ TalkDevilGuard = 0x81fA,
+ Sword1st = 0x81FC,
+ IluzjaNoCheck = 0x81FE,
+ RozdzielniaNumber = 0x8200,
+ JailChecked = 0x8202,
+ JailTalked = 0x8204,
+ TrickFailed = 0x8206,
+ WegielVisible = 0x8208,
+ WegielTimer1 = 0x820A,
+ RandomSample = 0x820C,
+ RandomSampleTimer = 0x820E,
+ SampleTimer = 0x8210,
+ ZonaSample = 0x8212,
+ HoleTryAgain = 0x8214,
+ TeleportTimer = 0x8216,
+ RozLezy = 0x8218,
+ UdkoTimer = 0x821A,
+ ZaworZatkany = 0x821C,
+ ZaworOpened = 0x821E,
+ DoorExploded = 0x8220,
+ SkoraTaken = 0x8222,
+ CiezkieByl = 0x8224,
+ MamWegiel = 0x8226,
+ SwiecaAway = 0x8228,
+ ITSAVE = 0x822A,
+ RozpadlSie = 0x822C,
+ WegielFullTimer = 0x822E,
+ WegielDown = 0x8230,
+ WegielDownTimer = 0x8232,
+ PaliSie = 0x8234,
+ DiabGuardTalked = 0x8236,
+ GuardsNoCheck = 0x8238,
+ TalkedPowloka = 0x823A,
+ JailOpen = 0x823C,
+ PrzytulTimer = 0x823E,
+ JailDone = 0x8240,
+ MamMonety = 0x8242,
+ LotTimer = 0x8244,
+ LotObj = 0x8246,
+ PtakTimer = 0x8248,
+ BookTimer = 0x824A,
+ BookGiba = 0x824C,
+ PtakLata = 0x824E,
+ Podej = 0x8250,
+ GotHint = 0x8252,
+ LawaLeci = 0x8254,
+ PowerKlik = 0x8258,
+ LucekBad = 0x825A,
+ LucekBad1st = 0x825C,
+ IntroDial1 = 0x825E,
+ IntroDial2 = 0x8260,
+ ItsOutro = 0x8262,
+ KamienComment = 0x8264,
+ KamienSkip = 0x8266,
+ TesterFlag = 0x8268,
+ RememberLine = 0x826A,
+ OpisLapek = 0x826C,
+ //OpisKamienia = 0x826E, // Redefinition
+ TalWait = 0x8270,
+ OpisKamienia = 0x8272,
+ JumpBox = 0x8274,
+ JumpBox1 = 0x8276,
+ JumpBox2 = 0x8278,
+ JumpBox3 = 0x827A,
+ SpecPiesek = 0x827C,
+ SpecPiesekCount = 0x827E,
+ SpecPiesekGadanie = 0x8282,
+ ZnikaFlag = 0x8284,
+ ZnikaTimer = 0x8286,
+ SowaTimer = 0x8288,
+ MamrotanieOff = 0x828A,
+ // Flagi systemowe do kontroli przez skrypt
+ // System flags controlled by script
+ CURRMOB = 0x8400,
+ KOLOR = 0x8402,
+ MBFLAG = 0x8404,
+ MXFLAG = 0x8406,
+ MYFLAG = 0x8408,
+ SCROLLTYPE = 0x840A,
+ SCROLLVALUE = 0x840C,
+ SCROLLVALUE2 = 0x840E,
+ TALKEXITCODE = 0x8410,
+ SPECROUTFLAG1 = 0x8412,
+ SPECROUTFLAG2 = 0x8414,
+ SPECROUTFLAG3 = 0x8416,
+ TALKFLAGCODE = 0x8418,
+ CURRROOM = 0x841A,
+ Talker1Init = 0x841C,
+ Talker2Init = 0x841E,
+ RESTOREROOM = 0x8420,
+ INVALLOWED = 0x8422,
+ BOXSEL = 0x8424,
+ CURSEBLINK = 0x8426,
+ EXACTMOVE = 0x8428,
+ MOVEDESTX = 0x842A,
+ MOVEDESTY = 0x842C,
+ NOANTIALIAS = 0x842E,
+ ESCAPED = 0x8430,
+ ALLOW1OPTION = 0x8432,
+ VOICE_H_LINE = 0x8434,
+ VOICE_A_LINE = 0x8436,
+ VOICE_B_LINE = 0x8438,
+ VOICE_C_LINE = 0x843A,
+ NOHEROATALL = 0x843C,
+ MOUSEENABLED = 0x843E,
+ DIALINES = 0x8440,
+ //SELITEM = 0x8442, // Redefinition
+ SHANWALK = 0x8444,
+ SHANDOG = 0x8446,
+ GETACTIONBACK = 0x8448,
+ GETACTIONDATA = 0x844C,
+ GETACTION = 0x8450,
+ HEROFAST = 0x8452,
+ SELITEM = 0x8454,
+ LMOUSE = 0x8456,
+ MINMX = 0x8458,
+ MAXMX = 0x845A,
+ MINMY = 0x845C,
+ MAXMY = 0x845E,
+ TORX1 = 0x8460,
+ TORY1 = 0x8462,
+ TORX2 = 0x8464,
+ TORY2 = 0x8466,
+ POWER = 0x8468,
+ POWERENABLED = 0x846A,
+ FLCRESTORE = 0x846C,
+ NOCLSTEXT = 0x846E,
+ ESCAPED2 = 0x8470
+ };
+};
+
+}
+#endif
+/* vim: set tabstop=4 noexpandtab: */
+
diff --git a/engines/prince/font.cpp b/engines/prince/font.cpp
new file mode 100644
index 0000000000..40b6d014e6
--- /dev/null
+++ b/engines/prince/font.cpp
@@ -0,0 +1,91 @@
+/* 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.
+ *
+ */
+
+#include "common/archive.h"
+#include "common/debug.h"
+#include "common/stream.h"
+#include "common/str.h"
+
+#include "graphics/surface.h"
+
+#include "prince/font.h"
+
+namespace Prince {
+
+Font::Font() {
+}
+
+Font::~Font() {
+ delete [] _fontData;
+}
+
+bool Font::loadFromStream(Common::SeekableReadStream &stream) {
+ stream.seek(0);
+ _fontData = new byte[stream.size()];
+ stream.read(_fontData, stream.size());
+ return true;
+}
+
+int Font::getFontHeight() const {
+ return _fontData[5];
+}
+
+int Font::getMaxCharWidth() const {
+ return 0;
+}
+
+Font::ChrData Font::getChrData(byte chr) const {
+ chr -= 32;
+ uint16 chrOffset = 4*chr+6;
+
+ ChrData chrData;
+ chrData._width = _fontData[chrOffset+2];
+ chrData._height = _fontData[chrOffset+3];
+ chrData._pixels = _fontData + READ_LE_UINT16(_fontData + chrOffset);
+
+ return chrData;
+}
+
+int Font::getCharWidth(uint32 chr) const {
+ return getChrData(chr)._width;
+}
+
+void Font::drawChar(Graphics::Surface *dst, uint32 chr, int posX, int posY, uint32 color) const {
+ const ChrData chrData = getChrData(chr);
+
+ for (int y = 0; y < chrData._height; ++y) {
+ for (int x = 0; x < chrData._width; ++x) {
+ byte d = chrData._pixels[x + (chrData._width * y)];
+ if (d == 0) d = 255;
+ else if (d == 1) d = 0;
+ else if (d == 2) d = color;
+ else if (d == 3) d = 0;
+ if (d != 255) {
+ *(byte*)dst->getBasePtr(posX + x, posY + y) = d;
+ }
+ }
+ }
+}
+
+}
+
+/* vim: set tabstop=4 expandtab!: */
diff --git a/engines/prince/font.h b/engines/prince/font.h
new file mode 100644
index 0000000000..bf9c09d0e9
--- /dev/null
+++ b/engines/prince/font.h
@@ -0,0 +1,70 @@
+/* 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.
+ */
+
+#ifndef PRINCE_FONT_H
+#define PRINCE_FONT_H
+
+#include "graphics/font.h"
+
+namespace Graphics {
+ struct Surface;
+}
+
+namespace Common {
+ class String;
+}
+
+namespace Prince {
+
+class Font : public Graphics::Font {
+public:
+ Font();
+ virtual ~Font();
+
+ bool loadFromStream(Common::SeekableReadStream &stream);
+
+ virtual int getFontHeight() const override;
+
+ virtual int getMaxCharWidth() const override;
+
+ virtual int getCharWidth(uint32 chr) const override;
+
+ virtual void drawChar(Graphics::Surface *dst, uint32 chr, int x, int y, uint32 color) const override;
+
+ virtual int getKerningOffset(uint32 left, uint32 right) const override { return -2; }
+
+private:
+ struct ChrData {
+ byte *_pixels;
+ byte _width;
+ byte _height;
+ };
+
+ ChrData getChrData(byte chr) const;
+
+ byte *_fontData;
+};
+
+}
+
+#endif
+
+/* vim: set tabstop=4 expandtab!: */
diff --git a/engines/prince/graphics.cpp b/engines/prince/graphics.cpp
new file mode 100644
index 0000000000..3f9517a6e9
--- /dev/null
+++ b/engines/prince/graphics.cpp
@@ -0,0 +1,87 @@
+/* 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.
+ *
+ */
+
+#include "prince/graphics.h"
+
+#include "prince/prince.h"
+
+#include "graphics/palette.h"
+
+namespace Prince {
+
+GraphicsMan::GraphicsMan(PrinceEngine *vm)
+ : _vm(vm), _changed(false) {
+ initGraphics(640, 480, true);
+ _frontScreen = new Graphics::Surface();
+ _frontScreen->create(640, 480, Graphics::PixelFormat::createFormatCLUT8());
+}
+
+GraphicsMan::~GraphicsMan() {
+ _frontScreen->free();
+ delete _frontScreen;
+}
+
+void GraphicsMan::update() {
+ if (_changed) {
+ _vm->_system->copyRectToScreen((byte*)_frontScreen->getBasePtr(0,0), 640, 0, 0, 640, 480);
+
+ _vm->_system->updateScreen();
+ _changed = false;
+ }
+}
+
+void GraphicsMan::setPalette(const byte *palette) {
+ _vm->_system->getPaletteManager()->setPalette(palette, 0, 256);
+}
+
+void GraphicsMan::change() {
+ _changed = true;
+}
+
+void GraphicsMan::draw(uint16 posX, uint16 posY, const Graphics::Surface *s)
+{
+ uint16 w = MIN(_frontScreen->w, s->w);
+ for (uint y = 0; y < s->h; y++) {
+ if (y < _frontScreen->h) {
+ memcpy((byte*)_frontScreen->getBasePtr(0, y), (byte*)s->getBasePtr(0, y), w);
+ }
+ }
+ change();
+}
+
+void GraphicsMan::drawTransparent(uint16 posX, uint16 posY, const Graphics::Surface *s)
+{
+ for (uint y = 0; y < s->h; ++y) {
+ for (uint x = 0; x < s->w; ++x) {
+ byte pixel = *((byte*)s->getBasePtr(x, y));
+ if (pixel != 255) {
+ //*((byte*)_frontScreen->getBasePtr(x, y)) = pixel;
+ *((byte*)_frontScreen->getBasePtr(x + posX, y + posY)) = pixel;
+ }
+ }
+ }
+ change();
+}
+
+}
+
+/* vim: set tabstop=4 noexpandtab: */
diff --git a/engines/prince/graphics.h b/engines/prince/graphics.h
new file mode 100644
index 0000000000..1766e2a04e
--- /dev/null
+++ b/engines/prince/graphics.h
@@ -0,0 +1,61 @@
+/* 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.
+ *
+ */
+
+#ifndef PRINCE_GRAPHICS_H
+#define PRINCE_GRAPHICS_H
+
+#include "graphics/surface.h"
+
+
+namespace Prince {
+
+class PrinceEngine;
+
+class GraphicsMan
+{
+public:
+ GraphicsMan(PrinceEngine *vm);
+ ~GraphicsMan();
+
+ void update();
+
+ void change();
+
+ void setPalette(const byte *palette);
+
+ void draw(uint16 x, uint16 y, const Graphics::Surface *s);
+ void drawTransparent(uint16 x, uint16 y, const Graphics::Surface *s);
+
+ Graphics::Surface *_frontScreen;
+ Graphics::Surface *_backScreen;
+ const Graphics::Surface *_roomBackground;
+
+private:
+
+ PrinceEngine *_vm;
+
+ bool _changed;
+};
+
+}
+
+#endif
diff --git a/engines/prince/hero.cpp b/engines/prince/hero.cpp
new file mode 100644
index 0000000000..81e686c740
--- /dev/null
+++ b/engines/prince/hero.cpp
@@ -0,0 +1,333 @@
+/* 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.
+ *
+ */
+#include "common/debug.h"
+#include "common/random.h"
+
+#include "prince/hero.h"
+#include "prince/hero_set.h"
+#include "prince/animation.h"
+#include "prince/resource.h"
+
+
+namespace Prince {
+
+Hero::Hero() : _number(0), _visible(false), _state(MOVE), _middleX(0), _middleY(0)
+ , _boreNum(1), _currHeight(0), _moveDelay(0), _shadMinus(1), _moveSetType(0)
+ , _lastDirection(DOWN), _destDirection(DOWN), _talkTime(0), _boredomTime(0), _phase(0)
+ , _specAnim(0), _drawX(0), _drawY(0), _randomSource("prince"), _zoomFactor(0), _scaleValue(0)
+{
+ _zoomBitmap = new Animation();
+}
+
+Hero::~Hero() {
+ delete _zoomBitmap;
+}
+
+bool Hero::loadAnimSet(uint32 animSetNr) {
+ if (animSetNr > sizeof(heroSetTable)) {
+ return false;
+ }
+
+ for (uint32 i = 0; i < _moveSet.size(); ++i) {
+ delete _moveSet[i];
+ }
+
+ const HeroSetAnimNames &animSet = *heroSetTable[animSetNr];
+
+ _moveSet.resize(kMoveSetSize);
+ for (uint32 i = 0; i < kMoveSetSize; ++i) {
+ debug("Anim set item %d %s", i, animSet[i]);
+ Animation *anim = NULL;
+ if (animSet[i] != NULL) {
+ anim = new Animation();
+ Resource::loadResource(anim, animSet[i]);
+ }
+ _moveSet[i] = anim;
+ }
+
+ return true;
+}
+
+const Graphics::Surface * Hero::getSurface() {
+ if (_moveSet[_moveSetType]) {
+ //debug("BaseX: %d", _moveSet[_moveSetType]->getBaseX());
+ //debug("BaseY: %d", _moveSet[_moveSetType]->getBaseY());
+ //debug("FrameCount: %d", _moveSet[_moveSetType]->getFrameCount());
+ //debug("LoopCount: %d", _moveSet[_moveSetType]->getLoopCount());
+ //debug("PhaseCount: %d", _moveSet[_moveSetType]->getPhaseCount());
+ //debug("PhaseFrameIndex(%d): %d", _frame, _moveSet[_moveSetType]->getPhaseFrameIndex(_frame));
+ //debug("PhaseOffsetX(%d): %d", _frame, _moveSet[_moveSetType]->getPhaseOffsetX(_frame));
+ //debug("PhaseOffsetY(%d) %d", _frame, _moveSet[_moveSetType]->getPhaseOffsetY(_frame));
+ //debug("FrameSizeX(%d) %d", _frame, _moveSet[_moveSetType]->getFrameWidth(_frame));
+ //debug("FrameSizeY(%d) %d", _frame, _moveSet[_moveSetType]->getFrameHeight(_frame));
+ //getState();
+ int16 phaseFrameIndex = _moveSet[_moveSetType]->getPhaseFrameIndex(_phase);
+ return _moveSet[_moveSetType]->getFrame(phaseFrameIndex);
+ }
+ return NULL;
+}
+
+//TEMP
+void Hero::getState() {
+ switch (_state) {
+ case STAY:
+ debug("STAY");
+ break;
+ case TURN:
+ debug("TURN");
+ break;
+ case MOVE:
+ debug("MOVE");
+ break;
+ case BORE:
+ debug("BORE");
+ break;
+ case SPEC:
+ debug("SPEC");
+ break;
+ case TALK:
+ debug("TALK");
+ break;
+ case MVAN:
+ debug("MVAN");
+ break;
+ case TRAN:
+ debug("TRAN");
+ break;
+ case RUN:
+ debug("RUN");
+ break;
+ case DMOVE:
+ debug("DMOVE");
+ break;
+ }
+}
+
+//TODO
+void Hero::countDrawPosition() {
+ int16 frameXSize = _moveSet[_moveSetType]->getFrameWidth(_phase);
+ int16 frameYSize = _moveSet[_moveSetType]->getFrameHeight(_phase);
+ _drawX = _middleX - frameXSize/2;
+ _drawY = _middleY - frameYSize;
+}
+
+void Hero::showHeroAnimFrame() {
+ if (_phase < _moveSet[_moveSetType]->getFrameCount() - 1) {
+ _phase++;
+ } else {
+ _phase = 0;
+ }
+ countDrawPosition();
+ //debug("_drawX: %d", _drawX);
+ //debug("_drawY: %d", _drawY);
+ //debug("_middleX: %d", _middleX);
+ //debug("_middleY: %d", _middleY);
+}
+
+void Hero::setScale(int8 zoomBitmapValue) {
+ if (zoomBitmapValue == 0) {
+ _zoomFactor = 1;
+ } else {
+ _zoomFactor = zoomBitmapValue;
+ }
+ _scaleValue = 10000 / _zoomFactor;
+ debug("_scaleValue: %d", _scaleValue);
+}
+
+void Hero::selectZoom() {
+ int8 zoomBitmapValue = _zoomBitmap->getZoom(_middleY / 4 * kZoomBitmapWidth + _middleX / 4);
+ debug("offset: %d", _middleY / 4 * kZoomBitmapWidth + _middleX / 4);
+ debug("zoomBitmapValue: %d", _zoomFactor);
+ setScale(zoomBitmapValue);
+}
+
+void Hero::specialAnim() {
+}
+
+void Hero::rotateHero() {
+ switch (_lastDirection) {
+ case LEFT:
+ switch (_destDirection) {
+ case RIGHT:
+ _moveSetType = Move_MLR;
+ break;
+ case UP:
+ _moveSetType = Move_MLU;
+ break;
+ case DOWN:
+ _moveSetType = Move_MLD;
+ break;
+ }
+ break;
+ case RIGHT:
+ switch (_destDirection) {
+ case LEFT:
+ _moveSetType = Move_MRL;
+ break;
+ case UP:
+ _moveSetType = Move_MRU;
+ break;
+ case DOWN:
+ _moveSetType = Move_MRD;
+ break;
+ }
+ break;
+ case UP:
+ switch (_destDirection) {
+ case LEFT:
+ _moveSetType = Move_MUL;
+ break;
+ case RIGHT:
+ _moveSetType = Move_MUR;
+ break;
+ case DOWN:
+ _moveSetType = Move_MUD;
+ break;
+ }
+ break;
+ case DOWN:
+ switch (_destDirection) {
+ case LEFT:
+ _moveSetType = Move_MDL;
+ break;
+ case RIGHT:
+ _moveSetType = Move_MDR;
+ break;
+ case UP:
+ _moveSetType = Move_MDU;
+ break;
+ }
+ break;
+ }
+}
+
+void Hero::showHero() {
+ if (_visible) {
+ // Is he talking?
+ if (_talkTime == 0) { //?
+ // Scale of hero
+ selectZoom();
+ switch (_state) {
+ case STAY:
+ //if(OptionsFlag == false) {
+ //if(OpcodePC == null) {
+ _boredomTime++;
+ if (_boredomTime == 200) { // 140 for second hero
+ _boredomTime = 0;
+ _state = BORE;
+ }
+ switch (_lastDirection) {
+ case LEFT:
+ _moveSetType = Move_SL;
+ break;
+ case RIGHT:
+ _moveSetType = Move_SR;
+ break;
+ case UP:
+ _moveSetType = Move_SU;
+ break;
+ case DOWN:
+ _moveSetType = Move_SD;
+ break;
+ }
+ break;
+ case TURN:
+ /*
+ if(_lastDirection == _destDirection) {
+ _state = STAY;
+ } else {
+ _frame = 0;
+ rotateHero();
+ _lastDirection = _destDirection;
+ }
+ */
+ break;
+ case MOVE:
+ switch (_lastDirection) {
+ case LEFT:
+ _moveSetType = Move_ML;
+ break;
+ case RIGHT:
+ _moveSetType = Move_MR;
+ break;
+ case UP:
+ _moveSetType = Move_MU;
+ break;
+ case DOWN:
+ _moveSetType = Move_MD;
+ break;
+ }
+ break;
+ case BORE:
+ //if (_direction == UP) {
+ switch (_boreNum) {
+ case 0:
+ _moveSetType = Move_BORED1;
+ break;
+ case 1:
+ _moveSetType = Move_BORED2;
+ break;
+ }
+ if (_phase == _moveSet[_moveSetType]->getFrameCount() - 1) {
+ _boreNum = _randomSource.getRandomNumber(1); // rand one of two 'bored' animation
+ _lastDirection = DOWN;
+ _state = STAY;
+ }
+ break;
+ case SPEC:
+ //specialAnim();
+ break;
+ case TALK:
+ switch (_lastDirection) {
+ case LEFT:
+ _moveSetType = Move_TL;
+ break;
+ case RIGHT:
+ _moveSetType = Move_TR;
+ break;
+ case UP:
+ _moveSetType = Move_TU;
+ break;
+ case DOWN:
+ _moveSetType = Move_TD;
+ break;
+ }
+ break;
+ case TRAN:
+ break;
+ case RUN:
+ break;
+ case DMOVE:
+ break;
+ }
+ } else {
+ _talkTime--; // o ile?
+ }
+ showHeroAnimFrame();
+ } else {
+ // no hero visible
+ return;
+ }
+}
+}
+
+/* vim: set tabstop=4 noexpandtab: */
diff --git a/engines/prince/hero.h b/engines/prince/hero.h
new file mode 100644
index 0000000000..e01a5c071f
--- /dev/null
+++ b/engines/prince/hero.h
@@ -0,0 +1,160 @@
+/* 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.
+ *
+ */
+
+#ifndef PRINCE_HERO_H
+#define PRINCE_HERO_H
+
+#include "common/scummsys.h"
+#include "common/array.h"
+
+#include "graphics/surface.h"
+
+namespace Prince {
+
+class Animation;
+
+class Hero {
+public:
+ static const uint32 kMoveSetSize = 26;
+ static const int16 kZoomStep = 4;
+ static const int16 kMaxPicWidth = 1280;
+ static const int16 kZoomBitmapWidth = kMaxPicWidth / kZoomStep;
+
+ enum State {
+ STAY = 0,
+ TURN = 1,
+ MOVE = 2,
+ BORE = 3,
+ SPEC = 4,
+ TALK = 5,
+ MVAN = 6,
+ TRAN = 7,
+ RUN = 8,
+ DMOVE = 9
+ };
+
+ enum Direction {
+ LEFT = 1,
+ RIGHT = 2,
+ UP = 3,
+ DOWN = 4
+ };
+
+ enum MoveSet {
+ Move_SL,
+ Move_SR,
+ Move_SU,
+ Move_SD,
+ Move_ML,
+ Move_MR,
+ Move_MU,
+ Move_MD,
+ Move_TL,
+ Move_TR,
+ Move_TU,
+ Move_TD,
+ Move_MLU,
+ Move_MLD,
+ Move_MLR,
+ Move_MRU,
+ Move_MRD,
+ Move_MRL,
+ Move_MUL,
+ Move_MUR,
+ Move_MUD,
+ Move_MDL,
+ Move_MDR,
+ Move_MDU,
+ Move_BORED1,
+ Move_BORED2
+ };
+
+ Hero();
+ ~Hero();
+ Common::RandomSource _randomSource;
+ bool loadAnimSet(uint32 heroAnimNumber);
+
+ const Graphics::Surface * getSurface();
+
+ void setPos(int16 x, int16 y) { _middleX = x; _middleY = y; }
+ void setVisible(bool flag) { _visible = flag; }
+
+ void showHero();
+ void moveHero();
+ void rotateHero();
+ void setScale(int8 zoomBitmapValue);
+ void selectZoom();
+ void countDrawPosition();
+ void showHeroAnimFrame();
+ void specialAnim();
+ void getState();
+
+//private:
+ uint16 _number;
+ uint16 _visible;
+ int16 _state;
+ int16 _middleX; // middle of X
+ int16 _middleY; // lower part of hero
+ int16 _drawX;
+ int16 _drawY;
+ int16 _lastDirection;
+ int16 _destDirection;
+ int16 _moveSetType;
+ int8 _zoomFactor;
+ int16 _scaleValue;
+
+ // Coords array of coordinates
+ // DirTab array of directions
+ // CurrCoords current coordinations
+ // CurrDirTab current direction
+ // LastDir previous move direction
+ // DestDir
+ // LeftRight previous left/right direction
+ // UpDown previous up/down direction
+ uint _phase; // Phase animation phase
+ // Step x/y step size depends on direction
+ // MaxBoredom stand still timeout
+ int16 _boredomTime;// Boredom current boredom time in frames
+ uint16 _boreNum; // Bore anim frame
+ int16 _talkTime; // TalkTime time of talk anim
+ int32 _specAnim; // SpecAnim additional anim
+
+ uint16 _currHeight; // height of current anim phase
+
+ // Inventory array of items
+ // Inventory2 array of items
+ // Font subtitiles font
+ // Color subtitiles color
+ // AnimSet number of animation set
+ Common::Array<Animation *> _moveSet; // MoveAnims MoveSet
+ // TurnAnim ??
+ Animation *_zoomBitmap; // change to sth else, not Animation ??
+
+ uint32 _moveDelay;
+ uint32 _shadMinus; //??
+};
+
+}
+
+#endif
+
+/* vim: set tabstop=4 noexpandtab: */
diff --git a/engines/prince/hero_set.cpp b/engines/prince/hero_set.cpp
new file mode 100644
index 0000000000..a8c05de724
--- /dev/null
+++ b/engines/prince/hero_set.cpp
@@ -0,0 +1,243 @@
+
+/* 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.
+ *
+ */
+
+#include "prince/hero_set.h"
+#include "common/scummsys.h"
+
+namespace Prince {
+
+static HeroSetAnimNames heroSet5= {
+ "SL_DIAB.ANI",
+ "SR_DIAB.ANI",
+ "SU_DIAB.ANI",
+ "SD_DIAB.ANI",
+ NULL,
+ NULL,
+ "MU_DIAB.ANI",
+ "MD_DIAB.ANI",
+ "TL_DIAB.ANI",
+ "TR_DIAB.ANI",
+ "TU_DIAB.ANI",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
+
+static HeroSetAnimNames heroSet1= {
+ "SL_HERO1.ANI",
+ "SR_HERO1.ANI",
+ "SU_HERO1.ANI",
+ "SD_HERO1.ANI",
+ "ML_HERO1.ANI",
+ "MR_HERO1.ANI",
+ "MU_HERO1.ANI",
+ "MD_HERO1.ANI",
+ "TL_HERO1.ANI",
+ "TR_HERO1.ANI",
+ "TU_HERO1.ANI",
+ "TD_HERO1.ANI",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "KSI_KURZ.ANI",
+ "KS_WLOSY.ANI"
+};
+
+static HeroSetAnimNames heroSet2= {
+ "SL_HERO2.ANI",
+ "SR_HERO2.ANI",
+ "SU_HERO2.ANI",
+ "SD_HERO2.ANI",
+ "ML_HERO2.ANI",
+ "MR_HERO2.ANI",
+ "MU_HERO2.ANI",
+ "MD_HERO2.ANI",
+ "TL_HERO2.ANI",
+ "TR_HERO2.ANI",
+ "TU_HERO2.ANI",
+ "TD_HERO2.ANI",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "KSI_KU_S.ANI",
+ "KS_WLO_S.ANI"
+};
+
+static HeroSetAnimNames heroSet3= {
+ "SL_BEAR.ANI",
+ "SR_BEAR.ANI",
+ "SU_BEAR.ANI",
+ "SD_BEAR.ANI",
+ "NIED-LEW.ANI",
+ "NIED-PRW.ANI",
+ "NIED-TYL.ANI",
+ "NIED-PRZ.ANI",
+ "SL_BEAR.ANI",
+ "SR_BEAR.ANI",
+ "SU_BEAR.ANI",
+ "SD_BEAR.ANI",
+ "N_LW-TYL.ANI",
+ "N_LW-PRZ.ANI",
+ "N_LW-PR.ANI",
+ "N_PR-TYL.ANI",
+ "N_PR-PRZ.ANI",
+ "N_PR-LW.ANI",
+ "N_TYL-LW.ANI",
+ "N_TYL-PR.ANI",
+ "N_TL-PRZ.ANI",
+ "N_PRZ-LW.ANI",
+ "N_PRZ-PR.ANI",
+ "N_PRZ-TL.ANI",
+ NULL,
+ NULL,
+};
+
+static HeroSetAnimNames shanSet1= {
+ "SL_SHAN.ANI",
+ "SR_SHAN.ANI",
+ "SU_SHAN.ANI",
+ "SD_SHAN.ANI",
+ "ML_SHAN.ANI",
+ "MR_SHAN.ANI",
+ "MU_SHAN.ANI",
+ "MD_SHAN.ANI",
+ "TL_SHAN.ANI",
+ "TR_SHAN.ANI",
+ "TU_SHAN.ANI",
+ "TD_SHAN.ANI",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "B1_SHAN.ANI",
+ "B2_SHAN.ANI",
+};
+
+static HeroSetAnimNames shanSet2= {
+ "SL_SHAN2.ANI",
+ "SR_SHAN2.ANI",
+ "SU_SHAN.ANI",
+ "SD_SHAN2.ANI",
+ "ML_SHAN2.ANI",
+ "MR_SHAN2.ANI",
+ "MU_SHAN.ANI",
+ "MD_SHAN2.ANI",
+ "TL_SHAN2.ANI",
+ "TR_SHAN2.ANI",
+ "TU_SHAN.ANI",
+ "TD_SHAN2.ANI",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "B1_SHAN2.ANI",
+ "B2_SHAN2.ANI"
+};
+
+static HeroSetAnimNames arivSet1= {
+ "SL_ARIV.ANI",
+ "SR_ARIV.ANI",
+ "SU_ARIV.ANI",
+ "SD_ARIV.ANI",
+ "ML_ARIV.ANI",
+ "MR_ARIV.ANI",
+ "MU_ARIV.ANI",
+ "MD_ARIV.ANI",
+ "TL_ARIV.ANI",
+ "TR_ARIV.ANI",
+ "TU_ARIV.ANI",
+ "TD_ARIV.ANI",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
+
+const HeroSetAnimNames *heroSetTable[7] = {
+ &heroSet1,
+ &heroSet2,
+ &heroSet3,
+ &shanSet1,
+ &arivSet1,
+ &heroSet5,
+ &shanSet2,
+};
+
+}
+/* vim: set tabstop=4 noexpandtab: */
diff --git a/engines/prince/hero_set.h b/engines/prince/hero_set.h
new file mode 100644
index 0000000000..335f70a6ab
--- /dev/null
+++ b/engines/prince/hero_set.h
@@ -0,0 +1,30 @@
+/* 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.
+ *
+ */
+
+namespace Prince {
+
+typedef const char *HeroSetAnimNames[26];
+
+extern const HeroSetAnimNames *heroSetTable[7];
+
+}
+/* vim: set tabstop=4 noexpandtab: */
diff --git a/engines/prince/mhwanh.cpp b/engines/prince/mhwanh.cpp
new file mode 100644
index 0000000000..3bd034e4a7
--- /dev/null
+++ b/engines/prince/mhwanh.cpp
@@ -0,0 +1,74 @@
+/* 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.
+ *
+ */
+
+#include "common/stream.h"
+
+#include "graphics/surface.h"
+
+#include "prince/mhwanh.h"
+
+namespace Prince {
+
+MhwanhDecoder::MhwanhDecoder()
+ : _surface(NULL), _palette(0), _paletteColorCount(0) {
+}
+
+MhwanhDecoder::~MhwanhDecoder() {
+ destroy();
+}
+
+void MhwanhDecoder::destroy() {
+ if (_surface) {
+ _surface->free();
+ delete _surface;
+ _surface = 0;
+ }
+
+ delete [] _palette; _palette = 0;
+ _paletteColorCount = 0;
+}
+
+bool MhwanhDecoder::loadStream(Common::SeekableReadStream &stream) {
+ destroy();
+ _paletteColorCount = 256;
+ stream.seek(0);
+ stream.skip(0x20);
+ // Read the palette
+ _palette = new byte[_paletteColorCount * 3];
+ for (uint16 i = 0; i < _paletteColorCount; i++) {
+ _palette[i * 3 + 0] = stream.readByte();
+ _palette[i * 3 + 1] = stream.readByte();
+ _palette[i * 3 + 2] = stream.readByte();
+ }
+
+ _surface = new Graphics::Surface();
+ _surface->create(640, 480, Graphics::PixelFormat::createFormatCLUT8());
+ for (int h = 0; h < 480; ++h) {
+ stream.read(_surface->getBasePtr(0, h), 640);
+ }
+
+ return true;
+}
+
+}
+
+/* vim: set tabstop=4 noexpandtab: */
diff --git a/engines/prince/mhwanh.h b/engines/prince/mhwanh.h
new file mode 100644
index 0000000000..5364c5d20a
--- /dev/null
+++ b/engines/prince/mhwanh.h
@@ -0,0 +1,67 @@
+/* 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.
+ *
+ */
+
+#ifndef PRINCE_MHWANH_H
+#define PRINCE_MHWANH_H
+
+#include "image/image_decoder.h"
+#include "image/bmp.h"
+#include "graphics/surface.h"
+#include "resource.h"
+
+namespace Prince {
+
+class MhwanhDecoder : public Image::ImageDecoder {
+public:
+ MhwanhDecoder();
+ virtual ~MhwanhDecoder();
+
+ // ImageDecoder API
+ void destroy();
+ virtual bool loadStream(Common::SeekableReadStream &stream);
+ virtual const Graphics::Surface *getSurface() const { return _surface; }
+ virtual const byte *getPalette() const { return _palette; }
+ uint16 getPaletteCount() const { return _paletteColorCount; }
+
+private:
+ Graphics::Surface *_surface;
+ byte *_palette;
+ uint16 _paletteColorCount;
+};
+
+namespace Resource {
+ template <> inline
+ bool loadFromStream<MhwanhDecoder>(MhwanhDecoder &image, Common::SeekableReadStream &stream) {
+ return image.loadStream(stream);
+ }
+
+ template <> inline
+ bool loadFromStream<Image::BitmapDecoder>(Image::BitmapDecoder &image, Common::SeekableReadStream &stream) {
+ return image.loadStream(stream);
+ }
+}
+
+}
+
+#endif
+
+/* vim: set tabstop=4 noexpandtab: */
diff --git a/engines/prince/mob.cpp b/engines/prince/mob.cpp
new file mode 100644
index 0000000000..c4bb607347
--- /dev/null
+++ b/engines/prince/mob.cpp
@@ -0,0 +1,101 @@
+/* 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.
+ *
+ */
+
+#include "prince/mob.h"
+
+#include "common/stream.h"
+
+namespace Prince {
+
+bool Mob::loadFromStream(Common::SeekableReadStream &stream) {
+ int32 pos = stream.pos();
+
+ uint16 visible = stream.readUint16LE();
+
+ if (visible == 0xFFFF)
+ return false;
+
+ _visible = visible;
+ _type = stream.readUint16LE();
+ _rect.left = stream.readUint16LE();
+ _rect.top = stream.readUint16LE();
+ _rect.right = stream.readUint16LE();
+ _rect.bottom = stream.readUint16LE();
+
+ _mask = stream.readUint16LE();
+
+ _examPosition.x = stream.readUint16LE();
+ _examPosition.y = stream.readUint16LE();
+ _examDirection = (Direction)stream.readUint16LE();
+
+ _usePosition.x = stream.readByte();
+ _usePosition.y = stream.readByte();
+ _useDirection = (Direction)stream.readUint16LE();
+
+ uint32 nameOffset = stream.readUint32LE();
+ uint32 examTextOffset = stream.readUint32LE();
+
+ byte c;
+ stream.seek(nameOffset);
+ _name.clear();
+ while ((c = stream.readByte()))
+ _name += c;
+
+ stream.seek(examTextOffset);
+ _examText.clear();
+ while ((c = stream.readByte()))
+ _examText += c;
+ stream.seek(pos + 32);
+
+ return true;
+}
+
+void Mob::setData(AttrId dataId, uint16 value) {
+ switch (dataId) {
+ case ExamDir:
+ _examDirection = (Direction)value;
+ break;
+ case ExamX:
+ _examPosition.x = value;
+ break;
+ case ExamY:
+ _examPosition.y = value;
+ break;
+ default:
+ assert(false);
+ }
+}
+
+uint16 Mob::getData(AttrId dataId) {
+ switch (dataId) {
+ case Visible: return _visible;
+ case ExamDir: return _examDirection;
+ case ExamX: return _examPosition.x;
+ case ExamY: return _examPosition.y;
+ default:
+ assert(false);
+ }
+}
+
+}
+
+/* vim: set tabstop=4 noexpandtab: */
diff --git a/engines/prince/mob.h b/engines/prince/mob.h
new file mode 100644
index 0000000000..36630eb6eb
--- /dev/null
+++ b/engines/prince/mob.h
@@ -0,0 +1,86 @@
+/* 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.
+ *
+ */
+
+#ifndef PRINCE_MOB_H
+#define PRINCE_MOB_H
+
+#include "common/scummsys.h"
+#include "common/rect.h"
+#include "common/str.h"
+
+#include "prince/common.h"
+
+namespace Common {
+ class SeekableReadStream;
+}
+
+namespace Prince {
+
+class Mob {
+public:
+
+ Mob() : _name(""), _examText("") {}
+
+ bool loadFromStream(Common::SeekableReadStream &stream);
+
+ // Used instead of offset in setData and getData
+ enum AttrId {
+ Visible = 0,
+ Type = 2,
+ X1 = 4,
+ Y1 = 6,
+ X2 = 8,
+ Y2 = 10,
+ Mask = 12,
+ ExamX = 14,
+ ExamY = 16,
+ ExamDir = 18,
+ UseX = 20,
+ UseY = 21,
+ UseDir = 22,
+ Name = 24,
+ ExamText = 28
+ };
+
+ void setData(AttrId dataId, uint16 value);
+ uint16 getData(AttrId dataId);
+
+ bool _visible;
+ uint16 _type;
+ uint16 _mask;
+ Common::Rect _rect;
+
+ Common::Point _examPosition;
+ Direction _examDirection;
+
+ Common::Point _usePosition;
+ Direction _useDirection;
+
+ Common::String _name;
+ Common::String _examText;
+};
+
+}
+
+#endif
+
+/* vim: set tabstop=4 noexpandtab: */
diff --git a/engines/prince/module.mk b/engines/prince/module.mk
new file mode 100644
index 0000000000..228e5990e2
--- /dev/null
+++ b/engines/prince/module.mk
@@ -0,0 +1,29 @@
+MODULE := engines/prince
+
+MODULE_OBJS = \
+ animation.o \
+ debugger.o \
+ script.o \
+ graphics.o \
+ mhwanh.o \
+ detection.o \
+ font.o \
+ mob.o \
+ object.o \
+ sound.o \
+ flags.o \
+ variatxt.o \
+ prince.o \
+ archive.o \
+ decompress.o \
+ hero.o \
+ hero_set.o \
+ cursor.o
+
+# This module can be built as a plugin
+ifeq ($(ENABLE_PRINCE), DYNAMIC_PLUGIN)
+PLUGIN := 1
+endif
+
+# Include common rules
+include $(srcdir)/rules.mk
diff --git a/engines/prince/musNum.h b/engines/prince/musNum.h
new file mode 100644
index 0000000000..65b31f8175
--- /dev/null
+++ b/engines/prince/musNum.h
@@ -0,0 +1,87 @@
+/* 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.
+ *
+ */
+
+namespace Prince {
+
+enum RoomMus {
+ ROOM01MUS = 3,
+ ROOM02MUS = 9,
+ ROOM03MUS = 9,
+ ROOM04MUS = 9,
+ ROOM05MUS = 13,
+ ROOM06MUS = 9,
+ ROOM07MUS = 9,
+ ROOM08MUS = 9,
+ ROOM09MUS = 14,
+ ROOM10MUS = 9,
+ ROOM11MUS = 9,
+ ROOM12MUS = 9,
+ ROOM13MUS = 9,
+ ROOM14MUS = 9,
+ ROOM15MUS = 5,
+ ROOM16MUS = 5,
+ ROOM17MUS = 5,
+ ROOM18MUS = 5,
+ ROOM19MUS = 5,
+ ROOM20MUS = 12,
+ ROOM21MUS = 9,
+ ROOM22MUS = 9,
+ ROOM23MUS = 1,
+ ROOM24MUS = 1,
+ ROOM25MUS = 2,
+ ROOM26MUS = 10,
+ ROOM27MUS = 7,
+ ROOM28MUS = 10,
+ ROOM29MUS = 10,
+ ROOM30MUS = 11,
+ ROOM31MUS = 14,
+ ROOM32MUS = 11,
+ ROOM33MUS = 7,
+ ROOM34MUS = 7,
+ ROOM35MUS = 7,
+ ROOM36MUS = 7,
+ ROOM37MUS = 7,
+ ROOM38MUS = 7,
+ ROOM39MUS = 7,
+ ROOM40MUS = 7,
+ ROOM41MUS = 7,
+ ROOM42MUS = 7,
+ ROOM43MUS = 15,
+ ROOM46MUS = 100,
+ ROOM47MUS = 100,
+ ROOM48MUS = 100,
+ ROOM49MUS = 100,
+ ROOM50MUS = 100,
+ ROOM51MUS = 12,
+ ROOM52MUS = 9,
+ ROOM53MUS = 5,
+ ROOM54MUS = 11,
+ ROOM55MUS = 11,
+ ROOM56MUS = 11,
+ ROOM57MUS = 7,
+ ROOM58MUS = 13,
+ ROOM59MUS = 16,
+ ROOM60MUS = 4,
+ ROOM61MUS = 0
+};
+
+}
diff --git a/engines/prince/object.cpp b/engines/prince/object.cpp
new file mode 100644
index 0000000000..4148cdf854
--- /dev/null
+++ b/engines/prince/object.cpp
@@ -0,0 +1,84 @@
+/* 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.
+ *
+ */
+
+#include "common/archive.h"
+#include "common/debug-channels.h"
+#include "common/debug.h"
+#include "common/stream.h"
+
+
+#include "graphics/surface.h"
+
+#include "prince/object.h"
+
+namespace Prince {
+
+Object::Object() : _surface(NULL), _x(0), _y(0), _z(0) {
+}
+
+Object::~Object() {
+ if (_surface) {
+ _surface->free();
+ delete _surface;
+ _surface = NULL;
+ }
+}
+
+void Object::loadSurface(Common::SeekableReadStream &stream) {
+ stream.skip(4);
+
+ _surface = new Graphics::Surface();
+ _surface->create(stream.readUint16LE(), stream.readUint16LE(), Graphics::PixelFormat::createFormatCLUT8());
+ for (int h = 0; h < _surface->h; ++h) {
+ stream.read(_surface->getBasePtr(0, h), _surface->w);
+ }
+}
+
+bool Object::loadFromStream(Common::SeekableReadStream &stream) {
+ int32 pos = stream.pos();
+ uint16 x = stream.readUint16LE();
+ if (x == 0xFFFF)
+ return false;
+ _x = x;
+ _y = stream.readUint16LE();
+
+ const Common::String obStreamName = Common::String::format("OB%02d", stream.readUint16LE());
+ Common::SeekableReadStream *obStream = SearchMan.createReadStreamForMember(obStreamName);
+ if (!obStream) {
+ error("Can't load %s", obStreamName.c_str());
+ return false;
+ }
+
+ loadSurface(*obStream);
+ delete obStream;
+
+ _z = stream.readUint16LE();
+
+ stream.seek(pos + 16);
+
+ debug("Object x %d, y %d, z %d", _x, _y, _z);
+
+ return true;
+}
+
+}
+/* vim: set tabstop=4 noexpandtab: */
diff --git a/engines/prince/object.h b/engines/prince/object.h
new file mode 100644
index 0000000000..7a3d19e906
--- /dev/null
+++ b/engines/prince/object.h
@@ -0,0 +1,49 @@
+/* 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.
+ *
+ */
+
+#ifndef PRINCE_OBJECT_H
+#define PRINCE_OBJECT_H
+
+#include "image/image_decoder.h"
+#include "graphics/surface.h"
+
+namespace Prince {
+
+class Object {
+public:
+ Object();
+ ~Object();
+
+ bool loadFromStream(Common::SeekableReadStream &stream);
+ const Graphics::Surface *getSurface() const { return _surface; }
+
+private:
+ void loadSurface(Common::SeekableReadStream &stream);
+
+ Graphics::Surface *_surface;
+ uint16 _x, _y, _z;
+};
+
+}
+
+#endif
+/* vim: set tabstop=4 noexpandtab: */
diff --git a/engines/prince/prince.cpp b/engines/prince/prince.cpp
new file mode 100644
index 0000000000..324c4592ae
--- /dev/null
+++ b/engines/prince/prince.cpp
@@ -0,0 +1,707 @@
+/* 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.
+ *
+ */
+
+#include "common/scummsys.h"
+
+#include "common/config-manager.h"
+#include "common/debug-channels.h"
+#include "common/debug.h"
+#include "common/events.h"
+#include "common/file.h"
+#include "common/random.h"
+#include "common/fs.h"
+#include "common/keyboard.h"
+#include "common/substream.h"
+#include "common/str.h"
+
+#include "graphics/cursorman.h"
+#include "graphics/surface.h"
+#include "graphics/palette.h"
+#include "graphics/pixelformat.h"
+
+#include "engines/util.h"
+#include "engines/advancedDetector.h"
+
+#include "audio/audiostream.h"
+
+#include "prince/prince.h"
+#include "prince/font.h"
+#include "prince/graphics.h"
+#include "prince/script.h"
+#include "prince/debugger.h"
+#include "prince/object.h"
+#include "prince/mob.h"
+#include "prince/sound.h"
+#include "prince/variatxt.h"
+#include "prince/flags.h"
+#include "prince/font.h"
+#include "prince/mhwanh.h"
+#include "prince/cursor.h"
+#include "prince/archive.h"
+#include "prince/hero.h"
+#include "prince/resource.h"
+#include "prince/animation.h"
+
+namespace Prince {
+
+void PrinceEngine::debugEngine(const char *s, ...) {
+ char buf[STRINGBUFLEN];
+ va_list va;
+
+ va_start(va, s);
+ vsnprintf(buf, STRINGBUFLEN, s, va);
+ va_end(va);
+
+ debug("Prince::Engine frame %08ld %s", _frameNr, buf);
+}
+
+PrinceEngine::PrinceEngine(OSystem *syst, const PrinceGameDescription *gameDesc) :
+ Engine(syst), _gameDescription(gameDesc), _graph(nullptr), _script(nullptr), _interpreter(nullptr), _flags(nullptr),
+ _locationNr(0), _debugger(nullptr), _midiPlayer(nullptr),
+ _cameraX(0), _newCameraX(0), _frameNr(0), _cursor1(nullptr), _cursor2(nullptr), _font(nullptr),
+ _walizkaBmp(nullptr), _roomBmp(nullptr), _cursorNr(0) {
+
+ // Debug/console setup
+ DebugMan.addDebugChannel(DebugChannel::kScript, "script", "Prince Script debug channel");
+ DebugMan.addDebugChannel(DebugChannel::kEngine, "engine", "Prince Engine debug channel");
+
+ DebugMan.enableDebugChannel("script");
+
+ memset(_voiceStream, 0, sizeof(_voiceStream));
+
+ gDebugLevel = 10;
+}
+
+PrinceEngine::~PrinceEngine() {
+ DebugMan.clearAllDebugChannels();
+
+ delete _rnd;
+ delete _debugger;
+ delete _cursor1;
+ delete _cursor2;
+ delete _midiPlayer;
+ delete _script;
+ delete _flags;
+ delete _interpreter;
+ delete _font;
+ delete _roomBmp;
+ delete _walizkaBmp;
+ delete _variaTxt;
+ delete[] _talkTxt;
+ delete _graph;
+ delete _mainHero;
+ delete _secondHero;
+
+ for (uint32 i = 0; i < _objList.size(); ++i) {
+ delete _objList[i];
+ }
+ _objList.clear();
+}
+
+GUI::Debugger *PrinceEngine::getDebugger() {
+ return _debugger;
+}
+
+void PrinceEngine::init() {
+
+ const Common::FSNode gameDataDir(ConfMan.get("path"));
+
+ debugEngine("Adding all path: %s", gameDataDir.getPath().c_str());
+
+ PtcArchive *all = new PtcArchive();
+ if (!all->open("all/databank.ptc"))
+ error("Can't open all/databank.ptc");
+
+ PtcArchive *voices = new PtcArchive();
+ if (!voices->open("data/voices/databank.ptc"))
+ error("Can't open data/voices/databank.ptc");
+
+ PtcArchive *sound = new PtcArchive();
+ if (!sound->open("sound/databank.ptc"))
+ error("Can't open sound/databank.ptc");
+
+ SearchMan.addSubDirectoryMatching(gameDataDir, "all");
+
+ SearchMan.add("all", all);
+ SearchMan.add("voices", voices);
+ SearchMan.add("sound", sound);
+
+ _graph = new GraphicsMan(this);
+
+ _rnd = new Common::RandomSource("prince");
+ _debugger = new Debugger(this);
+
+ _midiPlayer = new MusicPlayer(this);
+
+ _font = new Font();
+ Resource::loadResource(_font, "font1.raw");
+
+ _walizkaBmp = new MhwanhDecoder();
+ Resource::loadResource(_walizkaBmp, "walizka");
+
+ _script = new Script();
+ Resource::loadResource(_script, "skrypt.dat");
+
+ _flags = new InterpreterFlags();
+ _interpreter = new Interpreter(this, _script, _flags);
+
+ _variaTxt = new VariaTxt();
+ Resource::loadResource(_variaTxt, "variatxt.dat");
+
+ _cursor1 = new Cursor();
+ Resource::loadResource(_cursor1, "mouse1.cur");
+
+ _cursor2 = new Cursor();
+ Resource::loadResource(_cursor2, "mouse2.cur");
+
+ Common::SeekableReadStream *talkTxtStream = SearchMan.createReadStreamForMember("talktxt.dat");
+ if (!talkTxtStream) {
+ error("Can't load talkTxtStream");
+ return;
+ }
+ _talkTxtSize = talkTxtStream->size();
+ _talkTxt = new byte[_talkTxtSize];
+ talkTxtStream->read(_talkTxt, _talkTxtSize);
+
+ delete talkTxtStream;
+
+ _roomBmp = new Image::BitmapDecoder();
+
+ _mainHero = new Hero();
+ _secondHero = new Hero();
+
+ _mainHero->loadAnimSet(0);
+}
+
+void PrinceEngine::showLogo() {
+ MhwanhDecoder logo;
+ if (Resource::loadResource(&logo, "logo.raw")) {
+ _graph->setPalette(logo.getPalette());
+ _graph->draw(0, 0, logo.getSurface());
+ _graph->update();
+ _system->delayMillis(700);
+ }
+}
+
+Common::Error PrinceEngine::run() {
+
+ init();
+
+ showLogo();
+
+ mainLoop();
+
+ return Common::kNoError;
+}
+
+bool AnimListItem::loadFromStream(Common::SeekableReadStream &stream) {
+ int32 pos = stream.pos();
+
+ uint16 type = stream.readUint16LE();
+ if (type == 0xFFFF) {
+ return false;
+ }
+ _type = type;
+ _fileNumber = stream.readUint16LE();
+ _startPhase = stream.readUint16LE();
+ _endPhase = stream.readUint16LE();
+ _loopPhase = stream.readUint16LE();
+ _x = stream.readSint16LE();
+ _y = stream.readSint16LE();
+ _loopType = stream.readUint16LE();
+ _nextAnim = stream.readUint16LE();
+ _flags = stream.readUint16LE();
+
+ debug("AnimListItem type %d, fileNumber %d, x %d, y %d, flags %d", _type, _fileNumber, _x, _y, _flags);
+
+
+ // 32 byte aligment
+ stream.seek(pos + 32);
+
+ return true;
+}
+
+bool PrinceEngine::loadLocation(uint16 locationNr) {
+ _flicPlayer.close();
+
+ memset(_textSlots, 0, sizeof(_textSlots));
+ for(uint32 sampleId = 0; sampleId < MAX_SAMPLES; ++sampleId) {
+ stopSample(sampleId);
+ }
+
+ debugEngine("PrinceEngine::loadLocation %d", locationNr);
+ const Common::FSNode gameDataDir(ConfMan.get("path"));
+ SearchMan.remove(Common::String::format("%02d", _locationNr));
+
+ _locationNr = locationNr;
+ _debugger->_locationNr = locationNr;
+ _cameraX = 0;
+ _newCameraX = 0;
+
+ _flags->setFlagValue(Flags::CURRROOM, _locationNr);
+ _interpreter->stopBg();
+
+ changeCursor(0);
+
+ const Common::String locationNrStr = Common::String::format("%02d", _locationNr);
+ debugEngine("loadLocation %s", locationNrStr.c_str());
+
+ PtcArchive *locationArchive = new PtcArchive();
+ if (!locationArchive->open(locationNrStr + "/databank.ptc"))
+ error("Can't open location %s", locationNrStr.c_str());
+
+ SearchMan.add(locationNrStr, locationArchive);
+
+ const char *musName = MusicPlayer::_musTable[MusicPlayer::_musRoomTable[locationNr]];
+ _midiPlayer->loadMidi(musName);
+
+ // load location background, replace old one
+ Resource::loadResource(_roomBmp, "room");
+ if (_roomBmp->getSurface()) {
+ _sceneWidth = _roomBmp->getSurface()->w;
+ }
+
+ _mainHero->_zoomBitmap->clear();
+ Resource::loadResource(_mainHero->_zoomBitmap, "zoom", false);
+
+ _mobList.clear();
+ Resource::loadResource(_mobList, "mob.lst", false);
+
+ for (uint32 i = 0; i < _objList.size(); ++i) {
+ delete _objList[i];
+ }
+ _objList.clear();
+ Resource::loadResource(_objList, "obj.lst", false);
+
+ _animList.clear();
+ Resource::loadResource(_animList, "anim.lst", false);
+
+ return true;
+}
+
+void PrinceEngine::changeCursor(uint16 curId) {
+ _debugger->_cursorNr = curId;
+
+ const Graphics::Surface *curSurface = nullptr;
+
+ uint16 hotspotX = 0;
+ uint16 hotspotY = 0;
+
+ switch(curId) {
+ case 0:
+ CursorMan.showMouse(false);
+ return;
+ case 1:
+ curSurface = _cursor1->getSurface();
+ break;
+ case 2:
+ curSurface = _cursor2->getSurface();
+ hotspotX = curSurface->w >> 1;
+ hotspotY = curSurface->h >> 1;
+ break;
+ }
+
+ CursorMan.replaceCursorPalette(_roomBmp->getPalette(), 0, 255);
+ CursorMan.replaceCursor(
+ curSurface->getBasePtr(0, 0),
+ curSurface->w, curSurface->h,
+ hotspotX, hotspotY,
+ 255, false,
+ &curSurface->format
+ );
+ CursorMan.showMouse(true);
+}
+
+bool PrinceEngine::playNextFrame() {
+ if (!_flicPlayer.isVideoLoaded())
+ return false;
+
+ const Graphics::Surface *s = _flicPlayer.decodeNextFrame();
+ if (s) {
+ _graph->drawTransparent(0, 0, s);
+ _graph->change();
+ } else if (_flicLooped) {
+ _flicPlayer.rewind();
+ playNextFrame();
+ }
+
+ return true;
+}
+
+void PrinceEngine::playSample(uint16 sampleId, uint16 loopType) {
+ if (_voiceStream[sampleId]) {
+
+ if (_mixer->isSoundIDActive(sampleId)) {
+ return;
+ }
+
+ Audio::AudioStream *audioStream = Audio::makeWAVStream(_voiceStream[sampleId], DisposeAfterUse::YES);
+ if (loopType) {
+ audioStream = new Audio::LoopingAudioStream((Audio::RewindableAudioStream*)audioStream, 0, DisposeAfterUse::NO);
+ }
+ _mixer->playStream(Audio::Mixer::kSFXSoundType, &_soundHandle[sampleId], audioStream, sampleId);
+ }
+}
+
+void PrinceEngine::stopSample(uint16 sampleId) {
+ _mixer->stopID(sampleId);
+ _voiceStream[sampleId] = nullptr;
+}
+
+bool PrinceEngine::loadSample(uint32 sampleSlot, const Common::String &streamName) {
+ // FIXME: This is just a workaround streamName is a path
+ // SOUND\\SCIERKA1.WAV for now only last path component is used
+ Common::String normalizedPath = lastPathComponent(streamName, '\\');
+
+ debugEngine("loadSample slot %d, name %s", sampleSlot, normalizedPath.c_str());
+
+ _mixer->stopID(sampleSlot);
+ _voiceStream[sampleSlot] = nullptr;
+ _voiceStream[sampleSlot] = SearchMan.createReadStreamForMember(normalizedPath);
+ if (_voiceStream[sampleSlot] == nullptr) {
+ error("Can't load sample %s to slot %d", normalizedPath.c_str(), sampleSlot);
+ }
+ return _voiceStream[sampleSlot] == nullptr;
+}
+
+bool PrinceEngine::loadVoice(uint32 slot, uint32 sampleSlot, const Common::String &streamName) {
+ debugEngine("Loading wav %s slot %d", streamName.c_str(), slot);
+
+ if (slot > MAXTEXTS) {
+ error("Text slot bigger than MAXTEXTS %d", MAXTEXTS);
+ return false;
+ }
+
+ _voiceStream[sampleSlot] = SearchMan.createReadStreamForMember(streamName);
+ if (!_voiceStream[sampleSlot]) {
+ error("Can't open %s", streamName.c_str());
+ return false;
+ }
+
+ uint32 id = _voiceStream[sampleSlot]->readUint32LE();
+ if (id != 0x46464952) {
+ error("It's not RIFF file %s", streamName.c_str());
+ return false;
+ }
+
+ _voiceStream[sampleSlot]->skip(0x20);
+ id = _voiceStream[sampleSlot]->readUint32LE();
+ if (id != 0x61746164) {
+ error("No data section in %s id %04x", streamName.c_str(), id);
+ return false;
+ }
+
+ id = _voiceStream[sampleSlot]->readUint32LE();
+ debugEngine("SetVoice slot %d time %04x", slot, id);
+ id <<= 3;
+ id /= 22050;
+ id += 2;
+
+ _textSlots[slot]._time = id;
+
+ debugEngine("SetVoice slot %d time %04x", slot, id);
+ _voiceStream[sampleSlot]->seek(0);
+
+ return true;
+}
+
+bool PrinceEngine::loadAnim(uint16 animNr, bool loop) {
+ Common::String streamName = Common::String::format("AN%02d", animNr);
+ Common::SeekableReadStream * flicStream = SearchMan.createReadStreamForMember(streamName);
+
+ if (!flicStream) {
+ error("Can't open %s", streamName.c_str());
+ return false;
+ }
+
+ if (!_flicPlayer.loadStream(flicStream)) {
+ error("Can't load flic stream %s", streamName.c_str());
+ }
+
+ debugEngine("%s loaded", streamName.c_str());
+ _flicLooped = loop;
+ _flicPlayer.start();
+ playNextFrame();
+ return true;
+}
+
+void PrinceEngine::scrollCameraLeft(int16 delta) {
+ if (_newCameraX > 0) {
+ if (_newCameraX < delta)
+ _newCameraX = 0;
+ else
+ _newCameraX -= delta;
+ }
+}
+
+void PrinceEngine::scrollCameraRight(int16 delta) {
+ if (_newCameraX != _sceneWidth - 640) {
+ if (_sceneWidth - 640 < delta + _newCameraX)
+ delta += (_sceneWidth - 640) - (delta + _newCameraX);
+ _newCameraX += delta;
+ debugEngine("PrinceEngine::scrollCameraRight() _newCameraX = %d; delta = %d", _newCameraX, delta);
+ }
+}
+
+void PrinceEngine::keyHandler(Common::Event event) {
+ uint16 nChar = event.kbd.keycode;
+ switch (nChar) {
+ case Common::KEYCODE_d:
+ if (event.kbd.hasFlags(Common::KBD_CTRL)) {
+ getDebugger()->attach();
+ }
+ break;
+ case Common::KEYCODE_LEFT:
+ scrollCameraLeft(32);
+ break;
+ case Common::KEYCODE_RIGHT:
+ scrollCameraRight(32);
+ break;
+ case Common::KEYCODE_ESCAPE:
+ _flags->setFlagValue(Flags::ESCAPED2, 1);
+ break;
+ case Common::KEYCODE_UP:
+ _mainHero->_phase++;
+ debugEngine("%d", _mainHero->_phase);
+ break;
+ case Common::KEYCODE_DOWN:
+ if(_mainHero->_phase > 0) {
+ _mainHero->_phase--;
+ }
+ debugEngine("%d", _mainHero->_phase);
+ break;
+ case Common::KEYCODE_w:
+ _mainHero->_lastDirection = _mainHero->UP;
+ debugEngine("UP");
+ break;
+ case Common::KEYCODE_s:
+ _mainHero->_lastDirection = _mainHero->DOWN;
+ debugEngine("DOWN");
+ break;
+ case Common::KEYCODE_a:
+ _mainHero->_lastDirection = _mainHero->LEFT;
+ debugEngine("LEFT");
+ break;
+ case Common::KEYCODE_f:
+ _mainHero->_lastDirection = _mainHero->RIGHT;
+ debugEngine("RIGHT");
+ break;
+ case Common::KEYCODE_1:
+ if(_mainHero->_state > 0) {
+ _mainHero->_state--;
+ }
+ debugEngine("%d", _mainHero->_state);
+ break;
+ case Common::KEYCODE_2:
+ _mainHero->_state++;
+ debugEngine("%d", _mainHero->_state);
+ break;
+ case Common::KEYCODE_i:
+ _mainHero->_middleY -= 10;
+ break;
+ case Common::KEYCODE_k:
+ _mainHero->_middleY += 10;
+ break;
+ case Common::KEYCODE_j:
+ _mainHero->_middleX -= 10;
+ break;
+ case Common::KEYCODE_l:
+ _mainHero->_middleX += 10;
+ break;
+ }
+}
+
+void PrinceEngine::hotspot() {
+ Common::Point mousepos = _system->getEventManager()->getMousePos();
+ Common::Point mousePosCamera(mousepos.x + _cameraX, mousepos.y);
+
+ for (Common::Array<Mob>::const_iterator it = _mobList.begin()
+ ; it != _mobList.end() ; ++it) {
+ const Mob& mob = *it;
+ if (mob._visible)
+ continue;
+ if (mob._rect.contains(mousePosCamera)) {
+ uint16 textW = 0;
+ for (uint16 i = 0; i < mob._name.size(); ++i)
+ textW += _font->getCharWidth(mob._name[i]);
+
+ uint16 x = mousepos.x - textW/2;
+ if (x > _graph->_frontScreen->w)
+ x = 0;
+
+ if (x + textW > _graph->_frontScreen->w)
+ x = _graph->_frontScreen->w - textW;
+
+ uint16 y = mousepos.y - _font->getFontHeight();
+ if (y > _graph->_frontScreen->h)
+ y = _font->getFontHeight() - 2;
+
+ _font->drawString(
+ _graph->_frontScreen,
+ mob._name,
+ x,
+ y,
+ _graph->_frontScreen->w,
+ 216
+ );
+ break;
+ }
+ }
+}
+
+void PrinceEngine::printAt(uint32 slot, uint8 color, const char *s, uint16 x, uint16 y) {
+
+ debugC(1, DebugChannel::kEngine, "PrinceEngine::printAt slot %d, color %d, x %02d, y %02d, str %s", slot, color, x, y, s);
+
+ Text &text = _textSlots[slot];
+ text._str = s;
+ text._x = x;
+ text._y = y;
+ text._color = color;
+}
+
+uint32 PrinceEngine::getTextWidth(const char *s) {
+ uint16 textW = 0;
+ while (*s) {
+ textW += _font->getCharWidth(*s) + _font->getKerningOffset(0, 0);
+ ++s;
+ }
+ return textW;
+}
+
+void PrinceEngine::showTexts() {
+ for (uint32 slot = 0; slot < MAXTEXTS; ++slot) {
+ Text& text = _textSlots[slot];
+ if (!text._str && !text._time)
+ continue;
+
+ Common::Array<Common::String> lines;
+ _font->wordWrapText(text._str, _graph->_frontScreen->w, lines);
+
+ for (uint8 i = 0; i < lines.size(); ++i) {
+ _font->drawString(
+ _graph->_frontScreen,
+ lines[i],
+ text._x - getTextWidth(lines[i].c_str())/2,
+ text._y - (lines.size() - i) * (_font->getFontHeight()),
+ _graph->_frontScreen->w,
+ text._color
+ );
+ }
+
+ --text._time;
+ if (text._time == 0) {
+ text._str = nullptr;
+ }
+ }
+}
+
+void PrinceEngine::drawScreen() {
+ const Graphics::Surface *roomSurface = _roomBmp->getSurface();
+ if (roomSurface) {
+ _graph->setPalette(_roomBmp->getPalette());
+ const Graphics::Surface visiblePart = roomSurface->getSubArea(Common::Rect(_cameraX, 0, roomSurface->w, roomSurface->h));
+ _graph->draw(0, 0, &visiblePart);
+ }
+
+ if (_mainHero->_visible) {
+ const Graphics::Surface *mainHeroSurface = _mainHero->getSurface();
+
+ if (mainHeroSurface)
+ //_graph->drawTransparent(_mainHero->_middleX, _mainHero->_middleY, mainHeroSurface);
+ _graph->drawTransparent(_mainHero->_drawX, _mainHero->_drawY, mainHeroSurface);
+ }
+
+ playNextFrame();
+
+ //if (_objectList)
+ // _graph->drawTransparent(_objectList->getSurface());
+
+ hotspot();
+
+ showTexts();
+
+ getDebugger()->onFrame();
+
+ _graph->update();
+}
+
+void PrinceEngine::mainLoop() {
+
+ changeCursor(0);
+
+ while (!shouldQuit()) {
+ uint32 currentTime = _system->getMillis();
+
+ Common::Event event;
+ Common::EventManager *eventMan = _system->getEventManager();
+ while (eventMan->pollEvent(event)) {
+ switch (event.type) {
+ case Common::EVENT_KEYDOWN:
+ keyHandler(event);
+ break;
+ case Common::EVENT_KEYUP:
+ break;
+ case Common::EVENT_MOUSEMOVE:
+ break;
+ case Common::EVENT_LBUTTONDOWN:
+ case Common::EVENT_RBUTTONDOWN:
+ break;
+ case Common::EVENT_LBUTTONUP:
+ case Common::EVENT_RBUTTONUP:
+ break;
+ case Common::EVENT_QUIT:
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (shouldQuit())
+ return;
+
+ // TODO: Update all structures, animations, naks, heros etc.
+ _mainHero -> showHero();
+
+ _interpreter->step();
+
+ drawScreen();
+
+ // Calculate the frame delay based off a desired frame time
+ int delay = 1000/15 - int32(_system->getMillis() - currentTime);
+ // Ensure non-negative
+ delay = delay < 0 ? 0 : delay;
+ _system->delayMillis(delay);
+
+ _cameraX = _newCameraX;
+ ++_frameNr;
+
+ if (_debugger->_locationNr != _locationNr)
+ loadLocation(_debugger->_locationNr);
+ if (_debugger->_cursorNr != _cursorNr)
+ changeCursor(_debugger->_cursorNr);
+ }
+}
+
+} // End of namespace Prince
+
+/* vim: set tabstop=4 expandtab!: */
diff --git a/engines/prince/prince.h b/engines/prince/prince.h
new file mode 100644
index 0000000000..a48f056d4d
--- /dev/null
+++ b/engines/prince/prince.h
@@ -0,0 +1,197 @@
+/* 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.
+ *
+ */
+
+#ifndef PRINCE_H
+#define PRINCE_H
+
+#include "common/random.h"
+#include "common/system.h"
+#include "common/debug.h"
+#include "common/debug-channels.h"
+#include "common/textconsole.h"
+#include "common/rect.h"
+#include "common/events.h"
+
+#include "image/bmp.h"
+
+#include "gui/debugger.h"
+
+#include "engines/engine.h"
+#include "engines/util.h"
+
+#include "audio/mixer.h"
+
+#include "video/flic_decoder.h"
+
+#include "prince/mob.h"
+#include "prince/object.h"
+
+
+namespace Prince {
+
+struct PrinceGameDescription;
+
+class PrinceEngine;
+class GraphicsMan;
+class Script;
+class Interpreter;
+class InterpreterFlags;
+class Debugger;
+class MusicPlayer;
+class VariaTxt;
+class Cursor;
+class MhwanhDecoder;
+class Font;
+class Hero;
+class Animation;
+
+struct Text {
+ const char *_str;
+ uint16 _x, _y;
+ uint16 _time;
+ uint32 _color;
+
+ Text() : _str(NULL), _x(0), _y(0), _time(0), _color(255){
+ }
+};
+
+struct AnimListItem {
+ uint16 _type;
+ uint16 _fileNumber;
+ uint16 _startPhase;
+ uint16 _endPhase;
+ uint16 _loopPhase;
+ int16 _x;
+ int16 _y;
+ uint16 _loopType;
+ uint16 _nextAnim;
+ uint16 _flags;
+
+ bool loadFromStream(Common::SeekableReadStream &stream);
+};
+
+struct DebugChannel {
+
+enum Type {
+ kScript,
+ kEngine
+};
+
+};
+
+class PrinceEngine : public Engine {
+protected:
+ Common::Error run();
+
+public:
+ PrinceEngine(OSystem *syst, const PrinceGameDescription *gameDesc);
+ virtual ~PrinceEngine();
+
+ virtual bool hasFeature(EngineFeature f) const;
+
+ int getGameType() const;
+ const char *getGameId() const;
+ uint32 getFeatures() const;
+ Common::Language getLanguage() const;
+
+ const PrinceGameDescription *_gameDescription;
+ Video::FlicDecoder _flicPlayer;
+ VariaTxt *_variaTxt;
+
+ uint32 _talkTxtSize;
+ byte *_talkTxt;
+
+ bool loadLocation(uint16 locationNr);
+ bool loadAnim(uint16 animNr, bool loop);
+ bool loadVoice(uint32 textSlot, uint32 sampleSlot, const Common::String &name);
+ bool loadSample(uint32 sampleSlot, const Common::String &name);
+
+ void playSample(uint16 sampleId, uint16 loopType);
+ void stopSample(uint16 sampleId);
+
+ virtual GUI::Debugger *getDebugger();
+
+ void changeCursor(uint16 curId);
+ void printAt(uint32 slot, uint8 color, const char *s, uint16 x, uint16 y);
+
+ static const uint8 MAXTEXTS = 32;
+ Text _textSlots[MAXTEXTS];
+
+ uint64 _frameNr;
+ Hero* _mainHero;
+ Hero* _secondHero;
+
+private:
+ bool playNextFrame();
+ void keyHandler(Common::Event event);
+ void hotspot();
+ void scrollCameraRight(int16 delta);
+ void scrollCameraLeft(int16 delta);
+ void drawScreen();
+ void showTexts();
+ void init();
+ void showLogo();
+
+ uint32 getTextWidth(const char *s);
+ void debugEngine(const char *s, ...);
+
+ uint16 _locationNr;
+ uint8 _cursorNr;
+
+ Common::RandomSource *_rnd;
+ Image::BitmapDecoder *_roomBmp;
+ Cursor *_cursor1;
+ Cursor *_cursor2;
+ MhwanhDecoder *_walizkaBmp;
+ Debugger *_debugger;
+ GraphicsMan *_graph;
+ Script *_script;
+ InterpreterFlags *_flags;
+ Interpreter *_interpreter;
+ Font *_font;
+ MusicPlayer *_midiPlayer;
+
+
+ static const uint32 MAX_SAMPLES = 60;
+ Common::SeekableReadStream *_voiceStream[MAX_SAMPLES];
+ Audio::SoundHandle _soundHandle[MAX_SAMPLES];
+
+ Animation *_zoom;
+ Common::Array<Mob> _mobList;
+ Common::Array<Object *> _objList;
+ Common::Array<AnimListItem> _animList;
+
+ uint16 _cameraX;
+ uint16 _newCameraX;
+ uint16 _sceneWidth;
+
+ bool _flicLooped;
+
+ void mainLoop();
+
+};
+
+} // End of namespace Prince
+
+#endif
+
+/* vim: set tabstop=4 noexpandtab: */
diff --git a/engines/prince/resource.h b/engines/prince/resource.h
new file mode 100644
index 0000000000..2f7e6ba3a8
--- /dev/null
+++ b/engines/prince/resource.h
@@ -0,0 +1,102 @@
+/* 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.
+ *
+ */
+
+#ifndef PRINCE_RESOURCE_H
+#define PRINCE_RESOURCE_H
+
+#include "common/stream.h"
+#include "common/archive.h"
+#include "common/debug-channels.h"
+#include "common/ptr.h"
+
+namespace Prince {
+
+namespace Resource {
+
+ template <typename T>
+ bool loadFromStream(T &resource, Common::SeekableReadStream &stream) {
+ return resource.loadFromStream(stream);
+ }
+
+ template<typename T>
+ bool loadResource(T *resource, const char *resourceName, bool required = true) {
+ Common::ScopedPtr<Common::SeekableReadStream> stream(SearchMan.createReadStreamForMember(resourceName));
+ if (!stream) {
+ if (required)
+ error("Can't load %s", resourceName);
+ return false;
+ }
+
+ return loadFromStream(*resource, *stream);
+ }
+
+ template <typename T>
+ bool loadResource(Common::Array<T> &array, Common::SeekableReadStream &stream, bool required = true) {
+ T t;
+ while (t.loadFromStream(stream))
+ array.push_back(t);
+
+ return true;
+ }
+
+
+ template <typename T>
+ bool loadResource(Common::Array<T> &array, const char *resourceName, bool required = true) {
+ Common::ScopedPtr<Common::SeekableReadStream> stream(SearchMan.createReadStreamForMember(resourceName));
+ if (!stream) {
+ if (required)
+ error("Can't load %s", resourceName);
+ return false;
+ }
+
+ return loadResource(array, *stream, required);
+ }
+
+ template <typename T>
+ bool loadResource(Common::Array<T *> &array, const char *resourceName, bool required = true) {
+
+ Common::ScopedPtr<Common::SeekableReadStream> stream(SearchMan.createReadStreamForMember(resourceName));
+ if (!stream) {
+ if (required)
+ error("Can't load %s", resourceName);
+ return false;
+ }
+
+ // FIXME: This is stupid. Maybe loadFromStream should be helper method that returns initiailzed object
+ while (true) {
+ T* t = new T();
+ if (!t->loadFromStream(*stream)) {
+ delete t;
+ break;
+ }
+ array.push_back(t);
+ }
+ return true;
+ }
+
+}
+
+}
+
+#endif
+
+/* vim: set tabstop=4 noexpandtab: */
diff --git a/engines/prince/script.cpp b/engines/prince/script.cpp
new file mode 100644
index 0000000000..84ae64791e
--- /dev/null
+++ b/engines/prince/script.cpp
@@ -0,0 +1,1452 @@
+/* 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.
+ *
+ */
+
+#include "prince/script.h"
+#include "prince/prince.h"
+#include "prince/flags.h"
+#include "prince/variatxt.h"
+#include "prince/font.h"
+#include "prince/hero.h"
+#include "prince/resource.h"
+
+#include "common/debug.h"
+#include "common/debug-channels.h"
+#include "common/stream.h"
+#include "common/archive.h"
+#include "common/memstream.h"
+
+namespace Prince {
+
+static const uint16 NUM_OPCODES = 144;
+
+Room::Room() {}
+
+void Room::loadMobs(Common::SeekableReadStream &stream) {
+ debug("loadMobs %d", stream.pos());
+ static const uint8 MAX_MOBS = 64;
+ uint8 mobs[MAX_MOBS];
+ stream.read(&mobs, sizeof(mobs));
+ for(uint8 i = 0; i < sizeof(mobs); ++i) {
+ debug("mob %d flag %d", i, mobs[i]);
+ }
+}
+
+void Room::loadBackAnim(Common::SeekableReadStream &stream) {
+ debug("loadBackAnim %d", stream.pos());
+ static const uint8 MAX_BACK_ANIMS = 64;
+ uint32 backAnim[MAX_BACK_ANIMS];
+ debug("loadBackAnim sizeof %lu", sizeof(backAnim));
+ stream.read(backAnim, sizeof(backAnim));
+ for(uint8 i = 0; i < MAX_BACK_ANIMS; ++i) {
+ debug("back anim offset %d", backAnim[i]);
+ }
+}
+
+void Room::loadObj(Common::SeekableReadStream &stream) {}
+void Room::loadNak(Common::SeekableReadStream &stream) {}
+void Room::loadItemUse(Common::SeekableReadStream &stream) {}
+void Room::loadItemGive(Common::SeekableReadStream &stream) {}
+void Room::loadWalkTo(Common::SeekableReadStream &stream) {}
+void Room::loadExamine(Common::SeekableReadStream &stream) {}
+void Room::loadPickup(Common::SeekableReadStream &stream) {}
+void Room::loadUse(Common::SeekableReadStream &stream) {}
+void Room::loadPushOpen(Common::SeekableReadStream &stream) {}
+void Room::loadPullClose(Common::SeekableReadStream &stream) {}
+void Room::loadTalk(Common::SeekableReadStream &stream) {}
+void Room::loadGive(Common::SeekableReadStream &stream) {}
+
+void Room::nextLoadStep(Common::SeekableReadStream &stream, LoadingStep step) {
+ uint32 offset = stream.readUint32LE();
+ uint32 pos = stream.pos();
+ stream.seek(offset);
+
+ debug("nextLoadStep offset %d, pos %d", offset, pos);
+
+ (this->*step)(stream);
+
+ stream.seek(pos);
+}
+
+bool Room::loadFromStream(Common::SeekableReadStream &stream) {
+
+ uint32 pos = stream.pos();
+
+ nextLoadStep(stream, &Room::loadMobs);
+ nextLoadStep(stream, &Room::loadBackAnim);
+ nextLoadStep(stream, &Room::loadObj);
+ nextLoadStep(stream, &Room::loadNak);
+ nextLoadStep(stream, &Room::loadItemUse);
+ nextLoadStep(stream, &Room::loadItemGive);
+ nextLoadStep(stream, &Room::loadWalkTo);
+ nextLoadStep(stream, &Room::loadExamine);
+ nextLoadStep(stream, &Room::loadPickup);
+ nextLoadStep(stream, &Room::loadUse);
+ nextLoadStep(stream, &Room::loadPushOpen);
+ nextLoadStep(stream, &Room::loadPullClose);
+ nextLoadStep(stream, &Room::loadTalk);
+ nextLoadStep(stream, &Room::loadGive);
+
+ // skip some data for now
+ static const uint8 ROOM_ENTRY_SIZE = 64;
+ stream.seek(pos + ROOM_ENTRY_SIZE);
+
+ return true;;
+}
+
+Script::Script() : _data(nullptr), _dataSize(0) {
+}
+
+Script::~Script() {
+ delete[] _data;
+ _dataSize = 0;
+ _data = nullptr;
+}
+
+bool Script::loadFromStream(Common::SeekableReadStream &stream) {
+ _dataSize = stream.size();
+ if (!_dataSize)
+ return false;
+
+ _data = new byte[_dataSize];
+
+ if (!_data)
+ return false;
+
+ stream.read(_data, _dataSize);
+
+ Common::MemoryReadStream scriptDataStream(_data, _dataSize);
+ scriptDataStream.seek(getRoomTableOffset()+64);
+ debug("room table offset %d", scriptDataStream.pos());
+ Room room;
+ room.loadFromStream(scriptDataStream);
+
+ return true;
+}
+
+InterpreterFlags::InterpreterFlags() {
+ resetAllFlags();
+}
+
+void InterpreterFlags::resetAllFlags() {
+ memset(_flags, 0, sizeof(_flags));
+}
+
+void InterpreterFlags::setFlagValue(Flags::Id flagId, uint16 value) {
+ _flags[(uint16)flagId - FLAG_MASK] = value;
+}
+
+uint16 InterpreterFlags::getFlagValue(Flags::Id flagId) {
+ return _flags[(uint16)flagId - FLAG_MASK];
+}
+
+Interpreter::Interpreter(PrinceEngine *vm, Script *script, InterpreterFlags *flags) :
+ _vm(vm), _script(script), _flags(flags),
+ _stacktop(0), _opcodeNF(false),
+ _waitFlag(0), _result(true) {
+
+ // Initialize the script
+ _mode = "fg";
+ _fgOpcodePC = _script->getStartGameOffset();
+ _bgOpcodePC = 0;
+}
+
+void Interpreter::debugInterpreter(const char *s, ...) {
+ char buf[STRINGBUFLEN];
+ va_list va;
+
+ va_start(va, s);
+ vsnprintf(buf, STRINGBUFLEN, s, va);
+ va_end(va);
+
+ Common::String str = Common::String::format("@0x%08X: ", _lastInstruction);
+ str += Common::String::format("op %04d: ", _lastOpcode);
+ //debugC(10, DebugChannel::kScript, "PrinceEngine::Script %s %s", str.c_str(), buf);
+
+ //debug("Prince::Script frame %08ld mode %s %s %s", _vm->_frameNr, _mode, str.c_str(), buf);
+}
+
+void Interpreter::step() {
+ if (_bgOpcodePC) {
+ _mode = "bg";
+ _bgOpcodePC = step(_bgOpcodePC);
+ }
+ if (_fgOpcodePC) {
+ _mode = "fg";
+ _fgOpcodePC = step(_fgOpcodePC);
+ }
+}
+
+uint32 Interpreter::step(uint32 opcodePC) {
+ _currentInstruction = opcodePC;
+
+ while (!_opcodeNF) {
+ _lastInstruction = _currentInstruction;
+
+ // Get the current opcode
+ _lastOpcode = readScript<uint16>();
+
+ if (_lastOpcode > NUM_OPCODES)
+ error(
+ "Trying to execute unknown opcode @0x%04X: %02d",
+ _currentInstruction,
+ _lastOpcode);
+
+ // Execute the current opcode
+ OpcodeFunc op = _opcodes[_lastOpcode];
+ (this->*op)();
+ if (_opcodeNF) {
+ _opcodeNF = 0;
+ break;
+ }
+ }
+
+ return _currentInstruction;
+}
+
+template <typename T>
+T Interpreter::readScript() {
+ T data = _script->read<T>(_currentInstruction);
+ _currentInstruction += sizeof(data);
+ return data;
+}
+
+uint16 Interpreter::readScriptFlagValue() {
+ uint16 value = readScript<uint16>();
+ if (value & InterpreterFlags::FLAG_MASK) {
+ return _flags->getFlagValue((Flags::Id)value);
+ }
+ return value;
+}
+
+Flags::Id Interpreter::readScriptFlagId() {
+ return (Flags::Id)readScript<uint16>();
+}
+
+void Interpreter::O_WAITFOREVER() {
+ debugInterpreter("O_WAITFOREVER");
+ _opcodeNF = 1;
+ _currentInstruction -= 2;
+}
+
+void Interpreter::O_BLACKPALETTE() {
+ debugInterpreter("O_BLACKPALETTE");
+}
+
+void Interpreter::O_SETUPPALETTE() {
+ debugInterpreter("O_SETUPPALETTE");
+}
+
+void Interpreter::O_INITROOM() {
+ uint16 roomId = readScriptFlagValue();
+ debugInterpreter("O_INITROOM %d", roomId);
+ _vm->loadLocation(roomId);
+ _opcodeNF = 1;
+}
+
+void Interpreter::O_SETSAMPLE() {
+ uint16 sampleId = readScriptFlagValue();
+ int32 sampleNameOffset = readScript<uint32>();
+ const char * sampleName = _script->getString(_currentInstruction + sampleNameOffset - 4);
+ debugInterpreter("O_SETSAMPLE %d %s", sampleId, sampleName);
+ _vm->loadSample(sampleId, sampleName);
+}
+
+void Interpreter::O_FREESAMPLE() {
+ uint16 sample = readScriptFlagValue();
+ debugInterpreter("O_FREESAMPLE %d", sample);
+}
+
+void Interpreter::O_PLAYSAMPLE() {
+ uint16 sampleId = readScriptFlagValue();
+ uint16 loopType = readScript<uint16>();
+ debugInterpreter("O_PLAYSAMPLE sampleId %d loopType %d", sampleId, loopType);
+ _vm->playSample(sampleId, loopType);
+}
+
+void Interpreter::O_PUTOBJECT() {
+ uint16 roomId = readScriptFlagValue();
+ uint16 slot = readScriptFlagValue();
+ uint16 objectId = readScriptFlagValue();
+ debugInterpreter("O_PUTOBJECT roomId %d, slot %d, objectId %d", roomId, slot, objectId);
+}
+
+void Interpreter::O_REMOBJECT() {
+ uint16 roomId = readScriptFlagValue();
+ uint16 objectId = readScriptFlagValue();
+
+ debugInterpreter("O_REMOBJECT roomId %d objectId %d", roomId, objectId);
+}
+
+void Interpreter::O_SHOWANIM() {
+ uint16 slot = readScriptFlagValue();
+ uint16 animId = readScriptFlagValue();
+
+ debugInterpreter("O_SHOWANIM slot %d, animId %d", slot, animId);
+}
+
+void Interpreter::O_CHECKANIMEND() {
+ uint16 slot = readScriptFlagValue();
+ uint16 frameId = readScriptFlagValue();
+
+ debugInterpreter("O_CHECKANIMEND slot %d, frameId %d", slot, frameId);
+ _opcodeNF = 1;
+}
+
+void Interpreter::O_FREEANIM() {
+ uint16 slot = readScriptFlagValue();
+ debugInterpreter("O_FREEANIM slot %d", slot);
+}
+
+void Interpreter::O_CHECKANIMFRAME() {
+ uint16 slot = readScriptFlagValue();
+ uint16 frameId = readScriptFlagValue();
+
+ debugInterpreter("O_CHECKANIMFRAME slot %d, frameId %d", slot, frameId);
+ _opcodeNF = 1;
+}
+
+void Interpreter::O_PUTBACKANIM() {
+ uint16 roomId = readScriptFlagValue();
+ uint16 slot = readScriptFlagValue();
+ int32 animId = readScript<uint32>();
+ debugInterpreter("O_PUTBACKANIM roomId %d, slot %d, animId %d", roomId, slot, animId);
+}
+
+void Interpreter::O_REMBACKANIM() {
+ uint16 roomId = readScriptFlagValue();
+ uint16 slot = readScriptFlagValue();
+
+ debugInterpreter("O_REMBACKANIM roomId %d, slot %d", roomId, slot);
+}
+
+void Interpreter::O_CHECKBACKANIMFRAME() {
+ uint16 slotId = readScriptFlagValue();
+ uint16 frameId = readScriptFlagValue();
+
+ debugInterpreter("O_CHECKBACKANIMFRAME slotId %d, frameId %d", slotId, frameId);
+ _opcodeNF = 1;
+}
+
+void Interpreter::O_FREEALLSAMPLES() {
+ debugInterpreter("O_FREEALLSAMPLES");
+}
+
+void Interpreter::O_SETMUSIC() {
+ uint16 musicId = readScript<uint16>();
+
+ debugInterpreter("O_SETMUSIC musicId %d", musicId);
+}
+
+void Interpreter::O_STOPMUSIC() {
+ debugInterpreter("O_STOPMUSIC");
+}
+
+void Interpreter::O__WAIT() {
+ uint16 pause = readScriptFlagValue();
+
+ debugInterpreter("O__WAIT pause %d", pause);
+
+ if (_waitFlag == 0) {
+ // set new wait flag value and continue
+ _waitFlag = pause;
+ _opcodeNF = 1;
+ _currentInstruction -= 4;
+ return;
+ }
+
+ --_waitFlag;
+
+ if (_waitFlag > 0) {
+ _opcodeNF = 1;
+ _currentInstruction -= 4;
+ return;
+ }
+}
+
+void Interpreter::O_UPDATEOFF() {
+ debugInterpreter("O_UPDATEOFF");
+ //_updateEnable = false;
+}
+
+void Interpreter::O_UPDATEON() {
+ debugInterpreter("O_UPDATEON");
+ //_updateEnable = true;
+}
+
+void Interpreter::O_UPDATE () {
+ debugInterpreter("O_UPDATE");
+ // Refresh screen
+}
+
+void Interpreter::O_CLS() {
+ debugInterpreter("O_CLS");
+ // do nothing
+}
+
+void Interpreter::O__CALL() {
+ int32 address = readScript<uint32>();
+ _stack[_stacktop] = _currentInstruction;
+ _stacktop++;
+ _currentInstruction += address - 4;
+ debugInterpreter("O__CALL 0x%04X", _currentInstruction);
+}
+
+void Interpreter::O_RETURN() {
+ // Get the return address
+ if (_stacktop > 0) {
+ _stacktop--;
+ _currentInstruction = _stack[_stacktop];
+ debugInterpreter("O_RETURN 0x%04X", _currentInstruction);
+ } else {
+ error("Return: Stack is empty");
+ }
+}
+
+void Interpreter::O_GO() {
+ int32 opPC = readScript<uint32>();
+ debugInterpreter("O_GO 0x%04X", opPC);
+ _currentInstruction += opPC - 4;
+}
+
+void Interpreter::O_BACKANIMUPDATEOFF() {
+ uint16 slotId = readScriptFlagValue();
+ debugInterpreter("O_BACKANIMUPDATEOFF slotId %d", slotId);
+}
+
+void Interpreter::O_BACKANIMUPDATEON() {
+ uint16 slot = readScriptFlagValue();
+ debugInterpreter("O_BACKANIMUPDATEON %d", slot);
+}
+
+void Interpreter::O_CHANGECURSOR() {
+ uint16 cursorId = readScriptFlagValue();
+ debugInterpreter("O_CHANGECURSOR %x", cursorId);
+ _vm->changeCursor(cursorId);
+}
+
+void Interpreter::O_CHANGEANIMTYPE() {
+ // NOT IMPLEMENTED
+}
+
+void Interpreter::O__SETFLAG() {
+ Flags::Id flagId = readScriptFlagId();
+ uint16 value = readScriptFlagValue();
+
+ debugInterpreter("O__SETFLAG 0x%04X (%s) = %d", flagId, Flags::getFlagName(flagId), value);
+
+ _flags->setFlagValue((Flags::Id)(flagId), value);
+}
+
+void Interpreter::O_COMPARE() {
+ Flags::Id flagId = readScriptFlagId();
+ uint16 value = readScriptFlagValue();
+
+ _result = _flags->getFlagValue(flagId) != value;
+ debugInterpreter("O_COMPARE flagId 0x%04X (%s), value %d == %d (%d)", flagId, Flags::getFlagName(flagId), value, _flags->getFlagValue(flagId), _result);
+}
+
+void Interpreter::O_JUMPZ() {
+ int32 offset = readScript<uint32>();
+ if (! _result) {
+ _currentInstruction += offset - 4;
+ }
+
+ debugInterpreter("O_JUMPZ result = %d, next %08x, offset 0x%08X", _result, _currentInstruction, offset);
+}
+
+void Interpreter::O_JUMPNZ() {
+ int32 offset = readScript<uint32>();
+ if (_result) {
+ _currentInstruction += offset - 4;
+ }
+
+ debugInterpreter("O_JUMPNZ result = %d, next %08x, offset 0x%08X", _result, _currentInstruction, offset);
+}
+
+void Interpreter::O_EXIT() {
+ uint16 exitCode = readScriptFlagValue();
+ debugInterpreter("O_EXIT exitCode %d", exitCode);
+ // Set exit code and shows credits
+ // if exit code == 0x02EAD
+}
+
+void Interpreter::O_ADDFLAG() {
+ Flags::Id flagId = readScriptFlagId();
+ uint16 value = readScriptFlagValue();
+
+ _flags->setFlagValue(flagId, _flags->getFlagValue(flagId) + value);
+ if (_flags->getFlagValue(flagId))
+ _result = 1;
+ else
+ _result = 0;
+
+ debugInterpreter("O_ADDFLAG flagId %04x (%s), value %d", flagId, Flags::getFlagName(flagId), value);
+}
+
+void Interpreter::O_TALKANIM() {
+ uint16 animSlot = readScriptFlagValue();
+ uint16 slot = readScriptFlagValue();
+
+ debugInterpreter("O_TALKANIM animSlot %d, slot %d", animSlot, slot);
+}
+
+void Interpreter::O_SUBFLAG() {
+ Flags::Id flagId = readScriptFlagId();
+ uint16 value = readScriptFlagValue();
+
+ _flags->setFlagValue(flagId, _flags->getFlagValue(flagId) - value);
+ if (_flags->getFlagValue(flagId))
+ _result = 1;
+ else
+ _result = 0;
+
+ debugInterpreter("O_SUBFLAG flagId %d, value %d", flagId, value);
+}
+
+void Interpreter::O_SETSTRING() {
+ int32 offset = readScript<uint32>();
+ _currentString = offset;
+
+ // FIXME: Make it better ;)
+ if (offset >= 80000) {
+ debugInterpreter("GetVaria %s", _vm->_variaTxt->getString(offset - 80000));
+ }
+ else if (offset < 2000) {
+ uint32 of = READ_LE_UINT32(_vm->_talkTxt+offset*4);
+ const char * txt = (const char *)&_vm->_talkTxt[of];
+ _string = &_vm->_talkTxt[of];
+ debugInterpreter("TalkTxt %d %s", of, txt);
+ }
+
+ debugInterpreter("O_SETSTRING %04d", offset);
+}
+
+void Interpreter::O_ANDFLAG() {
+ Flags::Id flagId = readScriptFlagId();
+ uint16 value = readScriptFlagValue();
+
+ debugInterpreter("O_ANDFLAG flagId %d, value %d", flagId, value);
+
+ _flags->setFlagValue(flagId, _flags->getFlagValue(flagId) & value);
+
+ if (_flags->getFlagValue(flagId)) {
+ _result = 1;
+ } else {
+ _result = 0;
+ }
+}
+
+void Interpreter::O_GETMOBDATA() {
+ Flags::Id flagId = readScriptFlagId();
+ uint16 mobId = readScript<uint16>();
+ uint16 mobOffset = readScript<uint16>();
+
+ debugInterpreter("O_GETMOBDATA flagId %d, modId %d, mobOffset %d", flagId, mobId, mobOffset);
+}
+
+void Interpreter::O_ORFLAG() {
+ Flags::Id flagId = readScriptFlagId();
+ uint16 value = readScriptFlagValue();
+
+ debugInterpreter("O_ORFLAG flagId %d, value %d", flagId, value);
+
+ _flags->setFlagValue(flagId, _flags->getFlagValue(flagId) | value);
+
+ if (_flags->getFlagValue(flagId)) {
+ _result = 1;
+ } else {
+ _result = 0;
+ }
+}
+
+void Interpreter::O_SETMOBDATA() {
+ uint16 mobId = readScriptFlagValue();
+ uint16 mobOffset = readScriptFlagValue();
+ uint16 value = readScriptFlagValue();
+
+ debugInterpreter("O_SETMOBDATA mobId %d, mobOffset %d, value %d", mobId, mobOffset, value);
+}
+
+void Interpreter::O_XORFLAG() {
+ Flags::Id flagId = readScriptFlagId();
+ uint16 value = readScriptFlagValue();
+
+ debugInterpreter("O_XORFLAG flagId %d, value %d", flagId, value);
+
+ _flags->setFlagValue(flagId, _flags->getFlagValue(flagId) ^ value);
+
+ if (_flags->getFlagValue(flagId)) {
+ _result = 1;
+ } else {
+ _result = 0;
+ }
+}
+
+void Interpreter::O_GETMOBTEXT() {
+ uint16 value = readScriptFlagValue();
+
+ debugInterpreter("O_GETMOBTEXT value %d", value);
+ // Use Mob::ExamText as current string
+}
+
+void Interpreter::O_MOVEHERO() {
+ uint16 heroId = readScriptFlagValue();
+ uint16 x = readScriptFlagValue();
+ uint16 y = readScriptFlagValue();
+ uint16 dir = readScriptFlagValue();
+
+ debugInterpreter("O_MOVEHERO heroId %d, x %d, y %d, dir %d", heroId, x, y, dir);
+}
+
+void Interpreter::O_WALKHERO() {
+ uint16 heroId = readScriptFlagValue();
+
+ debugInterpreter("O_WALKHERO %d", heroId);
+ _opcodeNF = 1;
+}
+
+void Interpreter::O_SETHERO() {
+ uint16 hero = readScriptFlagValue();
+ int16 x = readScriptFlagValue();
+ int16 y = readScriptFlagValue();
+ uint16 dir = readScriptFlagValue();
+ debugInterpreter("O_SETHERO hero %d, x %d, y %d, dir %d", hero, x, y, dir);
+ _vm->_mainHero->setPos(x, y);
+ _vm->_mainHero->_lastDirection = dir;
+ _vm->_mainHero->_state = _vm->_mainHero->STAY;
+ _vm->_mainHero->_moveSetType = _vm->_mainHero->_lastDirection - 1; // for countDrawPosition
+ _vm->_mainHero->countDrawPosition(); //setting drawX, drawY
+}
+
+void Interpreter::O_HEROOFF() {
+ uint16 heroId = readScriptFlagValue();
+ debugInterpreter("O_HEROOFF %d", heroId);
+ _vm->_mainHero->setVisible(false);
+}
+
+void Interpreter::O_HEROON() {
+ uint16 heroId = readScriptFlagValue();
+ debugInterpreter("O_HEROON %d", heroId);
+ _vm->_mainHero->setVisible(true);
+}
+
+void Interpreter::O_CLSTEXT() {
+ uint16 slot = readScriptFlagValue();
+ debugInterpreter("O_CLSTEXT slot %d", slot);
+ // Sets text line to null
+ // Sets text timeout to zero
+}
+
+void Interpreter::O_CALLTABLE() {
+ uint16 flag = readScript<uint16>();
+ int32 table = readScript<uint32>();
+
+ debugInterpreter("O_CALLTABLE flag %d, table %d", flag, table);
+ // makes a call from script function table
+ // must read table pointer from _code and
+ // use table entry as next opcode
+}
+
+void Interpreter::O_CHANGEMOB() {
+ uint16 mob = readScriptFlagValue();
+ uint16 value = readScriptFlagValue();
+ debugInterpreter("O_CHANGEMOB mob %d, value %d", mob, value);
+ // Probably sets mobs visible flag to value
+}
+
+void Interpreter::O_ADDINV() {
+ uint16 hero = readScriptFlagValue();
+ uint16 item = readScriptFlagValue();
+ debugInterpreter("O_ADDINV hero %d, item %d", hero, item);
+}
+
+void Interpreter::O_REMINV() {
+ uint16 hero = readScriptFlagValue();
+ uint16 item = readScriptFlagValue();
+ debugInterpreter("O_REMINV hero %d, item %d", hero, item);
+}
+
+void Interpreter::O_REPINV() {
+ uint16 hero = readScript<uint16>();
+ uint16 item1 = readScript<uint16>();
+ uint16 item2 = readScript<uint16>();
+ // shouldn't be uses
+ error("O_REPINV hero %d, item1 %d, item2 %d", hero, item1, item2);
+}
+
+void Interpreter::O_OBSOLETE_GETACTION() {
+ // shouldn't be uses
+ error("O_OBSOLETE_GETACTION");
+}
+
+void Interpreter::O_ADDWALKAREA() {
+ uint16 x1 = readScript<uint16>();
+ uint16 y1 = readScript<uint16>();
+ uint16 x2 = readScript<uint16>();
+ uint16 y2 = readScript<uint16>();
+ // shouldn't be uses
+ error("O_ADDWALKAREA x1 %d, y1 %d, x2 %d, y2 %d", x1, y1, x2, y2);
+}
+
+void Interpreter::O_REMWALKAREA() {
+ uint16 x1 = readScript<uint16>();
+ uint16 y1 = readScript<uint16>();
+ uint16 x2 = readScript<uint16>();
+ uint16 y2 = readScript<uint16>();
+
+ // shouldn't be uses
+ error("O_REMWALKAREA x1 %d, y1 %d, x2 %d, y2 %d", x1, y1, x2, y2);
+}
+
+void Interpreter::O_RESTOREWALKAREA() {
+ debugInterpreter("O_RESTOREWALKAREA");
+}
+
+void Interpreter::O_WAITFRAME() {
+ debugInterpreter("O_WAITFRAME");
+ _opcodeNF = true;
+}
+
+void Interpreter::O_SETFRAME() {
+ uint16 anim = readScriptFlagValue();
+ uint16 frame = readScriptFlagValue();
+ debugInterpreter("O_SETFRAME anim %d, frame %d", anim, frame);
+}
+
+void Interpreter::O_RUNACTION() {
+ // It's empty in original and never used in script
+ // it's better to report error
+ error("O_RUNACTION");
+}
+
+void Interpreter::O_COMPAREHI() {
+ Flags::Id flag = readScriptFlagId();
+ uint16 value = readScriptFlagValue();
+
+ debugInterpreter("O_COMPAREHI flag %d, value %d", flag, value);
+ _result = value < _flags->getFlagValue(flag);
+}
+
+void Interpreter::O_COMPARELO() {
+ Flags::Id flag = readScriptFlagId();
+ uint16 value = readScriptFlagValue();
+
+ debugInterpreter("O_COMPARELO flag %d, value %d", flag, value);
+ _result = value > _flags->getFlagValue(flag);
+}
+
+void Interpreter::O_PRELOADSET() {
+ // not used in script
+ int32 offset = readScript<uint32>();
+ debugInterpreter("O_PRELOADSET offset %04x", offset);
+}
+
+void Interpreter::O_FREEPRELOAD() {
+ // not used in script
+ debugInterpreter("O_FREEPRELOAD");
+}
+
+void Interpreter::O_CHECKINV() {
+ uint16 hero = readScriptFlagValue();
+ uint16 item = readScriptFlagValue();
+ debugInterpreter("O_CHECKINV hero %d, item %d", hero, item);
+ // checks if item is in heros inventory
+}
+
+void Interpreter::O_TALKHERO() {
+ uint16 hero = readScriptFlagValue();
+ debugInterpreter("O_TALKHERO hero %d", hero);
+}
+
+void Interpreter::O_WAITTEXT() {
+ uint16 slot = readScriptFlagValue();
+ Text &text = _vm->_textSlots[slot];
+ if (text._time) {
+ _opcodeNF = 1;
+ _currentInstruction -= 4;
+ }
+}
+
+void Interpreter::O_SETHEROANIM() {
+ uint16 hero = readScriptFlagValue();
+ int32 offset = readScript<uint32>();
+ debugInterpreter("O_SETHEROANIM hero %d, offset %d", hero, offset);
+}
+
+void Interpreter::O_WAITHEROANIM() {
+ uint16 hero = readScriptFlagValue();
+
+ debugInterpreter("O_WAITHEROANIM hero %d", hero);
+}
+
+void Interpreter::O_GETHERODATA() {
+ uint16 flag = readScript<uint16>();
+ uint16 hero = readScriptFlagValue();
+ uint16 heroOffset = readScriptFlagValue();
+ debugInterpreter("O_GETHERODATA flag %d, hero %d, heroOffset %d", flag, hero, heroOffset);
+}
+
+void Interpreter::O_GETMOUSEBUTTON() {
+ debugInterpreter("O_GETMOUSEBUTTON");
+}
+
+void Interpreter::O_CHANGEFRAMES() {
+ uint16 anim = readScriptFlagValue();
+ uint16 frame = readScriptFlagValue();
+ uint16 lastFrame = readScriptFlagValue();
+ uint16 loopFrame = readScriptFlagValue();
+
+ debugInterpreter(
+ "O_CHANGFRAMES anim %d, fr1 %d, fr2 %d, fr3 %d",
+ anim,
+ frame,
+ lastFrame,
+ loopFrame);
+
+}
+
+void Interpreter::O_CHANGEBACKFRAMES() {
+ uint16 anim = readScriptFlagValue();
+ uint16 frame = readScriptFlagValue();
+ uint16 lastFrame = readScriptFlagValue();
+ uint16 loopFrame = readScriptFlagValue();
+
+ debugInterpreter(
+ "O_CHANGEBACKFRAMES anim %d, fr1 %d, fr2 %d, fr3 %d",
+ anim,
+ frame,
+ lastFrame,
+ loopFrame);
+}
+
+void Interpreter::O_GETBACKANIMDATA() {
+ uint16 flag = readScript<uint16>();
+ uint16 anim = readScript<uint16>();
+ uint16 animOffset = readScript<uint16>();
+ debugInterpreter("O_GETBACKANIMDATA flag %d, anim %d, animOffset %d", flag, anim, animOffset);
+}
+
+void Interpreter::O_GETANIMDATA() {
+ uint16 flag = readScript<uint16>();
+ uint16 anim = readScriptFlagValue();
+ uint16 animOffset = readScriptFlagValue();
+ debugInterpreter("O_GETANIMDATA flag %d, anim %d, animOffset %d", flag, anim, animOffset);
+ // Gets value of anim data
+ // use anim offset as attribute id not an offset
+}
+
+void Interpreter::O_SETBGCODE() {
+ int32 offset = readScript<uint32>();
+ _bgOpcodePC = _currentInstruction + offset - 4;
+ debugInterpreter("O_SETBGCODE next %08x, offset %08x", _bgOpcodePC, offset);
+}
+
+void Interpreter::O_SETBACKFRAME() {
+ uint16 anim = readScriptFlagValue();
+ uint16 frame = readScriptFlagValue();
+
+ debugInterpreter("O_SETBACKFRAME anim %d, frame %d", anim, frame);
+}
+
+void Interpreter::O_GETRND() {
+ Flags::Id flag = readScriptFlagId();
+ uint16 rndSeed = readScript<uint16>();
+ debugInterpreter("O_GETRND flag %d, rndSeed %d", flag, rndSeed);
+ // puts and random value as flag value
+ // fairly random value ;)
+ // _flags->setFlagValue(flag, 4);
+}
+
+void Interpreter::O_TALKBACKANIM() {
+ uint16 animSlot = readScriptFlagValue();
+ uint16 slot = readScriptFlagValue();
+ debugInterpreter("O_TALKBACKANIM animSlot %d, slot %d", animSlot, slot);
+}
+
+void Interpreter::O_LOADPATH() {
+ int32 offset = readScript<uint32>();
+ debugInterpreter("O_LOADPATH offset %d", offset);
+ // _currentInstruction + offset path file name ptr
+ // free path bitmap
+ // load packet path bitmap and puts in Sala
+}
+
+void Interpreter::O_GETCHAR() {
+ Flags::Id flagId = readScriptFlagId();
+
+ _flags->setFlagValue(flagId, *_string);
+
+ debugInterpreter(
+ "O_GETCHAR %04X (%s) %02x",
+ flagId,
+ Flags::getFlagName(flagId),
+ _flags->getFlagValue(flagId));
+
+ ++_string;
+}
+
+void Interpreter::O_SETDFLAG() {
+ uint16 flag = readScript<uint16>();
+ int32 offset = readScript<uint32>();
+ debugInterpreter("O_SETDFLAG flag %d, offset %04x", flag, offset);
+ // run this through debugger looks strange
+ // it looks like this one store two 16 bit value in one go
+}
+
+void Interpreter::O_CALLDFLAG() {
+ uint16 flag = readScript<uint16>();
+ debugInterpreter("O_CALLDFLAG flag %d", flag);
+ // it seems that some flags are 32 bit long
+}
+
+void Interpreter::O_PRINTAT() {
+ uint16 slot = readScriptFlagValue();
+ uint16 fr1 = readScriptFlagValue();
+ uint16 fr2 = readScriptFlagValue();
+
+ debugInterpreter("O_PRINTAT slot %d, fr1 %d, fr2 %d", slot, fr1, fr2);
+
+ uint8 color = _flags->getFlagValue(Flags::KOLOR);
+
+ _vm->printAt(slot, color, (const char *)_string, fr1, fr2);
+
+ while (*_string) {
+ ++_string;
+ }
+ ++_string;
+}
+
+void Interpreter::O_ZOOMIN() {
+ uint16 slot = readScriptFlagValue();
+ debugInterpreter("O_ZOOMIN slot %04d", slot);
+}
+
+void Interpreter::O_ZOOMOUT() {
+ uint16 slot = readScriptFlagValue();
+ debugInterpreter("O_ZOOMOUT slot %d", slot);
+}
+
+void Interpreter::O_SETSTRINGOFFSET() {
+ int32 offset = readScript<uint32>();
+ debugInterpreter("O_SETSTRINGOFFSET offset %04x", offset);
+ // _currentString = ""
+ // _string = (const char *)_currentInstruction + offset
+}
+
+void Interpreter::O_GETOBJDATA() {
+ Flags::Id flag = readScriptFlagId();
+ uint16 obj = readScriptFlagValue();
+ int16 objOffset = readScriptFlagValue();
+ debugInterpreter("O_GETOBJDATA flag %d, obj %d, objOffset %d", flag, obj, objOffset);
+}
+
+void Interpreter::O_SETOBJDATA() {
+ uint16 obj = readScriptFlagValue();
+ int16 objOffset = readScriptFlagValue();
+ uint16 value = readScriptFlagValue();
+ debugInterpreter("O_SETOBJDATA obj %d, objOffset %d, value %d", obj, objOffset, value);
+}
+
+void Interpreter::O_SWAPOBJECTS() {
+ uint16 obj1 = readScript<uint16>();
+ uint16 obj2 = readScript<uint16>();
+ debugInterpreter("O_SWAPOBJECTS obj1 %d, obj2 %d", obj1, obj2);
+}
+
+void Interpreter::O_CHANGEHEROSET() {
+ uint16 hero = readScriptFlagValue();
+ uint16 heroSet = readScriptFlagValue();
+ debugInterpreter("O_CHANGEHEROSET hero %d, heroSet %d", hero, heroSet);
+}
+
+void Interpreter::O_ADDSTRING() {
+ uint16 value = readScriptFlagValue();
+ debugInterpreter("O_ADDSTRING value %d", value);
+ // _string += value
+}
+
+void Interpreter::O_SUBSTRING() {
+ uint16 value = readScriptFlagValue();
+ debugInterpreter("O_SUBSTRING value %d", value);
+ // _string -= value
+}
+
+void Interpreter::O_INITDIALOG() {
+ debugInterpreter("O_INITDIALOG");
+}
+
+void Interpreter::O_ENABLEDIALOGOPT() {
+ uint16 opt = readScriptFlagValue();
+ debugInterpreter("O_ENABLEDIALOGOPT opt %d", opt);
+}
+
+void Interpreter::O_DISABLEDIALOGOPT() {
+ uint16 opt = readScriptFlagValue();
+ debugInterpreter("O_DISABLEDIALOGOPT opt %d", opt);
+}
+
+void Interpreter::O_SHOWDIALOGBOX() {
+ uint16 box = readScriptFlagValue();
+ debugInterpreter("O_SHOWDIALOGBOX box %d", box);
+}
+
+void Interpreter::O_STOPSAMPLE() {
+ uint16 slot = readScriptFlagValue();
+ debugInterpreter("O_STOPSAMPLE slot %d", slot);
+ _vm->stopSample(slot);
+}
+
+void Interpreter::O_BACKANIMRANGE() {
+ uint16 slotId = readScriptFlagValue();
+ uint16 animId = readScript<uint16>();
+ uint16 low = readScriptFlagValue();
+ uint16 high = readScriptFlagValue();
+
+ if (animId != 0xFFFF) {
+ if (animId & InterpreterFlags::FLAG_MASK) {
+ animId = _flags->getFlagValue((Flags::Id)animId);
+ }
+ }
+
+ debugInterpreter("O_BACKANIMRANGE slotId %d, animId %d, low %d, high %d", slotId, animId, low, high);
+ _result = 1;
+}
+
+void Interpreter::O_CLEARPATH() {
+ debugInterpreter("O_CLEARPATH");
+ // Fill Sala with 255
+}
+
+void Interpreter::O_SETPATH() {
+ debugInterpreter("O_SETPATH");
+ // CopyPath
+}
+
+void Interpreter::O_GETHEROX() {
+ uint16 heroId = readScriptFlagValue();
+ Flags::Id flagId = readScriptFlagId();
+
+ debugInterpreter("O_GETHEROX heroId %d, flagId %d", heroId, flagId);
+}
+
+void Interpreter::O_GETHEROY() {
+ uint16 heroId = readScript<uint16>();
+ Flags::Id flagId = readScriptFlagId();
+
+ debugInterpreter("O_GETHEROY heroId %d, flagId %d", heroId, flagId);
+}
+
+void Interpreter::O_GETHEROD() {
+ uint16 heroId = readScriptFlagValue();
+ Flags::Id flagId = readScriptFlagId();
+
+ debugInterpreter("O_GETHEROD heroId %d, flagId %d", heroId, flagId);
+}
+
+void Interpreter::O_PUSHSTRING() {
+ debugInterpreter("O_PUSHSTRING");
+ // push on the stack
+ // _currentString
+ // _dialogData
+ // _string
+}
+
+void Interpreter::O_POPSTRING() {
+ debugInterpreter("O_POPSTRING");
+ // pop from the stack
+ // _currentString
+ // _dialogData
+ // _string
+}
+
+void Interpreter::O_SETFGCODE() {
+ int32 offset = readScript<uint32>();
+ _fgOpcodePC = _currentInstruction + offset - 4;
+
+ debugInterpreter("O_SETFGCODE next %08x, offset %08x", _fgOpcodePC, offset);
+}
+
+void Interpreter::O_STOPHERO() {
+ uint16 heroId = readScriptFlagValue();
+
+ debugInterpreter("O_STOPHERO heroId %d", heroId);
+
+ // clear move steps for hero
+}
+
+void Interpreter::O_ANIMUPDATEOFF() {
+ uint16 slotId = readScript<uint16>();
+ debugInterpreter("O_ANIMUPDATEOFF slotId %d", slotId);
+}
+
+void Interpreter::O_ANIMUPDATEON() {
+ uint16 slotId = readScriptFlagValue();
+ debugInterpreter("O_ANIMUPDATEON slotId %d", slotId);
+}
+
+void Interpreter::O_FREECURSOR() {
+ debugInterpreter("O_FREECURSOR");
+ // Change cursor to 0
+ // free inv cursor 1
+}
+
+void Interpreter::O_ADDINVQUIET() {
+ uint16 heroId = readScriptFlagValue();
+ uint16 itemId = readScriptFlagValue();
+
+ debugInterpreter("O_ADDINVQUIET heorId %d, itemId %d", heroId, itemId);
+}
+
+void Interpreter::O_RUNHERO() {
+ uint16 heroId = readScriptFlagValue();
+ uint16 x = readScriptFlagValue();
+ uint16 y = readScriptFlagValue();
+ uint16 dir = readScriptFlagValue();
+
+ debugInterpreter("O_RUNHERO heroId %d, x %d, y %d, dir %d", heroId, x, y, dir);
+}
+
+void Interpreter::O_SETBACKANIMDATA() {
+ uint16 animId = readScriptFlagValue();
+ uint16 animOffset = readScriptFlagValue();
+ uint16 wart = readScriptFlagValue();
+
+ debugInterpreter("O_SETBACKANIMDATA animId %d, animOffset %d, wart %d", animId, animOffset, wart);
+}
+
+void Interpreter::O_VIEWFLC() {
+ uint16 animNr = readScriptFlagValue();
+ debugInterpreter("O_VIEWFLC animNr %d", animNr);
+ _vm->loadAnim(animNr, false);
+}
+
+void Interpreter::O_CHECKFLCFRAME() {
+ uint16 frameNr = readScriptFlagValue();
+
+ debugInterpreter("O_CHECKFLCFRAME frame number %d", frameNr);
+
+ if (_vm->_flicPlayer.getCurFrame() != frameNr) {
+ // Move instruction pointer before current instruciton
+ // must do this check once again till it's false
+ _currentInstruction -= 2;
+ _opcodeNF = 1;
+ }
+}
+
+void Interpreter::O_CHECKFLCEND() {
+
+ //debugInterpreter("O_CHECKFLCEND");
+
+ const Video::FlicDecoder &flicPlayer = _vm->_flicPlayer;
+
+ //debug("frameCount %d, currentFrame %d", flicPlayer.getFrameCount(), flicPlayer.getCurFrame());
+
+ if (flicPlayer.getFrameCount() - flicPlayer.getCurFrame() > 1) {
+ // Move instruction pointer before current instruciton
+ // must do this check once again till it's false
+ _currentInstruction -= 2;
+ _opcodeNF = 1;
+ }
+}
+
+void Interpreter::O_FREEFLC() {
+ debugInterpreter("O_FREEFLC");
+}
+
+void Interpreter::O_TALKHEROSTOP() {
+ uint16 heroId = readScriptFlagValue();
+ debugInterpreter("O_TALKHEROSTOP %d", heroId);
+}
+
+void Interpreter::O_HEROCOLOR() {
+ uint16 heroId = readScriptFlagValue();
+ uint16 kolorr = readScriptFlagValue();
+ debugInterpreter("O_HEROCOLOR heroId %d, kolorr %d", heroId, kolorr);
+}
+
+void Interpreter::O_GRABMAPA() {
+ debugInterpreter("O_GRABMAPA");
+}
+
+void Interpreter::O_ENABLENAK() {
+ uint16 nakId = readScriptFlagValue();
+ debugInterpreter("O_ENABLENAK nakId %d", nakId);
+}
+
+void Interpreter::O_DISABLENAK() {
+ uint16 nakId = readScriptFlagValue();
+ debugInterpreter("O_DISABLENAK nakId %d", nakId);
+}
+
+void Interpreter::O_GETMOBNAME() {
+ uint16 war = readScriptFlagValue();
+ debugInterpreter("O_GETMOBNAME war %d", war);
+}
+
+void Interpreter::O_SWAPINVENTORY() {
+ uint16 heroId = readScriptFlagValue();
+ debugInterpreter("O_SWAPINVENTORY heroId %d", heroId);
+}
+
+void Interpreter::O_CLEARINVENTORY() {
+ uint16 heroId = readScriptFlagValue();
+ debugInterpreter("O_CLEARINVENTORY heroId %d", heroId);
+}
+
+void Interpreter::O_SKIPTEXT() {
+ debugInterpreter("O_SKIPTEXT");
+}
+
+void Interpreter::SetVoice(uint32 sampleSlot) {
+ uint16 slot = readScriptFlagValue();
+ _vm->loadVoice(
+ slot,
+ sampleSlot,
+ Common::String::format(
+ "%03d-%02d.WAV",
+ _currentString,
+ _flags->getFlagValue(Flags::VOICE_H_LINE)
+ )
+ );
+}
+
+void Interpreter::O_SETVOICEH() {
+ static const uint32 VOICE_H_SLOT = 28;
+ SetVoice(VOICE_H_SLOT);
+}
+
+void Interpreter::O_SETVOICEA() {
+ static const uint32 VOICE_A_SLOT = 29;
+ SetVoice(VOICE_A_SLOT);
+}
+
+void Interpreter::O_SETVOICEB() {
+ static const uint32 VOICE_B_SLOT = 30;
+ SetVoice(VOICE_B_SLOT);
+}
+
+void Interpreter::O_SETVOICEC() {
+ static const uint32 VOICE_C_SLOT = 31;
+ SetVoice(VOICE_C_SLOT);
+}
+
+void Interpreter::O_SETVOICED() {
+ static const uint32 VOICE_D_SLOT = 32;
+ SetVoice(VOICE_D_SLOT);
+}
+
+void Interpreter::O_VIEWFLCLOOP() {
+ uint16 value = readScriptFlagValue();
+ debugInterpreter("O_VIEWFLCLOOP animId %d", value);
+
+ _vm->loadAnim(value, true);
+}
+
+void Interpreter::O_FLCSPEED() {
+ uint16 speed = readScriptFlagValue();
+ debugInterpreter("O_FLCSPEED speed %d", speed);
+}
+
+void Interpreter::O_OPENINVENTORY() {
+ debugInterpreter("O_OPENINVENTORY");
+ _opcodeNF = 1;
+ // _showInventoryFlag = true
+}
+
+void Interpreter::O_KRZYWA() {
+ debugInterpreter("O_KRZYWA");
+}
+
+void Interpreter::O_GETKRZYWA() {
+ debugInterpreter("O_GETKRZYWA");
+ // _flags->setFlagValue(Flags::TORX1, krzywa[_krzywaIndex++])
+ // _flags->setFlagValue(Flags::TORY1, krzywa[_krzywaIndex++])
+ // Check _krzywaIndex
+}
+
+void Interpreter::O_GETMOB() {
+ Flags::Id flagId = readScriptFlagId();
+ uint16 mx = readScriptFlagValue();
+ uint16 my = readScriptFlagValue();
+ debugInterpreter("O_GETMOB flagId %d, mx %d, my %d", flagId, mx, my);
+ // check if current mob pos = (mx, my)
+}
+
+void Interpreter::O_INPUTLINE() {
+ debugInterpreter("O_INPUTLINE");
+}
+
+
+void Interpreter::O_BREAK_POINT() {
+ debugInterpreter("O_BREAK_POINT");
+}
+
+Interpreter::OpcodeFunc Interpreter::_opcodes[NUM_OPCODES] = {
+ &Interpreter::O_WAITFOREVER,
+ &Interpreter::O_BLACKPALETTE,
+ &Interpreter::O_SETUPPALETTE,
+ &Interpreter::O_INITROOM,
+ &Interpreter::O_SETSAMPLE,
+ &Interpreter::O_FREESAMPLE,
+ &Interpreter::O_PLAYSAMPLE,
+ &Interpreter::O_PUTOBJECT,
+ &Interpreter::O_REMOBJECT,
+ &Interpreter::O_SHOWANIM,
+ &Interpreter::O_CHECKANIMEND,
+ &Interpreter::O_FREEANIM,
+ &Interpreter::O_CHECKANIMFRAME,
+ &Interpreter::O_PUTBACKANIM,
+ &Interpreter::O_REMBACKANIM,
+ &Interpreter::O_CHECKBACKANIMFRAME,
+ &Interpreter::O_FREEALLSAMPLES,
+ &Interpreter::O_SETMUSIC,
+ &Interpreter::O_STOPMUSIC,
+ &Interpreter::O__WAIT,
+ &Interpreter::O_UPDATEOFF,
+ &Interpreter::O_UPDATEON,
+ &Interpreter::O_UPDATE ,
+ &Interpreter::O_CLS,
+ &Interpreter::O__CALL,
+ &Interpreter::O_RETURN,
+ &Interpreter::O_GO,
+ &Interpreter::O_BACKANIMUPDATEOFF,
+ &Interpreter::O_BACKANIMUPDATEON,
+ &Interpreter::O_CHANGECURSOR,
+ &Interpreter::O_CHANGEANIMTYPE,
+ &Interpreter::O__SETFLAG,
+ &Interpreter::O_COMPARE,
+ &Interpreter::O_JUMPZ,
+ &Interpreter::O_JUMPNZ,
+ &Interpreter::O_EXIT,
+ &Interpreter::O_ADDFLAG,
+ &Interpreter::O_TALKANIM,
+ &Interpreter::O_SUBFLAG,
+ &Interpreter::O_SETSTRING,
+ &Interpreter::O_ANDFLAG,
+ &Interpreter::O_GETMOBDATA,
+ &Interpreter::O_ORFLAG,
+ &Interpreter::O_SETMOBDATA,
+ &Interpreter::O_XORFLAG,
+ &Interpreter::O_GETMOBTEXT,
+ &Interpreter::O_MOVEHERO,
+ &Interpreter::O_WALKHERO,
+ &Interpreter::O_SETHERO,
+ &Interpreter::O_HEROOFF,
+ &Interpreter::O_HEROON,
+ &Interpreter::O_CLSTEXT,
+ &Interpreter::O_CALLTABLE,
+ &Interpreter::O_CHANGEMOB,
+ &Interpreter::O_ADDINV,
+ &Interpreter::O_REMINV,
+ &Interpreter::O_REPINV,
+ &Interpreter::O_OBSOLETE_GETACTION,
+ &Interpreter::O_ADDWALKAREA,
+ &Interpreter::O_REMWALKAREA,
+ &Interpreter::O_RESTOREWALKAREA,
+ &Interpreter::O_WAITFRAME,
+ &Interpreter::O_SETFRAME,
+ &Interpreter::O_RUNACTION,
+ &Interpreter::O_COMPAREHI,
+ &Interpreter::O_COMPARELO,
+ &Interpreter::O_PRELOADSET,
+ &Interpreter::O_FREEPRELOAD,
+ &Interpreter::O_CHECKINV,
+ &Interpreter::O_TALKHERO,
+ &Interpreter::O_WAITTEXT,
+ &Interpreter::O_SETHEROANIM,
+ &Interpreter::O_WAITHEROANIM,
+ &Interpreter::O_GETHERODATA,
+ &Interpreter::O_GETMOUSEBUTTON,
+ &Interpreter::O_CHANGEFRAMES,
+ &Interpreter::O_CHANGEBACKFRAMES,
+ &Interpreter::O_GETBACKANIMDATA,
+ &Interpreter::O_GETANIMDATA,
+ &Interpreter::O_SETBGCODE,
+ &Interpreter::O_SETBACKFRAME,
+ &Interpreter::O_GETRND,
+ &Interpreter::O_TALKBACKANIM,
+ &Interpreter::O_LOADPATH,
+ &Interpreter::O_GETCHAR,
+ &Interpreter::O_SETDFLAG,
+ &Interpreter::O_CALLDFLAG,
+ &Interpreter::O_PRINTAT,
+ &Interpreter::O_ZOOMIN,
+ &Interpreter::O_ZOOMOUT,
+ &Interpreter::O_SETSTRINGOFFSET,
+ &Interpreter::O_GETOBJDATA,
+ &Interpreter::O_SETOBJDATA,
+ &Interpreter::O_SWAPOBJECTS,
+ &Interpreter::O_CHANGEHEROSET,
+ &Interpreter::O_ADDSTRING,
+ &Interpreter::O_SUBSTRING,
+ &Interpreter::O_INITDIALOG,
+ &Interpreter::O_ENABLEDIALOGOPT,
+ &Interpreter::O_DISABLEDIALOGOPT,
+ &Interpreter::O_SHOWDIALOGBOX,
+ &Interpreter::O_STOPSAMPLE,
+ &Interpreter::O_BACKANIMRANGE,
+ &Interpreter::O_CLEARPATH,
+ &Interpreter::O_SETPATH,
+ &Interpreter::O_GETHEROX,
+ &Interpreter::O_GETHEROY,
+ &Interpreter::O_GETHEROD,
+ &Interpreter::O_PUSHSTRING,
+ &Interpreter::O_POPSTRING,
+ &Interpreter::O_SETFGCODE,
+ &Interpreter::O_STOPHERO,
+ &Interpreter::O_ANIMUPDATEOFF,
+ &Interpreter::O_ANIMUPDATEON,
+ &Interpreter::O_FREECURSOR,
+ &Interpreter::O_ADDINVQUIET,
+ &Interpreter::O_RUNHERO,
+ &Interpreter::O_SETBACKANIMDATA,
+ &Interpreter::O_VIEWFLC,
+ &Interpreter::O_CHECKFLCFRAME,
+ &Interpreter::O_CHECKFLCEND,
+ &Interpreter::O_FREEFLC,
+ &Interpreter::O_TALKHEROSTOP,
+ &Interpreter::O_HEROCOLOR,
+ &Interpreter::O_GRABMAPA,
+ &Interpreter::O_ENABLENAK,
+ &Interpreter::O_DISABLENAK,
+ &Interpreter::O_GETMOBNAME,
+ &Interpreter::O_SWAPINVENTORY,
+ &Interpreter::O_CLEARINVENTORY,
+ &Interpreter::O_SKIPTEXT,
+ &Interpreter::O_SETVOICEH,
+ &Interpreter::O_SETVOICEA,
+ &Interpreter::O_SETVOICEB,
+ &Interpreter::O_SETVOICEC,
+ &Interpreter::O_VIEWFLCLOOP,
+ &Interpreter::O_FLCSPEED,
+ &Interpreter::O_OPENINVENTORY,
+ &Interpreter::O_KRZYWA,
+ &Interpreter::O_GETKRZYWA,
+ &Interpreter::O_GETMOB,
+ &Interpreter::O_INPUTLINE,
+ &Interpreter::O_SETVOICED,
+ &Interpreter::O_BREAK_POINT,
+};
+
+}
+
+/* vim: set tabstop=4 noexpandtab: */
diff --git a/engines/prince/script.h b/engines/prince/script.h
new file mode 100644
index 0000000000..d51e01b559
--- /dev/null
+++ b/engines/prince/script.h
@@ -0,0 +1,321 @@
+/* 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.
+ *
+ */
+
+#ifndef PRINCE_SCRIPT_H
+#define PRINCE_SCRIPT_H
+
+#include "common/random.h"
+#include "common/endian.h"
+#include "common/array.h"
+
+#include "prince/flags.h"
+
+namespace Common {
+ class SeekableReadStream;
+}
+
+namespace Prince {
+
+class PrinceEngine;
+
+namespace Detail {
+ template <typename T> T LittleEndianReader(void *data);
+ template <> inline uint8 LittleEndianReader<uint8>(void *data) { return *(uint8*)(data); }
+ template <> inline uint16 LittleEndianReader<uint16>(void *data) { return READ_LE_UINT16(data); }
+ template <> inline uint32 LittleEndianReader<uint32>(void *data) { return READ_LE_UINT32(data); }
+}
+
+class Room {
+public:
+ Room();
+
+ bool loadFromStream(Common::SeekableReadStream &stream);
+
+private:
+
+ typedef void (Room::*LoadingStep)(Common::SeekableReadStream &stream);
+
+ void nextLoadStep(Common::SeekableReadStream &stream, LoadingStep step);
+
+ void loadMobs(Common::SeekableReadStream &stream);
+ void loadBackAnim(Common::SeekableReadStream &stream);
+ void loadObj(Common::SeekableReadStream &stream);
+ void loadNak(Common::SeekableReadStream &stream);
+ void loadItemUse(Common::SeekableReadStream &stream);
+ void loadItemGive(Common::SeekableReadStream &stream);
+ void loadWalkTo(Common::SeekableReadStream &stream);
+ void loadExamine(Common::SeekableReadStream &stream);
+ void loadPickup(Common::SeekableReadStream &stream);
+ void loadUse(Common::SeekableReadStream &stream);
+ void loadPushOpen(Common::SeekableReadStream &stream);
+ void loadPullClose(Common::SeekableReadStream &stream);
+ void loadTalk(Common::SeekableReadStream &stream);
+ void loadGive(Common::SeekableReadStream &stream);
+};
+
+
+class Script {
+public:
+ Script();
+ ~Script();
+
+ bool loadFromStream(Common::SeekableReadStream &stream);
+
+ template <typename T>
+ T read(uint32 address) {
+ assert((_data + address + sizeof(T)) <= (_data + _dataSize));
+ return Detail::LittleEndianReader<T>(&_data[address]);
+ }
+
+ // Some magic numbers for now, data stored in header
+ uint32 getRoomTableOffset() { return read<uint32>(0); }
+ uint32 getStartGameOffset() { return read<uint32>(4); }
+
+ const char *getString(uint32 offset) {
+ return (const char *)(&_data[offset]);
+ }
+
+private:
+ uint8 *_data;
+ uint32 _dataSize;
+ Common::Array<Room> _roomList;
+};
+
+class InterpreterFlags {
+public:
+ InterpreterFlags();
+
+ void setFlagValue(Flags::Id flag, uint16 value);
+ uint16 getFlagValue(Flags::Id flag);
+
+ void resetAllFlags();
+
+ static const uint16 FLAG_MASK = 0x8000;
+
+private:
+ static const uint16 MAX_FLAGS = 2000;
+ int16 _flags[MAX_FLAGS];
+};
+
+class Interpreter {
+public:
+ Interpreter(PrinceEngine *vm, Script *script, InterpreterFlags *flags);
+
+ void stopBg() { _bgOpcodePC = 0; }
+
+ void step();
+
+private:
+ PrinceEngine *_vm;
+ Script *_script;
+ InterpreterFlags *_flags;
+
+ uint32 _currentInstruction;
+
+ uint32 _bgOpcodePC;
+ uint32 _fgOpcodePC;
+
+ uint16 _lastOpcode;
+ uint32 _lastInstruction;
+ byte _result;
+
+ bool _opcodeNF; // break interpreter loop
+
+ static const uint32 _STACK_SIZE = 500;
+ uint32 _stack[_STACK_SIZE];
+ uint8 _stacktop;
+ //uint8 _savedStacktop;
+ uint32 _waitFlag;
+
+ const byte *_string;
+ uint32 _currentString;
+ const char *_mode;
+
+ // Helper functions
+ uint32 step(uint32 opcodePC);
+
+ uint16 readScriptFlagValue();
+ Flags::Id readScriptFlagId();
+
+ // instantiation not needed here
+ template <typename T> T readScript();
+
+ void debugInterpreter(const char *s, ...);
+ void SetVoice(uint32 slot);
+
+ typedef void (Interpreter::*OpcodeFunc)();
+ static OpcodeFunc _opcodes[];
+
+ // Keep opcode handlers names as they are in original code
+ // it easier to switch back and forth
+ void O_WAITFOREVER();
+ void O_BLACKPALETTE();
+ void O_SETUPPALETTE();
+ void O_INITROOM();
+ void O_SETSAMPLE();
+ void O_FREESAMPLE();
+ void O_PLAYSAMPLE();
+ void O_PUTOBJECT();
+ void O_REMOBJECT();
+ void O_SHOWANIM();
+ void O_CHECKANIMEND();
+ void O_FREEANIM();
+ void O_CHECKANIMFRAME();
+ void O_PUTBACKANIM();
+ void O_REMBACKANIM();
+ void O_CHECKBACKANIMFRAME();
+ void O_FREEALLSAMPLES();
+ void O_SETMUSIC();
+ void O_STOPMUSIC();
+ void O__WAIT();
+ void O_UPDATEOFF();
+ void O_UPDATEON();
+ void O_UPDATE ();
+ void O_CLS();
+ void O__CALL();
+ void O_RETURN();
+ void O_GO();
+ void O_BACKANIMUPDATEOFF();
+ void O_BACKANIMUPDATEON();
+ void O_CHANGECURSOR();
+ void O_CHANGEANIMTYPE();
+ void O__SETFLAG();
+ void O_COMPARE();
+ void O_JUMPZ();
+ void O_JUMPNZ();
+ void O_EXIT();
+ void O_ADDFLAG();
+ void O_TALKANIM();
+ void O_SUBFLAG();
+ void O_SETSTRING();
+ void O_ANDFLAG();
+ void O_GETMOBDATA();
+ void O_ORFLAG();
+ void O_SETMOBDATA();
+ void O_XORFLAG();
+ void O_GETMOBTEXT();
+ void O_MOVEHERO();
+ void O_WALKHERO();
+ void O_SETHERO();
+ void O_HEROOFF();
+ void O_HEROON();
+ void O_CLSTEXT();
+ void O_CALLTABLE();
+ void O_CHANGEMOB();
+ void O_ADDINV();
+ void O_REMINV();
+ void O_REPINV();
+ void O_OBSOLETE_GETACTION();
+ void O_ADDWALKAREA();
+ void O_REMWALKAREA();
+ void O_RESTOREWALKAREA();
+ void O_WAITFRAME();
+ void O_SETFRAME();
+ void O_RUNACTION();
+ void O_COMPAREHI();
+ void O_COMPARELO();
+ void O_PRELOADSET();
+ void O_FREEPRELOAD();
+ void O_CHECKINV();
+ void O_TALKHERO();
+ void O_WAITTEXT();
+ void O_SETHEROANIM();
+ void O_WAITHEROANIM();
+ void O_GETHERODATA();
+ void O_GETMOUSEBUTTON();
+ void O_CHANGEFRAMES();
+ void O_CHANGEBACKFRAMES();
+ void O_GETBACKANIMDATA();
+ void O_GETANIMDATA();
+ void O_SETBGCODE();
+ void O_SETBACKFRAME();
+ void O_GETRND();
+ void O_TALKBACKANIM();
+ void O_LOADPATH();
+ void O_GETCHAR();
+ void O_SETDFLAG();
+ void O_CALLDFLAG();
+ void O_PRINTAT();
+ void O_ZOOMIN();
+ void O_ZOOMOUT();
+ void O_SETSTRINGOFFSET();
+ void O_GETOBJDATA();
+ void O_SETOBJDATA();
+ void O_SWAPOBJECTS();
+ void O_CHANGEHEROSET();
+ void O_ADDSTRING();
+ void O_SUBSTRING();
+ void O_INITDIALOG();
+ void O_ENABLEDIALOGOPT();
+ void O_DISABLEDIALOGOPT();
+ void O_SHOWDIALOGBOX();
+ void O_STOPSAMPLE();
+ void O_BACKANIMRANGE();
+ void O_CLEARPATH();
+ void O_SETPATH();
+ void O_GETHEROX();
+ void O_GETHEROY();
+ void O_GETHEROD();
+ void O_PUSHSTRING();
+ void O_POPSTRING();
+ void O_SETFGCODE();
+ void O_STOPHERO();
+ void O_ANIMUPDATEOFF();
+ void O_ANIMUPDATEON();
+ void O_FREECURSOR();
+ void O_ADDINVQUIET();
+ void O_RUNHERO();
+ void O_SETBACKANIMDATA();
+ void O_VIEWFLC();
+ void O_CHECKFLCFRAME();
+ void O_CHECKFLCEND();
+ void O_FREEFLC();
+ void O_TALKHEROSTOP();
+ void O_HEROCOLOR();
+ void O_GRABMAPA();
+ void O_ENABLENAK();
+ void O_DISABLENAK();
+ void O_GETMOBNAME();
+ void O_SWAPINVENTORY();
+ void O_CLEARINVENTORY();
+ void O_SKIPTEXT();
+ void O_SETVOICEH();
+ void O_SETVOICEA();
+ void O_SETVOICEB();
+ void O_SETVOICEC();
+ void O_VIEWFLCLOOP();
+ void O_FLCSPEED();
+ void O_OPENINVENTORY();
+ void O_KRZYWA();
+ void O_GETKRZYWA();
+ void O_GETMOB();
+ void O_INPUTLINE();
+ void O_SETVOICED();
+ void O_BREAK_POINT();
+
+};
+
+}
+
+#endif
+
+/* vim: set tabstop=4 noexpandtab: */
diff --git a/engines/prince/sound.cpp b/engines/prince/sound.cpp
new file mode 100644
index 0000000000..af139f708e
--- /dev/null
+++ b/engines/prince/sound.cpp
@@ -0,0 +1,222 @@
+/* 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.
+ *
+ */
+
+/*
+ * This code is based on original Soltys source code
+ * Copyright (c) 1994-1995 Janus B. Wisniewski and L.K. Avalon
+ */
+
+#include "prince/prince.h"
+#include "prince/sound.h"
+#include "prince/musNum.h"
+
+#include "common/config-manager.h"
+#include "common/memstream.h"
+#include "common/archive.h"
+#include "audio/decoders/raw.h"
+#include "audio/audiostream.h"
+
+namespace Prince {
+
+const char * MusicPlayer::_musTable[] = {
+ "",
+ "Battlfld.mid",
+ "Cave.mid",
+ "Cemetery.mid",
+ "Credits.mid",
+ "Fjord.mid",
+ "Guitar.mid",
+ "Hell.mid",
+ "Jingle.mid",
+ "Main.mid",
+ "Night.mid",
+ "Reality.mid",
+ "Sunlord.mid",
+ "Tavern.mid",
+ "Temple.mid",
+ "Boruta.mid",
+ "Intro.mid"
+};
+
+const uint8 MusicPlayer::_musRoomTable[] = {
+ 0,
+ ROOM01MUS,
+ ROOM02MUS,
+ ROOM03MUS,
+ ROOM04MUS,
+ ROOM05MUS,
+ ROOM06MUS,
+ ROOM07MUS,
+ ROOM08MUS,
+ ROOM09MUS,
+ ROOM10MUS,
+ ROOM11MUS,
+ ROOM12MUS,
+ ROOM13MUS,
+ ROOM14MUS,
+ ROOM15MUS,
+ ROOM16MUS,
+ ROOM17MUS,
+ ROOM18MUS,
+ ROOM19MUS,
+ ROOM20MUS,
+ ROOM21MUS,
+ ROOM22MUS,
+ ROOM23MUS,
+ ROOM24MUS,
+ ROOM25MUS,
+ ROOM26MUS,
+ ROOM27MUS,
+ ROOM28MUS,
+ ROOM29MUS,
+ ROOM30MUS,
+ ROOM31MUS,
+ ROOM32MUS,
+ ROOM33MUS,
+ ROOM34MUS,
+ ROOM35MUS,
+ ROOM36MUS,
+ ROOM37MUS,
+ ROOM38MUS,
+ ROOM39MUS,
+ ROOM40MUS,
+ ROOM41MUS,
+ ROOM42MUS,
+ ROOM43MUS,
+ 0,
+ 0,
+ ROOM46MUS,
+ ROOM47MUS,
+ ROOM48MUS,
+ ROOM49MUS,
+ ROOM50MUS,
+ ROOM51MUS,
+ ROOM52MUS,
+ ROOM53MUS,
+ ROOM54MUS,
+ ROOM55MUS,
+ ROOM56MUS,
+ ROOM57MUS,
+ ROOM58MUS,
+ ROOM59MUS,
+ ROOM60MUS,
+ ROOM61MUS
+};
+
+
+MusicPlayer::MusicPlayer(PrinceEngine *vm) : _vm(vm) {
+ _data = NULL;
+ _isGM = false;
+
+ MidiPlayer::createDriver();
+
+ int ret = _driver->open();
+ if (ret == 0) {
+ if (_nativeMT32)
+ _driver->sendMT32Reset();
+ else
+ _driver->sendGMReset();
+
+ // TODO: Load cmf.ins with the instrument table. It seems that an
+ // interface for such an operation is supported for AdLib. Maybe for
+ // this card, setting instruments is necessary.
+
+ _driver->setTimerCallback(this, &timerCallback);
+ }
+}
+
+MusicPlayer::~MusicPlayer() {
+ killMidi();
+}
+
+void MusicPlayer::killMidi() {
+ Audio::MidiPlayer::stop();
+
+ free(_data);
+ _data = NULL;
+}
+
+void MusicPlayer::loadMidi(const char * name) {
+ Common::SeekableReadStream * stream = SearchMan.createReadStreamForMember(name);
+ if (!stream) {
+ debug("Can't load midi stream %s", name);
+ return;
+ }
+
+ // Stop any currently playing MIDI file
+ killMidi();
+
+ // Read in the data for the file
+ _dataSize = stream->size();
+ _data = (byte *)malloc(_dataSize);
+ stream->read(_data, _dataSize);
+
+ delete stream;
+
+ // Start playing the music
+ sndMidiStart();
+}
+
+void MusicPlayer::sndMidiStart() {
+ _isGM = true;
+
+ MidiParser *parser = MidiParser::createParser_SMF();
+ if (parser->loadMusic(_data, _dataSize)) {
+ parser->setTrack(0);
+ parser->setMidiDriver(this);
+ parser->setTimerRate(_driver->getBaseTempo());
+ parser->property(MidiParser::mpCenterPitchWheelOnUnload, 1);
+
+ _parser = parser;
+
+ syncVolume();
+
+ // Al the tracks are supposed to loop
+ _isLooping = true;
+ _isPlaying = true;
+ }
+}
+
+void MusicPlayer::send(uint32 b) {
+ if ((b & 0xF0) == 0xC0 && !_isGM && !_nativeMT32) {
+ b = (b & 0xFFFF00FF) | MidiDriver::_mt32ToGm[(b >> 8) & 0xFF] << 8;
+ }
+
+ Audio::MidiPlayer::send(b);
+}
+
+void MusicPlayer::sendToChannel(byte channel, uint32 b) {
+ if (!_channelsTable[channel]) {
+ _channelsTable[channel] = (channel == 9) ? _driver->getPercussionChannel() : _driver->allocateChannel();
+ // If a new channel is allocated during the playback, make sure
+ // its volume is correctly initialized.
+ if (_channelsTable[channel])
+ _channelsTable[channel]->volume(_channelsVolume[channel] * _masterVolume / 255);
+ }
+
+ if (_channelsTable[channel])
+ _channelsTable[channel]->send(b);
+}
+
+} // End of namespace CGE
+
+/* vim: set tabstop=4 expandtab!: */
diff --git a/engines/prince/sound.h b/engines/prince/sound.h
new file mode 100644
index 0000000000..07ac9f38d9
--- /dev/null
+++ b/engines/prince/sound.h
@@ -0,0 +1,74 @@
+/* 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.
+ *
+ */
+
+/*
+ * This code is based on original Soltys source code
+ * Copyright (c) 1994-1995 Janus B. Wisniewski and L.K. Avalon
+ */
+
+#ifndef PRINCE_SOUND_H
+#define PRINCE_SOUND_H
+
+#include "audio/audiostream.h"
+#include "audio/decoders/wave.h"
+#include "audio/fmopl.h"
+#include "audio/mididrv.h"
+#include "audio/midiparser.h"
+#include "audio/midiplayer.h"
+#include "audio/mixer.h"
+#include "common/memstream.h"
+
+namespace Prince {
+
+class PrinceEngine;
+
+class MusicPlayer: public Audio::MidiPlayer {
+private:
+ PrinceEngine *_vm;
+ byte *_data;
+ int _dataSize;
+ bool _isGM;
+
+ // Start MIDI File
+ void sndMidiStart();
+
+ // Stop MIDI File
+ void sndMidiStop();
+public:
+ MusicPlayer(PrinceEngine *vm);
+ ~MusicPlayer();
+
+ void loadMidi(const char *);
+ void killMidi();
+
+ virtual void send(uint32 b);
+ virtual void sendToChannel(byte channel, uint32 b);
+
+ static const char * _musTable[];
+ static const uint8 _musRoomTable[];
+};
+
+} // End of namespace Prince
+
+#endif
+
+/* vim: set tabstop=4 expandtab!: */
diff --git a/engines/prince/variatxt.cpp b/engines/prince/variatxt.cpp
new file mode 100644
index 0000000000..4270444793
--- /dev/null
+++ b/engines/prince/variatxt.cpp
@@ -0,0 +1,59 @@
+/* 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.
+ *
+ */
+
+#include "prince/variatxt.h"
+#include "common/debug.h"
+
+namespace Prince {
+
+VariaTxt::VariaTxt() : _dataSize(0), _data(NULL) {
+}
+
+VariaTxt::~VariaTxt() {
+ _dataSize = 0;
+ delete[] _data;
+ _data = NULL;
+}
+
+
+bool VariaTxt::loadFromStream(Common::SeekableReadStream &stream) {
+ _dataSize = stream.size();
+ _data = new byte [_dataSize];
+ stream.read(_data, _dataSize);
+ return true;
+}
+
+const char * VariaTxt::getString(uint32 stringId) {
+ uint32 stringOffset = READ_LE_UINT32(_data + stringId);
+
+ if (stringOffset > _dataSize) {
+ assert(false);
+ }
+
+ debug("VariaTxt::getString %04X %04X", stringId, stringOffset);
+
+ return (const char *)_data + stringOffset;
+}
+
+}
+
+/* vim: set tabstop=4 noexpandtab: */
diff --git a/engines/prince/variatxt.h b/engines/prince/variatxt.h
new file mode 100644
index 0000000000..dcdba7bd8a
--- /dev/null
+++ b/engines/prince/variatxt.h
@@ -0,0 +1,44 @@
+/* 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.
+ *
+ */
+
+#include "common/stream.h"
+
+namespace Prince {
+
+class VariaTxt {
+public:
+ VariaTxt();
+
+ ~VariaTxt();
+
+ bool loadFromStream(Common::SeekableReadStream &stream);
+
+ const char * getString(uint32 stringId);
+
+private:
+ uint32 _dataSize;
+ byte *_data;
+};
+
+}
+
+/* vim: set tabstop=4 noexpandtab: */