Skip to content

Commit

Permalink
GLK: FROTZ: Change Quetzal restoring to use new base Quetzal reader
Browse files Browse the repository at this point in the history
  • Loading branch information
dreammaster committed Jun 16, 2019
1 parent c405203 commit 3d299df
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 88 deletions.
102 changes: 38 additions & 64 deletions engines/glk/frotz/quetzal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -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;

Expand All @@ -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. ;)
Expand All @@ -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");
Expand All @@ -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;
}

Expand All @@ -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) {
Expand All @@ -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))
Expand All @@ -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) {
Expand All @@ -354,28 +332,27 @@ 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)) {
_storyFile->seek(0);

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;
Expand All @@ -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 {
Expand All @@ -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
}
}
Expand All @@ -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;
}
Expand All @@ -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
Expand Down
12 changes: 0 additions & 12 deletions engines/glk/frotz/quetzal.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,18 +38,6 @@ class Quetzal {
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
Expand Down
6 changes: 4 additions & 2 deletions engines/glk/quetzal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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);

Expand Down
40 changes: 30 additions & 10 deletions engines/glk/quetzal.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,35 +53,55 @@ class QuetzalReader {
/**
* 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:
Expand All @@ -106,12 +126,12 @@ class QuetzalReader {
/**
* 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()); }
};

/**
Expand Down

0 comments on commit 3d299df

Please sign in to comment.