MACVENTURE: Add generic non-persistent container loading

This commit is contained in:
Borja Lorente 2016-06-15 00:21:57 +02:00
parent 9fc9e33981
commit 56e8ac873b
2 changed files with 60 additions and 64 deletions

View file

@ -26,6 +26,7 @@
#include "macventure/macventure.h" #include "macventure/macventure.h"
#include "common/file.h" #include "common/file.h"
#include "common/bitstream.h"
namespace MacVenture { namespace MacVenture {
@ -56,8 +57,8 @@ public:
_numObjs = dataLen / _lenObjs; _numObjs = dataLen / _lenObjs;
} }
else { else {
ContainerHeader subHead = _header & 0x7fffffff; _header &= 0x7fffffff;
_res->seek(subHead, SEEK_SET); _res->seek(_header, SEEK_SET);
_numObjs = _res->readUint16BE(); _numObjs = _res->readUint16BE();
for (int i = 0; i < 15; ++i) for (int i = 0; i < 15; ++i)
@ -66,71 +67,50 @@ public:
for (int i = 0; i < 16; ++i) for (int i = 0; i < 16; ++i)
_lens[i] = _res->readByte(); _lens[i] = _res->readByte();
ItemGroup group; // Read groups
for (int i = 0; i < _numObjs; ++i) { uint numGroups = _numObjs / 64;
uint32 bits; if ((_numObjs % 64) > 0)
if ((i & 0x37) == 0) { // It's the start of a group numGroups++;
// Place myself in the correct position to read group
_res->seek(subHead + (i >> 6) * 6 + 0x30, SEEK_SET);
_res->read(&bits, 3);
bits >>= 4;
_res->read(&group.offset, 3); // Read 3 bytes
group.offset >>= 4;
bits &= 7;
group.bitOffset = bits;
_res->seek(subHead + (bits >> 3), SEEK_SET);
}
// Workaround to implement peek for (uint i = 0; i < numGroups; ++i) {
// Read the value in 32 bits ItemGroup group;
uint32 v = (_res->readUint32BE() >> (16 - bits)) & 0xffff;
// Go back // Place myself in the correct position to read group
_res->seek(-4, SEEK_CUR); _res->seek(_header + (i * 6) + 0x30, SEEK_SET);
byte b1, b2, b3;
b1 = _res->readByte();
b2 = _res->readByte();
b3 = _res->readByte();
group.bitOffset = (b1 << 16) + (b2 << 8) + (b3 << 0);
// Look in the Huffman table b1 = _res->readByte();
int x; b2 = _res->readByte();
for (x = 0; x<16; x++) b3 = _res->readByte();
if (_huff[x] > v) break; group.offset = (b1 << 16) + (b2 << 8) + (b3 << 0);
// Bits that we need to read from the length table // Place the bit reader in the correct position
uint8 bitsToRead = _lens[x]; // group.bitOffset indicates the offset from the start of the subHeader
_res->seek(_header + (group.bitOffset >> 3), SEEK_SET);
bits += (bitsToRead & 0xf); Common::BitStream32BEMSB bitStream(_res);
if (bits & 0x10) { // Skip the last 3 bits that we couldn't skip with seek
bits &= 0xf; bitStream.skip(group.bitOffset & 7);
_res->seek(2, SEEK_CUR); for (uint j = 0; j < 64; ++j) {
} uint32 length = 0;
uint32 mask = bitStream.peekBits(16);
// We already have in bits the first 4 bits (97) // Look in the Huffman table
bitsToRead = bitsToRead >> 4; int x;
for (x = 0; x<16; x++)
// The actual length of the object if (_huff[x] > mask) break;
uint32 len = 0; // OK UNTIL HERE
if (bitsToRead) { // There may be a bug from this point forward, as the
// Peek 4 bytes // lengths do not seem to coincide
len = _res->readUint32BE(); length = bitStream.getBits(_lens[x]);
_res->seek(-4, SEEK_CUR);
group.lengths[j] = length;
bitsToRead--;
if (bitsToRead == 0) len = 0;
else len >>= (32 - bitsToRead) - bits;
len &= (1 << bitsToRead) - 1;
len |= 1 << bitsToRead;
if (bits & 0x10) {
bits &= 0xf;
_res->seek(2, SEEK_CUR);
}
}
group.lengths[(i & 0x3f)] = len;
if ((i & 0x37) == 0) {
_groups.push_back(group);
} }
_groups.push_back(group);
} }
} }
} }
@ -169,6 +149,19 @@ public:
return item; return item;
} }
/*
void seekBits(uint32 bitNum) {
uint bytes = bits / 8;
_remainderOffset = bits % 8;
_res->seek(bytes, SEEK_SET);
}
void readBits((void*)target, uint32 bitNum) {
// Skip the first _remainderOffset bits, read bitNum from that point
byte offset = 0xFF << _remainderOffset;
}*/
protected: protected:
uint _lenObjs; uint _lenObjs;
@ -183,6 +176,9 @@ protected:
Common::File _file; Common::File _file;
Common::SeekableReadStream *_res; Common::SeekableReadStream *_res;
// To be moved
//byte _remainderOffset;
}; };
/* /*

View file

@ -19,7 +19,7 @@ World::World(MacVentureEngine *engine, Common::MacResManager *resMan) {
_saveGame = new SaveGame(_engine, saveGameRes); _saveGame = new SaveGame(_engine, saveGameRes);
_objectConstants = new Container<uint16>("Shadowgate II/Shadow Object.TXT"); _objectConstants = new Container<uint16>("Shadowgate II/Shadow Graphic");
delete saveGameRes; delete saveGameRes;
saveGameFile.close(); saveGameFile.close();
@ -47,7 +47,7 @@ bool World::loadStartGameFileName() {
res->read(fileName, length); res->read(fileName, length);
fileName[length] = '\0'; fileName[length] = '\0';
_startGameFileName = Common::String(fileName, length); _startGameFileName = Common::String(fileName, length);
_startGameFileName.replace(_startGameFileName.end(), _startGameFileName.end(), ".TXT"); _startGameFileName.replace(_startGameFileName.end(), _startGameFileName.end(), ".bin");
return true; return true;
} }