aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--engines/glk/blorb.cpp251
-rw-r--r--engines/glk/blorb.h86
-rw-r--r--engines/glk/frotz/mem.cpp40
-rw-r--r--engines/glk/frotz/mem.h1
-rw-r--r--engines/glk/frotz/processor_streams.cpp4
-rw-r--r--engines/glk/glk.cpp32
-rw-r--r--engines/glk/glk.h2
-rw-r--r--engines/glk/glk_api.h2
8 files changed, 211 insertions, 207 deletions
diff --git a/engines/glk/blorb.cpp b/engines/glk/blorb.cpp
index ed730bfa8a..2a8ef45a85 100644
--- a/engines/glk/blorb.cpp
+++ b/engines/glk/blorb.cpp
@@ -54,7 +54,6 @@ struct giblorb_resdesc_struct {
*/
struct giblorb_map_struct {
glui32 inited; ///< holds giblorb_Inited_Magic if the map structure is valid
- Common::SeekableReadStream *file;
uint numchunks;
giblorb_chunkdesc_t *chunks; ///< list of chunk descriptors
@@ -66,13 +65,68 @@ struct giblorb_map_struct {
/*--------------------------------------------------------------------------*/
-giblorb_err_t Blorb::giblorb_initialize() {
- _file = nullptr;
- _map = nullptr;
- return giblorb_err_None;
+Blorb::Blorb(const Common::String &filename, InterpreterType interpType) :
+ Common::Archive(), _interpType(interpType), _map(nullptr) {
+ if (!_file.open(filename))
+ error("Could not open blorb file");
+
+ if (create_map() != giblorb_err_None)
+ error("Could not parse blorb file");
+}
+
+Blorb::~Blorb() {
+ for (uint ix = 0; ix < _map->numchunks; ix++) {
+ giblorb_chunkdesc_t *chu = &(_map->chunks[ix]);
+ if (chu->ptr) {
+ delete chu->ptr;
+ chu->ptr = nullptr;
+ }
+ }
+
+ if (_map->chunks) {
+ delete[] _map->chunks;
+ _map->chunks = nullptr;
+ }
+
+ _map->numchunks = 0;
+
+ if (_map->resources) {
+ delete[] _map->resources;
+ _map->resources = nullptr;
+ }
+
+ if (_map->ressorted) {
+ delete[] _map->ressorted;
+ _map->ressorted = nullptr;
+ }
+
+ _map->numresources = 0;
+ _map->inited = 0;
+
+ delete _map;
+}
+
+bool Blorb::hasFile(const Common::String &name) const {
+ return false;
+}
+
+int Blorb::listMatchingMembers(Common::ArchiveMemberList &list, const Common::String &pattern) const {
+ return 0;
+}
+
+int Blorb::listMembers(Common::ArchiveMemberList &list) const {
+ return 0;
}
-giblorb_err_t Blorb::giblorb_create_map(Common::SeekableReadStream *file, giblorb_map_t **newmap) {
+const Common::ArchiveMemberPtr Blorb::getMember(const Common::String &name) const {
+ return Common::ArchiveMemberPtr();
+}
+
+Common::SeekableReadStream *Blorb::createReadStreamForMember(const Common::String &name) const {
+ return nullptr;
+}
+
+giblorb_err_t Blorb::create_map() {
giblorb_err_t err;
giblorb_map_t *map;
glui32 readlen;
@@ -81,21 +135,12 @@ giblorb_err_t Blorb::giblorb_create_map(Common::SeekableReadStream *file, giblor
int chunks_size, numchunks;
char buffer[16];
- *newmap = nullptr;
-
- if (!_libInited) {
- err = giblorb_initialize();
- if (err)
- return err;
- _libInited = true;
- }
-
- /* First, chew through the file and index the chunks. */
- file->seek(0);
+ // First, chew through the file and index the chunks
+ _file.seek(0);
- readlen = file->read(buffer, 12);
+ readlen = _file.read(buffer, 12);
if (readlen != 12)
- return giblorb_err_Read;
+ return giblorb_err_Format;
if (READ_BE_INT32(buffer + 0) != giblorb_ID_FORM)
return giblorb_err_Format;
@@ -114,9 +159,9 @@ giblorb_err_t Blorb::giblorb_create_map(Common::SeekableReadStream *file, giblor
int chunum;
giblorb_chunkdesc_t *chu;
- file->seek(nextpos);
+ _file.seek(nextpos);
- readlen = file->read(buffer, 8);
+ readlen = _file.read(buffer, 8);
if (readlen != 8) {
delete[] chunks;
return giblorb_err_Read;
@@ -158,34 +203,29 @@ giblorb_err_t Blorb::giblorb_create_map(Common::SeekableReadStream *file, giblor
// The basic IFF structure seems to be ok, and we have a list of chunks.
// Now we allocate the map structure itself.
- map = new giblorb_map_t();
- if (!map) {
+ _map = new giblorb_map_t();
+ if (!_map) {
delete[] chunks;
return giblorb_err_Alloc;
}
- map->inited = giblorb_Inited_Magic;
- map->file = file;
- map->chunks = chunks;
- map->numchunks = numchunks;
- map->resources = nullptr;
- map->ressorted = nullptr;
- map->numresources = 0;
+ _map->inited = giblorb_Inited_Magic;
+ _map->chunks = chunks;
+ _map->numchunks = numchunks;
+ _map->resources = nullptr;
+ _map->ressorted = nullptr;
+ _map->numresources = 0;
// Now we do everything else involved in loading the Blorb file,
// such as building resource lists.
- err = giblorb_initialize_map(map);
- if (err) {
- giblorb_destroy_map(map);
+ err = initialize_map();
+ if (err)
return err;
- }
- *newmap = map;
return giblorb_err_None;
}
-
-giblorb_err_t Blorb::giblorb_initialize_map(giblorb_map_t *map) {
+giblorb_err_t Blorb::initialize_map() {
// It is important that the map structure be kept valid during this function.
// If this returns an error, giblorb_destroy_map() will be called.
uint ix, jx;
@@ -196,8 +236,8 @@ giblorb_err_t Blorb::giblorb_initialize_map(giblorb_map_t *map) {
glui32 numres;
int gotindex = false;
- for (ix = 0; ix<map->numchunks; ix++) {
- giblorb_chunkdesc_t *chu = &map->chunks[ix];
+ for (ix = 0; ix < _map->numchunks; ix++) {
+ giblorb_chunkdesc_t *chu = &_map->chunks[ix];
switch (chu->type) {
case giblorb_ID_RIdx:
@@ -205,7 +245,7 @@ giblorb_err_t Blorb::giblorb_initialize_map(giblorb_map_t *map) {
if (gotindex)
return giblorb_err_Format; // duplicate index chunk
- err = giblorb_load_chunk_by_number(map, giblorb_method_Memory, &chunkres, ix);
+ err = load_chunk_by_number(giblorb_method_Memory, &chunkres, ix);
if (err)
return err;
@@ -238,12 +278,12 @@ giblorb_err_t Blorb::giblorb_initialize_map(giblorb_map_t *map) {
res->resnum = READ_BE_INT32(ptr + jx * 12 + 8);
respos = READ_BE_INT32(ptr + jx * 12 + 12);
- while (ix2 < map->numchunks
- && map->chunks[ix2].startpos < respos)
+ while (ix2 < _map->numchunks
+ && _map->chunks[ix2].startpos < respos)
ix2++;
- if (ix2 >= map->numchunks
- || map->chunks[ix2].startpos != respos) {
+ if (ix2 >= _map->numchunks
+ || _map->chunks[ix2].startpos != respos) {
delete[] resources;
delete[] ressorted;
return giblorb_err_Format; // start pos does not match a real chunk
@@ -254,16 +294,16 @@ giblorb_err_t Blorb::giblorb_initialize_map(giblorb_map_t *map) {
ressorted[jx] = res;
}
- // Sort a resource list (actually a list of pointers to structures in map->resources.)
+ // Sort a resource list (actually a list of pointers to structures in _map->resources.)
// This makes it easy to find resources by usage and resource number.
- giblorb_qsort(ressorted, numres);
+ qsort(ressorted, numres);
- map->numresources = numres;
- map->resources = resources;
- map->ressorted = ressorted;
+ _map->numresources = numres;
+ _map->resources = resources;
+ _map->ressorted = ressorted;
}
- giblorb_unload_chunk(map, ix);
+ unload_chunk(ix);
gotindex = true;
break;
}
@@ -272,7 +312,7 @@ giblorb_err_t Blorb::giblorb_initialize_map(giblorb_map_t *map) {
return giblorb_err_None;
}
-void Blorb::giblorb_qsort(giblorb_resdesc_t **list, size_t len) {
+void Blorb::qsort(giblorb_resdesc_t **list, size_t len) {
int ix, jx, res;
giblorb_resdesc_t *tmpptr, *pivot;
@@ -306,12 +346,12 @@ void Blorb::giblorb_qsort(giblorb_resdesc_t **list, size_t len) {
}
ix++;
// Sort the halves.
- giblorb_qsort(list + 0, ix);
- giblorb_qsort(list + ix, len - ix);
+ qsort(list + 0, ix);
+ qsort(list + ix, len - ix);
}
}
-giblorb_resdesc_t *Blorb::giblorb_bsearch(giblorb_resdesc_t *sample,
+giblorb_resdesc_t *Blorb::bsearch(giblorb_resdesc_t *sample,
giblorb_resdesc_t **list, int len) {
int top, bot, val, res;
@@ -345,71 +385,31 @@ int Blorb::sortsplot(giblorb_resdesc_t *v1, giblorb_resdesc_t *v2) {
return 0;
}
-giblorb_err_t Blorb::giblorb_destroy_map(giblorb_map_t *map) {
- if (!map || !map->chunks || map->inited != giblorb_Inited_Magic)
- return giblorb_err_NotAMap;
-
- for (uint ix = 0; ix<map->numchunks; ix++) {
- giblorb_chunkdesc_t *chu = &(map->chunks[ix]);
- if (chu->ptr) {
- delete chu->ptr;
- chu->ptr = nullptr;
- }
- }
-
- if (map->chunks) {
- delete[] map->chunks;
- map->chunks = nullptr;
- }
-
- map->numchunks = 0;
-
- if (map->resources) {
- delete[] map->resources;
- map->resources = nullptr;
- }
-
- if (map->ressorted) {
- delete[] map->ressorted;
- map->ressorted = nullptr;
- }
-
- map->numresources = 0;
- map->file = nullptr;
- map->inited = 0;
-
- delete map;
-
- return giblorb_err_None;
-}
-
-giblorb_err_t Blorb::giblorb_load_chunk_by_type(giblorb_map_t *map,
- glui32 method, giblorb_result_t *res, glui32 chunktype, glui32 count) {
+giblorb_err_t Blorb::load_chunk_by_type(glui32 method, giblorb_result_t *res, glui32 chunktype, glui32 count) {
uint ix;
- for (ix = 0; ix < map->numchunks; ix++) {
- if (map->chunks[ix].type == chunktype) {
+ for (ix = 0; ix < _map->numchunks; ix++) {
+ if (_map->chunks[ix].type == chunktype) {
if (count == 0)
break;
count--;
}
}
- if (ix >= map->numchunks) {
+ if (ix >= _map->numchunks) {
return giblorb_err_NotFound;
}
- return giblorb_load_chunk_by_number(map, method, res, ix);
+ return load_chunk_by_number(method, res, ix);
}
-giblorb_err_t Blorb::giblorb_load_chunk_by_number(giblorb_map_t *map,
- glui32 method, giblorb_result_t *res, glui32 chunknum) {
+giblorb_err_t Blorb::load_chunk_by_number(glui32 method, giblorb_result_t *res, glui32 chunknum) {
giblorb_chunkdesc_t *chu;
- if (chunknum >= map->numchunks)
+ if (chunknum >= _map->numchunks)
return giblorb_err_NotFound;
- chu = &(map->chunks[chunknum]);
+ chu = &(_map->chunks[chunknum]);
switch (method) {
case giblorb_method_DontLoad:
@@ -428,9 +428,9 @@ giblorb_err_t Blorb::giblorb_load_chunk_by_number(giblorb_map_t *map,
if (!dat)
return giblorb_err_Alloc;
- map->file->seek(chu->datpos);
+ _file.seek(chu->datpos);
- readlen = map->file->read(dat, chu->len);
+ readlen = _file.read(dat, chu->len);
if (readlen != chu->len)
return giblorb_err_Read;
@@ -448,13 +448,13 @@ giblorb_err_t Blorb::giblorb_load_chunk_by_number(giblorb_map_t *map,
return giblorb_err_None;
}
-giblorb_err_t Blorb::giblorb_unload_chunk(giblorb_map_t *map, glui32 chunknum) {
+giblorb_err_t Blorb::unload_chunk(glui32 chunknum) {
giblorb_chunkdesc_t *chu;
- if (chunknum >= map->numchunks)
+ if (chunknum >= _map->numchunks)
return giblorb_err_NotFound;
- chu = &(map->chunks[chunknum]);
+ chu = &(_map->chunks[chunknum]);
if (chu->ptr) {
delete chu->ptr;
@@ -464,24 +464,22 @@ giblorb_err_t Blorb::giblorb_unload_chunk(giblorb_map_t *map, glui32 chunknum) {
return giblorb_err_None;
}
-giblorb_err_t Blorb::giblorb_load_resource(giblorb_map_t *map, glui32 method,
- giblorb_result_t *res, glui32 usage, glui32 resnum) {
+giblorb_err_t Blorb::load_resource(glui32 method, giblorb_result_t *res, glui32 usage, glui32 resnum) {
giblorb_resdesc_t sample;
giblorb_resdesc_t *found;
sample.usage = usage;
sample.resnum = resnum;
- found = giblorb_bsearch(&sample, map->ressorted, map->numresources);
+ found = bsearch(&sample, _map->ressorted, _map->numresources);
if (!found)
return giblorb_err_NotFound;
- return giblorb_load_chunk_by_number(map, method, res, found->chunknum);
+ return load_chunk_by_number(method, res, found->chunknum);
}
-giblorb_err_t Blorb::giblorb_count_resources(giblorb_map_t *map,
- glui32 usage, glui32 *num, glui32 *min, glui32 *max) {
+giblorb_err_t Blorb::count_resources(glui32 usage, glui32 *num, glui32 *min, glui32 *max) {
int ix;
int count;
glui32 val;
@@ -491,9 +489,9 @@ giblorb_err_t Blorb::giblorb_count_resources(giblorb_map_t *map,
minval = 0;
maxval = 0;
- for (ix = 0; ix<map->numresources; ix++) {
- if (map->resources[ix].usage == usage) {
- val = map->resources[ix].resnum;
+ for (ix = 0; ix<_map->numresources; ix++) {
+ if (_map->resources[ix].usage == usage) {
+ val = _map->resources[ix].resnum;
if (count == 0) {
count++;
minval = val;
@@ -519,25 +517,4 @@ giblorb_err_t Blorb::giblorb_count_resources(giblorb_map_t *map,
return giblorb_err_None;
}
-giblorb_err_t Blorb::giblorb_set_resource_map(Common::SeekableReadStream *file) {
- giblorb_err_t err;
-
- err = giblorb_create_map(file, &_map);
- if (err) {
- _map = nullptr;
- return err;
- }
-
- _file = file;
- return giblorb_err_None;
-}
-
-giblorb_map_t *Blorb::giblorb_get_resource_map(void) {
- return _map;
-}
-
-bool Blorb::giblorb_is_resource_map(void) const {
- return _map != nullptr;
-}
-
} // End of namespace Glk
diff --git a/engines/glk/blorb.h b/engines/glk/blorb.h
index ae9c5032fc..97fd520fcc 100644
--- a/engines/glk/blorb.h
+++ b/engines/glk/blorb.h
@@ -25,10 +25,11 @@
#include "glk/glk_types.h"
#include "glk/streams.h"
+#include "common/archive.h"
+#include "common/array.h"
namespace Glk {
-
/**
* Error type
*/
@@ -101,46 +102,81 @@ typedef struct giblorb_result_struct {
typedef struct giblorb_resdesc_struct giblorb_resdesc_t;
-class Blorb {
+/**
+ * Blorb file manager
+ */
+class Blorb : public Common::Archive {
private:
- bool _libInited;
- Common::SeekableReadStream *_file;
+ Common::File _file;
+ InterpreterType _interpType;
giblorb_map_t *_map;
private:
/**
- * Initializes Blorb
+ * Parses the Blorb file index to load in a list of the chunks
*/
- giblorb_err_t giblorb_initialize();
+ giblorb_err_t create_map();
- giblorb_err_t giblorb_initialize_map(giblorb_map_t *map);
- void giblorb_qsort(giblorb_resdesc_t **list, size_t len);
- giblorb_resdesc_t *giblorb_bsearch(giblorb_resdesc_t *sample,
- giblorb_resdesc_t **list, int len);
+ giblorb_err_t initialize_map();
+ void qsort(giblorb_resdesc_t **list, size_t len);
+ giblorb_resdesc_t *bsearch(giblorb_resdesc_t *sample, giblorb_resdesc_t **list, int len);
int sortsplot(giblorb_resdesc_t *v1, giblorb_resdesc_t *v2);
public:
/**
* Constructor
*/
- Blorb() : _libInited(false), _file(nullptr), _map(nullptr) {}
+ Blorb(const Common::String &filename, InterpreterType interpType);
- giblorb_err_t giblorb_set_resource_map(Common::SeekableReadStream *file);
- giblorb_map_t *giblorb_get_resource_map(void);
- bool giblorb_is_resource_map(void) const;
+ /**
+ * Destructor
+ */
+ ~Blorb();
+ /**
+ * Check if a member with the given name is present in the Archive.
+ * Patterns are not allowed, as this is meant to be a quick File::exists()
+ * replacement.
+ */
+ virtual bool hasFile(const Common::String &name) const override;
- giblorb_err_t giblorb_create_map(Common::SeekableReadStream *file, giblorb_map_t **newmap);
- giblorb_err_t giblorb_destroy_map(giblorb_map_t *map);
+ /**
+ * Add all members of the Archive matching the specified pattern to list.
+ * Must only append to list, and not remove elements from it.
+ *
+ * @return the number of members added to list
+ */
+ virtual int listMatchingMembers(Common::ArchiveMemberList &list, const Common::String &pattern) const override;
+
+ /**
+ * Add all members of the Archive to list.
+ * Must only append to list, and not remove elements from it.
+ *
+ * @return the number of names added to list
+ */
+ virtual int listMembers(Common::ArchiveMemberList &list) const override;
+
+ /**
+ * Returns a ArchiveMember representation of the given file.
+ */
+ virtual const Common::ArchiveMemberPtr getMember(const Common::String &name) const override;
+
+ /**
+ * Create a stream bound to a member with the specified name in the
+ * archive. If no member with this name exists, 0 is returned.
+ * @return the newly created input stream
+ */
+ virtual Common::SeekableReadStream *createReadStreamForMember(const Common::String &name) const override;
+public:
+ /**
+ * Get a pointer to the Blorb's resource map
+ */
+ giblorb_map_t *get_resource_map() const { return _map; }
- giblorb_err_t giblorb_load_chunk_by_type(giblorb_map_t *map,
- glui32 method, giblorb_result_t *res, glui32 chunktype, glui32 count);
- giblorb_err_t giblorb_load_chunk_by_number(giblorb_map_t *map,
- glui32 method, giblorb_result_t *res, glui32 chunknum);
- giblorb_err_t giblorb_unload_chunk(giblorb_map_t *map, glui32 chunknum);
+ giblorb_err_t load_chunk_by_type(glui32 method, giblorb_result_t *res, glui32 chunktype, glui32 count);
+ giblorb_err_t load_chunk_by_number(glui32 method, giblorb_result_t *res, glui32 chunknum);
+ giblorb_err_t unload_chunk(glui32 chunknum);
- giblorb_err_t giblorb_load_resource(giblorb_map_t *map, glui32 method,
- giblorb_result_t *res, glui32 usage, glui32 resnum);
- giblorb_err_t giblorb_count_resources(giblorb_map_t *map,
- glui32 usage, glui32 *num, glui32 *min, glui32 *max);
+ giblorb_err_t load_resource(glui32 method, giblorb_result_t *res, glui32 usage, glui32 resnum);
+ giblorb_err_t count_resources(glui32 usage, glui32 *num, glui32 *min, glui32 *max);
};
} // End of namespace Glk
diff --git a/engines/glk/frotz/mem.cpp b/engines/glk/frotz/mem.cpp
index 12e860add2..bec30b00f7 100644
--- a/engines/glk/frotz/mem.cpp
+++ b/engines/glk/frotz/mem.cpp
@@ -28,10 +28,9 @@
namespace Glk {
namespace Frotz {
-Mem::Mem() : story_fp(nullptr), blorb_ofs(0), blorb_len(0), story_size(0),
- first_undo(nullptr), last_undo(nullptr), curr_undo(nullptr),
- undo_mem(nullptr), prev_zmp(nullptr), undo_diff(nullptr),
- undo_count(0), reserve_mem(0) {
+Mem::Mem() : story_fp(nullptr), story_size(0), first_undo(nullptr), last_undo(nullptr),
+ curr_undo(nullptr), undo_mem(nullptr), zmp(nullptr), prev_zmp(nullptr),
+ undo_diff(nullptr), undo_count(0), reserve_mem(0) {
}
void Mem::initialize() {
@@ -60,32 +59,7 @@ void Mem::initialize() {
}
void Mem::initializeStoryFile() {
- Common::SeekableReadStream *f = story_fp;
- giblorb_map_t *map;
- giblorb_result_t res;
- uint32 magic;
-
- magic = f->readUint32BE();
-
- if (magic == MKTAG('F', 'O', 'R', 'M')) {
- if (g_vm->giblorb_set_resource_map(f))
- error("This Blorb file seems to be invalid.");
-
- map = g_vm->giblorb_get_resource_map();
-
- if (g_vm->giblorb_load_resource(map, giblorb_method_FilePos, &res, giblorb_ID_Exec, 0))
- error("This Blorb file does not contain an executable chunk.");
- if (res.chunktype != MKTAG('Z', 'C', 'O', 'D'))
- error("This Blorb file contains an executable chunk, but it is not a Z-code file.");
-
- blorb_ofs = res.data.startpos;
- blorb_len = res.length;
- } else {
- blorb_ofs = 0;
- blorb_len = f->size();
- }
-
- if (blorb_len < 64)
+ if (story_fp->size() < 64)
error("This file is too small to be a Z-code file.");
}
@@ -115,7 +89,7 @@ void Mem::initializeUndo() {
void Mem::loadGameHeader() {
// Load header
zmp = new byte[64];
- story_fp->seek(blorb_ofs);
+ story_fp->seek(0);
story_fp->read(zmp, 64);
Common::MemoryReadStream h(zmp, 64);
@@ -131,7 +105,7 @@ void Mem::loadGameHeader() {
story_size *= 2;
} else {
// Some old games lack the file size entry
- story_size = blorb_len;
+ story_size = story_fp->size();
}
}
@@ -254,8 +228,6 @@ void Mem::free_undo(int count) {
void Mem::reset_memory() {
story_fp = nullptr;
- blorb_ofs = 0;
- blorb_len = 0;
if (undo_mem) {
free_undo(undo_count);
diff --git a/engines/glk/frotz/mem.h b/engines/glk/frotz/mem.h
index d973890605..a632bc6e63 100644
--- a/engines/glk/frotz/mem.h
+++ b/engines/glk/frotz/mem.h
@@ -57,7 +57,6 @@ typedef undo_struct undo_t;
class Mem : public Header, public virtual UserOptions {
protected:
Common::SeekableReadStream *story_fp;
- uint blorb_ofs, blorb_len;
uint story_size;
byte *pcp;
byte *zmp;
diff --git a/engines/glk/frotz/processor_streams.cpp b/engines/glk/frotz/processor_streams.cpp
index cbef38aaa6..095ef247fd 100644
--- a/engines/glk/frotz/processor_streams.cpp
+++ b/engines/glk/frotz/processor_streams.cpp
@@ -519,7 +519,7 @@ void Processor::z_restart() {
seed_random(0);
if (!first_restart) {
- story_fp->seek(blorb_ofs);
+ story_fp->seek(0);
if (story_fp->read(zmp, h_dynamic_size) != h_dynamic_size)
error("Story file read error");
@@ -599,7 +599,7 @@ void Processor::z_verify() {
zword checksum = 0;
// Sum all bytes in story file except header bytes
- story_fp->seek(blorb_ofs + 64);
+ story_fp->seek(64);
for (uint i = 64; i < story_size; i++)
checksum += story_fp->readByte();
diff --git a/engines/glk/glk.cpp b/engines/glk/glk.cpp
index 0e44f04e51..c2a8264750 100644
--- a/engines/glk/glk.cpp
+++ b/engines/glk/glk.cpp
@@ -29,6 +29,7 @@
#include "graphics/scaler.h"
#include "graphics/thumbnail.h"
#include "glk/glk.h"
+#include "glk/blorb.h"
#include "glk/conf.h"
#include "glk/events.h"
#include "glk/picture.h"
@@ -42,14 +43,16 @@ namespace Glk {
GlkEngine *g_vm;
GlkEngine::GlkEngine(OSystem *syst, const GlkGameDescription &gameDesc) :
- _gameDescription(gameDesc), Engine(syst), _random("Glk"), _clipboard(nullptr),
- _conf(nullptr), _events(nullptr), _pictures(nullptr), _screen(nullptr),
- _selection(nullptr), _windows(nullptr), _copySelect(false), _terminated(false),
- gli_unregister_obj(nullptr), gli_register_arr(nullptr), gli_unregister_arr(nullptr) {
+ _gameDescription(gameDesc), Engine(syst), _random("Glk"), _blorb(nullptr),
+ _clipboard(nullptr), _conf(nullptr), _events(nullptr), _pictures(nullptr),
+ _screen(nullptr), _selection(nullptr), _windows(nullptr), _copySelect(false),
+ _terminated(false), gli_unregister_obj(nullptr), gli_register_arr(nullptr),
+ gli_unregister_arr(nullptr) {
g_vm = this;
}
GlkEngine::~GlkEngine() {
+ delete _blorb;
delete _clipboard;
delete _conf;
delete _events;
@@ -96,11 +99,26 @@ void GlkEngine::initGraphicsMode() {
}
Common::Error GlkEngine::run() {
+ Common::File f;
+ Common::String filename = getFilename();
+ if (!Common::File::exists(filename))
+ return Common::kNoGameDataFoundError;
+
initialize();
- Common::File f;
- if (f.open(getFilename()))
- runGame(&f);
+ if (filename.hasSuffixIgnoreCase(".blorb") || filename.hasSuffixIgnoreCase(".zblorb")) {
+ // Blorb archive
+ _blorb = new Blorb(filename, getInterpreterType());
+ SearchMan.add("blorb", _blorb, 99, false);
+
+ if (!f.open("EXEC", *_blorb))
+ return Common::kNoGameDataFoundError;
+ } else {
+ if (!f.open(filename))
+ return Common::kNoGameDataFoundError;
+ }
+
+ runGame(&f);
return Common::kNoError;
}
diff --git a/engines/glk/glk.h b/engines/glk/glk.h
index 50722ae8dc..af9a42ba43 100644
--- a/engines/glk/glk.h
+++ b/engines/glk/glk.h
@@ -35,6 +35,7 @@
namespace Glk {
class Clipboard;
+class Blorb;
class Conf;
class Events;
class Pictures;
@@ -93,6 +94,7 @@ protected:
*/
virtual void runGame(Common::SeekableReadStream *gameFile) = 0;
public:
+ Blorb *_blorb;
Clipboard *_clipboard;
Conf *_conf;
Events *_events;
diff --git a/engines/glk/glk_api.h b/engines/glk/glk_api.h
index 400f3c08cd..b625f69bf7 100644
--- a/engines/glk/glk_api.h
+++ b/engines/glk/glk_api.h
@@ -34,7 +34,7 @@ namespace Glk {
/**
* Implements the GLK interface
*/
-class GlkAPI : public GlkEngine, public Blorb {
+class GlkAPI : public GlkEngine {
private:
bool _gliFirstEvent;
unsigned char _charTolowerTable[256];