aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--engines/glk/frotz/quetzal.cpp102
-rw-r--r--engines/glk/frotz/quetzal.h12
-rw-r--r--engines/glk/quetzal.cpp6
-rw-r--r--engines/glk/quetzal.h40
4 files changed, 72 insertions, 88 deletions
diff --git a/engines/glk/frotz/quetzal.cpp b/engines/glk/frotz/quetzal.cpp
index 0ae6d2f239..d12d41da88 100644
--- a/engines/glk/frotz/quetzal.cpp
+++ b/engines/glk/frotz/quetzal.cpp
@@ -172,47 +172,27 @@ bool Quetzal::save(Common::WriteStream *svf, Processor *proc, const Common::Stri
return true;
}
-int Quetzal::restore(Common::SeekableReadStream *svf, Processor *proc) {
+int Quetzal::restore(Common::SeekableReadStream *sv, Processor *proc) {
Processor &p = *proc;
- uint ifzslen, currlen, tmpl;
+ uint tmpl, currlen;
offset_t pc;
- zword i, tmpw;
+ zword tmpw;
int fatal = 0; // Set to -1 when errors must be fatal.
- zbyte skip, progress = GOT_NONE;
- int x, y;
-
- // Check it's really an `IFZS' file.
- tmpl = svf->readUint32BE();
- ifzslen = svf->readUint32BE();
- currlen = svf->readUint32BE();
- if (tmpl != ID_FORM || currlen != ID_IFZS) {
+ zbyte progress = GOT_NONE;
+ int i, x, y;
+
+ // Load the savefile for reading
+ if (!_reader.open(sv, ID_IFZS)) {
p.print_string("This is not a saved game file!\n");
return 0;
}
- if ((ifzslen & 1) || ifzslen<4)
- // Sanity checks
- return 0;
- ifzslen -= 4;
// Read each chunk and process it
- while (ifzslen > 0) {
- // Read chunk header
- if (ifzslen < 8)
- // Couldn't contain a chunk
- return 0;
-
- tmpl = svf->readUint32BE();
- currlen = svf->readUint32BE();
- ifzslen -= 8; // Reduce remaining by size of header
-
- // Handle chunk body
- if (ifzslen < currlen)
- // Chunk goes past EOF?!
- return 0;
- skip = currlen & 1;
- ifzslen -= currlen + (uint)skip;
-
- switch (tmpl) {
+ for (QuetzalReader::Iterator it = _reader.begin(); it != _reader.end(); ++it) {
+ Common::SeekableReadStream *s = it.getStream();
+ currlen = (*it)._size;
+
+ switch ((*it)._id) {
// `IFhd' header chunk; must be first in file
case ID_IFhd:
if (progress & GOT_HEADER) {
@@ -223,17 +203,17 @@ int Quetzal::restore(Common::SeekableReadStream *svf, Processor *proc) {
if (currlen < 13)
return fatal;
- tmpw = svf->readUint16BE();
+ tmpw = s->readUint16BE();
if (tmpw != p.h_release)
progress = GOT_ERROR;
- for (i = H_SERIAL; i < H_SERIAL + 6; ++i) {
- x = svf->readByte();
- if (x != p[i])
+ for (int idx = H_SERIAL; idx < H_SERIAL + 6; ++idx) {
+ x = s->readByte();
+ if (x != p[idx])
progress = GOT_ERROR;
}
- tmpw = svf->readUint16BE();
+ tmpw = s->readUint16BE();
if (tmpw != p.h_checksum)
progress = GOT_ERROR;
@@ -242,17 +222,15 @@ int Quetzal::restore(Common::SeekableReadStream *svf, Processor *proc) {
return fatal;
}
- x = svf->readByte();
+ x = s->readByte();
pc = (uint)x << 16;
- x = svf->readByte();
+ x = s->readByte();
pc |= (uint)x << 8;
- x = svf->readByte();
+ x = s->readByte();
pc |= (uint)x;
fatal = -1; // Setting PC means errors must be fatal
p.setPC(pc);
-
- svf->skip(currlen - 13); // Skip rest of chunk
break;
// `Stks' stacks chunk; restoring this is quite complex. ;)
@@ -273,8 +251,8 @@ int Quetzal::restore(Common::SeekableReadStream *svf, Processor *proc) {
if (currlen < 8)
return fatal;
- svf->skip(6);
- tmpw = svf->readUint16BE();
+ s->skip(6);
+ tmpw = s->readUint16BE();
if (tmpw > STACK_SIZE) {
p.print_string("Save-file has too much stack (and I can't cope).\n");
@@ -285,7 +263,7 @@ int Quetzal::restore(Common::SeekableReadStream *svf, Processor *proc) {
if (currlen < (uint)tmpw * 2)
return fatal;
for (i = 0; i < tmpw; ++i)
- *--p._sp = svf->readUint16BE();
+ *--p._sp = s->readUint16BE();
currlen -= tmpw * 2;
}
@@ -300,12 +278,12 @@ int Quetzal::restore(Common::SeekableReadStream *svf, Processor *proc) {
}
// Read PC, procedure flag and formal param count
- tmpl = svf->readUint32BE();
+ tmpl = s->readUint32BE();
y = (int)(tmpl & 0x0F); // Number of formals
tmpw = y << 8;
// Read result variable
- x = svf->readByte();
+ x = s->readByte();
// Check the procedure flag...
if (tmpl & 0x10) {
@@ -328,7 +306,7 @@ int Quetzal::restore(Common::SeekableReadStream *svf, Processor *proc) {
*--p._sp = (zword)(p._fp - p._stack - 1); // FP
// Read and process argument mask
- x = svf->readByte();
+ x = s->readByte();
++x; // Should now be a power of 2
for (i = 0; i<8; ++i)
if (x & (1 << i))
@@ -343,7 +321,7 @@ int Quetzal::restore(Common::SeekableReadStream *svf, Processor *proc) {
p._fp = p._sp; // FP for next frame
// Read amount of eval stack used
- tmpw = svf->readUint16BE();
+ tmpw = s->readUint16BE();
tmpw += y; // Amount of stack + number of locals
if (p._sp - p._stack <= tmpw) {
@@ -354,14 +332,13 @@ int Quetzal::restore(Common::SeekableReadStream *svf, Processor *proc) {
return fatal;
for (i = 0; i < tmpw; ++i)
- --*p._sp = svf->readUint16BE();
+ --*p._sp = s->readUint16BE();
currlen -= tmpw * 2;
}
// End of `Stks' processing...
break;
- // Any more special chunk types must go in HERE or ABOVE
// `CMem' compressed memory chunk; uncompress it
case ID_CMem:
if (!(progress & GOT_MEMORY)) {
@@ -369,13 +346,13 @@ int Quetzal::restore(Common::SeekableReadStream *svf, Processor *proc) {
i = 0; // Bytes written to data area
for (; currlen > 0; --currlen) {
- x = svf->readByte();
+ x = s->readByte();
if (x == 0) {
// Start of run
// Check for bogus run
if (currlen < 2) {
p.print_string("File contains bogus `CMem' chunk.\n");
- svf->skip(currlen);
+ s->skip(currlen);
currlen = 1;
i = 0xFFFF;
@@ -384,7 +361,7 @@ int Quetzal::restore(Common::SeekableReadStream *svf, Processor *proc) {
// Copy story file to memory during the run
--currlen;
- x = svf->readByte();
+ x = s->readByte();
for (; x >= 0 && i < p.h_dynamic_size; --x, ++i)
p[i] = _storyFile->readByte();
} else {
@@ -397,7 +374,7 @@ int Quetzal::restore(Common::SeekableReadStream *svf, Processor *proc) {
// Make sure we don't load too much
if (i > p.h_dynamic_size) {
p.print_string("warning: `CMem' chunk too long!\n");
- svf->skip(currlen);
+ s->skip(currlen);
break; // Keep going; there may be a `UMem' too
}
}
@@ -410,14 +387,14 @@ int Quetzal::restore(Common::SeekableReadStream *svf, Processor *proc) {
progress |= GOT_MEMORY; // Only if succeeded
break;
}
+ break;
- // fall through
-
+ // 'UMem' Uncompressed memory chunk
case ID_UMem:
if (!(progress & GOT_MEMORY)) {
// Must be exactly the right size
if (currlen == p.h_dynamic_size) {
- if (svf->read(p.zmp, currlen) == currlen) {
+ if (s->read(p.zmp, currlen) == currlen) {
progress |= GOT_MEMORY; // Only on success
break;
}
@@ -427,16 +404,13 @@ int Quetzal::restore(Common::SeekableReadStream *svf, Processor *proc) {
// Fall into default action (skip chunk) on errors
}
-
- // fall through
+ break;
default:
- svf->seek(currlen, SEEK_CUR); // Skip chunk
break;
}
- if (skip)
- svf->skip(1); // Skip pad byte
+ delete s;
}
// We've reached the end of the file. For the restoration to have been a
diff --git a/engines/glk/frotz/quetzal.h b/engines/glk/frotz/quetzal.h
index ce6b1bdcb2..ee3f3b3205 100644
--- a/engines/glk/frotz/quetzal.h
+++ b/engines/glk/frotz/quetzal.h
@@ -38,18 +38,6 @@ private:
QuetzalReader _reader;
QuetzalWriter _writer;
zword frames[STACK_SIZE / 4 + 1];
-/*
-private:
- void write_byte(zbyte b) { _out->writeByte(b); }
- void write_bytx(zword b) { _out->writeByte(b & 0xFF); }
- void write_word(zword w) { _out->writeUint16BE(w); }
- void write_long(uint l) { _out->writeUint32BE(l); }
- void write_run(zword run) { write_byte(0); write_byte(run); }
- void write_chnk(uint32 id, zword len) {
- _out->writeUint32BE(id);
- _out->writeUint32BE(len);
- }
- */
public:
/**
* Constructor
diff --git a/engines/glk/quetzal.cpp b/engines/glk/quetzal.cpp
index 4a3ea8b88e..fb2f70cb78 100644
--- a/engines/glk/quetzal.cpp
+++ b/engines/glk/quetzal.cpp
@@ -31,8 +31,10 @@ void QuetzalReader::clear() {
}
bool QuetzalReader::open(Common::SeekableReadStream *stream, uint32 formType) {
- _chunks.clear();
+ clear();
stream->seek(0);
+ _stream = stream;
+
if (stream->readUint32BE() != ID_FORM)
return false;
@@ -54,7 +56,7 @@ bool QuetzalReader::open(Common::SeekableReadStream *stream, uint32 formType) {
// Get in the chunk header
Chunk c;
c._id = stream->readUint32BE();
- c._size = stream->readUint32BE() - 8;
+ c._size = stream->readUint32BE();
c._offset = stream->pos();
_chunks.push_back(c);
diff --git a/engines/glk/quetzal.h b/engines/glk/quetzal.h
index 706fb9fe43..19dd9397a2 100644
--- a/engines/glk/quetzal.h
+++ b/engines/glk/quetzal.h
@@ -53,35 +53,55 @@ public:
/**
* Iterator for the chunks list
*/
- struct Iterator : public Chunk {
+ struct Iterator {
private:
Common::SeekableReadStream *_stream;
Common::Array<Chunk> &_chunks;
int _index;
- int _size;
public:
/**
* Constructor
*/
- Iterator(Common::SeekableReadStream *stream, Common::Array<Chunk> &chunks, int index, int size) :
- _stream(stream), _chunks(chunks), _index(index), _size(size) {}
+ Iterator(Common::SeekableReadStream *stream, Common::Array<Chunk> &chunks, int index) :
+ _stream(stream), _chunks(chunks), _index(index) {}
+
+ /**
+ * Deference
+ */
+ Chunk &operator*() const { return _chunks[_index]; }
/**
* Incrementer
*/
- Iterator &operator++() { ++_index; }
+ Iterator &operator++() {
+ ++_index;
+ return *this;
+ }
/**
* Decrementer
*/
- Iterator &operator--() { --_index; }
+ Iterator &operator--() {
+ --_index;
+ return *this;
+ }
+
+ /**
+ * Equality test
+ */
+ bool operator==(const Iterator &rhs) { return _index == rhs._index; }
+
+ /**
+ * Inequality test
+ */
+ bool operator!=(const Iterator &rhs) { return _index != rhs._index; }
/**
* Get a read stream for the contents of a chunk
*/
Common::SeekableReadStream *getStream() {
- _stream->seek(_offset);
- return _stream->readStream(_size);
+ _stream->seek(_chunks[_index]._offset);
+ return _stream->readStream(_chunks[_index]._size);
}
};
private:
@@ -106,12 +126,12 @@ public:
/**
* Return an iterator for the beginning of the chunks list
*/
- Iterator begin() { return Iterator(_stream, _chunks, 0, _chunks.size()); }
+ Iterator begin() { return Iterator(_stream, _chunks, 0); }
/**
* Return an iterator for the beginning of the chunks list
*/
- Iterator end() { return Iterator(_stream, _chunks, 0, _chunks.size()); }
+ Iterator end() { return Iterator(_stream, _chunks, _chunks.size()); }
};
/**