From 39a8c71f776254b272e68a36fa5355293c0ae5f9 Mon Sep 17 00:00:00 2001 From: Denis Kasak Date: Mon, 8 Jun 2009 22:18:52 +0000 Subject: Adding Draci Historie engine skeleton (engine stub, BAR archiver, rudimentary GPL disassembler) svn-id: r41390 --- base/plugins.cpp | 3 + configure | 1 + engines/draci/barchive.cpp | 201 +++++++++++++++++++++++++++ engines/draci/barchive.h | 76 ++++++++++ engines/draci/detection.cpp | 126 +++++++++++++++++ engines/draci/draci.cpp | 189 +++++++++++++++++++++++++ engines/draci/draci.h | 58 ++++++++ engines/draci/gpldisasm.cpp | 329 ++++++++++++++++++++++++++++++++++++++++++++ engines/draci/gpldisasm.h | 35 +++++ engines/draci/module.mk | 18 +++ engines/engines.mk | 5 + 11 files changed, 1041 insertions(+) create mode 100644 engines/draci/barchive.cpp create mode 100644 engines/draci/barchive.h create mode 100644 engines/draci/detection.cpp create mode 100644 engines/draci/draci.cpp create mode 100644 engines/draci/draci.h create mode 100644 engines/draci/gpldisasm.cpp create mode 100644 engines/draci/gpldisasm.h create mode 100644 engines/draci/module.mk diff --git a/base/plugins.cpp b/base/plugins.cpp index 446c26e57c..bcfb865492 100644 --- a/base/plugins.cpp +++ b/base/plugins.cpp @@ -157,6 +157,9 @@ public: #if PLUGIN_ENABLED_STATIC(TUCKER) LINK_PLUGIN(TUCKER) #endif + #if PLUGIN_ENABLED_STATIC(DRACI) + LINK_PLUGIN(DRACI) + #endif // Music plugins // TODO: Use defines to disable or enable each MIDI driver as a diff --git a/configure b/configure index c2641b31f0..e298b80006 100755 --- a/configure +++ b/configure @@ -96,6 +96,7 @@ add_engine sword2 "Broken Sword 2" yes add_engine tinsel "Tinsel" no add_engine touche "Touche: The Adventures of the Fifth Musketeer" yes add_engine tucker "Bud Tucker in Double Trouble" yes +add_engine draci "Dragon History" no # diff --git a/engines/draci/barchive.cpp b/engines/draci/barchive.cpp new file mode 100644 index 0000000000..f813222552 --- /dev/null +++ b/engines/draci/barchive.cpp @@ -0,0 +1,201 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#include "common/debug.h" +#include "common/file.h" +#include "common/str.h" +#include "common/stream.h" + +#include "draci/barchive.h" +#include "draci/draci.h" + +namespace Draci { + +const char BArchive::_magicNumber[] = "BAR!"; + +/** + * @brief BArchive open method + * @param path Path to input file + * + * Opens a BAR (Bob's Archiver) archive, which is the game's archiving format. + * BAR archives have a .DFW file extension, due to an unused historical interface. + * + * archive format: header, + * file0, file1, ... + * footer + * header format: [4 bytes] magic number "BAR!" + * [uint16LE] file count (number of archived streams), + * [uint32LE] footer offset from start of file + * file format: [2 bytes] compressed length + * [2 bytes] original length + * [1 byte] compression type + * [1 byte] CRC + * footer format: [array of uint32LE] offsets of individual files from start of archive + * (last entry is footer offset again) + */ + +void BArchive::openArchive(const Common::String &path) { + byte buf[4]; + byte *footer; + uint32 footerOffset, footerSize; + Common::File f; + + // Close previously opened archive (if any) + closeArchive(); + + debugC(5, kDraciGeneralDebugLevel, "Loading BAR archive %s:", + path.c_str()); + + f.open(path); + if (f.isOpen()) { + debugC(5, kDraciGeneralDebugLevel, "Success"); + } else { + debugC(5, kDraciGeneralDebugLevel, "Error"); + return; + } + + // Save path for reading in files later on + _path = path; + + // Read archive header + debugC(5, kDraciGeneralDebugLevel, "Checking magic number:"); + + f.read(buf, 4); + if (memcmp(buf, _magicNumber, 4) == 0) { + debugC(5, kDraciGeneralDebugLevel, "Success"); + } else { + debugC(5, kDraciGeneralDebugLevel, "Error"); + f.close(); + return; + } + + _fileCount = f.readUint16LE(); + footerOffset = f.readUint32LE(); + footerSize = f.size() - footerOffset; + + debugC(5, kDraciGeneralDebugLevel, "Archive info: %d files, %d data bytes", + _fileCount, footerOffset - _archiveHeaderSize); + + // Read in footer + footer = new byte[footerSize]; + f.seek(footerOffset); + f.read(footer, footerSize); + Common::MemoryReadStream reader(footer, footerSize); + + // Read in file headers, but do not read the actual data yet + // The data will be read on demand to save memory + _files = new BAFile[_fileCount]; + + for (unsigned int i = 0; i < _fileCount; i++) { + uint32 fileOffset; + + fileOffset = reader.readUint32LE(); + f.seek(fileOffset); // Seek to next file in archive + f.readUint16LE(); // Compressed size, not used + _files[i]._length = f.readUint16LE(); // Original size + _files[i]._offset = fileOffset; + + assert(f.readByte() == 0 && + "Compression type flag is non-zero (file is compressed)"); + + _files[i]._crc = f.readByte(); // CRC checksum of the file + _files[i]._data = NULL; // File data will be read in on demand + } + + // Last footer item should be equal to footerOffset + assert(reader.readUint32LE() == footerOffset && "Footer offset mismatch"); + + f.close(); +} + +/** + * @brief BArchive close method + * + * Closes the currently opened archive. It can be called explicitly to + * free up memory. + */ +void BArchive::closeArchive(void) { + if (!_files) { + return; + } + + for (unsigned int i = 0; i < _fileCount; ++i) { + if (_files[i]._data) { + delete _files[i]._data; + } + } + + delete[] _files; + + _files = NULL; + _fileCount = 0; +} + +BAFile *BArchive::operator[](unsigned int i) const { + Common::File f; + + // Check whether requested file exists + if (i >= _fileCount) { + return NULL; + } + + debugC(5, kDraciGeneralDebugLevel, "Accessing file %d from archive %s", + i, _path.c_str()); + + // Check if file has already been opened and return that + if (_files[i]._data) { + return _files + i; + } + + // Else open archive and read in requested file + f.open(_path); + if (f.isOpen()) { + debugC(5, kDraciGeneralDebugLevel, "Success"); + } else { + debugC(5, kDraciGeneralDebugLevel, "Error"); + return NULL; + } + + // Read in the file (without the file header) + f.seek(_files[i]._offset + _fileHeaderSize); + _files[i]._data = new byte[_files[i]._length]; + f.read(_files[i]._data, _files[i]._length); + + // Calculate CRC + byte tmp = 0; + for (unsigned int j = 0; j < _files[i]._length; j++) { + tmp ^= _files[i]._data[j]; + } + + debugC(5, kDraciGeneralDebugLevel, "Read in file %d", i); + assert(tmp == _files[i]._crc && "CRC checksum mismatch"); + + return _files + i; +} + +} // End of namespace Draci + + + diff --git a/engines/draci/barchive.h b/engines/draci/barchive.h new file mode 100644 index 0000000000..0a0ecc832b --- /dev/null +++ b/engines/draci/barchive.h @@ -0,0 +1,76 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#ifndef BARCHIVE_H +#define BARCHIVE_H + +#include "common/str.h" + +namespace Draci { + +/** + * Represents individual files inside the archive + */ + +struct BAFile { + uint16 _length; + uint32 _offset; //!< Offset of file inside archive + byte *_data; + byte _crc; + + void closeFile(void) { //!< Releases the file data (for memory considerations) + delete _data; + _data = NULL; + } +}; + +class BArchive { +public: + BArchive() : _files(NULL), _fileCount(0) {} + BArchive(Common::String &path) : _files(NULL), _fileCount(0) { openArchive(path); } + ~BArchive() { closeArchive(); } + + void openArchive(const Common::String &path); + void closeArchive(void); + uint16 size() const { return _fileCount; } + + BAFile *operator[](unsigned int i) const; + +private: + // Archive header data + static const char _magicNumber[]; + static const unsigned int _archiveHeaderSize = 10; + + // File stream header data + static const unsigned int _fileHeaderSize = 6; + + Common::String _path; //!< Path to file + BAFile *_files; //!< Internal array of files + uint16 _fileCount; //!< Number of files in archive +}; + +} // End of namespace Draci + +#endif // BARCHIVE_H diff --git a/engines/draci/detection.cpp b/engines/draci/detection.cpp new file mode 100644 index 0000000000..02ce9f4764 --- /dev/null +++ b/engines/draci/detection.cpp @@ -0,0 +1,126 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#include "draci/draci.h" + +#include "base/plugins.h" +#include "engines/metaengine.h" + +static const PlainGameDescriptor draciGames[] = { + { "draci", "Draci Historie" }, + { 0, 0 } +}; + +namespace Draci { + +const ADGameDescription gameDescriptions[] = { + + { + "draci", + 0, + AD_ENTRY1s("INIT.DFW", "b890a5aeebaf16af39219cba2416b0a3", 906), + Common::EN_ANY, + Common::kPlatformPC, + ADGF_NO_FLAGS + }, + + { + "draci", + 0, + AD_ENTRY1s("INIT.DFW", "9921c8f0045679a8f37eca8d41c5ec02", 906), + Common::CZ_CZE, + Common::kPlatformPC, + ADGF_NO_FLAGS + }, + + { + "draci", + 0, + AD_ENTRY1s("INIT.DFW", "76b9b78a8a8809a240acc395df4d0715", 906), + Common::PL_POL, + Common::kPlatformPC, + ADGF_NO_FLAGS + }, + + AD_TABLE_END_MARKER +}; + +} // End of namespace Draci + +const ADParams detectionParams = { + // Pointer to ADGameDescription or its superset structure + (const byte *)Draci::gameDescriptions, + // Size of that superset structure + sizeof(ADGameDescription), + // Number of bytes to compute MD5 sum for + 5000, + // List of all engine targets + draciGames, + // Structure for autoupgrading obsolete targets + 0, + // Name of single gameid (optional) + "draci", + // List of files for file-based fallback detection (optional) + 0, + // Flags + 0 +}; + +class DraciMetaEngine : public AdvancedMetaEngine { +public: + DraciMetaEngine() : AdvancedMetaEngine(detectionParams) {} + + virtual const char *getName() const { + return "Draci Historie Engine"; + } + + virtual const char *getOriginalCopyright() const { + return "Copyright (C) 1995 NoSense"; + } + + virtual bool hasFeature(MetaEngineFeature f) const; + virtual bool createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const; +}; + +bool DraciMetaEngine::hasFeature(MetaEngineFeature f) const { + return false; +} + +bool Draci::DraciEngine::hasFeature(EngineFeature f) const { + return false; +} + +bool DraciMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const { + if (desc) { + *engine = new Draci::DraciEngine(syst, Draci::gameDescriptions); + } + return desc != 0; +} + +#if PLUGIN_ENABLED_DYNAMIC(DRACI) + REGISTER_PLUGIN_DYNAMIC(DRACI, PLUGIN_TYPE_ENGINE, DraciMetaEngine); +#else + REGISTER_PLUGIN_STATIC(DRACI, PLUGIN_TYPE_ENGINE, DraciMetaEngine); +#endif diff --git a/engines/draci/draci.cpp b/engines/draci/draci.cpp new file mode 100644 index 0000000000..4de72549f6 --- /dev/null +++ b/engines/draci/draci.cpp @@ -0,0 +1,189 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#include +#include "common/scummsys.h" + +#include "common/config-manager.h" +#include "common/events.h" +#include "common/file.h" + +#include "graphics/font.h" + +#include "draci/draci.h" +#include "draci/barchive.h" +#include "draci/gpldisasm.h" + +namespace Draci { + +DraciEngine::DraciEngine(OSystem *syst, const ADGameDescription *gameDesc) + : Engine(syst) { + // Put your engine in a sane state, but do nothing big yet; + // in particular, do not load data from files; rather, if you + // need to do such things, do them from init(). + + // Do not initialize graphics here + + // However this is the place to specify all default directories + //Common::File::addDefaultDirectory(_gameDataPath + "sound/"); + + // Here is the right place to set up the engine specific debug levels + Common::addDebugChannel(kDraciGeneralDebugLevel, "general", "Draci general debug level"); + Common::addDebugChannel(kDraciBytecodeDebugLevel, "bytecode", "GPL bytecode instructions"); + + // Don't forget to register your random source + syst->getEventManager()->registerRandomSource(_rnd, "draci"); +} + +void drawString(Graphics::Surface *surf, Common::String str, int x, int y, byte color) { + Graphics::ScummFont temp; + int curx = x; + const int space = 0; + uint len = str.size(); + for (unsigned int i = 0; i < len; ++i) { + temp.drawChar(surf, str.c_str()[i], curx, y, color); + curx += temp.getCharWidth(str.c_str()[i]) + space; + } +} + +int DraciEngine::init() { + // Initialize graphics using following: + initGraphics(320, 200, false); + + // Basic archive test + Common::String path("INIT.DFW"); + BArchive ar(path); + BAFile *f; + debugC(3, kDraciGeneralDebugLevel, "Number of file streams in archive: %d\n", ar.size()); + f = ar[0]; + debugC(3, kDraciGeneralDebugLevel, "First 10 bytes of file %d: ", 0); + for (unsigned int i = 0; i < 10; ++i) { + debugC(3, kDraciGeneralDebugLevel, "0x%02x%c", f->_data[i], (i < 9) ? ' ' : '\n'); + } + + // Read in GPL script for the first game location + debugC(2, kDraciBytecodeDebugLevel, "Disassembling GPL script " + "for the first game location..."); + Common::String path2("MIST.DFW"); + ar.closeArchive(); + ar.openArchive(path2); + f = ar[3]; + + // Disassemble GPL script for the first location + gpldisasm(f->_data, f->_length); + + return 0; +} + +int DraciEngine::go() { + debugC(1, kDraciGeneralDebugLevel, "DraciEngine::go()"); + + // Read in a sample palette + byte *palette = new byte[4 * 256]; + + Common::String path("PALETY.DFW"); + BArchive ar(path); + BAFile *f; + + ar.closeArchive(); + ar.openArchive(path); + f = ar[0]; + Common::MemoryReadStream readerZ(f->_data, f->_length); + + palette[0] = readerZ.readByte(); + palette[1] = readerZ.readByte(); + palette[2] = readerZ.readByte(); + palette[3] = 0; + palette[4] = readerZ.readByte(); + palette[5] = readerZ.readByte(); + palette[6] = readerZ.readByte(); + palette[7] = 0; + for (unsigned int i = 2; i < 256; ++i) { + // FIXME: Sprite is too dark, add a fixed value as a workaround + palette[i*4] = readerZ.readByte() + 20; + palette[i*4+1] = readerZ.readByte() + 20; + palette[i*4+2] = readerZ.readByte() + 20; + palette[i*4+3] = 0; + } + _system->setPalette(palette, 0, 256); + + // Draw a test string + Graphics::Surface *surf = _system->lockScreen(); + drawString(surf, "Testing, testing, read all about it!", 5, 60, 3); + _system->unlockScreen(); + + // Draw and animate the dragon + path = "OBR_AN.DFW"; + ar.closeArchive(); + ar.openArchive(path); + + for (unsigned int t = 0; t < 25; ++t) { + debugC(4, kDraciGeneralDebugLevel, "Drawing frame %d...", t); + + // Load frame to memory + f = ar[t]; + Common::MemoryReadStream reader(f->_data, f->_length); + + // Read in frame width and height + uint16 w = reader.readUint16LE(); + uint16 h = reader.readUint16LE(); + + // Allocate frame memory + byte *scr = new byte[w * h]; + + // Draw frame + for (uint16 i = 0; i < w; ++i) { + for (uint16 j = 0; j < h; ++j) { + scr[j*w+i] = reader.readByte(); + } + } + _system->copyRectToScreen(scr, w, 0, 0, w, h); + _system->updateScreen(); + _system->delayMillis(100); + + debugC(4, kDraciGeneralDebugLevel, "Finished frame %d", t); + + // Free frame memory + delete [] scr; + } + getchar(); + + return 0; +} + +DraciEngine::~DraciEngine() { + // Dispose your resources here + + // Remove all of our debug levels here + Common::clearAllDebugChannels(); +} + +Common::Error DraciEngine::run() { + init(); + go(); + return Common::kNoError; +} + +} // End of namespace Draci diff --git a/engines/draci/draci.h b/engines/draci/draci.h new file mode 100644 index 0000000000..49da23b43e --- /dev/null +++ b/engines/draci/draci.h @@ -0,0 +1,58 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#ifndef DRACI_H +#define DRACI_H + +#include "common/system.h" +#include "engines/engine.h" +#include "engines/advancedDetector.h" + +namespace Draci { + +class DraciEngine : public Engine { +public: + DraciEngine(OSystem *syst, const ADGameDescription *gameDesc); + ~DraciEngine(); + + int init(); + int go(); + Common::Error run(); + + bool hasFeature(Engine::EngineFeature f) const; + +private: + Common::RandomSource _rnd; +}; + +enum { + kDraciGeneralDebugLevel = 1 << 0, + kDraciBytecodeDebugLevel = 1 << 1 +}; + +} // End of namespace Draci + +#endif // DRACI_H + diff --git a/engines/draci/gpldisasm.cpp b/engines/draci/gpldisasm.cpp new file mode 100644 index 0000000000..1749136702 --- /dev/null +++ b/engines/draci/gpldisasm.cpp @@ -0,0 +1,329 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +/** + * @brief GPL2 bytecode disassembler + * @param gplcode A pointer to the bytecode + * len Length of the bytecode + * + * GPL2 is short for Game Programming Language 2 which is the script language + * used by Draci Historie. This is a simple disassembler for the language. + * + * A compiled GPL2 program consists of a stream of bytes representing commands + * and their parameters. The syntax is as follows: + * + * Syntax of a command: + * + * + * Syntax of a parameter: + * - 1: integer number literally passed to the program + * - 2-1: string stored in the reservouir of game strings (i.e. something to be + * displayed) and stored as an index in this list + * - 2-2: string resolved by the compiler (i.e., a path to another file) and + * replaced by an integer index of this entity in the appropriate namespace + * (e.g., the index of the palette, location, ...) + * - 3-0: relative jump to a label defined in this code. Each label must be + * first declared in the beginning of the program. + * - 3-1 .. 3-9: index of an entity in several namespaces, defined in file ident + * - 4: mathematical expression compiled into a postfix format + * + * In the compiled program, parameters of type 1..3 are represented by a single + * 16-bit integer. The called command knows by its definition what namespace the + * value comes from. + */ + +#include "common/debug.h" +#include "common/stream.h" + +#include "draci/gpldisasm.h" +#include "draci/barchive.h" +#include "draci/draci.h" + +#define skipParams(x) for(unsigned int i = 0; i < (x); ++i) reader.readUint16LELE() +#define CMDPAIR(x, y) (((x) << 8) | y) + +namespace Draci { + +// FIXME: Handle math expressions properly instead of just skipping them +void handleMathExpression(Common::MemoryReadStream &reader) { + uint16 temp; + while (1) { + temp = reader.readUint16LE(); + if (temp == 0) { + break; + } + temp = reader.readUint16LE(); + } + return; +} + +int gpldisasm(byte *gplcode, uint16 len) { + Common::MemoryReadStream reader(gplcode, len); + + while (!reader.eos()) { + // read in command pair + uint16 cmdpair = reader.readUint16BE(); + + uint16 param1, param2, param3; + + switch (cmdpair) { + case CMDPAIR(5,1): + param1 = reader.readUint16LE(); + param2 = reader.readUint16LE(); + debugC(2, kDraciBytecodeDebugLevel, "C_Load %hu %hu", param1, param2); + break; + case CMDPAIR(4,1): + param1 = reader.readUint16LE(); + param2 = reader.readUint16LE(); + debugC(2, kDraciBytecodeDebugLevel, "C_Start %hu %hu", param1, param2); + break; + case CMDPAIR(5,2): + param1 = reader.readUint16LE(); + param2 = reader.readUint16LE(); + debugC(2, kDraciBytecodeDebugLevel, "C_StartPlay %hu %hu", + param1, param2); + break; + case CMDPAIR(5,3): + debugC(2, kDraciBytecodeDebugLevel, "C_JustTalk"); + break; + case CMDPAIR(5,4): + debugC(2, kDraciBytecodeDebugLevel, "C_JustStay"); + break; + case CMDPAIR(10,2): + param1 = reader.readUint16LE(); + param2 = reader.readUint16LE(); + param3 = reader.readUint16LE(); + debugC(2, kDraciBytecodeDebugLevel, "C_StayOn %hu %hu %hu", + param1, param2, param3); + break; + case CMDPAIR(10,1): + param1 = reader.readUint16LE(); + param2 = reader.readUint16LE(); + param3 = reader.readUint16LE(); + debugC(2, kDraciBytecodeDebugLevel, "C_WalkOn %hu %hu %hu", + param1, param2, param3); + break; + case CMDPAIR(10,3): + param1 = reader.readUint16LE(); + param2 = reader.readUint16LE(); + param3 = reader.readUint16LE(); + debugC(2, kDraciBytecodeDebugLevel, "C_WalkOnPlay %hu %hu %hu", + param1, param2, param3); + break; + case CMDPAIR(7,1): + param1 = reader.readUint16LE(); + param2 = reader.readUint16LE(); + debugC(2, kDraciBytecodeDebugLevel, "C_ObjStat %hu %hu", + param1, param2); + break; + case CMDPAIR(7,2): + param1 = reader.readUint16LE(); + param2 = reader.readUint16LE(); + debugC(2, kDraciBytecodeDebugLevel, "C_ObjStat_On %hu %hu", + param1, param2); + break; + case CMDPAIR(8,1): + param1 = reader.readUint16LE(); + param2 = reader.readUint16LE(); + debugC(2, kDraciBytecodeDebugLevel, "C_IcoStat %hu %hu", + param1, param2); + break; + case CMDPAIR(14,1): + param1 = reader.readUint16LE(); + param2 = reader.readUint16LE(); + debugC(2, kDraciBytecodeDebugLevel, "C_NewRoom %hu %hu", + param1, param2); + break; + case CMDPAIR(6,1): + param1 = reader.readUint16LE(); + param2 = reader.readUint16LE(); + debugC(2, kDraciBytecodeDebugLevel, "C_Talk %hu %hu", + param1, param2); + break; + case CMDPAIR(2,1): + param1 = reader.readUint16LE(); + handleMathExpression(reader); + debugC(2, kDraciBytecodeDebugLevel, "C_Let %hu", param1); + break; + case CMDPAIR(15,1): + param1 = reader.readUint16LE(); + debugC(2, kDraciBytecodeDebugLevel, "C_ExecInit %hu", param1); + break; + case CMDPAIR(15,2): + param1 = reader.readUint16LE(); + debugC(2, kDraciBytecodeDebugLevel, "C_ExecLook %hu", param1); + break; + case CMDPAIR(15,3): + param1 = reader.readUint16LE(); + debugC(2, kDraciBytecodeDebugLevel, "C_ExecUse %hu", param1); + break; + case CMDPAIR(16,1): + debugC(2, kDraciBytecodeDebugLevel, "C_RepaintInventory"); + break; + case CMDPAIR(16,2): + debugC(2, kDraciBytecodeDebugLevel, "C_ExitInventory"); + break; + case CMDPAIR(1,1): + param1 = reader.readUint16LE(); + debugC(2, kDraciBytecodeDebugLevel, "C_goto %hu", param1); + break; + case CMDPAIR(3,1): + handleMathExpression(reader); + param1 = reader.readUint16LE(); + debugC(2, kDraciBytecodeDebugLevel, "C_if %hu", param1); + break; + case CMDPAIR(9,1): + param1 = reader.readUint16LE(); + debugC(2, kDraciBytecodeDebugLevel, "C_Dialogue %hu", param1); + break; + case CMDPAIR(9,2): + debugC(2, kDraciBytecodeDebugLevel, "C_ExitDialogue"); + break; + case CMDPAIR(9,3): + debugC(2, kDraciBytecodeDebugLevel, "C_ResetDialogue"); + break; + case CMDPAIR(9,4): + debugC(2, kDraciBytecodeDebugLevel, "C_ResetDialogueFrom"); + break; + case CMDPAIR(9,5): + param1 = reader.readUint16LE(); + debugC(2, kDraciBytecodeDebugLevel, "C_ResetBlock %hu", param1); + break; + case CMDPAIR(11,1): + param1 = reader.readUint16LE(); + debugC(2, kDraciBytecodeDebugLevel, "C_LoadPalette %hu", param1); + break; + case CMDPAIR(12,1): + debugC(2, kDraciBytecodeDebugLevel, "C_SetPalette"); + break; + case CMDPAIR(12,2): + debugC(2, kDraciBytecodeDebugLevel, "C_BlackPalette"); + break; + case CMDPAIR(13,1): + param1 = reader.readUint16LE(); + param2 = reader.readUint16LE(); + param3 = reader.readUint16LE(); + debugC(2, kDraciBytecodeDebugLevel, "C_FadePalette %hu %hu %hu", + param1, param2, param3); + break; + case CMDPAIR(13,2): + param1 = reader.readUint16LE(); + param2 = reader.readUint16LE(); + param3 = reader.readUint16LE(); + debugC(2, kDraciBytecodeDebugLevel, "C_FadePalettePlay %hu %hu %hu", + param1, param2, param3); + break; + case CMDPAIR(17,1): + debugC(2, kDraciBytecodeDebugLevel, "C_ExitMap"); + break; + case CMDPAIR(18,1): + param1 = reader.readUint16LE(); + debugC(2, kDraciBytecodeDebugLevel, "C_LoadMusic %hu", param1); + break; + case CMDPAIR(18,2): + debugC(2, kDraciBytecodeDebugLevel, "C_StartMusic"); + break; + case CMDPAIR(18,3): + debugC(2, kDraciBytecodeDebugLevel, "C_StopMusic"); + break; + case CMDPAIR(18,4): + param1 = reader.readUint16LE(); + debugC(2, kDraciBytecodeDebugLevel, "C_FadeOutMusic %hu", param1); + break; + case CMDPAIR(18,5): + param1 = reader.readUint16LE(); + debugC(2, kDraciBytecodeDebugLevel, "C_FadeInMusic %hu", param1); + break; + case CMDPAIR(19,1): + debugC(2, kDraciBytecodeDebugLevel, "C_Mark"); + break; + case CMDPAIR(19,2): + debugC(2, kDraciBytecodeDebugLevel, "C_Release"); + break; + case CMDPAIR(20,1): + debugC(2, kDraciBytecodeDebugLevel, "C_Play"); + break; + case CMDPAIR(21,1): + param1 = reader.readUint16LE(); + debugC(2, kDraciBytecodeDebugLevel, "C_LoadMap %hu", param1); + break; + case CMDPAIR(21,2): + debugC(2, kDraciBytecodeDebugLevel, "C_RoomMap"); + break; + case CMDPAIR(22,1): + debugC(2, kDraciBytecodeDebugLevel, "C_DisableQuickHero"); + break; + case CMDPAIR(22,2): + debugC(2, kDraciBytecodeDebugLevel, "C_EnableQuickHero"); + break; + case CMDPAIR(23,1): + debugC(2, kDraciBytecodeDebugLevel, "C_DisableSpeedText"); + break; + case CMDPAIR(23,2): + debugC(2, kDraciBytecodeDebugLevel, "C_EnableSpeedText"); + break; + case CMDPAIR(24,1): + debugC(2, kDraciBytecodeDebugLevel, "C_QuitGame"); + break; + case CMDPAIR(25,1): + debugC(2, kDraciBytecodeDebugLevel, "C_PushNewRoom"); + break; + case CMDPAIR(25,2): + debugC(2, kDraciBytecodeDebugLevel, "C_PopNewRoom"); + break; + case CMDPAIR(26,1): + debugC(2, kDraciBytecodeDebugLevel, "C_ShowCheat"); + break; + case CMDPAIR(26,2): + debugC(2, kDraciBytecodeDebugLevel, "C_HideCheat"); + break; + case CMDPAIR(26,3): + param1 = reader.readUint16LE(); + debugC(2, kDraciBytecodeDebugLevel, "C_ClearCheat %hu", param1); + break; + case CMDPAIR(27,1): + param1 = reader.readUint16LE(); + param2 = reader.readUint16LE(); + param3 = reader.readUint16LE(); + debugC(2, kDraciBytecodeDebugLevel, "C_FeedPassword %hu %hu %hu", + param1, param2, param3); + break; + case CMDPAIR(0, 0): + debugC(2, kDraciBytecodeDebugLevel, "gplend"); + break; + case CMDPAIR(0, 1): + debugC(2, kDraciBytecodeDebugLevel, "exit"); + break; + default: + debugC(2, kDraciBytecodeDebugLevel, "Unknown opcode %hu, %hu", + (cmdpair >> 8) & 0xFF, cmdpair & 0xFF); + } + } + + return 0; +} + +} + diff --git a/engines/draci/gpldisasm.h b/engines/draci/gpldisasm.h new file mode 100644 index 0000000000..b37a670507 --- /dev/null +++ b/engines/draci/gpldisasm.h @@ -0,0 +1,35 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#ifndef GPLDISASM_H +#define GPLDISASM_H + +namespace Draci { + +int gpldisasm(byte *gplcode, uint16 len); + +} + +#endif // GPLDIASM_H diff --git a/engines/draci/module.mk b/engines/draci/module.mk new file mode 100644 index 0000000000..98a0d90a31 --- /dev/null +++ b/engines/draci/module.mk @@ -0,0 +1,18 @@ +MODULE := engines/draci + +MODULE_OBJS := \ + draci.o \ + detection.o \ + barchive.o \ + gpldisasm.o + +MODULE_DIRS += \ + engines/draci + +# This module can be built as a plugin +ifeq ($(ENABLE_DRACI), DYNAMIC_PLUGIN) +PLUGIN := 1 +endif + +# Include common rules +include $(srcdir)/rules.mk diff --git a/engines/engines.mk b/engines/engines.mk index 8d7d8de9ff..6c403a61a7 100644 --- a/engines/engines.mk +++ b/engines/engines.mk @@ -36,6 +36,11 @@ DEFINES += -DENABLE_CRUISE=$(ENABLE_CRUISE) MODULES += engines/cruise endif +ifdef ENABLE_DRACI +DEFINES += -DENABLE_DRACI=$(ENABLE_DRACI) +MODULES += engines/draci +endif + ifdef ENABLE_DRASCULA DEFINES += -DENABLE_DRASCULA=$(ENABLE_DRASCULA) MODULES += engines/drascula -- cgit v1.2.3