mirror of
https://github.com/libretro/scummvm.git
synced 2024-12-14 05:38:56 +00:00
GLK: FROTZ: Change Quetzal restoring to use new base Quetzal reader
This commit is contained in:
parent
c405203cde
commit
3d299df773
@ -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;
|
||||
zbyte progress = GOT_NONE;
|
||||
int i, 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) {
|
||||
// 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;
|
||||
for (QuetzalReader::Iterator it = _reader.begin(); it != _reader.end(); ++it) {
|
||||
Common::SeekableReadStream *s = it.getStream();
|
||||
currlen = (*it)._size;
|
||||
|
||||
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) {
|
||||
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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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()); }
|
||||
};
|
||||
|
||||
/**
|
||||
|
Loading…
Reference in New Issue
Block a user