Ticket #8990: dh.patch

File dh.patch, 19.0 KB (added by SF/next_ghost, 15 years ago)

Basic infrastructure for future Dragon History engine

  • base/plugins.cpp

    diff --git a/base/plugins.cpp b/base/plugins.cpp
    index 446c26e..1ec923c 100644
    a b public:  
    157157                #if PLUGIN_ENABLED_STATIC(TUCKER)
    158158                LINK_PLUGIN(TUCKER)
    159159                #endif
     160                #if PLUGIN_ENABLED_STATIC(DHE)
     161                LINK_PLUGIN(DHE)
     162                #endif
    160163
    161164                // Music plugins
    162165                // TODO: Use defines to disable or enable each MIDI driver as a
  • configure

    diff --git a/configure b/configure
    index 2bd998c..5832321 100755
    a b add_engine sword2 "Broken Sword 2" yes  
    9696add_engine tinsel "Tinsel" no
    9797add_engine touche "Touche: The Adventures of the Fifth Musketeer" yes
    9898add_engine tucker "Bud Tucker in Double Trouble" yes
     99add_engine dhe "Dragon History" no
    99100
    100101
    101102#
  • new file engines/dh/barchive.cpp

    diff --git a/engines/dh/barchive.cpp b/engines/dh/barchive.cpp
    new file mode 100644
    index 0000000..04c397d
    - +  
     1/* ScummVM - Graphic Adventure Engine
     2 *
     3 * ScummVM is the legal property of its developers, whose names
     4 * are too numerous to list here. Please refer to the COPYRIGHT
     5 * file distributed with this source distribution.
     6 *
     7 * This program is free software; you can redistribute it and/or
     8 * modify it under the terms of the GNU General Public License
     9 * as published by the Free Software Foundation; either version 2
     10 * of the License, or (at your option) any later version.
     11
     12 * This program is distributed in the hope that it will be useful,
     13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15 * GNU General Public License for more details.
     16
     17 * You should have received a copy of the GNU General Public License
     18 * along with this program; if not, write to the Free Software
     19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
     20 *
     21 * $URL$
     22 * $Id$
     23 *
     24 */
     25
     26#include "common/str.h"
     27#include "common/file.h"
     28#include "common/stream.h"
     29#include "common/debug.h"
     30
     31#include "dh/barchive.h"
     32#include "dh/dh.h"
     33
     34namespace DH {
     35
     36const char BArchive::_signature[] = "BAR!";
     37const char BArchive::_dfwSignature[] = "BS";
     38
     39/**
     40 * @brief Simple RLE decompression
     41 * @param dst Destination BArchive entry
     42 * @param src ReadStream containing input data
     43 *
     44 * input: [uint16LE] uncompressed length, [uint16LE] compressed length,
     45 *     [byte] stopper mark, [multiple bytes] data
     46 */
     47void decompress(BArchive::BAEntry &dst, Common::ReadStream &src) {
     48        unsigned int length, i;
     49        byte *tmp, stopper, last;
     50
     51        dst._length = src.readUint16LE();
     52        dst._data = tmp = new byte[dst._length];
     53        dst._uncompressed = 1;
     54
     55        // 2 bytes for compressed size, 1 for stopper mark
     56        length = src.readUint16LE() - 3;
     57        stopper = src.readByte();
     58
     59        debugC(5, kDHDebugResource, "Uncompressing %d bytes to %d", length,
     60                dst._length);
     61        debugC(5, kDHDebugResource, "Stopper mark is %02x", stopper);
     62
     63        for (last = src.readByte(); !src.eos(); last = src.readByte()) {
     64                // inflate RLE block
     65                if ((last == stopper) && (length = src.readByte())) {
     66                        last = src.readByte();
     67                        for (i = 0; i < length; i++) {
     68                                *tmp++ = last;
     69                        }
     70                // just copy the byte
     71                } else {
     72                        *tmp++ = last;
     73                }
     74        }
     75}
     76
     77/**
     78 * @brief DFW archive reader
     79 * @param path Path to input file
     80 *
     81 * file format: header, index table, data
     82 * header format: [uint16LE] archived file count, [uint16LE] index table
     83 *     length, [2 bytes] signature "BS"
     84 * index table format: [uint16LE] compressed data length, [uint32LE] data
     85 *     offset from start of file
     86 * data format: [uint16LE] uncompressed length, [uint16LE] compressed length
     87 *     (not including uncompressed length), [byte] stopper mark,
     88 *     [multiple bytes] data
     89 */
     90void BArchive::openDFW(const Common::String &path) {
     91        byte *buf;
     92        unsigned int i, pos, offset, length, tableCount, bufSize = 4096;
     93        Common::File fr;
     94
     95        debugC(5, kDHDebugResource, "Retrying file %s as DFW:", path.c_str());
     96
     97        fr.open(path);
     98        if (fr.isOpen()) {
     99                debugC(5, kDHDebugResource, "OK");
     100        } else {
     101                debugC(5, kDHDebugResource, "Error");
     102                return;
     103        }
     104
     105        // read file header
     106        debugC(5, kDHDebugResource, "Checking DFW signature:");
     107
     108        _itemCount = fr.readUint16LE();
     109        tableCount = fr.readUint16LE();
     110        buf = new byte[bufSize];
     111        fr.read(buf, 2);
     112
     113        if (!memcmp(buf, _dfwSignature, 2)) {
     114                debugC(5, kDHDebugResource, "OK");
     115        } else {
     116                debugC(5, kDHDebugResource, "Error");
     117                _itemCount = 0;
     118                return;
     119        }
     120
     121        debugC(5, kDHDebugResource, "Archive stats: %d files, %d table items",
     122                _itemCount, tableCount);
     123
     124        // read files from archive
     125        _contents = new BAEntry[_itemCount];
     126        _rawData = NULL;
     127
     128        for (i = 0; i < _itemCount; i++) {
     129                // 2 extra bytes for uncompressed size not included
     130                length = fr.readUint16LE() + 2;
     131                offset = fr.readUint32LE();
     132
     133                pos = fr.pos();
     134                debugC(5, kDHDebugResource, "Reading %d bytes at offset %d (pos %d)",
     135                        length, offset, pos);
     136                fr.seek(offset);
     137
     138                Common::MemoryReadStream *comp = fr.readStream(length);
     139                decompress(_contents[i], *comp);
     140                delete comp;
     141                fr.seek(pos);
     142        }
     143}
     144
     145/**
     146 * @brief BArchive reader
     147 * @param path Path to input file
     148 *
     149 * file format: header, data, footer
     150 * header format: [4 bytes] signature "BAR!", [uint16LE] archived file count,
     151 *     [uint32LE] footer offset from start of file
     152 * data format: [multiple bytes]
     153 * footer format: [uint32LE] offset from start of file (last entry is footer
     154 *     offset again)
     155 */
     156void BArchive::openArchive(const Common::String &path) {
     157        byte buf[4], crc, tmp;
     158        unsigned int i, j, footerOffset, offset;
     159        Common::File fr;
     160
     161        // free old memory
     162        closeArchive();
     163
     164        debugC(5, kDHDebugResource, "Opening file %s as Barchive:",
     165                path.c_str());
     166
     167        fr.open(path);
     168        if (fr.isOpen()) {
     169                debugC(5, kDHDebugResource, "OK");
     170        } else {
     171                debugC(5, kDHDebugResource, "Error");
     172                return;
     173        }
     174
     175        // read file header
     176        debugC(5, kDHDebugResource, "Checking signature:");
     177        fr.read(buf, 4);
     178        if (!memcmp(buf, _signature, 4)) {
     179                debugC(5, kDHDebugResource, "OK");
     180        } else {
     181                debugC(5, kDHDebugResource, "Error");
     182                fr.close();
     183                openDFW(path); // try DFW format instead
     184                return;
     185        }
     186
     187        _itemCount = fr.readUint16LE();
     188        footerOffset = fr.readUint32LE();
     189        debugC(5, kDHDebugResource, "Archive stats: %d files, %d data bytes total",
     190                _itemCount, footerOffset - _headerSize);
     191
     192        // read files in archive
     193        _rawData = new byte[footerOffset - _headerSize];
     194        _contents = new BAEntry[_itemCount];
     195
     196        fr.read(_rawData, footerOffset - _headerSize);
     197        Common::MemoryReadStream reader(_rawData, footerOffset - _headerSize);
     198
     199        for (i = 0; i < _itemCount; i++) {
     200                offset = fr.readUint32LE() - _headerSize;
     201                reader.seek(offset);
     202                reader.readUint16LE(); // compressed size, not used here
     203                _contents[i]._length = reader.readUint16LE();
     204                // compression type flag, must be 0.
     205                assert(!reader.readByte() && "Decompression not implemented!");
     206                crc = reader.readByte(); // CRC checksum of the file
     207
     208                _contents[i]._data = _rawData + offset + 6;
     209                _contents[i]._uncompressed = 0;
     210
     211                // CRC check
     212                for (tmp = 0, j = 0; j < _contents[i]._length; j++) {
     213                        tmp ^= _contents[i]._data[j];
     214                }
     215
     216                assert(tmp == crc && "CRC check failed");
     217        }
     218
     219        // last footer entry points back at the start of the footer.
     220        assert(fr.readUint32LE() == footerOffset && "Last footer entry doesn't "
     221                "match footer offset");
     222}
     223
     224/**
     225 * @brief Memory cleanup
     226 */
     227void BArchive::closeArchive(void) {
     228        unsigned int i;
     229
     230        if (!_contents) {
     231                return;
     232        }
     233
     234        for (i = 0; i < _itemCount; i++) {
     235                // _uncompressed == 0 means that _data points somewhere into _rawData
     236                // otherwise it's a buffer allocated separately
     237                if (_contents[i]._uncompressed) {
     238                        delete[] _contents[i]._data;
     239                }
     240        }
     241
     242        delete[] _contents;
     243        delete[] _rawData;
     244
     245        _contents = NULL;
     246        _rawData = NULL;
     247        _itemCount = 0;
     248}
     249
     250} // End of namespace DH
  • new file engines/dh/barchive.h

    diff --git a/engines/dh/barchive.h b/engines/dh/barchive.h
    new file mode 100644
    index 0000000..db7f1fb
    - +  
     1/* ScummVM - Graphic Adventure Engine
     2 *
     3 * ScummVM is the legal property of its developers, whose names
     4 * are too numerous to list here. Please refer to the COPYRIGHT
     5 * file distributed with this source distribution.
     6 *
     7 * This program is free software; you can redistribute it and/or
     8 * modify it under the terms of the GNU General Public License
     9 * as published by the Free Software Foundation; either version 2
     10 * of the License, or (at your option) any later version.
     11
     12 * This program is distributed in the hope that it will be useful,
     13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15 * GNU General Public License for more details.
     16
     17 * You should have received a copy of the GNU General Public License
     18 * along with this program; if not, write to the Free Software
     19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
     20 *
     21 * $URL$
     22 * $Id$
     23 *
     24 */
     25
     26#ifndef BARCHIVE_H
     27#define BARCHIVE_H
     28
     29#include "common/str.h"
     30
     31namespace DH {
     32
     33class BArchive {
     34public:
     35        struct BAEntry {
     36                unsigned int _length;
     37                const byte *_data;
     38                int _uncompressed; //!< whether data points into rawdata buffer
     39        };
     40
     41private:
     42        // file header data
     43        static const char _signature[];
     44        static const char _dfwSignature[];
     45        static const int _headerSize = 10;
     46        static const int _dfwHeaderSize = 6;
     47        static const int _dfwTableSize = 6;
     48
     49        BAEntry *_contents;
     50        unsigned char *_rawData; //!< raw data read from file, may be NULL
     51        unsigned int _itemCount; //!< size of _contents
     52
     53        void openDFW(const Common::String &path);
     54
     55public:
     56        BArchive() : _contents(NULL), _rawData(NULL), _itemCount(0) { }
     57        ~BArchive() { closeArchive(); }
     58
     59        void openArchive(const Common::String &path);
     60        void closeArchive(void);
     61
     62        const BAEntry *operator[](unsigned int i) const {
     63                return i < _itemCount ? _contents + i : NULL;
     64        }
     65
     66        unsigned int size() const { return _itemCount; }
     67};
     68
     69} // End of namespace DH
     70
     71#endif
  • new file engines/dh/detection.cpp

    diff --git a/engines/dh/detection.cpp b/engines/dh/detection.cpp
    new file mode 100644
    index 0000000..6ec1691
    - +  
     1/* ScummVM - Graphic Adventure Engine
     2 *
     3 * ScummVM is the legal property of its developers, whose names
     4 * are too numerous to list here. Please refer to the COPYRIGHT
     5 * file distributed with this source distribution.
     6 *
     7 * This program is free software; you can redistribute it and/or
     8 * modify it under the terms of the GNU General Public License
     9 * as published by the Free Software Foundation; either version 2
     10 * of the License, or (at your option) any later version.
     11
     12 * This program is distributed in the hope that it will be useful,
     13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15 * GNU General Public License for more details.
     16
     17 * You should have received a copy of the GNU General Public License
     18 * along with this program; if not, write to the Free Software
     19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
     20 *
     21 * $URL$
     22 * $Id$
     23 *
     24 */
     25
     26#include "dh/dh.h"
     27 
     28#include "base/plugins.h"
     29#include "engines/metaengine.h"
     30#include "engines/advancedDetector.h"
     31 
     32static const PlainGameDescriptor gameList[] = {
     33        { "dh", "Dragon History" },
     34        { 0, 0 }
     35};
     36
     37const ADGameDescription adGameDescs[] = {
     38        {
     39                "dh",
     40                0,
     41                {
     42                        {"HRA.DFW", 0, "a461d1b1ffbbeb8128bfbcb13e8aa406", -1},
     43                        {"INIT.DFW", 0, "9921c8f0045679a8f37eca8d41c5ec02", -1},
     44                        {NULL, 0, NULL, 0}
     45                },
     46                Common::CZ_CZE,
     47                Common::kPlatformPC,
     48                ADGF_NO_FLAGS
     49        },
     50
     51        {
     52                "dh",
     53                0,
     54                {
     55                        {"HRA.DFW", 0, "a461d1b1ffbbeb8128bfbcb13e8aa406", -1},
     56                        {"INIT.DFW", 0, "b890a5aeebaf16af39219cba2416b0a3", -1},
     57                        {NULL, 0, NULL, 0}
     58                },
     59                Common::EN_ANY,
     60                Common::kPlatformPC,
     61                ADGF_NO_FLAGS
     62        },
     63
     64        {
     65                "dh",
     66                0,
     67                {
     68                        {"HRA.DFW", 0, "a461d1b1ffbbeb8128bfbcb13e8aa406", -1},
     69                        {"INIT.DFW", 0, "76b9b78a8a8809a240acc395df4d0715", -1},
     70                        {NULL, 0, NULL, 0}
     71                },
     72                Common::PL_POL,
     73                Common::kPlatformPC,
     74                ADGF_NO_FLAGS
     75        },
     76
     77        AD_TABLE_END_MARKER
     78};
     79
     80const ADParams detectionParams = {
     81        // Pointer to ADGameDescription or its superset structure
     82        (const byte *)adGameDescs,
     83        // Size of that superset structure
     84        sizeof(ADGameDescription),
     85        // Number of bytes to compute MD5 sum for
     86        4096,
     87        // List of all engine targets
     88        gameList,
     89        // Structure for autoupgrading obsolete targets
     90        0,
     91        // Name of single gameid (optional)
     92        0,
     93        // List of files for file-based fallback detection (optional)
     94        0,
     95        // Flags
     96        0
     97};
     98
     99class DHMetaEngine : public AdvancedMetaEngine {
     100public:
     101        DHMetaEngine() : AdvancedMetaEngine(detectionParams) {}
     102
     103        virtual const char *getName() const {
     104                return "Dragon History game engine";
     105        }
     106
     107        virtual const char *getOriginalCopyright() const {
     108                return "Copyright (C) 1995 NoSense";
     109        }
     110
     111        virtual bool createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const;
     112        virtual bool hasFeature(MetaEngineFeature f) const;
     113        virtual SaveStateList listSaves(const char *target) const;
     114        virtual int getMaximumSaveSlot() const;
     115        virtual void removeSaveState(const char *target, int slot) const;
     116};
     117
     118bool DHMetaEngine::hasFeature(MetaEngineFeature f) const {
     119        return false;
     120/*
     121                (f == kSupportsListSaves) ||
     122                (f == kSupportsLoadingDuringStartup) ||
     123                (f == kSupportsDeleteSave);
     124*/
     125}
     126
     127bool DH::DHEngine::hasFeature(EngineFeature f) const {
     128        return false;
     129/*
     130                (f == kSupportsRTL) ||
     131                (f == kSupportsLoadingDuringRuntime) ||
     132                (f == kSupportsSavingDuringRuntime);
     133*/
     134}
     135
     136bool DHMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {
     137        if (desc) {
     138                *engine = new DH::DHEngine(syst, desc);
     139        }
     140        return desc != 0;
     141}
     142
     143SaveStateList DHMetaEngine::listSaves(const char *target) const {
     144
     145}
     146
     147int DHMetaEngine::getMaximumSaveSlot() const {
     148        return 0;
     149}
     150
     151void DHMetaEngine::removeSaveState(const char *target, int slot) const {
     152
     153}
     154
     155#if PLUGIN_ENABLED_DYNAMIC(DHE)
     156        REGISTER_PLUGIN_DYNAMIC(DHE, PLUGIN_TYPE_ENGINE, DHMetaEngine);
     157#else
     158        REGISTER_PLUGIN_STATIC(DHE, PLUGIN_TYPE_ENGINE, DHMetaEngine);
     159#endif
  • new file engines/dh/dh.cpp

    diff --git a/engines/dh/dh.cpp b/engines/dh/dh.cpp
    new file mode 100644
    index 0000000..02923e0
    - +  
     1/* ScummVM - Graphic Adventure Engine
     2 *
     3 * ScummVM is the legal property of its developers, whose names
     4 * are too numerous to list here. Please refer to the COPYRIGHT
     5 * file distributed with this source distribution.
     6 *
     7 * This program is free software; you can redistribute it and/or
     8 * modify it under the terms of the GNU General Public License
     9 * as published by the Free Software Foundation; either version 2
     10 * of the License, or (at your option) any later version.
     11
     12 * This program is distributed in the hope that it will be useful,
     13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15 * GNU General Public License for more details.
     16
     17 * You should have received a copy of the GNU General Public License
     18 * along with this program; if not, write to the Free Software
     19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
     20 *
     21 * $URL$
     22 * $Id$
     23 *
     24 */
     25
     26#include "common/scummsys.h"
     27#include "common/system.h"
     28 
     29#include "common/events.h" // for getEventManager()
     30#include "common/config-manager.h"
     31#include "common/file.h"
     32#include "common/fs.h"
     33 
     34#include "dh/dh.h"
     35#include "dh/barchive.h"
     36 
     37namespace DH {
     38 
     39DHEngine::DHEngine(OSystem *syst, const ADGameDescription *gameDesc)
     40 : Engine(syst) {
     41        // Put your engine in a sane state, but do nothing big yet;
     42        // in particular, do not load data from files; rather, if you
     43        // need to do such things, do them from init().
     44 
     45        // Do not initialize graphics here
     46 
     47        // However this is the place to specify all default directories
     48        //Common::File::addDefaultDirectory(_gameDataPath + "sound/");
     49 
     50        // Here is the right place to set up the engine specific debug levels
     51        Common::addDebugChannel(kDHDebugResource, "resource", "Resource management debug channel");
     52 
     53        // Don't forget to register your random source
     54        //syst->getEventManager()->registerRandomSource(_rnd, "dh");
     55}
     56 
     57DHEngine::~DHEngine() {
     58        // Dispose your resources here
     59 
     60        // Remove all of our debug levels here
     61        Common::clearAllDebugChannels();
     62}
     63 
     64int DHEngine::init() {
     65        // Initialize graphics using following:
     66        initGraphics(320, 200, false);
     67 
     68        return 0;
     69}
     70 
     71int DHEngine::go() {
     72        // Your main even loop should be (invoked from) here.
     73        //printf("DHEngine::go: Hello, World!\n");
     74 
     75        return 0;
     76}
     77
     78Common::Error DHEngine::run() {
     79        init();
     80        go();
     81        return Common::kNoError;
     82}
     83 
     84} // End of namespace DH
  • new file engines/dh/dh.h

    diff --git a/engines/dh/dh.h b/engines/dh/dh.h
    new file mode 100644
    index 0000000..3741b70
    - +  
     1/* ScummVM - Graphic Adventure Engine
     2 *
     3 * ScummVM is the legal property of its developers, whose names
     4 * are too numerous to list here. Please refer to the COPYRIGHT
     5 * file distributed with this source distribution.
     6 *
     7 * This program is free software; you can redistribute it and/or
     8 * modify it under the terms of the GNU General Public License
     9 * as published by the Free Software Foundation; either version 2
     10 * of the License, or (at your option) any later version.
     11
     12 * This program is distributed in the hope that it will be useful,
     13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15 * GNU General Public License for more details.
     16
     17 * You should have received a copy of the GNU General Public License
     18 * along with this program; if not, write to the Free Software
     19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
     20 *
     21 * $URL$
     22 * $Id$
     23 *
     24 */
     25
     26#ifndef DH_H
     27#define DH_H
     28
     29#include "common/scummsys.h"
     30
     31#include "engines/engine.h"
     32#include "engines/advancedDetector.h"
     33
     34namespace DH {
     35
     36class DHEngine : public Engine {
     37public:
     38        DHEngine(OSystem *syst, const ADGameDescription *gameDesc);
     39        ~DHEngine();
     40
     41        int init();
     42        int go();
     43        Common::Error run();
     44
     45        bool hasFeature(Engine::EngineFeature f) const;
     46};
     47
     48enum {
     49        kDHDebugResource = 1 << 0
     50};
     51
     52} // End of namespace DH
     53
     54#endif
  • new file engines/dh/module.mk

    diff --git a/engines/dh/module.mk b/engines/dh/module.mk
    new file mode 100644
    index 0000000..e05e580
    - +  
     1MODULE := engines/dh
     2 
     3MODULE_OBJS := \
     4        dh.o detection.o barchive.o
     5 
     6MODULE_DIRS += \
     7        engines/dh
     8 
     9# This module can be built as a plugin
     10ifeq ($(ENABLE_DHE), DYNAMIC_PLUGIN)
     11PLUGIN := 1
     12endif
     13 
     14# Include common rules
     15include $(srcdir)/rules.mk
  • engines/engines.mk

    diff --git a/engines/engines.mk b/engines/engines.mk
    index 8d7d8de..ca5acf8 100644
    a b ifdef ENABLE_TUCKER  
    141141DEFINES += -DENABLE_TUCKER=$(ENABLE_TUCKER)
    142142MODULES += engines/tucker
    143143endif
     144
     145ifdef ENABLE_DHE
     146DEFINES += -DENABLE_DHE=$(ENABLE_DHE)
     147MODULES += engines/dh
     148endif