diff options
37 files changed, 5481 insertions, 0 deletions
diff --git a/engines/configure.engines b/engines/configure.engines index ec7d4667ca..195d0a3426 100644 --- a/engines/configure.engines +++ b/engines/configure.engines @@ -34,6 +34,7 @@ add_engine myst "Myst" no "" "" "16bit" add_engine neverhood "Neverhood" no add_engine parallaction "Parallaction" yes add_engine pegasus "The Journeyman Project: Pegasus Prime" yes "" "" "16bit" +add_engine prince "The Prince & The Coward" no add_engine queen "Flight of the Amazon Queen" yes add_engine saga "SAGA" yes "ihnm saga2" "ITE" add_engine ihnm "IHNM" yes diff --git a/engines/engines.mk b/engines/engines.mk index cfde77321d..ff43c5403c 100644 --- a/engines/engines.mk +++ b/engines/engines.mk @@ -160,6 +160,11 @@ DEFINES += -DENABLE_PEGASUS=$(ENABLE_PEGASUS) MODULES += engines/pegasus endif +ifdef ENABLE_PRINCE +DEFINES += -DENABLE_PRINCE=$(ENABLE_PRINCE) +MODULES += engines/prince +endif + ifdef ENABLE_QUEEN DEFINES += -DENABLE_QUEEN=$(ENABLE_QUEEN) MODULES += engines/queen diff --git a/engines/plugins_table.h b/engines/plugins_table.h index 38cd43ac74..939c756581 100644 --- a/engines/plugins_table.h +++ b/engines/plugins_table.h @@ -74,6 +74,9 @@ LINK_PLUGIN(PARALLACTION) #if PLUGIN_ENABLED_STATIC(PEGASUS) LINK_PLUGIN(PEGASUS) #endif +#if PLUGIN_ENABLED_STATIC(PRINCE) +LINK_PLUGIN(PRINCE) +#endif #if PLUGIN_ENABLED_STATIC(QUEEN) LINK_PLUGIN(QUEEN) #endif diff --git a/engines/prince/animation.cpp b/engines/prince/animation.cpp new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/engines/prince/animation.cpp diff --git a/engines/prince/animation.h b/engines/prince/animation.h new file mode 100644 index 0000000000..e6a76d33d2 --- /dev/null +++ b/engines/prince/animation.h @@ -0,0 +1,39 @@ +/* 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 + +namespace Prince { + +class Animation { + + bool loadFromStream(Common::SeekableReadStream &stream); + + const Graphics::Surface *getSurface(uint16 frameIndex) 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..0b1367f966 --- /dev/null +++ b/engines/prince/archive.cpp @@ -0,0 +1,145 @@ +/* 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 { + 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/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..ed52aaf6f7 --- /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..88b19c6ae3 --- /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..33149c14e4 --- /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(byte chr) const { + return getChrData(chr)._width; +} + +void Font::drawChar(Graphics::Surface *dst, byte 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..020e12bf54 --- /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(byte chr) const override; + + virtual void drawChar(Graphics::Surface *dst, byte chr, int x, int y, uint32 color) const override; + + virtual int getKerningOffset(byte left, byte right) const { 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..025fa70003 --- /dev/null +++ b/engines/prince/graphics.cpp @@ -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. + * + */ + +#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(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; + } + } + } + change(); +} + +} + +/* vim: set tabstop=4 noexpandtab: */ diff --git a/engines/prince/graphics.h b/engines/prince/graphics.h new file mode 100644 index 0000000000..884aac2c84 --- /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(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/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..b11ecd08e6 --- /dev/null +++ b/engines/prince/mhwanh.h @@ -0,0 +1,53 @@ +/* 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 "graphics/decoders/image_decoder.h" +#include "graphics/surface.h" + +namespace Prince { + +class MhwanhDecoder : public Graphics::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; +}; + +} + +#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..48edcec9dd --- /dev/null +++ b/engines/prince/module.mk @@ -0,0 +1,26 @@ +MODULE := engines/prince + +MODULE_OBJS = \ + 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 \ + 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..aa55bf06a6 --- /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 "graphics/decoders/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..9f4ae19af3 --- /dev/null +++ b/engines/prince/prince.cpp @@ -0,0 +1,636 @@ +/* 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 "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" + +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(NULL), _script(NULL), + _locationNr(0), _debugger(NULL), _midiPlayer(NULL), + _cameraX(0), _newCameraX(0), _frameNr(0), _cursor1(NULL), _cursor2(NULL), _font(NULL), + _walizkaBmp(NULL), _roomBmp(NULL), _voiceStream(NULL), _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"); + + gDebugLevel = 10; +} + +PrinceEngine::~PrinceEngine() { + DebugMan.clearAllDebugChannels(); + + delete _rnd; + delete _debugger; + delete _cursor1; + delete _cursor2; + delete _midiPlayer; + delete _script; + delete _font; + delete _roomBmp; + delete _walizkaBmp; + delete _variaTxt; + delete[] _talkTxt; + delete _graph; + + for (uint32 i = 0; i < _objList.size(); ++i) { + delete _objList[i]; + } + _objList.clear(); +} + +GUI::Debugger *PrinceEngine::getDebugger() { + return _debugger; +} + +template <typename T> +bool loadFromStream(T &resource, Common::SeekableReadStream &stream) { + return resource.loadFromStream(stream); +} + +template <> +bool loadFromStream<MhwanhDecoder>(MhwanhDecoder &image, Common::SeekableReadStream &stream) { + return image.loadStream(stream); +} + +template <> +bool loadFromStream<Graphics::BitmapDecoder>(Graphics::BitmapDecoder &image, Common::SeekableReadStream &stream) { + return image.loadStream(stream); +} + +template<typename T> +bool loadResource(T *resource, const char *resourceName, bool required = true) { + Common::SeekableReadStream *stream = SearchMan.createReadStreamForMember(resourceName); + if (!stream) { + if (required) + error("Can't load %s", resourceName); + return false; + } + + bool ret = loadFromStream(*resource, *stream); + + delete stream; + + return ret; +} + +template <typename T> +bool loadResource(Common::Array<T> &array, const char *resourceName, bool required = true) { + Common::SeekableReadStream *stream = SearchMan.createReadStreamForMember(resourceName); + if (!stream) { + if (required) + error("Can't load %s", resourceName); + return false; + } + + T t; + while (t.loadFromStream(*stream)) + array.push_back(t); + + delete stream; + return true; +} + +template <typename T> +bool loadResource(Common::Array<T *> &array, const char *resourceName, bool required = true) { + 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); + } + + delete stream; + return true; +} + +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"); + + SearchMan.add("all", all); + SearchMan.add("data/voices", voices); + + _graph = new GraphicsMan(this); + + _rnd = new Common::RandomSource("prince"); + _debugger = new Debugger(this); + + SearchMan.addSubDirectoryMatching(gameDataDir, "all", 0, 2); + SearchMan.addSubDirectoryMatching(gameDataDir, "data/voices", 0, 2); + + _midiPlayer = new MusicPlayer(this); + + _font = new Font(); + loadResource(_font, "all/font1.raw"); + + _walizkaBmp = new MhwanhDecoder(); + loadResource(_walizkaBmp, "all/walizka"); + + _script = new Script(this); + loadResource(_script, "all/skrypt.dat"); + + _variaTxt = new VariaTxt(); + loadResource(_variaTxt, "all/variatxt.dat"); + + _cursor1 = new Cursor(); + loadResource(_cursor1, "all/mouse1.cur"); + + _cursor2 = new Cursor(); + loadResource(_cursor2, "all/mouse2.cur"); + + Common::SeekableReadStream *talkTxtStream = SearchMan.createReadStreamForMember("all/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 Graphics::BitmapDecoder(); +} + +void PrinceEngine::showLogo() { + MhwanhDecoder logo; + if (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 PrinceEngine::loadLocation(uint16 locationNr) { + 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; + + _script->setFlagValue(Flags::CURRROOM, _locationNr); + _script->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 + loadResource(_roomBmp, "room"); + if (_roomBmp->getSurface()) { + _sceneWidth = _roomBmp->getSurface()->w; + } + + _mobList.clear(); + loadResource(_mobList, "mob.lst", false); + + for (uint32 i = 0; i < _objList.size(); ++i) { + delete _objList[i]; + } + _objList.clear(); + loadResource(_objList, "obj.lst", false); + + return true; +} + +void PrinceEngine::changeCursor(uint16 curId) { + _debugger->_cursorNr = curId; + + const Graphics::Surface *curSurface = NULL; + + 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(s); + _graph->change(); + } else if (_flicLooped) { + _flicPlayer.rewind(); + playNextFrame(); + } + + return true; +} + +void PrinceEngine::playSample(uint16 sampleId, uint16 loopType) { + if (_voiceStream) { + + Audio::RewindableAudioStream *audioStream = Audio::makeWAVStream(_voiceStream, DisposeAfterUse::YES); + _mixer->playStream(Audio::Mixer::kSFXSoundType, &_soundHandle, audioStream, sampleId); + } +} + +void PrinceEngine::stopSample(uint16 sampleId) { + _mixer->stopID(sampleId); + _voiceStream = NULL; +} + +bool PrinceEngine::loadVoice(uint32 slot, 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 = SearchMan.createReadStreamForMember(streamName); + if (!_voiceStream) { + error("Can't open %s", streamName.c_str()); + return false; + } + + uint32 id = _voiceStream->readUint32LE(); + if (id != 0x46464952) { + error("It's not RIFF file %s", streamName.c_str()); + return false; + } + + _voiceStream->skip(0x20); + id = _voiceStream->readUint32LE(); + if (id != 0x61746164) { + error("No data section in %s id %04x", streamName.c_str(), id); + return false; + } + + id = _voiceStream->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->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: + _script->setFlagValue(Flags::ESCAPED2, 1); + 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 = NULL; + } + } +} + +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); + } + + playNextFrame(); + + //if (_objectList) + // _graph->drawTransparent(_objectList->getSurface()); + + hotspot(); + + showTexts(); + + getDebugger()->onFrame(); + + _graph->update(); +} + +void PrinceEngine::mainLoop() { + + loadLocation(4); + 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. + + _script->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..374048f285 --- /dev/null +++ b/engines/prince/prince.h @@ -0,0 +1,168 @@ +/* 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 "graphics/decoders/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 Debugger; +class MusicPlayer; +class VariaTxt; +class Cursor; +class MhwanhDecoder; +class Font; + +struct Text { + const char *_str; + uint16 _x, _y; + uint16 _time; + uint32 _color; + + Text() : _str(NULL), _x(0), _y(0), _time(0), _color(255){ + } +}; + +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 slot, 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; + +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; + Graphics::BitmapDecoder *_roomBmp; + Cursor *_cursor1; + Cursor *_cursor2; + MhwanhDecoder *_walizkaBmp; + Debugger *_debugger; + GraphicsMan *_graph; + Script *_script; + Font *_font; + MusicPlayer *_midiPlayer; + + Audio::SoundHandle _soundHandle; + Common::SeekableReadStream *_voiceStream; + Common::Array<Mob> _mobList; + Common::Array<Object *> _objList; + + 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/script.cpp b/engines/prince/script.cpp new file mode 100644 index 0000000000..07821f27a8 --- /dev/null +++ b/engines/prince/script.cpp @@ -0,0 +1,1356 @@ +/* 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 "common/debug.h" +#include "common/debug-channels.h" +#include "common/stream.h" +#include "common/archive.h" + +#include "audio/decoders/wave.h" +#include "audio/audiostream.h" + +namespace Prince { + +static const uint16 NUM_OPCODES = 144; + +Script::Script(PrinceEngine *vm) : + _code(NULL), _stacktop(0), _vm(vm), _opcodeNF(false), + _waitFlag(0), _result(true) { +} + +Script::~Script() { + delete[] _code; +} + +void Script::setFlagValue(Flags::Id flagId, uint16 value) { + _flags[(uint16)flagId - FLAG_MASK] = value; +} + +uint16 Script::getFlagValue(Flags::Id flagId) { + return _flags[(uint16)flagId - FLAG_MASK]; +} + +bool Script::loadFromStream(Common::SeekableReadStream &stream) { + _codeSize = stream.size(); + _code = new byte[_codeSize]; + + if (!_code) + return false; + + stream.read(_code, _codeSize); + // Initialize the script + _mode = "fg"; + _fgOpcodePC = READ_LE_UINT32(_code + 4); + _bgOpcodePC = 0; + + return true; +} + +void Script::debugScript(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 Script::step() { + if (_bgOpcodePC) { + _mode = "bg"; + _bgOpcodePC = step(_bgOpcodePC); + } + if (_fgOpcodePC) { + _mode = "fg"; + _fgOpcodePC = step(_fgOpcodePC); + } +} + +uint32 Script::step(uint32 opcodePC) { + _currentInstruction = opcodePC; + + while (!_opcodeNF) { + _lastInstruction = _currentInstruction; + + // Get the current opcode + _lastOpcode = readScript16bits(); + + 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; +} + +uint8 Script::getCodeByte(uint32 address) { + if (address >= _codeSize) + error("Trying to read a script byte at address 0x%04X, while the " + "script is just 0x%04X bytes long", address, _codeSize); + return _code[address]; +} + +uint8 Script::readScript8bits() { + uint8 data = getCodeByte(_currentInstruction); + _currentInstruction++; + return data; +} + +uint16 Script::readScript16bits() { + uint8 lower = readScript8bits(); + uint8 upper = readScript8bits(); + return lower | (upper << 8); +} + +uint16 Script::readScriptValue() { + uint16 value = readScript16bits(); + if (value & FLAG_MASK) { + value = _flags[value - FLAG_MASK]; + } + return value; +} + +uint32 Script::readScript32bits() { + uint16 lower = readScript16bits(); + uint16 upper = readScript16bits(); + return lower | (upper << 16); +} + +void Script::O_WAITFOREVER() { + debugScript("O_WAITFOREVER"); + _opcodeNF = 1; + _currentInstruction -= 2; +} + +void Script::O_BLACKPALETTE() { + debugScript("O_BLACKPALETTE"); +} + +void Script::O_SETUPPALETTE() { + debugScript("O_SETUPPALETTE"); +} + +void Script::O_INITROOM() { + uint16 roomId = readScriptValue(); + debugScript("O_INITROOM %d", roomId); + _vm->loadLocation(roomId); + _opcodeNF = 1; +} + +void Script::O_SETSAMPLE() { + uint16 sampleId = readScriptValue(); + int32 sampleNameOffset = readScript32bits(); + const char * sampleName = (const char *)&_code[_currentInstruction + sampleNameOffset - 4]; + debugScript("O_SETSAMPLE %d %s", sampleId, sampleName); +} + +void Script::O_FREESAMPLE() { + uint16 sample = readScriptValue(); + debugScript("O_FREESAMPLE %d", sample); +} + +void Script::O_PLAYSAMPLE() { + uint16 sampleId = readScriptValue(); + uint16 loopType = readScript16bits(); + debugScript("O_PLAYSAMPLE sampleId %d loopType %d", sampleId, loopType); + _vm->playSample(sampleId, loopType); +} + +void Script::O_PUTOBJECT() { + uint16 roomId = readScriptValue(); + uint16 slot = readScriptValue(); + uint16 objectId = readScriptValue(); + debugScript("O_PUTOBJECT roomId %d, slot %d, objectId %d", roomId, slot, objectId); +} + +void Script::O_REMOBJECT() { + uint16 roomId = readScriptValue(); + uint16 objectId = readScriptValue(); + + debugScript("O_REMOBJECT roomId %d objectId %d", roomId, objectId); +} + +void Script::O_SHOWANIM() { + uint16 slot = readScriptValue(); + uint16 animId = readScriptValue(); + + debugScript("O_SHOWANIM slot %d, animId %d", slot, animId); +} + +void Script::O_CHECKANIMEND() { + uint16 slot = readScriptValue(); + uint16 frameId = readScriptValue(); + + debugScript("O_CHECKANIMEND slot %d, frameId %d", slot, frameId); + _opcodeNF = 1; +} + +void Script::O_FREEANIM() { + uint16 slot = readScriptValue(); + debugScript("O_FREEANIM slot %d", slot); +} + +void Script::O_CHECKANIMFRAME() { + uint16 slot = readScriptValue(); + uint16 frameId = readScriptValue(); + + debugScript("O_CHECKANIMFRAME slot %d, frameId %d", slot, frameId); + _opcodeNF = 1; +} + +void Script::O_PUTBACKANIM() { + uint16 roomId = readScriptValue(); + uint16 slot = readScriptValue(); + int32 animId = readScript32bits(); + debugScript("O_PUTBACKANIM roomId %d, slot %d, animId %d", roomId, slot, animId); +} + +void Script::O_REMBACKANIM() { + uint16 roomId = readScriptValue(); + uint16 slot = readScriptValue(); + + debugScript("O_REMBACKANIM roomId %d, slot %d", roomId, slot); +} + +void Script::O_CHECKBACKANIMFRAME() { + uint16 slotId = readScriptValue(); + uint16 frameId = readScriptValue(); + + debugScript("O_CHECKBACKANIMFRAME slotId %d, frameId %d", slotId, frameId); + _opcodeNF = 1; +} + +void Script::O_FREEALLSAMPLES() { + debugScript("O_FREEALLSAMPLES"); +} + +void Script::O_SETMUSIC() { + uint16 musicId = readScript16bits(); + + debugScript("O_SETMUSIC musicId %d", musicId); +} + +void Script::O_STOPMUSIC() { + debugScript("O_STOPMUSIC"); +} + +void Script::O__WAIT() { + uint16 pause = readScriptValue(); + + debugScript("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 Script::O_UPDATEOFF() { + debugScript("O_UPDATEOFF"); + //_updateEnable = false; +} + +void Script::O_UPDATEON() { + debugScript("O_UPDATEON"); + //_updateEnable = true; +} + +void Script::O_UPDATE () { + debugScript("O_UPDATE"); + // Refresh screen +} + +void Script::O_CLS() { + debugScript("O_CLS"); + // do nothing +} + +void Script::O__CALL() { + int32 address = readScript32bits(); + _stack[_stacktop] = _currentInstruction; + _stacktop++; + _currentInstruction += address - 4; + debugScript("O__CALL 0x%04X", _currentInstruction); +} + +void Script::O_RETURN() { + // Get the return address + if (_stacktop > 0) { + _stacktop--; + _currentInstruction = _stack[_stacktop]; + debugScript("O_RETURN 0x%04X", _currentInstruction); + } else { + error("Return: Stack is empty"); + } +} + +void Script::O_GO() { + int32 opPC = readScript32bits(); + debugScript("O_GO 0x%04X", opPC); + _currentInstruction += opPC - 4; +} + +void Script::O_BACKANIMUPDATEOFF() { + uint16 slotId = readScriptValue(); + debugScript("O_BACKANIMUPDATEOFF slotId %d", slotId); +} + +void Script::O_BACKANIMUPDATEON() { + uint16 slot = readScriptValue(); + debugScript("O_BACKANIMUPDATEON %d", slot); +} + +void Script::O_CHANGECURSOR() { + uint16 cursorId = readScriptValue(); + debugScript("O_CHANGECURSOR %x", cursorId); +} + +void Script::O_CHANGEANIMTYPE() { + // NOT IMPLEMENTED +} + +void Script::O__SETFLAG() { + Flags::Id flagId = readScriptFlagId(); + uint16 value = readScriptValue(); + + debugScript("O__SETFLAG 0x%04X (%s) = %d", flagId, Flags::getFlagName(flagId), value); + + setFlagValue((Flags::Id)(flagId), value); +} + +void Script::O_COMPARE() { + Flags::Id flagId = readScriptFlagId(); + uint16 value = readScriptValue(); + + _result = getFlagValue(flagId) != value; + debugScript("O_COMPARE flagId 0x%04X (%s), value %d == %d (%d)", flagId, Flags::getFlagName(flagId), value, getFlagValue(flagId), _result); +} + +void Script::O_JUMPZ() { + int32 offset = readScript32bits(); + if (! _result) { + _currentInstruction += offset - 4; + } + + debugScript("O_JUMPZ result = %d, next %08x, offset 0x%08X", _result, _currentInstruction, offset); +} + +void Script::O_JUMPNZ() { + int32 offset = readScript32bits(); + if (_result) { + _currentInstruction += offset - 4; + } + + debugScript("O_JUMPNZ result = %d, next %08x, offset 0x%08X", _result, _currentInstruction, offset); +} + +void Script::O_EXIT() { + uint16 exitCode = readScriptValue(); + debugScript("O_EXIT exitCode %d", exitCode); + // Set exit code and shows credits + // if exit code == 0x02EAD +} + +void Script::O_ADDFLAG() { + Flags::Id flagId = readScriptFlagId(); + uint16 value = readScriptValue(); + + setFlagValue(flagId, getFlagValue(flagId) + value); + if (getFlagValue(flagId)) + _result = 1; + else + _result = 0; + + debugScript("O_ADDFLAG flagId %04x (%s), value %d", flagId, Flags::getFlagName(flagId), value); +} + +void Script::O_TALKANIM() { + uint16 animSlot = readScriptValue(); + uint16 slot = readScriptValue(); + + debugScript("O_TALKANIM animSlot %d, slot %d", animSlot, slot); +} + +void Script::O_SUBFLAG() { + Flags::Id flagId = readScriptFlagId(); + uint16 value = readScriptValue(); + + setFlagValue(flagId, getFlagValue(flagId) - value); + if (getFlagValue(flagId)) + _result = 1; + else + _result = 0; + + debugScript("O_SUBFLAG flagId %d, value %d", flagId, value); +} + +void Script::O_SETSTRING() { + int32 offset = readScript32bits(); + _currentString = offset; + + // FIXME: Make it better ;) + if (offset >= 80000) { + debugScript("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]; + debugScript("TalkTxt %d %s", of, txt); + } + + debugScript("O_SETSTRING %04d", offset); +} + +void Script::O_ANDFLAG() { + Flags::Id flagId = readScriptFlagId(); + uint16 value = readScriptValue(); + + debugScript("O_ANDFLAG flagId %d, value %d", flagId, value); + + setFlagValue(flagId, getFlagValue(flagId) & value); + + if (getFlagValue(flagId)) { + _result = 1; + } else { + _result = 0; + } +} + +void Script::O_GETMOBDATA() { + Flags::Id flagId = readScriptFlagId(); + uint16 mobId = readScript16bits(); + uint16 mobOffset = readScript16bits(); + + debugScript("O_GETMOBDATA flagId %d, modId %d, mobOffset %d", flagId, mobId, mobOffset); +} + +void Script::O_ORFLAG() { + Flags::Id flagId = readScriptFlagId(); + uint16 value = readScriptValue(); + + debugScript("O_ORFLAG flagId %d, value %d", flagId, value); + + setFlagValue(flagId, getFlagValue(flagId) | value); + + if (getFlagValue(flagId)) { + _result = 1; + } else { + _result = 0; + } +} + +void Script::O_SETMOBDATA() { + uint16 mobId = readScriptValue(); + uint16 mobOffset = readScriptValue(); + uint16 value = readScriptValue(); + + debugScript("O_SETMOBDATA mobId %d, mobOffset %d, value %d", mobId, mobOffset, value); +} + +void Script::O_XORFLAG() { + Flags::Id flagId = readScriptFlagId(); + uint16 value = readScriptValue(); + + debugScript("O_XORFLAG flagId %d, value %d", flagId, value); + + setFlagValue(flagId, getFlagValue(flagId) ^ value); + + if (getFlagValue(flagId)) { + _result = 1; + } else { + _result = 0; + } +} + +void Script::O_GETMOBTEXT() { + uint16 value = readScriptValue(); + + debugScript("O_GETMOBTEXT value %d", value); + // Use Mob::ExamText as current string +} + +void Script::O_MOVEHERO() { + uint16 heroId = readScriptValue(); + uint16 x = readScriptValue(); + uint16 y = readScriptValue(); + uint16 dir = readScriptValue(); + + debugScript("O_MOVEHERO heroId %d, x %d, y %d, dir %d", heroId, x, y, dir); +} + +void Script::O_WALKHERO() { + uint16 heroId = readScriptValue(); + + debugScript("O_WALKHERO %d", heroId); + _opcodeNF = 1; +} + +void Script::O_SETHERO() { + uint16 hero = readScriptValue(); + uint16 x = readScriptValue(); + uint16 y = readScriptValue(); + uint16 dir = readScriptValue(); + debugScript("O_SETHERO hero %d, x %d, y %d, dir %d", hero, x, y, dir); +} + +void Script::O_HEROOFF() { + uint16 heroId = readScriptValue(); + debugScript("O_HEROOFF %d", heroId); + // sets hero visible flag to false +} + +void Script::O_HEROON() { + uint16 heroId = readScriptValue(); + debugScript("O_HEROON %d", heroId); + // sets hero visible flag to true +} + +void Script::O_CLSTEXT() { + uint16 slot = readScriptValue(); + debugScript("O_CLSTEXT slot %d", slot); + // Sets text line to null + // Sets text timeout to zero +} + +void Script::O_CALLTABLE() { + uint16 flag = readScript16bits(); + int32 table = readScript32bits(); + + debugScript("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 Script::O_CHANGEMOB() { + uint16 mob = readScriptValue(); + uint16 value = readScriptValue(); + debugScript("O_CHANGEMOB mob %d, value %d", mob, value); + // Probably sets mobs visible flag to value +} + +void Script::O_ADDINV() { + uint16 hero = readScriptValue(); + uint16 item = readScriptValue(); + debugScript("O_ADDINV hero %d, item %d", hero, item); +} + +void Script::O_REMINV() { + uint16 hero = readScriptValue(); + uint16 item = readScriptValue(); + debugScript("O_REMINV hero %d, item %d", hero, item); +} + +void Script::O_REPINV() { + uint16 hero = readScript16bits(); + uint16 item1 = readScript16bits(); + uint16 item2 = readScript16bits(); + // shouldn't be uses + error("O_REPINV hero %d, item1 %d, item2 %d", hero, item1, item2); +} + +void Script::O_OBSOLETE_GETACTION() { + // shouldn't be uses + error("O_OBSOLETE_GETACTION"); +} + +void Script::O_ADDWALKAREA() { + uint16 x1 = readScript16bits(); + uint16 y1 = readScript16bits(); + uint16 x2 = readScript16bits(); + uint16 y2 = readScript16bits(); + // shouldn't be uses + error("O_ADDWALKAREA x1 %d, y1 %d, x2 %d, y2 %d", x1, y1, x2, y2); +} + +void Script::O_REMWALKAREA() { + uint16 x1 = readScript16bits(); + uint16 y1 = readScript16bits(); + uint16 x2 = readScript16bits(); + uint16 y2 = readScript16bits(); + + // shouldn't be uses + error("O_REMWALKAREA x1 %d, y1 %d, x2 %d, y2 %d", x1, y1, x2, y2); +} + +void Script::O_RESTOREWALKAREA() { + debugScript("O_RESTOREWALKAREA"); +} + +void Script::O_WAITFRAME() { + debugScript("O_WAITFRAME"); + _opcodeNF = true; +} + +void Script::O_SETFRAME() { + uint16 anim = readScriptValue(); + uint16 frame = readScriptValue(); + debugScript("O_SETFRAME anim %d, frame %d", anim, frame); +} + +void Script::O_RUNACTION() { + // It's empty in original and never used in script + // it's better to report error + error("O_RUNACTION"); +} + +void Script::O_COMPAREHI() { + Flags::Id flag = readScriptFlagId(); + uint16 value = readScriptValue(); + + debugScript("O_COMPAREHI flag %d, value %d", flag, value); + _result = value < getFlagValue(flag); +} + +void Script::O_COMPARELO() { + Flags::Id flag = readScriptFlagId(); + uint16 value = readScriptValue(); + + debugScript("O_COMPARELO flag %d, value %d", flag, value); + _result = value > getFlagValue(flag); +} + +void Script::O_PRELOADSET() { + // not used in script + int32 offset = readScript32bits(); + debugScript("O_PRELOADSET offset %04x", offset); +} + +void Script::O_FREEPRELOAD() { + // not used in script + debugScript("O_FREEPRELOAD"); +} + +void Script::O_CHECKINV() { + uint16 hero = readScriptValue(); + uint16 item = readScriptValue(); + debugScript("O_CHECKINV hero %d, item %d", hero, item); + // checks if item is in heros inventory +} + +void Script::O_TALKHERO() { + uint16 hero = readScriptValue(); + debugScript("O_TALKHERO hero %d", hero); +} + +void Script::O_WAITTEXT() { + uint16 slot = readScriptValue(); + Text &text = _vm->_textSlots[slot]; + if (text._time) { + _opcodeNF = 1; + _currentInstruction -= 4; + } +} + +void Script::O_SETHEROANIM() { + uint16 hero = readScriptValue(); + int32 offset = readScript32bits(); + debugScript("O_SETHEROANIM hero %d, offset %d", hero, offset); +} + +void Script::O_WAITHEROANIM() { + uint16 hero = readScriptValue(); + + debugScript("O_WAITHEROANIM hero %d", hero); +} + +void Script::O_GETHERODATA() { + uint16 flag = readScript16bits(); + uint16 hero = readScriptValue(); + uint16 heroOffset = readScriptValue(); + debugScript("O_GETHERODATA flag %d, hero %d, heroOffset %d", flag, hero, heroOffset); +} + +void Script::O_GETMOUSEBUTTON() { + debugScript("O_GETMOUSEBUTTON"); +} + +void Script::O_CHANGEFRAMES() { + uint16 anim = readScriptValue(); + uint16 frame = readScriptValue(); + uint16 lastFrame = readScriptValue(); + uint16 loopFrame = readScriptValue(); + + debugScript( + "O_CHANGFRAMES anim %d, fr1 %d, fr2 %d, fr3 %d", + anim, + frame, + lastFrame, + loopFrame); + +} + +void Script::O_CHANGEBACKFRAMES() { + uint16 anim = readScriptValue(); + uint16 frame = readScriptValue(); + uint16 lastFrame = readScriptValue(); + uint16 loopFrame = readScriptValue(); + + debugScript( + "O_CHANGEBACKFRAMES anim %d, fr1 %d, fr2 %d, fr3 %d", + anim, + frame, + lastFrame, + loopFrame); +} + +void Script::O_GETBACKANIMDATA() { + uint16 flag = readScript16bits(); + uint16 anim = readScript16bits(); + uint16 animOffset = readScript16bits(); + debugScript("O_GETBACKANIMDATA flag %d, anim %d, animOffset %d", flag, anim, animOffset); +} + +void Script::O_GETANIMDATA() { + uint16 flag = readScript16bits(); + uint16 anim = readScriptValue(); + uint16 animOffset = readScriptValue(); + debugScript("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 Script::O_SETBGCODE() { + int32 offset = readScript32bits(); + _bgOpcodePC = _currentInstruction + offset; + debugScript("O_SETBGCODE next %08x, offset %08x", _bgOpcodePC, offset); +} + +void Script::O_SETBACKFRAME() { + uint16 anim = readScriptValue(); + uint16 frame = readScriptValue(); + + debugScript("O_SETBACKFRAME anim %d, frame %d", anim, frame); +} + +void Script::O_GETRND() { + Flags::Id flag = readScriptFlagId(); + uint16 rndSeed = readScript16bits(); + debugScript("O_GETRND flag %d, rndSeed %d", flag, rndSeed); + // puts and random value as flag value + // fairly random value ;) + // setFlagValue(flag, 4); +} + +void Script::O_TALKBACKANIM() { + uint16 animSlot = readScriptValue(); + uint16 slot = readScriptValue(); + debugScript("O_TALKBACKANIM animSlot %d, slot %d", animSlot, slot); +} + +void Script::O_LOADPATH() { + int32 offset = readScript32bits(); + debugScript("O_LOADPATH offset %d", offset); + // _currentInstruction + offset path file name ptr + // free path bitmap + // load packet path bitmap and puts in Sala +} + +void Script::O_GETCHAR() { + Flags::Id flagId = readScriptFlagId(); + + setFlagValue(flagId, *_string); + + debugScript( + "O_GETCHAR %04X (%s) %02x", + flagId, + Flags::getFlagName(flagId), + getFlagValue(flagId)); + + ++_string; +} + +void Script::O_SETDFLAG() { + uint16 flag = readScript16bits(); + int32 offset = readScript32bits(); + debugScript("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 Script::O_CALLDFLAG() { + uint16 flag = readScript16bits(); + debugScript("O_CALLDFLAG flag %d", flag); + // it seems that some flags are 32 bit long +} + +void Script::O_PRINTAT() { + uint16 slot = readScriptValue(); + uint16 fr1 = readScriptValue(); + uint16 fr2 = readScriptValue(); + + debugScript("O_PRINTAT slot %d, fr1 %d, fr2 %d", slot, fr1, fr2); + + uint8 color = getFlagValue(Flags::KOLOR); + + _vm->printAt(slot, color, (const char *)_string, fr1, fr2); + + while (*_string) { + ++_string; + } + ++_string; +} + +void Script::O_ZOOMIN() { + uint16 slot = readScriptValue(); + debugScript("O_ZOOMIN slot %04d", slot); +} + +void Script::O_ZOOMOUT() { + uint16 slot = readScriptValue(); + debugScript("O_ZOOMOUT slot %d", slot); +} + +void Script::O_SETSTRINGOFFSET() { + int32 offset = readScript32bits(); + debugScript("O_SETSTRINGOFFSET offset %04x", offset); + // _currentString = "" + // _string = (const char *)_currentInstruction + offset +} + +void Script::O_GETOBJDATA() { + Flags::Id flag = readScriptFlagId(); + uint16 obj = readScriptValue(); + int16 objOffset = readScriptValue(); + debugScript("O_GETOBJDATA flag %d, obj %d, objOffset %d", flag, obj, objOffset); +} + +void Script::O_SETOBJDATA() { + uint16 obj = readScriptValue(); + int16 objOffset = readScriptValue(); + uint16 value = readScriptValue(); + debugScript("O_SETOBJDATA obj %d, objOffset %d, value %d", obj, objOffset, value); +} + +void Script::O_SWAPOBJECTS() { + uint16 obj1 = readScript16bits(); + uint16 obj2 = readScript16bits(); + debugScript("O_SWAPOBJECTS obj1 %d, obj2 %d", obj1, obj2); +} + +void Script::O_CHANGEHEROSET() { + uint16 hero = readScriptValue(); + uint16 heroSet = readScriptValue(); + debugScript("O_CHANGEHEROSET hero %d, heroSet %d", hero, heroSet); +} + +void Script::O_ADDSTRING() { + uint16 value = readScriptValue(); + debugScript("O_ADDSTRING value %d", value); + // _string += value +} + +void Script::O_SUBSTRING() { + uint16 value = readScriptValue(); + debugScript("O_SUBSTRING value %d", value); + // _string -= value +} + +void Script::O_INITDIALOG() { + debugScript("O_INITDIALOG"); +} + +void Script::O_ENABLEDIALOGOPT() { + uint16 opt = readScriptValue(); + debugScript("O_ENABLEDIALOGOPT opt %d", opt); +} + +void Script::O_DISABLEDIALOGOPT() { + uint16 opt = readScriptValue(); + debugScript("O_DISABLEDIALOGOPT opt %d", opt); +} + +void Script::O_SHOWDIALOGBOX() { + uint16 box = readScriptValue(); + debugScript("O_SHOWDIALOGBOX box %d", box); +} + +void Script::O_STOPSAMPLE() { + uint16 slot = readScriptValue(); + debugScript("O_STOPSAMPLE slot %d", slot); + _vm->stopSample(slot); +} + +void Script::O_BACKANIMRANGE() { + uint16 slotId = readScriptValue(); + uint16 animId = readScriptValue(); + uint16 low = readScriptValue(); + uint16 high = readScriptValue(); + + debugScript("O_BACKANIMRANGE slotId %d, animId %d, low %d, high %d", slotId, animId, low, high); +} + +void Script::O_CLEARPATH() { + debugScript("O_CLEARPATH"); + // Fill Sala with 255 +} + +void Script::O_SETPATH() { + debugScript("O_SETPATH"); + // CopyPath +} + +void Script::O_GETHEROX() { + uint16 heroId = readScriptValue(); + Flags::Id flagId = readScriptFlagId(); + + debugScript("O_GETHEROX heroId %d, flagId %d", heroId, flagId); +} + +void Script::O_GETHEROY() { + uint16 heroId = readScript16bits(); + Flags::Id flagId = readScriptFlagId(); + + debugScript("O_GETHEROY heroId %d, flagId %d", heroId, flagId); +} + +void Script::O_GETHEROD() { + uint16 heroId = readScriptValue(); + Flags::Id flagId = readScriptFlagId(); + + debugScript("O_GETHEROD heroId %d, flagId %d", heroId, flagId); +} + +void Script::O_PUSHSTRING() { + debugScript("O_PUSHSTRING"); + // push on the stack + // _currentString + // _dialogData + // _string +} + +void Script::O_POPSTRING() { + debugScript("O_POPSTRING"); + // pop from the stack + // _currentString + // _dialogData + // _string +} + +void Script::O_SETFGCODE() { + int32 offset = readScript32bits(); + _fgOpcodePC = _currentInstruction + offset; + + debugScript("O_SETFGCODE next %08x, offset %08x", _fgOpcodePC, offset); +} + +void Script::O_STOPHERO() { + uint16 heroId = readScriptValue(); + + debugScript("O_STOPHERO heroId %d", heroId); + + // clear move steps for hero +} + +void Script::O_ANIMUPDATEOFF() { + uint16 slotId = readScript16bits(); + debugScript("O_ANIMUPDATEOFF slotId %d", slotId); +} + +void Script::O_ANIMUPDATEON() { + uint16 slotId = readScriptValue(); + debugScript("O_ANIMUPDATEON slotId %d", slotId); +} + +void Script::O_FREECURSOR() { + debugScript("O_FREECURSOR"); + // Change cursor to 0 + // free inv cursor 1 +} + +void Script::O_ADDINVQUIET() { + uint16 heroId = readScriptValue(); + uint16 itemId = readScriptValue(); + + debugScript("O_ADDINVQUIET heorId %d, itemId %d", heroId, itemId); +} + +void Script::O_RUNHERO() { + uint16 heroId = readScriptValue(); + uint16 x = readScriptValue(); + uint16 y = readScriptValue(); + uint16 dir = readScriptValue(); + + debugScript("O_RUNHERO heroId %d, x %d, y %d, dir %d", heroId, x, y, dir); +} + +void Script::O_SETBACKANIMDATA() { + uint16 animId = readScriptValue(); + uint16 animOffset = readScriptValue(); + uint16 wart = readScriptValue(); + + debugScript("O_SETBACKANIMDATA animId %d, animOffset %d, wart %d", animId, animOffset, wart); +} + +void Script::O_VIEWFLC() { + uint16 animNr = readScriptValue(); + debugScript("O_VIEWFLC animNr %d", animNr); + _vm->loadAnim(animNr, false); +} + +void Script::O_CHECKFLCFRAME() { + uint16 frameNr = readScriptValue(); + + debugScript("O_CHECKFLCFRAME frame number %d", frameNr); + + const Video::FlicDecoder &flicPlayer = _vm->_flicPlayer; + + if (flicPlayer.getCurFrame() != frameNr) { + // Move instruction pointer before current instruciton + // must do this check once again till it's false + _currentInstruction -= 2; + _opcodeNF = 1; + } +} + +void Script::O_CHECKFLCEND() { + + //debugScript("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 Script::O_FREEFLC() { + debugScript("O_FREEFLC"); +} + +void Script::O_TALKHEROSTOP() { + uint16 heroId = readScriptValue(); + debugScript("O_TALKHEROSTOP %d", heroId); +} + +void Script::O_HEROCOLOR() { + uint16 heroId = readScriptValue(); + uint16 kolorr = readScriptValue(); + debugScript("O_HEROCOLOR heroId %d, kolorr %d", heroId, kolorr); +} + +void Script::O_GRABMAPA() { + debugScript("O_GRABMAPA"); +} + +void Script::O_ENABLENAK() { + uint16 nakId = readScriptValue(); + debugScript("O_ENABLENAK nakId %d", nakId); +} + +void Script::O_DISABLENAK() { + uint16 nakId = readScriptValue(); + debugScript("O_DISABLENAK nakId %d", nakId); +} + +void Script::O_GETMOBNAME() { + uint16 war = readScriptValue(); + debugScript("O_GETMOBNAME war %d", war); +} + +void Script::O_SWAPINVENTORY() { + uint16 heroId = readScriptValue(); + debugScript("O_SWAPINVENTORY heroId %d", heroId); +} + +void Script::O_CLEARINVENTORY() { + uint16 heroId = readScriptValue(); + debugScript("O_CLEARINVENTORY heroId %d", heroId); +} + +void Script::O_SKIPTEXT() { + debugScript("O_SKIPTEXT"); +} + +void Script::SetVoice(uint32 sampleSlot) { + // TODO: use sample slot + uint16 slot = readScriptValue(); + _vm->loadVoice( + slot, + Common::String::format( + "%03d-%02d.WAV", + _currentString, + getFlagValue(Flags::VOICE_H_LINE) + ) + ); +} + +void Script::O_SETVOICEH() { + static const uint32 VOICE_H_SLOT = 28; + SetVoice(VOICE_H_SLOT); +} + +void Script::O_SETVOICEA() { + static const uint32 VOICE_A_SLOT = 29; + SetVoice(VOICE_A_SLOT); +} + +void Script::O_SETVOICEB() { + static const uint32 VOICE_B_SLOT = 30; + SetVoice(VOICE_B_SLOT); +} + +void Script::O_SETVOICEC() { + static const uint32 VOICE_C_SLOT = 31; + SetVoice(VOICE_C_SLOT); +} + +void Script::O_SETVOICED() { + static const uint32 VOICE_D_SLOT = 32; + SetVoice(VOICE_D_SLOT); +} + +void Script::O_VIEWFLCLOOP() { + uint16 value = readScriptValue(); + debugScript("O_VIEWFLCLOOP animId %d", value); + + _vm->loadAnim(value, true); +} + +void Script::O_FLCSPEED() { + uint16 speed = readScriptValue(); + debugScript("O_FLCSPEED speed %d", speed); +} + +void Script::O_OPENINVENTORY() { + debugScript("O_OPENINVENTORY"); + _opcodeNF = 1; + // _showInventoryFlag = true +} + +void Script::O_KRZYWA() { + debugScript("O_KRZYWA"); +} + +void Script::O_GETKRZYWA() { + debugScript("O_GETKRZYWA"); + // setFlagValue(Flags::TORX1, krzywa[_krzywaIndex++]) + // setFlagValue(Flags::TORY1, krzywa[_krzywaIndex++]) + // Check _krzywaIndex +} + +void Script::O_GETMOB() { + Flags::Id flagId = readScriptFlagId(); + uint16 mx = readScriptValue(); + uint16 my = readScriptValue(); + debugScript("O_GETMOB flagId %d, mx %d, my %d", flagId, mx, my); + // check if current mob pos = (mx, my) +} + +void Script::O_INPUTLINE() { + debugScript("O_INPUTLINE"); +} + + +void Script::O_BREAK_POINT() { + debugScript("O_BREAK_POINT"); +} + +Script::OpcodeFunc Script::_opcodes[NUM_OPCODES] = { + &Script::O_WAITFOREVER, + &Script::O_BLACKPALETTE, + &Script::O_SETUPPALETTE, + &Script::O_INITROOM, + &Script::O_SETSAMPLE, + &Script::O_FREESAMPLE, + &Script::O_PLAYSAMPLE, + &Script::O_PUTOBJECT, + &Script::O_REMOBJECT, + &Script::O_SHOWANIM, + &Script::O_CHECKANIMEND, + &Script::O_FREEANIM, + &Script::O_CHECKANIMFRAME, + &Script::O_PUTBACKANIM, + &Script::O_REMBACKANIM, + &Script::O_CHECKBACKANIMFRAME, + &Script::O_FREEALLSAMPLES, + &Script::O_SETMUSIC, + &Script::O_STOPMUSIC, + &Script::O__WAIT, + &Script::O_UPDATEOFF, + &Script::O_UPDATEON, + &Script::O_UPDATE , + &Script::O_CLS, + &Script::O__CALL, + &Script::O_RETURN, + &Script::O_GO, + &Script::O_BACKANIMUPDATEOFF, + &Script::O_BACKANIMUPDATEON, + &Script::O_CHANGECURSOR, + &Script::O_CHANGEANIMTYPE, + &Script::O__SETFLAG, + &Script::O_COMPARE, + &Script::O_JUMPZ, + &Script::O_JUMPNZ, + &Script::O_EXIT, + &Script::O_ADDFLAG, + &Script::O_TALKANIM, + &Script::O_SUBFLAG, + &Script::O_SETSTRING, + &Script::O_ANDFLAG, + &Script::O_GETMOBDATA, + &Script::O_ORFLAG, + &Script::O_SETMOBDATA, + &Script::O_XORFLAG, + &Script::O_GETMOBTEXT, + &Script::O_MOVEHERO, + &Script::O_WALKHERO, + &Script::O_SETHERO, + &Script::O_HEROOFF, + &Script::O_HEROON, + &Script::O_CLSTEXT, + &Script::O_CALLTABLE, + &Script::O_CHANGEMOB, + &Script::O_ADDINV, + &Script::O_REMINV, + &Script::O_REPINV, + &Script::O_OBSOLETE_GETACTION, + &Script::O_ADDWALKAREA, + &Script::O_REMWALKAREA, + &Script::O_RESTOREWALKAREA, + &Script::O_WAITFRAME, + &Script::O_SETFRAME, + &Script::O_RUNACTION, + &Script::O_COMPAREHI, + &Script::O_COMPARELO, + &Script::O_PRELOADSET, + &Script::O_FREEPRELOAD, + &Script::O_CHECKINV, + &Script::O_TALKHERO, + &Script::O_WAITTEXT, + &Script::O_SETHEROANIM, + &Script::O_WAITHEROANIM, + &Script::O_GETHERODATA, + &Script::O_GETMOUSEBUTTON, + &Script::O_CHANGEFRAMES, + &Script::O_CHANGEBACKFRAMES, + &Script::O_GETBACKANIMDATA, + &Script::O_GETANIMDATA, + &Script::O_SETBGCODE, + &Script::O_SETBACKFRAME, + &Script::O_GETRND, + &Script::O_TALKBACKANIM, + &Script::O_LOADPATH, + &Script::O_GETCHAR, + &Script::O_SETDFLAG, + &Script::O_CALLDFLAG, + &Script::O_PRINTAT, + &Script::O_ZOOMIN, + &Script::O_ZOOMOUT, + &Script::O_SETSTRINGOFFSET, + &Script::O_GETOBJDATA, + &Script::O_SETOBJDATA, + &Script::O_SWAPOBJECTS, + &Script::O_CHANGEHEROSET, + &Script::O_ADDSTRING, + &Script::O_SUBSTRING, + &Script::O_INITDIALOG, + &Script::O_ENABLEDIALOGOPT, + &Script::O_DISABLEDIALOGOPT, + &Script::O_SHOWDIALOGBOX, + &Script::O_STOPSAMPLE, + &Script::O_BACKANIMRANGE, + &Script::O_CLEARPATH, + &Script::O_SETPATH, + &Script::O_GETHEROX, + &Script::O_GETHEROY, + &Script::O_GETHEROD, + &Script::O_PUSHSTRING, + &Script::O_POPSTRING, + &Script::O_SETFGCODE, + &Script::O_STOPHERO, + &Script::O_ANIMUPDATEOFF, + &Script::O_ANIMUPDATEON, + &Script::O_FREECURSOR, + &Script::O_ADDINVQUIET, + &Script::O_RUNHERO, + &Script::O_SETBACKANIMDATA, + &Script::O_VIEWFLC, + &Script::O_CHECKFLCFRAME, + &Script::O_CHECKFLCEND, + &Script::O_FREEFLC, + &Script::O_TALKHEROSTOP, + &Script::O_HEROCOLOR, + &Script::O_GRABMAPA, + &Script::O_ENABLENAK, + &Script::O_DISABLENAK, + &Script::O_GETMOBNAME, + &Script::O_SWAPINVENTORY, + &Script::O_CLEARINVENTORY, + &Script::O_SKIPTEXT, + &Script::O_SETVOICEH, + &Script::O_SETVOICEA, + &Script::O_SETVOICEB, + &Script::O_SETVOICEC, + &Script::O_VIEWFLCLOOP, + &Script::O_FLCSPEED, + &Script::O_OPENINVENTORY, + &Script::O_KRZYWA, + &Script::O_GETKRZYWA, + &Script::O_GETMOB, + &Script::O_INPUTLINE, + &Script::O_SETVOICED, + &Script::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..d9b42baf39 --- /dev/null +++ b/engines/prince/script.h @@ -0,0 +1,255 @@ +/* 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 "audio/mixer.h" + +#include "prince/flags.h" + +namespace Common { + class SeekableReadStream; +} + +namespace Prince { + +class PrinceEngine; + +class Script { +public: + Script(PrinceEngine *vm); + virtual ~Script(); + + bool loadFromStream(Common::SeekableReadStream &stream); + + void step(); + + void setFlagValue(Flags::Id flag, uint16 value); + uint16 getFlagValue(Flags::Id flag); + + void stopBg() { _bgOpcodePC = 0; } + +private: + PrinceEngine *_vm; + + byte *_code; + uint32 _codeSize; + uint32 _currentInstruction; + + uint32 _bgOpcodePC; + uint32 _fgOpcodePC; + + uint16 _lastOpcode; + uint32 _lastInstruction; + byte _result; + static const uint16 MAX_FLAGS = 2000; + static const uint16 FLAG_MASK = 0x8000; + int16 _flags[MAX_FLAGS]; + bool _opcodeNF; + + + // Stack + 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); + void checkPC(uint32 address); + uint8 getCodeByte(uint32 address); + uint8 readScript8bits(); + uint16 readScript16bits(); + + uint32 readScript32bits(); + uint16 readScript8or16bits(); + + uint16 readScriptValue(); + Flags::Id readScriptFlagId() { return (Flags::Id)readScript16bits(); } + + void debugScript(const char *s, ...); + void SetVoice(uint32 slot); + + typedef void (Script::*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..fcdca8a0d1 --- /dev/null +++ b/engines/prince/sound.cpp @@ -0,0 +1,218 @@ +/* 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) + 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 diff --git a/engines/prince/sound.h b/engines/prince/sound.h new file mode 100644 index 0000000000..7219411b36 --- /dev/null +++ b/engines/prince/sound.h @@ -0,0 +1,73 @@ +/* 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 + 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: */ |