Merge pull request #447 from YakBizzarro/resource-enhance3

Enhance resource loading
This commit is contained in:
Einar Johan Trøan Sømåen 2011-12-30 09:30:23 -08:00
commit 1a0ed0c852
38 changed files with 841 additions and 787 deletions

View File

@ -30,7 +30,6 @@
#include "engines/grim/grim.h"
#include "engines/grim/bitmap.h"
#include "engines/grim/resource.h"
#include "engines/grim/lab.h"
#include "engines/grim/gfx_base.h"
namespace Grim {
@ -94,7 +93,7 @@ char *makeBitmapFromTile(char **bits, int width, int height, int bpp) {
#endif
BitmapData *BitmapData::getBitmapData(const Common::String &fname, const char *data, int len) {
BitmapData *BitmapData::getBitmapData(const Common::String &fname, Common::SeekableReadStream *data) {
Common::String str(fname);
if (_bitmaps && _bitmaps->contains(str)) {
BitmapData *b = (*_bitmaps)[str];
@ -102,7 +101,7 @@ BitmapData *BitmapData::getBitmapData(const Common::String &fname, const char *d
return b;
}
BitmapData *b = new BitmapData(fname, data, len);
BitmapData *b = new BitmapData(fname, data);
if (!_bitmaps) {
_bitmaps = new Common::HashMap<Common::String, BitmapData *>();
}
@ -110,52 +109,73 @@ BitmapData *BitmapData::getBitmapData(const Common::String &fname, const char *d
return b;
}
BitmapData::BitmapData(const Common::String &fname, const char *data, int len) {
BitmapData::BitmapData(const Common::String &fname, Common::SeekableReadStream *data) {
_fname = fname;
_refCount = 1;
if (len > 4 && memcmp(data, "\x1f\x8b\x08\0", 4) == 0) {
loadTile(data, len);
return;
} else if (len < 8 || memcmp(data, "BM F\0\0\0", 8) != 0) {
Debug::error(Debug::Bitmaps, "Invalid magic loading bitmap");
}
int codec = READ_LE_UINT32(data + 8);
// _paletteIncluded = READ_LE_UINT32(data + 12);
_numImages = READ_LE_UINT32(data + 16);
_x = READ_LE_UINT32(data + 20);
_y = READ_LE_UINT32(data + 24);
// _transparentColor = READ_LE_UINT32(data + 28);
_format = READ_LE_UINT32(data + 32);
_bpp = READ_LE_UINT32(data + 36);
// _blueBits = READ_LE_UINT32(data + 40);
// _greenBits = READ_LE_UINT32(data + 44);
// _redBits = READ_LE_UINT32(data + 48);
// _blueShift = READ_LE_UINT32(data + 52);
// _greenShift = READ_LE_UINT32(data + 56);
// _redShift = READ_LE_UINT32(data + 60);
_width = READ_LE_UINT32(data + 128);
_height = READ_LE_UINT32(data + 132);
uint32 tag = data->readUint32BE();
switch(tag) {
case(MKTAG('B','M',' ',' ')): //Grim bitmap
loadGrimBm(fname, data);
break;
case(MKTAG('\x1f','\x8b','\x08','\0')): //MI4 bitmap
loadTile(fname, data);
break;
default:
assert(false);
Debug::error(Debug::Bitmaps, "Invalid magic loading bitmap");
break;
}
delete data;
}
bool BitmapData::loadGrimBm(const Common::String &fname, Common::SeekableReadStream *data) {
uint32 tag2 = data->readUint32BE();
if(tag2 != (MKTAG('F','\0','\0','\0')))
return false;
int codec = data->readUint32LE();
data->readUint32LE(); //_paletteIncluded
_numImages = data->readUint32LE();
_x = data->readUint32LE();
_y = data->readUint32LE();
data->readUint32LE(); //_transparentColor
_format = data->readUint32LE();
_bpp = data->readUint32LE();
// _blueBits = data->readUint32LE();
// _greenBits = data->readUint32LE();
// _redBits = data->readUint32LE();
// _blueShift = data->readUint32LE();
// _greenShift = data->readUint32LE();
// _redShift = data->readUint32LE();
data->seek(128, SEEK_SET);
_width = data->readUint32LE();
_height = data->readUint32LE();
_colorFormat = BM_RGB565;
_hasTransparency = false;
_data = new char *[_numImages];
int pos = 0x88;
data->seek(0x80, SEEK_SET);
for (int i = 0; i < _numImages; i++) {
data->seek(8, SEEK_CUR);
_data[i] = new char[_bpp / 8 * _width * _height];
if (codec == 0) {
memcpy(_data[i], data + pos, _bpp / 8 * _width * _height);
pos += _bpp / 8 * _width * _height + 8;
uint32 dsize = _bpp / 8 * _width * _height;
data->read(_data[i], dsize);
} else if (codec == 3) {
int compressed_len = READ_LE_UINT32(data + pos);
bool success = decompress_codec3(data + pos + 4, _data[i], _bpp / 8 * _width * _height);
int compressed_len = data->readUint32LE();
char *compressed = new char[compressed_len];
data->read(compressed, compressed_len);
bool success = decompress_codec3(compressed, _data[i], _bpp / 8 * _width * _height);
delete[] compressed;
if (!success)
warning(".. when loading image %s.\n", fname.c_str());
char *temp = new char[_bpp / 8 * _width * _height];
memcpy(temp, _data[i], _bpp / 8 * _width * _height);
delete[] _data[i];
_data[i] = temp;
pos += compressed_len + 12;
}
else
Debug::error(Debug::Bitmaps, "Unknown image codec in BitmapData ctor!");
@ -174,6 +194,7 @@ BitmapData::BitmapData(const Common::String &fname, const char *data, int len) {
_texIds = NULL;
g_driver->createBitmap(this);
return true;
}
BitmapData::BitmapData(const char *data, int w, int h, int bpp, const char *fname) {
@ -225,14 +246,13 @@ BitmapData::~BitmapData() {
}
}
bool BitmapData::loadTile(const char *data, int len) {
bool BitmapData::loadTile(const Common::String &fname, Common::SeekableReadStream *data) {
#ifdef ENABLE_MONKEY4
_x = 0;
_y = 0;
_format = 1;
//warning("Loading TILE: %s",filename);
Common::MemoryReadStream stream((const byte *)data, len);
Common::SeekableReadStream *o = Common::wrapCompressedReadStream(&stream);
Common::SeekableReadStream *o = Common::wrapCompressedReadStream(data);
uint32 id, bmoffset;
id = o->readUint32LE();
@ -290,9 +310,9 @@ char *BitmapData::getImageData(int num) const {
// Bitmap
Bitmap::Bitmap(const Common::String &fname, const char *data, int len) :
Bitmap::Bitmap(const Common::String &fname, Common::SeekableReadStream *data) :
PoolObject<Bitmap, MKTAG('V', 'B', 'U', 'F')>() {
_data = BitmapData::getBitmapData(fname, data, len);
_data = BitmapData::getBitmapData(fname, data);
_x = _data->_x;
_y = _data->_y;
_currImage = 1;
@ -323,8 +343,8 @@ void Bitmap::restoreState(SaveGame *state) {
freeData();
Common::String fname = state->readString();
Block *b = g_resourceloader->getBlock(fname);
_data = BitmapData::getBitmapData(fname, b->getData(), b->getLen());
Common::SeekableReadStream *data = g_resourceloader->openNewStreamFile(fname.c_str(), true);
_data = BitmapData::getBitmapData(fname, data);
_currImage = state->readLESint32();
_x = state->readLESint32();

View File

@ -36,7 +36,7 @@ namespace Grim {
*/
class BitmapData {
public:
BitmapData(const Common::String &fname, const char *data, int len);
BitmapData(const Common::String &fname, Common::SeekableReadStream *data);
BitmapData(const char *data, int w, int h, int bpp, const char *fname);
BitmapData();
~BitmapData();
@ -47,9 +47,10 @@ public:
* @param data the data for the TILE.
* @param len the length of the data.
*/
bool loadTile(const char *data, int len);
bool loadTile(const Common::String &fname, Common::SeekableReadStream *data);
bool loadGrimBm(const Common::String &fname, Common::SeekableReadStream *data);
static BitmapData *getBitmapData(const Common::String &fname, const char *data, int len);
static BitmapData *getBitmapData(const Common::String &fname, Common::SeekableReadStream *data);
static Common::HashMap<Common::String, BitmapData *> *_bitmaps;
char *getImageData(int num) const;
@ -89,7 +90,7 @@ public:
* @param data the actual data to construct from
* @param len the length of the data
*/
Bitmap(const Common::String &filename, const char *data, int len);
Bitmap(const Common::String &filename, Common::SeekableReadStream *data);
Bitmap(const char *data, int width, int height, int bpp, const char *filename);
Bitmap();

View File

@ -26,11 +26,15 @@
namespace Grim {
// Load a colormap from the given data.
CMap::CMap(const Common::String &fileName, const char *data, int len) :
CMap::CMap(const Common::String &fileName, Common::SeekableReadStream *data) :
Object(), _fname(fileName) {
if (len < 4 || READ_BE_UINT32(data) != MKTAG('C','M','P',' '))
uint32 tag = data->readUint32BE();
if (tag != MKTAG('C','M','P',' '))
error("Invalid magic loading colormap");
memcpy(_colors, data + 64, sizeof(_colors));
data->seek(64, SEEK_SET);
data->read(_colors, sizeof(_colors));
delete data;
}
CMap::~CMap() {

View File

@ -25,12 +25,16 @@
#include "engines/grim/object.h"
namespace Common {
class SeekableReadStream;
}
namespace Grim {
class CMap : public Object {
public:
// Load a colormap from the given data.
CMap(const Common::String &fileName, const char *data, int len);
CMap(const Common::String &fileName, Common::SeekableReadStream *data);
~CMap();
const Common::String &getFilename() const { return _fname; }

View File

@ -104,19 +104,19 @@ namespace Grim {
// marked OBJSTATE_OVERLAY. So the BitmapComponent just needs to pass
// along setKey requests to the actual bitmap object.
Costume::Costume(const Common::String &fname, const char *data, int len, Costume *prevCost) :
Costume::Costume(const Common::String &fname, Common::SeekableReadStream *data, Costume *prevCost) :
Object(), _head(new Head()), _chores(NULL) {
_fname = fname;
_lookAtRate = 200;
_prevCostume = prevCost;
if (g_grim->getGameType() == GType_MONKEY4) {
Common::MemoryReadStream ms((const byte *)data, len);
loadEMI(ms, prevCost);
loadEMI(data, prevCost);
} else {
TextSplitter ts(data, len);
TextSplitter ts(data);
loadGRIM(ts, prevCost);
}
delete data;
}
void Costume::loadGRIM(TextSplitter &ts, Costume *prevCost) {
@ -205,34 +205,34 @@ void Costume::loadGRIM(TextSplitter &ts, Costume *prevCost) {
}
}
void Costume::loadEMI(Common::MemoryReadStream &ms, Costume *prevCost) {
void Costume::loadEMI(Common::SeekableReadStream *data, Costume *prevCost) {
Common::List<Component *>components;
_numChores = ms.readUint32LE();
_numChores = data->readUint32LE();
_chores = new Chore *[_numChores];
for (int i = 0; i < _numChores; i++) {
_chores[i] = new PoolChore();
uint32 nameLength;
Component *prevComponent = NULL;
nameLength = ms.readUint32LE();
ms.read(_chores[i]->_name, nameLength);
nameLength = data->readUint32LE();
data->read(_chores[i]->_name, nameLength);
float length;
ms.read(&length, 4);
data->read(&length, 4);
_chores[i]->_length = (int)length;
_chores[i]->_owner = this;
_chores[i]->_numTracks = ms.readUint32LE();
_chores[i]->_numTracks = data->readUint32LE();
_chores[i]->_tracks = new ChoreTrack[_chores[i]->_numTracks];
for (int k = 0; k < _chores[i]->_numTracks; k++) {
int componentNameLength = ms.readUint32LE();
int componentNameLength = data->readUint32LE();
assert(componentNameLength < 64);
char name[64];
ms.read(name, componentNameLength);
data->read(name, componentNameLength);
ms.readUint32LE();
int parentID = ms.readUint32LE();
data->readUint32LE();
int parentID = data->readUint32LE();
if (parentID == -1 && prevCost) {
MainModelComponent *mmc;
@ -256,15 +256,15 @@ void Costume::loadEMI(Common::MemoryReadStream &ms, Costume *prevCost) {
components.push_back(component);
ChoreTrack &track = _chores[i]->_tracks[k];
track.numKeys = ms.readUint32LE();
track.numKeys = data->readUint32LE();
track.keys = new TrackKey[track.numKeys];
// this is probably wrong
track.compID = 0;
for (int j = 0; j < track.numKeys; j++) {
float time, value;
ms.read(&time, 4);
ms.read(&value, 4);
data->read(&time, 4);
data->read(&value, 4);
track.keys[j].time = (int)time;
track.keys[j].value = (int)value;
}

View File

@ -44,10 +44,10 @@ class Head;
class Costume : public Object {
public:
Costume(const Common::String &filename, const char *data, int len, Costume *prevCost);
Costume(const Common::String &filename, Common::SeekableReadStream *data, Costume *prevCost);
void loadGRIM(TextSplitter &ts, Costume *prevCost);
void loadEMI(Common::MemoryReadStream &ms, Costume *prevCost);
void loadEMI(Common::SeekableReadStream *data, Costume *prevCost);
virtual ~Costume();

View File

@ -30,13 +30,12 @@
#include "engines/grim/colormap.h"
#include "engines/grim/resource.h"
#include "engines/grim/gfx_base.h"
#include "engines/grim/lab.h"
namespace Grim {
Font::Font(const Common::String &filename, const char *data, int len) :
Font::Font(const Common::String &filename, Common::SeekableReadStream *data) :
PoolObject<Font, MKTAG('F', 'O', 'N', 'T')>(), _userData(0) {
load(filename, data, len);
load(filename, data);
}
Font::Font() :
@ -53,55 +52,52 @@ Font::~Font() {
g_driver->destroyFont(this);
}
void Font::load(const Common::String &filename, const char *data, int len) {
void Font::load(const Common::String &filename, Common::SeekableReadStream *data) {
_filename = filename;
_numChars = READ_LE_UINT32(data);
_dataSize = READ_LE_UINT32(data + 4);
_height = READ_LE_UINT32(data + 8);
_baseOffsetY = READ_LE_UINT32(data + 12);
_firstChar = READ_LE_UINT32(data + 24);
_lastChar = READ_LE_UINT32(data + 28);
_numChars = data->readUint32LE();
_dataSize = data->readUint32LE();
_height = data->readUint32LE();
_baseOffsetY = data->readUint32LE();
data->seek(24, SEEK_SET);
_firstChar = data->readUint32LE();
_lastChar = data->readUint32LE();
int8 available_height = _height - _baseOffsetY;
data += 32;
// Read character indexes - are the key/value reversed?
_charIndex = new uint16[_numChars];
if (!_charIndex)
error("Could not load font %s. Out of memory", _filename.c_str());
for (uint i = 0; i < _numChars; ++i) {
_charIndex[i] = READ_LE_UINT16(data + 2 * i);
}
data += _numChars * 2;
for (uint i = 0; i < _numChars; ++i)
_charIndex[i] = data->readUint16LE();
// Read character headers
_charHeaders = new CharHeader[_numChars];
if (!_charHeaders)
error("Could not load font %s. Out of memory", _filename.c_str());
for (uint i = 0; i < _numChars; ++i) {
_charHeaders[i].offset = READ_LE_UINT32(data);
_charHeaders[i].width = *(int8 *)(data + 4);
_charHeaders[i].startingCol = *(int8 *)(data + 5);
_charHeaders[i].startingLine = *(int8 *)(data + 6);
_charHeaders[i].dataWidth = READ_LE_UINT32(data + 8);
_charHeaders[i].dataHeight = READ_LE_UINT32(data + 12);
_charHeaders[i].offset = data->readUint32LE();
_charHeaders[i].width = data->readSByte();
_charHeaders[i].startingCol = data->readSByte();
_charHeaders[i].startingLine = data->readSByte();
data->seek(1, SEEK_CUR);
_charHeaders[i].dataWidth = data->readUint32LE();
_charHeaders[i].dataHeight = data->readUint32LE();
int8 overflow = (_charHeaders[i].dataHeight + _charHeaders[i].startingLine) - available_height;
if (overflow > 0) {
warning("Font %s, char 0x%02x exceeds font height by %d, increasing font height", _filename.c_str(), i, overflow);
available_height += overflow;
_height += overflow;
}
data += 16;
}
// Read font data
_fontData = new byte[_dataSize];
if (!_fontData)
error("Could not load font %s. Out of memory", _filename.c_str());
memcpy(_fontData, data, _dataSize);
data->read(_fontData, _dataSize);
g_driver->createFont(this);
delete data;
}
uint16 Font::getCharIndex(unsigned char c) const {
@ -148,8 +144,10 @@ void Font::saveState(SaveGame *state) const {
void Font::restoreState(SaveGame *state) {
Common::String fname = state->readString();
Block *b = g_resourceloader->getBlock(fname);
load(fname, b->getData(), b->getLen());
Common::SeekableReadStream *stream;
stream = g_resourceloader->openNewStreamFile(fname.c_str(), true);
load(fname, stream);
}
// Hardcoded default font for GUI, etc

View File

@ -25,16 +25,20 @@
#include "engines/grim/pool.h"
namespace Common {
class SeekableReadStream;
}
namespace Grim {
class SaveGame;
class Font : public PoolObject<Font, MKTAG('F', 'O', 'N', 'T')> {
public:
Font(const Common::String &filename, const char *data, int len);
Font(const Common::String &filename, Common::SeekableReadStream *data);
Font();
~Font();
void load(const Common::String &filename, const char *data, int len);
void load(const Common::String &filename, Common::SeekableReadStream *data);
const Common::String &getFilename() const { return _filename; }
int32 getHeight() const { return _height; }

View File

@ -60,7 +60,6 @@
#include "engines/grim/resource.h"
#include "engines/grim/localize.h"
#include "engines/grim/gfx_base.h"
#include "engines/grim/lab.h"
#include "engines/grim/bitmap.h"
#include "engines/grim/font.h"
#include "engines/grim/primitives.h"
@ -959,11 +958,12 @@ Set *GrimEngine::loadSet(const Common::String &name) {
if (g_grim->getGameType() == GType_MONKEY4) {
filename += "b";
}
Block *b = g_resourceloader->getFileBlock(filename);
if (!b)
Common::SeekableReadStream *stream;
stream = g_resourceloader->openNewStreamFile(filename.c_str());
if(!stream)
warning("Could not find scene file %s", name.c_str());
s = new Set(name, b->getData(), b->getLen());
delete b;
s = new Set(name, stream);
}
return s;

View File

@ -43,18 +43,12 @@ McmpMgr::McmpMgr() {
}
McmpMgr::~McmpMgr() {
delete _file;
delete[] _compTable;
delete[] _compInput;
}
bool McmpMgr::openSound(const char *filename, byte **resPtr, int &offsetData) {
_file = g_resourceloader->openNewStreamFile(filename);
if (!_file) {
warning("McmpMgr::openSound() Can't open sound MCMP file: %s", filename);
return false;
}
bool McmpMgr::openSound(const char *filename, Common::SeekableReadStream *data, int &offsetData) {
_file = data;
uint32 tag = _file->readUint32BE();
if (tag != 'MCMP') {
@ -90,9 +84,8 @@ bool McmpMgr::openSound(const char *filename, byte **resPtr, int &offsetData) {
_file->seek(sizeCodecs, SEEK_CUR);
// hack: two more bytes at the end of input buffer
_compInput = new byte[maxSize + 2];
_file->read(_compInput, headerSize);
*resPtr = _compInput;
offsetData = headerSize;
return true;
}

View File

@ -49,7 +49,7 @@ public:
McmpMgr();
~McmpMgr();
bool openSound(const char *filename, byte **resPtr, int &offsetData);
bool openSound(const char *filename, Common::SeekableReadStream *data, int &offsetData);
int32 decompressSample(int32 offset, int32 size, byte **comp_final);
};

View File

@ -23,7 +23,6 @@
#include "common/endian.h"
#include "engines/grim/resource.h"
#include "engines/grim/lab.h"
#include "engines/grim/colormap.h"
#include "engines/grim/imuse/imuse_sndmgr.h"
@ -44,95 +43,109 @@ ImuseSndMgr::~ImuseSndMgr() {
}
}
void ImuseSndMgr::countElements(byte *ptr, int &numRegions, int &numJumps) {
void ImuseSndMgr::countElements(SoundDesc *sound) {
uint32 tag;
int32 size = 0;
uint32 pos = sound->inStream->pos();
do {
tag = READ_BE_UINT32(ptr); ptr += 4;
tag = sound->inStream->readUint32BE();
switch(tag) {
case MKTAG('T','E','X','T'):
case MKTAG('S','T','O','P'):
case MKTAG('F','R','M','T'):
case MKTAG('D','A','T','A'):
size = READ_BE_UINT32(ptr); ptr += size + 4;
size = sound->inStream->readUint32BE();
sound->inStream->seek(size, SEEK_CUR);
break;
case MKTAG('R','E','G','N'):
numRegions++;
size = READ_BE_UINT32(ptr); ptr += size + 4;
sound->numRegions++;
size = sound->inStream->readUint32BE();
sound->inStream->seek(size, SEEK_CUR);
break;
case MKTAG('J','U','M','P'):
numJumps++;
size = READ_BE_UINT32(ptr); ptr += size + 4;
sound->numJumps++;
size = sound->inStream->readUint32BE();
sound->inStream->seek(size, SEEK_CUR);
break;
case MKTAG('D','A','T','A'):
break;
default:
error("ImuseSndMgr::countElements() Unknown MAP tag '%s'", Common::tag2string(tag).c_str());
}
} while (tag != MKTAG('D','A','T','A'));
sound->inStream->seek(pos, SEEK_SET);
}
void ImuseSndMgr::parseSoundHeader(byte *ptr, SoundDesc *sound, int &headerSize) {
if (READ_BE_UINT32(ptr) == MKTAG('R','I','F','F')) {
void ImuseSndMgr::parseSoundHeader(SoundDesc *sound, int &headerSize) {
Common::SeekableReadStream *data = sound->inStream;
uint32 tag = data->readUint32BE();
if (tag == MKTAG('R','I','F','F')) {
sound->region = new Region[1];
sound->jump = new Jump[1];
sound->numJumps = 0;
sound->numRegions = 1;
sound->region[0].offset = 0;
sound->region[0].length = READ_LE_UINT32(ptr + 40);
sound->bits = *(ptr + 34);
sound->freq = READ_LE_UINT32(ptr + 24);
sound->channels = *(ptr + 22);
data->seek(18, SEEK_CUR);
sound->channels = data->readByte();
data->readByte();
sound->freq = data->readUint32LE();
data->seek(6, SEEK_CUR);
sound->bits = data->readByte();
data->seek(5, SEEK_CUR);
sound->region[0].length = data->readUint32LE();
headerSize = 44;
} else if (READ_BE_UINT32(ptr) == MKTAG('i','M','U','S')) {
uint32 tag;
} else if (tag == MKTAG('i','M','U','S')) {
int32 size = 0;
byte *s_ptr = ptr;
ptr += 16;
int32 headerStart = data->pos();
data->seek(12, SEEK_CUR);
int curIndexRegion = 0;
int curIndexJump = 0;
sound->numRegions = 0;
sound->numJumps = 0;
countElements(ptr, sound->numRegions, sound->numJumps);
countElements(sound);
sound->region = new Region [sound->numRegions];
sound->jump = new Jump [sound->numJumps];
do {
tag = READ_BE_UINT32(ptr); ptr += 4;
tag = data->readUint32BE();
switch(tag) {
case MKTAG('F','R','M','T'):
ptr += 12;
sound->bits = READ_BE_UINT32(ptr); ptr += 4;
sound->freq = READ_BE_UINT32(ptr); ptr += 4;
sound->channels = READ_BE_UINT32(ptr); ptr += 4;
data->seek(12, SEEK_CUR);
sound->bits = data->readUint32BE();
sound->freq = data->readUint32BE();
sound->channels = data->readUint32BE();
break;
case MKTAG('T','E','X','T'):
case MKTAG('S','T','O','P'):
size = READ_BE_UINT32(ptr); ptr += size + 4;
size = data->readUint32BE();
data->seek(size, SEEK_CUR);
break;
case MKTAG('R','E','G','N'):
ptr += 4;
sound->region[curIndexRegion].offset = READ_BE_UINT32(ptr); ptr += 4;
sound->region[curIndexRegion].length = READ_BE_UINT32(ptr); ptr += 4;
data->seek(4, SEEK_CUR);
sound->region[curIndexRegion].offset = data->readUint32BE();
sound->region[curIndexRegion].length = data->readUint32BE();
curIndexRegion++;
break;
case MKTAG('J','U','M','P'):
ptr += 4;
sound->jump[curIndexJump].offset = READ_BE_UINT32(ptr); ptr += 4;
sound->jump[curIndexJump].dest = READ_BE_UINT32(ptr); ptr += 4;
sound->jump[curIndexJump].hookId = READ_BE_UINT32(ptr); ptr += 4;
sound->jump[curIndexJump].fadeDelay = READ_BE_UINT32(ptr); ptr += 4;
data->seek(4, SEEK_CUR);
sound->jump[curIndexJump].offset = data->readUint32BE();
sound->jump[curIndexJump].dest = data->readUint32BE();
sound->jump[curIndexJump].hookId = data->readUint32BE();
sound->jump[curIndexJump].fadeDelay = data->readUint32BE();
curIndexJump++;
break;
case MKTAG('D','A','T','A'):
ptr += 4;
data->seek(4, SEEK_CUR);
break;
default:
error("ImuseSndMgr::prepareSound(%s) Unknown MAP tag '%s'", sound->name, Common::tag2string(tag).c_str());
}
} while (tag != MKTAG('D','A','T','A'));
headerSize = ptr - s_ptr;
headerSize = data->pos() - headerStart;
int i;
for (i = 0; i < sound->numRegions; i++) {
sound->region[i].offset -= headerSize;
@ -162,7 +175,6 @@ ImuseSndMgr::SoundDesc *ImuseSndMgr::openSound(const char *soundName, int volGro
s.toLowercase();
soundName = s.c_str();
const char *extension = soundName + strlen(soundName) - 3;
byte *ptr = NULL;
int headerSize = 0;
SoundDesc *sound = allocSlot();
@ -172,26 +184,26 @@ ImuseSndMgr::SoundDesc *ImuseSndMgr::openSound(const char *soundName, int volGro
strcpy(sound->name, soundName);
sound->volGroupId = volGroupId;
sound->inStream = NULL;
sound->inStream = g_resourceloader->openNewStreamFile(soundName);
if (!sound->inStream) {
closeSound(sound);
return NULL;
}
if (!_demo && scumm_stricmp(extension, "imu") == 0) {
sound->blockRes = g_resourceloader->getFileBlock(soundName);
if (sound->blockRes) {
ptr = (byte *)sound->blockRes->getData();
parseSoundHeader(ptr, sound, headerSize);
sound->mcmpData = false;
sound->resPtr = ptr + headerSize;
} else {
closeSound(sound);
return NULL;
}
parseSoundHeader(sound, headerSize);
sound->mcmpData = false;
sound->headerSize = headerSize;
} else if (scumm_stricmp(extension, "wav") == 0 || scumm_stricmp(extension, "imc") == 0 ||
(_demo && scumm_stricmp(extension, "imu") == 0)) {
sound->mcmpMgr = new McmpMgr();
if (!sound->mcmpMgr->openSound(soundName, &ptr, headerSize)) {
if (!sound->mcmpMgr->openSound(soundName, sound->inStream, headerSize)) {
closeSound(sound);
return NULL;
}
parseSoundHeader(ptr, sound, headerSize);
parseSoundHeader(sound, headerSize);
sound->mcmpData = true;
} else {
error("ImuseSndMgr::openSound() Unrecognized extension for sound file %s", soundName);
@ -208,11 +220,6 @@ void ImuseSndMgr::closeSound(SoundDesc *sound) {
sound->mcmpMgr = NULL;
}
if (sound->blockRes) {
delete sound->blockRes;
sound->blockRes = NULL;
}
if (sound->region) {
delete[] sound->region;
sound->region = NULL;
@ -223,6 +230,11 @@ void ImuseSndMgr::closeSound(SoundDesc *sound) {
sound->jump = NULL;
}
if (sound->inStream) {
delete sound->inStream;
sound->inStream = NULL;
}
memset(sound, 0, sizeof(SoundDesc));
}
@ -345,7 +357,8 @@ int32 ImuseSndMgr::getDataFromRegion(SoundDesc *sound, int region, byte **buf, i
size = sound->mcmpMgr->decompressSample(region_offset + offset, size, buf);
} else {
*buf = (byte *)malloc(sizeof(byte) * size);
memcpy(*buf, sound->resPtr + region_offset + offset, size);
sound->inStream->seek(region_offset + offset + sound->headerSize, SEEK_SET);
sound->inStream->read(*buf, size);
}
return size;

View File

@ -29,7 +29,6 @@
namespace Grim {
class McmpMgr;
class Block;
class ImuseSndMgr {
public:
@ -73,11 +72,11 @@ public:
bool inUse;
char name[32];
McmpMgr *mcmpMgr;
Block *blockRes;
int type;
int volGroupId;
byte *resPtr;
bool mcmpData;
uint32 headerSize;
Common::SeekableReadStream *inStream;
};
private:
@ -87,8 +86,8 @@ private:
bool checkForProperHandle(SoundDesc *soundDesc);
SoundDesc *allocSlot();
void parseSoundHeader(byte *ptr, SoundDesc *sound, int &headerSize);
void countElements(byte *ptr, int &numRegions, int &numJumps);
void parseSoundHeader(SoundDesc *sound, int &headerSize);
void countElements(SoundDesc *sound);
public:

View File

@ -33,58 +33,76 @@
namespace Grim {
KeyframeAnim::KeyframeAnim(const Common::String &fname, const char *data, int len) :
KeyframeAnim::KeyframeAnim(const Common::String &fname, Common::SeekableReadStream *data) :
Object(), _fname(fname) {
if (len >= 4 && READ_BE_UINT32(data) == MKTAG('F','Y','E','K'))
loadBinary(data, len);
uint32 tag = data->readUint32BE();
if (tag == MKTAG('F','Y','E','K'))
loadBinary(data);
else {
TextSplitter ts(data, len);
data->seek(0, SEEK_SET);
TextSplitter ts(data);
loadText(ts);
}
delete data;
}
void KeyframeAnim::loadBinary(const char *data, int len) {
void KeyframeAnim::loadBinary(Common::SeekableReadStream *data) {
// First four bytes are the FYEK Keyframe identifier code
// Next 36 bytes are the filename
Debug::debug(Debug::Keyframes, "Loading Keyframe '%s'.", _fname.c_str());
// Next four bytes are the flags
_flags = READ_LE_UINT32(data + 40);
data->seek(40, SEEK_SET);
_flags = data->readUint32LE();
// Next four bytes are a duplicate of _numJoints (?)
// Next four bytes are the type
_type = READ_LE_UINT32(data + 48);
data->readUint32LE();
_type = data->readUint32LE();
// Next four bytes are the frames per second
// The fps value seems to be ignored and causes the animation the first time manny
// enters the kitchen of the Blue Casket to go out of sync. So we force it to 15.
// _fps = get_float(data + 52);
_fps = 15.;
// Next four bytes are the number of frames
_numFrames = READ_LE_UINT32(data + 56);
data->seek(56, SEEK_SET);
_numFrames = data->readUint32LE();
// Next four bytes are the number of joints
_numJoints = READ_LE_UINT32(data + 60);
_numJoints = data->readUint32LE();
// Next four bytes are unknown (?)
// Next four bytes are the number of markers
_numMarkers = READ_LE_UINT32(data + 68);
data->readUint32LE();
_numMarkers = data->readUint32LE();
_markers = new Marker[_numMarkers];
data->seek(72, SEEK_SET);
for (int i = 0; i < _numMarkers; i++) {
_markers[i].frame = get_float(data + 72 + 4 * i);
_markers[i].val = READ_LE_UINT32(data + 104 + 4 * i);
char f[4];
data->read(f, 4);
_markers[i].frame = get_float(f);
}
data->seek(104, SEEK_SET);
for (int i = 0; i < _numMarkers; i++)
_markers[i].val = data->readUint32LE();
_nodes = new KeyframeNode *[_numJoints];
for (int i = 0; i < _numJoints; i++)
_nodes[i] = NULL;
const char *dataEnd = data + len;
// The first 136 bytes are for the header, this was originally
// listed as 180 bytes since the first operation is usually a
// "null" key, however ma_card_hold.key showed that this is
// not always the case so we should not skip this operation
data += 136;
while (data < dataEnd) {
data->seek(136, SEEK_SET);
for (int i = 0; i < _numJoints; i++) {
_nodes[i] = NULL;
int nodeNum;
// The first 32 bytes (of a keyframe) are the name handle
char nameHandle[32];
data->read(nameHandle, 32);
// If the name handle is entirely null (like ma_rest.key)
// then we shouldn't try to set the name
if(nameHandle[0] == 0)
memcpy(nameHandle, "(null)", 7);
// The next four bytes are the node number identifier
nodeNum = READ_LE_UINT32(data + 32);
nodeNum = data->readUint32LE();
// Because of the issue above ma_card_hold.key used to crash
// at this part without checking to make sure nodeNum is a
@ -97,11 +115,11 @@ void KeyframeAnim::loadBinary(const char *data, int len) {
}
if (_nodes[nodeNum]) {
// Null node. Usually 7, 13 and 27 are null nodes.
data += 44;
data->seek(8, SEEK_CUR);
continue;
}
_nodes[nodeNum] = new KeyframeNode;
_nodes[nodeNum]->loadBinary(data);
_nodes[nodeNum] = new KeyframeNode();
_nodes[nodeNum]->loadBinary(data, nameHandle);
}
}
@ -180,7 +198,7 @@ int KeyframeAnim::getMarker(float startTime, float stopTime) const {
return 0;
}
void KeyframeAnim::KeyframeEntry::loadBinary(const char *&data) {
void KeyframeAnim::KeyframeEntry::loadBinary(const char *data) {
_frame = get_float(data);
_flags = READ_LE_UINT32(data + 4);
_pos = Math::Vector3d::get_vector3d(data + 8);
@ -191,21 +209,19 @@ void KeyframeAnim::KeyframeEntry::loadBinary(const char *&data) {
_dpitch = get_float(data + 44);
_dyaw = get_float(data + 48);
_droll = get_float(data + 52);
data += 56;
}
void KeyframeAnim::KeyframeNode::loadBinary(const char *&data) {
// If the name handle is entirely null (like ma_rest.key)
// then we shouldn't try to set the name
if (READ_LE_UINT32(data) == 0)
memcpy(_meshName, "(null)", 7);
else
memcpy(_meshName, data, 32);
_numEntries = READ_LE_UINT32(data + 36);
data += 44;
void KeyframeAnim::KeyframeNode::loadBinary(Common::SeekableReadStream *data, char *meshName) {
memcpy(_meshName, meshName, 32);
_numEntries = data->readUint32LE();
data->seek(4, SEEK_CUR);
_entries = new KeyframeEntry[_numEntries];
for (int i = 0; i < _numEntries; i++)
_entries[i].loadBinary(data);
char kfEntry[56];
for (int i = 0; i < _numEntries; i++) {
data->read(kfEntry, 56);
_entries[i].loadBinary(kfEntry);
}
}
void KeyframeAnim::KeyframeNode::loadText(TextSplitter &ts) {

View File

@ -27,6 +27,10 @@
#include "engines/grim/object.h"
namespace Common {
class SeekableReadStream;
}
namespace Grim {
class ModelNode;
@ -34,10 +38,10 @@ class TextSplitter;
class KeyframeAnim : public Object {
public:
KeyframeAnim(const Common::String &filename, const char *data, int len);
KeyframeAnim(const Common::String &filename, Common::SeekableReadStream *data);
~KeyframeAnim();
void loadBinary(const char *data, int len);
void loadBinary(Common::SeekableReadStream *data);
void loadText(TextSplitter &ts);
bool animate(ModelNode *nodes, int num, float time, float fade, bool tagged) const;
int getMarker(float startTime, float stopTime) const;
@ -66,7 +70,7 @@ private:
Marker *_markers;
struct KeyframeEntry {
void loadBinary(const char *&data);
void loadBinary(const char *data);
float _frame;
int _flags;
@ -75,7 +79,7 @@ private:
};
struct KeyframeNode {
void loadBinary(const char *&data);
void loadBinary(Common::SeekableReadStream *data, char *meshName);
void loadText(TextSplitter &ts);
~KeyframeNode();

View File

@ -23,23 +23,51 @@
#include "common/endian.h"
#include "common/file.h"
#include "common/substream.h"
#include "common/memstream.h"
#include "engines/grim/grim.h"
#include "engines/grim/lab.h"
#include "engines/grim/lua/lua.h"
#include "engines/grim/colormap.h"
namespace Grim {
LabEntry::LabEntry()
: _name(Common::String()), _offset(0), _len(0), _parent(NULL) {
}
LabEntry::LabEntry(Common::String name, uint32 offset, uint32 len, Lab *parent)
: _offset(offset), _len(len), _parent(parent) {
_name = name;
_name.toLowercase();
}
Common::SeekableReadStream *LabEntry::createReadStream() const {
return _parent->createReadStreamForMember(_name);
}
bool Lab::open(const byte *memLab, const uint32 size) {
_f = new Common::MemoryReadStream(memLab, size);
_labFileName = "";
_memLab = memLab;
return loadLab();
}
bool Lab::open(const Common::String &filename) {
_labFileName = filename;
close();
_f = new Common::File();
if (!_f->open(filename))
Common::File *file = new Common::File();
if (!file->open(filename)) {
delete file;
return false;
}
_f = (Common::SeekableReadStream *)file;
return loadLab();
}
bool Lab::loadLab() {
if (_f->readUint32BE() != MKTAG('L','A','B','N')) {
close();
return false;
@ -71,12 +99,10 @@ void Lab::parseGrimFileTable() {
_f->readUint32LE();
Common::String fname = stringTable + fnameOffset;
fname.toLowercase();
LabEntry entry;
entry.offset = start;
entry.len = size;
_entries[fname] = entry;
LabEntry *entry = new LabEntry(fname, start, size, this);
_entries[fname] = LabEntryPtr(entry);
}
delete[] stringTable;
@ -111,84 +137,73 @@ void Lab::parseMonkey4FileTable() {
str[l] = '/';
}
Common::String fname = str;
fname.toLowercase();
LabEntry entry;
entry.offset = start;
entry.len = size;
_entries[fname] = entry;
LabEntry *entry = new LabEntry(fname, start, size, this);
_entries[fname] = LabEntryPtr(entry);
}
delete[] stringTable;
}
bool Lab::getFileExists(const Common::String &filename) const {
return _entries.contains(filename);
bool Lab::hasFile(const Common::String &filename) {
Common::String fname(filename);
fname.toLowercase();
return _entries.contains(fname);
}
bool Lab::isOpen() const {
return _f && _f->isOpen();
bool Lab::hasFile(const Common::String &filename) const {
Common::String fname(filename);
fname.toLowercase();
return _entries.contains(fname);
}
Block *Lab::getFileBlock(const Common::String &filename) const {
if (!getFileExists(filename))
int Lab::listMembers(Common::ArchiveMemberList &list) {
int count = 0;
for (LabMap::const_iterator i = _entries.begin(); i != _entries.end(); ++i) {
list.push_back(Common::ArchiveMemberList::value_type(i->_value));
++count;
}
return count;
}
Common::ArchiveMemberPtr Lab::getMember(const Common::String &name) {
if (!hasFile(name))
return Common::ArchiveMemberPtr();
Common::String fname(name);
fname.toLowercase();
return _entries[fname];
}
Common::SeekableReadStream *Lab::createReadStreamForMember(const Common::String &filename) const {
if (!hasFile(filename))
return 0;
const LabEntry &i = _entries[filename];
Common::String fname(filename);
fname.toLowercase();
LabEntryPtr i = _entries[fname];
_f->seek(i.offset, SEEK_SET);
char *data = new char[i.len];
_f->read(data, i.len);
return new Block(data, i.len);
}
LuaFile *Lab::openNewStreamLua(const Common::String &filename) const {
if (!getFileExists(filename))
return 0;
/*If the whole Lab has been loaded into ram, we return a MemoryReadStream
that map requested data directly, without copying them. Otherwise open a new
stream from disk.*/
if(_memLab)
return new Common::MemoryReadStream((_memLab + i->_offset), i->_len, DisposeAfterUse::NO);
Common::File *file = new Common::File();
file->open(_labFileName);
file->seek(_entries[filename].offset, SEEK_SET);
LuaFile *filehandle = new LuaFile();
filehandle->_in = file;
return filehandle;
}
Common::File *Lab::openNewStreamFile(const Common::String &filename) const {
if (!getFileExists(filename))
return 0;
Common::File *file = new Common::File();
file->open(_labFileName);
file->seek(_entries[filename].offset, SEEK_SET);
return file;
}
// SubStream, for usage with GZipReadStream
Common::SeekableReadStream *Lab::openNewSubStreamFile(const Common::String &filename) const {
if (!getFileExists(filename))
return 0;
Common::File *file = new Common::File();
file->open(_labFileName);
Common::SeekableSubReadStream *substream;
substream = new Common::SeekableSubReadStream(file, _entries[filename].offset, _entries[filename].offset + _entries[filename].len, DisposeAfterUse::YES );
return substream;
}
int Lab::getFileLength(const Common::String &filename) const {
if (!getFileExists(filename))
return -1;
return _entries[filename].len;
return new Common::SeekableSubReadStream(file, i->_offset, i->_offset + i->_len, DisposeAfterUse::YES );
}
void Lab::close() {
delete _f;
_f = NULL;
if(_memLab)
delete _memLab;
_entries.clear();
}

View File

@ -26,57 +26,53 @@
#include "common/hashmap.h"
#include "common/hash-str.h"
#include "common/str.h"
namespace Common {
class File;
}
#include "common/archive.h"
#include "common/file.h"
#include "common/types.h"
namespace Grim {
class LuaFile;
class Lab;
class Block {
class LabEntry : public Common::ArchiveMember {
Lab *_parent;
Common::String _name;
uint32 _offset, _len;
public:
Block(const char *dataPtr, int length) : _data(dataPtr), _len(length) {}
const char *getData() const { return _data; }
int getLen() const { return _len; }
~Block() { delete[] _data; }
private:
Block();
const char *_data;
int _len;
LabEntry();
LabEntry(Common::String name, uint32 offset, uint32 len, Lab *parent);
Common::String getName() const { return _name; }
Common::SeekableReadStream *createReadStream() const;
friend class Lab;
};
class Lab {
class Lab : public Common::Archive {
public:
Lab() : _f(NULL) { }
bool open(const Common::String &filename);
bool isOpen() const;
void close();
bool getFileExists(const Common::String &filename) const;
Block *getFileBlock(const Common::String &filename) const;
Common::File *openNewStreamFile(const Common::String &filename) const;
Common::SeekableReadStream *openNewSubStreamFile(const Common::String &filename) const;
LuaFile *openNewStreamLua(const Common::String &filename) const;
int getFileLength(const Common::String &filename) const;
Lab() : _f(NULL), _memLab(NULL) { }
~Lab() { close(); }
struct LabEntry {
int offset, len;
};
bool open(const Common::String &filename);
bool open(const byte *memLab, const uint32 size);
void close();
// Common::Archive implementation
virtual bool hasFile(const Common::String &name); //TODO: Remove at next scummvm sync
virtual bool hasFile(const Common::String &name) const;
virtual int listMembers(Common::ArchiveMemberList &list);
virtual Common::ArchiveMemberPtr getMember(const Common::String &name);
virtual Common::SeekableReadStream *createReadStreamForMember(const Common::String &name) const;
private:
bool loadLab();
void parseGrimFileTable();
void parseMonkey4FileTable();
Common::File *_f;
typedef Common::HashMap<Common::String, LabEntry, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> LabMap;
LabMap _entries;
Common::SeekableReadStream *_f;
const byte *_memLab;
Common::String _labFileName;
typedef Common::SharedPtr<LabEntry> LabEntryPtr;
typedef Common::HashMap<Common::String, LabEntryPtr, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> LabMap;
LabMap _entries;
};
} // end of namespace Grim

View File

@ -32,29 +32,29 @@ template class ObjectPtr<LipSync>;
// A new define that'll be around when theres a configure script :)
#undef DEBUG_VERBOSE
LipSync::LipSync(const Common::String &filename, const char *data, int len) :
LipSync::LipSync(const Common::String &filename, Common::SeekableReadStream *data) :
Object() {
_fname = filename;
uint16 readPhoneme;
int j;
if (READ_BE_UINT32(data) != MKTAG('L','I','P','!')) {
if (data->readUint32BE() != MKTAG('L','I','P','!')) {
error("Invalid file format in %s", _fname.c_str());
} else {
_numEntries = (len - 8) / 4;
_numEntries = (data->size() - 8) / 4;
// There are cases where the lipsync file has no entries
if (_numEntries == 0) {
_entries = NULL;
} else {
data += 8;
data->readUint32LE();
#ifdef DEBUG_VERBOSE
printf("Reading LipSync %s, %d entries\n", filename, _numEntries);
#endif
_entries = new LipEntry[_numEntries];
for (int i = 0; i < _numEntries; i++) {
_entries[i].frame = READ_LE_UINT16(data);
readPhoneme = READ_LE_UINT16(data + 2);
_entries[i].frame = data->readUint16LE();
readPhoneme = data->readUint16LE();
// Look for the animation corresponding to the phoneme
for (j = 0; j < _animTableSize; j++) {
@ -69,7 +69,6 @@ LipSync::LipSync(const Common::String &filename, const char *data, int len) :
_entries[i].anim = 1;
}
data += 4;
}
#ifdef DEBUG_VERBOSE
for (int j = 0; j < _numEntries; j++)
@ -77,6 +76,8 @@ LipSync::LipSync(const Common::String &filename, const char *data, int len) :
#endif
}
}
delete data;
}
LipSync::~LipSync() {

View File

@ -25,11 +25,15 @@
#include "engines/grim/object.h"
namespace Common {
class SeekableReadStream;
}
namespace Grim {
class LipSync : public Object {
public:
LipSync(const Common::String &filename, const char *data, int len);
LipSync(const Common::String &filename, Common::SeekableReadStream *data);
~LipSync();
struct LipEntry {

View File

@ -27,6 +27,7 @@
#include "engines/grim/localize.h"
#include "engines/grim/grim.h"
#include "engines/grim/colormap.h"
#include "engines/grim/resource.h"
namespace Grim {
@ -37,31 +38,24 @@ static int sortCallback(const void *entry1, const void *entry2) {
}
Localizer::Localizer() {
Common::File f;
const char *namesToTry[] = { "GRIM.TAB", "Grim.tab", "grim.tab" };
_data = 0;
if (g_grim->getGameFlags() & ADGF_DEMO || g_grim->getGameType() == GType_MONKEY4)
return;
for (unsigned i = 0; i < sizeof(namesToTry) / sizeof(namesToTry[0]); i++) {
f.open(namesToTry[i]);
if (f.isOpen())
break;
}
if (!f.isOpen()) {
Common::SeekableReadStream *f = g_resourceloader->openNewStreamFile("grim.tab");
if (!f) {
error("Localizer::Localizer: Unable to find localization information (grim.tab)");
return;
}
long filesize = f.size();
long filesize = f->size();
// Read in the data
_data = new char[filesize + 1];
f.read(_data, filesize);
f->read(_data, filesize);
_data[filesize] = '\0';
f.close();
delete f;
if (filesize < 4 || READ_BE_UINT32(_data) != MKTAG('R','C','N','E'))
error("Invalid magic reading grim.tab");

View File

@ -37,7 +37,6 @@
#include "engines/grim/grim.h"
#include "engines/grim/savegame.h"
#include "engines/grim/resource.h"
#include "engines/grim/lab.h"
#include "engines/grim/bitmap.h"
#include "engines/grim/font.h"
#include "engines/grim/set.h"
@ -288,9 +287,9 @@ void LuaBase::setMovieTime(float movieTime) {
}
int LuaBase::bundle_dofile(const char *filename) {
Block *b = g_resourceloader->getFileBlock(filename);
if (!b) {
delete b;
Common::SeekableReadStream *stream;
stream = g_resourceloader->openNewStreamFile(filename);
if (!stream) {
// Don't print warnings on Scripts\foo.lua,
// d:\grimFandango\Scripts\foo.lua
if (!strstr(filename, "Scripts\\"))
@ -299,8 +298,12 @@ int LuaBase::bundle_dofile(const char *filename) {
return 2;
}
int result = lua_dobuffer(const_cast<char *>(b->getData()), b->getLen(), const_cast<char *>(filename));
delete b;
int32 size = stream->size();
char *buffer = new char[size];
stream->read(buffer, size);
int result = lua_dobuffer(const_cast<char *>(buffer), size, const_cast<char *>(filename));
delete stream;
delete buffer;
return result;
}

View File

@ -34,38 +34,41 @@ namespace Grim {
Common::List<MaterialData *> *MaterialData::_materials = NULL;
MaterialData::MaterialData(const Common::String &filename, const char *data, int len, CMap *cmap) :
MaterialData::MaterialData(const Common::String &filename, Common::SeekableReadStream *data, CMap *cmap) :
_fname(filename), _cmap(cmap), _refCount(1) {
if (g_grim->getGameType() == GType_MONKEY4) {
initEMI(filename, data, len);
initEMI(filename, data);
} else {
initGrim(filename, data, len, cmap);
initGrim(filename, data, cmap);
}
}
void MaterialData::initGrim(const Common::String &filename, const char *data, int len, CMap *cmap) {
if (len < 4 || memcmp(data, "MAT ", 4) != 0)
error("invalid magic loading texture");
void MaterialData::initGrim(const Common::String &filename, Common::SeekableReadStream *data, CMap *cmap) {
uint32 tag = data->readUint32BE();
if (tag != MKTAG('M','A','T',' '))
error("invalid magic loading texture");
_numImages = READ_LE_UINT32(data + 12);
data->seek(12, SEEK_SET);
_numImages = data->readUint32LE();
_textures = new Texture[_numImages];
/* Discovered by diffing orange.mat with pink.mat and blue.mat .
* Actual meaning unknown, so I prefer to use it as an enum-ish
* at the moment, to detect unexpected values.
*/
uint32 offset = READ_LE_UINT32(data + 0x4c);
data->seek(0x4c, SEEK_SET);
uint32 offset = data->readUint32LE();
if (offset == 0x8)
data += 16;
offset = 16;
else if (offset != 0)
error("Unknown offset: %d", offset);
data += 60 + _numImages * 40;
data->seek(60 + _numImages * 40 + offset, SEEK_SET);
for (int i = 0; i < _numImages; ++i) {
Texture *t = _textures + i;
t->_width = READ_LE_UINT32(data);
t->_height = READ_LE_UINT32(data + 4);
t->_hasAlpha = READ_LE_UINT32(data + 8);
t->_width = data->readUint32LE();
t->_height = data->readUint32LE();
t->_hasAlpha = data->readUint32LE();
t->_texture = NULL;
t->_data = NULL;
if (t->_width == 0 || t->_height == 0) {
@ -74,18 +77,18 @@ void MaterialData::initGrim(const Common::String &filename, const char *data, in
break;
}
t->_data = new char[t->_width * t->_height];
memcpy(t->_data, data + 24, t->_width * t->_height);
data += 24 + t->_width * t->_height;
data->seek(12, SEEK_CUR);
data->read(t->_data, t->_width * t->_height);
}
delete data;
}
void MaterialData::initEMI(const Common::String &filename, const char *data, int len) {
void MaterialData::initEMI(const Common::String &filename, Common::SeekableReadStream *data) {
Common::Array<Common::String> texFileNames;
char *readFileName = new char[64];
if (filename.hasSuffix(".sur")) { // This expects that we want all the materials in the sur-file
TextSplitter *ts = new TextSplitter(data, len);
TextSplitter *ts = new TextSplitter(data);
ts->setLineNumber(1); // Skip copyright-line
ts->expectString("VERSION 1.0");
while(!ts->checkString("END_OF_SECTION")) {
@ -106,7 +109,9 @@ void MaterialData::initEMI(const Common::String &filename, const char *data, int
}
return; // Leave the rest till we have models to put materials on.
int format = data[1];
//TODO: The following code was written when data was a data buffer, instead a stream
//but it wasn't adapetd since there wasn't a way to check it
/*int format = data[1];
assert(format == 2); // Verify that we have uncompressed TGA (2)
data += 12;
_numImages = 1;
@ -117,7 +122,7 @@ void MaterialData::initEMI(const Common::String &filename, const char *data, int
int bpp = data[4];
assert(bpp == 24); // Assure we have 24 bpp
data += 6;
g_driver->createMaterial(_textures, data, 0);
g_driver->createMaterial(_textures, data, 0);*/
}
MaterialData::~MaterialData() {
@ -136,7 +141,7 @@ MaterialData::~MaterialData() {
delete[] _textures;
}
MaterialData *MaterialData::getMaterialData(const Common::String &filename, const char *data, int len, CMap *cmap) {
MaterialData *MaterialData::getMaterialData(const Common::String &filename, Common::SeekableReadStream *data, CMap *cmap) {
if (!_materials) {
_materials = new Common::List<MaterialData *>();
}
@ -149,14 +154,14 @@ MaterialData *MaterialData::getMaterialData(const Common::String &filename, cons
}
}
MaterialData *m = new MaterialData(filename, data, len, cmap);
MaterialData *m = new MaterialData(filename, data, cmap);
_materials->push_back(m);
return m;
}
Material::Material(const Common::String &filename, const char *data, int len, CMap *cmap) :
Material::Material(const Common::String &filename, Common::SeekableReadStream *data, CMap *cmap) :
Object(), _currImage(0) {
_data = MaterialData::getMaterialData(filename, data, len, cmap);
_data = MaterialData::getMaterialData(filename, data, cmap);
}
void Material::reload(CMap *cmap) {

View File

@ -40,10 +40,10 @@ public:
class MaterialData {
public:
MaterialData(const Common::String &filename, const char *data, int len, CMap *cmap);
MaterialData(const Common::String &filename, Common::SeekableReadStream *data, CMap *cmap);
~MaterialData();
static MaterialData *getMaterialData(const Common::String &filename, const char *data, int len, CMap *cmap);
static MaterialData *getMaterialData(const Common::String &filename, Common::SeekableReadStream *data, CMap *cmap);
static Common::List<MaterialData *> *_materials;
Common::String _fname;
@ -53,14 +53,14 @@ public:
int _refCount;
private:
void initGrim(const Common::String &filename, const char *data, int len, CMap *cmap);
void initEMI(const Common::String &filename, const char *data, int len);
void initGrim(const Common::String &filename, Common::SeekableReadStream *data, CMap *cmap);
void initEMI(const Common::String &filename, Common::SeekableReadStream *data);
};
class Material : public Object {
public:
// Load a texture from the given data.
Material(const Common::String &filename, const char *data, int len, CMap *cmap);
Material(const Common::String &filename, Common::SeekableReadStream *data, CMap *cmap);
void reload(CMap *cmap);
// Load this texture into the GL context

View File

@ -44,19 +44,20 @@ void Sprite::draw() const {
/**
* @class Model
*/
Model::Model(const Common::String &filename, const char *data, int len, CMap *cmap, Model *parent) :
Model::Model(const Common::String &filename, Common::SeekableReadStream *data, CMap *cmap, Model *parent) :
Object(), _parent(parent), _numMaterials(0), _numGeosets(0), _cmap(cmap) {
_fname = filename;
if (g_grim->getGameType() == GType_MONKEY4) {
Common::MemoryReadStream ms((const byte *)data, len);
loadEMI(ms);
} else if (len >= 4 && READ_BE_UINT32(data) == MKTAG('L','D','O','M'))
loadEMI(data);
} else if (data->readUint32BE() == MKTAG('L','D','O','M'))
loadBinary(data, cmap);
else {
TextSplitter ts(data, len);
data->seek(0, SEEK_SET);
TextSplitter ts(data);
loadText(&ts, cmap);
}
delete data;
Math::Vector3d max;
@ -107,65 +108,67 @@ Model::~Model() {
g_resourceloader->uncacheModel(this);
}
void Model::loadEMI(Common::MemoryReadStream &ms) {
void Model::loadEMI(Common::SeekableReadStream *data) {
char name[64];
int nameLength = ms.readUint32LE();
int nameLength = data->readUint32LE();
assert(nameLength < 64);
ms.read(name, nameLength);
data->read(name, nameLength);
// skip over some unkown floats
ms.seek(48, SEEK_CUR);
data->seek(48, SEEK_CUR);
_numMaterials = ms.readUint32LE();
_numMaterials = data->readUint32LE();
_materials = new Material*[_numMaterials];
_materialNames = new char[_numMaterials][32];
for (int i = 0; i < _numMaterials; i++) {
nameLength = ms.readUint32LE();
nameLength = data->readUint32LE();
assert(nameLength < 32);
ms.read(_materialNames[i], nameLength);
data->read(_materialNames[i], nameLength);
// I'm not sure what specialty mateials are, but they are handled differently.
if (memcmp(_materialNames[i], "specialty", 9) == 0) {
_materials[i] = 0;
} else {
loadMaterial(i, 0);
}
ms.seek(4, SEEK_CUR);
data->seek(4, SEEK_CUR);
}
ms.seek(4, SEEK_CUR);
data->seek(4, SEEK_CUR);
}
void Model::loadBinary(const char *&data, CMap *cmap) {
_numMaterials = READ_LE_UINT32(data + 4);
data += 8;
void Model::loadBinary(Common::SeekableReadStream *data, CMap *cmap) {
char v3[4 * 3], f[4];
_numMaterials = data->readUint32LE();
_materials = new Material*[_numMaterials];
_materialNames = new char[_numMaterials][32];
_materialsShared = new bool[_numMaterials];
for (int i = 0; i < _numMaterials; i++) {
strcpy(_materialNames[i], data);
data->read(_materialNames[i], 32);
_materialsShared[i] = false;
_materials[i] = NULL;
loadMaterial(i, cmap);
data += 32;
}
data += 32; // skip name
_numGeosets = READ_LE_UINT32(data + 4);
data += 8;
data->seek(32, SEEK_CUR); // skip name
data->seek(4, SEEK_CUR);
_numGeosets = data->readUint32LE();
_geosets = new Geoset[_numGeosets];
for (int i = 0; i < _numGeosets; i++)
_geosets[i].loadBinary(data, _materials);
_numHierNodes = READ_LE_UINT32(data + 4);
data += 8;
data->seek(4, SEEK_CUR);
_numHierNodes = data->readUint32LE();
_rootHierNode = new ModelNode[_numHierNodes];
for (int i = 0; i < _numHierNodes; i++) {
_rootHierNode[i].loadBinary(data, _rootHierNode, &_geosets[0]);
}
_radius = get_float(data);
_insertOffset = Math::Vector3d::get_vector3d(data + 40);
data->read(f, 4);
_radius = get_float(f);
data->seek(36, SEEK_CUR);
data->read(v3, 3 * 4);
_insertOffset = Math::Vector3d::get_vector3d(v3);
}
void Model::loadText(TextSplitter *ts, CMap *cmap) {
@ -309,9 +312,8 @@ Model::Geoset::~Geoset() {
delete[] _meshes;
}
void Model::Geoset::loadBinary(const char *&data, Material *materials[]) {
_numMeshes = READ_LE_UINT32(data);
data += 4;
void Model::Geoset::loadBinary(Common::SeekableReadStream *data, Material *materials[]) {
_numMeshes = data->readUint32LE();
_meshes = new Mesh[_numMeshes];
for (int i = 0; i < _numMeshes; i++)
_meshes[i].loadBinary(data, materials);
@ -340,38 +342,39 @@ MeshFace::~MeshFace() {
delete[] _texVertices;
}
int MeshFace::loadBinary(const char *&data, Material *materials[]) {
_type = READ_LE_UINT32(data + 4);
_geo = READ_LE_UINT32(data + 8);
_light = READ_LE_UINT32(data + 12);
_tex = READ_LE_UINT32(data + 16);
_numVertices = READ_LE_UINT32(data + 20);
int texPtr = READ_LE_UINT32(data + 28);
int materialPtr = READ_LE_UINT32(data + 32);
_extraLight = get_float(data + 48);
_normal = Math::Vector3d::get_vector3d(data + 64);
data += 76;
int MeshFace::loadBinary(Common::SeekableReadStream *data, Material *materials[]) {
char v3[4 * 3], f[4];
data->seek(4, SEEK_CUR);
_type = data->readUint32LE();
_geo = data->readUint32LE();
_light = data->readUint32LE();
_tex = data->readUint32LE();
_numVertices = data->readUint32LE();
data->seek(4, SEEK_CUR);
int texPtr = data->readUint32LE();
int materialPtr = data->readUint32LE();
data->seek(12, SEEK_CUR);
data->read(f, 4);
_extraLight = get_float(f);
data->seek(12, SEEK_CUR);
data->read(v3, 4 * 3);
_normal = Math::Vector3d::get_vector3d(v3);
_vertices = new int[_numVertices];
for (int i = 0; i < _numVertices; i++) {
_vertices[i] = READ_LE_UINT32(data);
data += 4;
}
for (int i = 0; i < _numVertices; i++)
_vertices[i] = data->readUint32LE();
if (texPtr == 0)
_texVertices = NULL;
else {
_texVertices = new int[_numVertices];
for (int i = 0; i < _numVertices; i++) {
_texVertices[i] = READ_LE_UINT32(data);
data += 4;
}
for (int i = 0; i < _numVertices; i++)
_texVertices[i] = data->readUint32LE();
}
if (materialPtr == 0)
_material = 0;
else {
_material = materials[READ_LE_UINT32(data)];
materialPtr = READ_LE_UINT32(data);
data += 4;
materialPtr = data->readUint32LE();
_material = materials[materialPtr];
}
return materialPtr;
}
@ -397,43 +400,46 @@ Mesh::~Mesh() {
delete[] _materialid;
}
void Mesh::loadBinary(const char *&data, Material *materials[]) {
memcpy(_name, data, 32);
_geometryMode = READ_LE_UINT32(data + 36);
_lightingMode = READ_LE_UINT32(data + 40);
_textureMode = READ_LE_UINT32(data + 44);
_numVertices = READ_LE_UINT32(data + 48);
_numTextureVerts = READ_LE_UINT32(data + 52);
_numFaces = READ_LE_UINT32(data + 56);
void Mesh::loadBinary(Common::SeekableReadStream *data, Material *materials[]) {
char f[4];
data->read(_name, 32);
data->seek(4, SEEK_CUR);
_geometryMode = data->readUint32LE();
_lightingMode = data->readUint32LE();
_textureMode = data->readUint32LE();
_numVertices = data->readUint32LE();
_numTextureVerts = data->readUint32LE();
_numFaces = data->readUint32LE();
_vertices = new float[3 * _numVertices];
_verticesI = new float[_numVertices];
_vertNormals = new float[3 * _numVertices];
_textureVerts = new float[2 * _numTextureVerts];
_faces = new MeshFace[_numFaces];
_materialid = new int[_numFaces];
data += 60;
for (int i = 0; i < 3 * _numVertices; i++) {
_vertices[i] = get_float(data);
data += 4;
data->read(f, 4);
_vertices[i] = get_float(f);
}
for (int i = 0; i < 2 * _numTextureVerts; i++) {
_textureVerts[i] = get_float(data);
data += 4;
data->read(f, 4);
_textureVerts[i] = get_float(f);
}
for (int i = 0; i < _numVertices; i++) {
_verticesI[i] = get_float(data);
data += 4;
data->read(f, 4);
_verticesI[i] = get_float(f);
}
data += _numVertices * 4;
data->seek(_numVertices * 4, SEEK_CUR);
for (int i = 0; i < _numFaces; i++)
_materialid[i] = _faces[i].loadBinary(data, materials);
for (int i = 0; i < 3 * _numVertices; i++) {
_vertNormals[i] = get_float(data);
data += 4;
data->read(f, 4);
_vertNormals[i] = get_float(f);
}
_shadow = READ_LE_UINT32(data);
_radius = get_float(data + 8);
data += 36;
_shadow = data->readUint32LE();
data->seek(4, SEEK_CUR);
data->read(f, 4);
_radius = get_float(f);
data->seek(24, SEEK_CUR);
}
void Mesh::loadText(TextSplitter *ts, Material* materials[]) {
@ -572,47 +578,53 @@ ModelNode::~ModelNode() {
}
}
void ModelNode::loadBinary(const char *&data, ModelNode *hierNodes, const Model::Geoset *g) {
memcpy(_name, data, 64);
_flags = READ_LE_UINT32(data + 64);
_type = READ_LE_UINT32(data + 72);
int meshNum = READ_LE_UINT32(data + 76);
void ModelNode::loadBinary(Common::SeekableReadStream *data, ModelNode *hierNodes, const Model::Geoset *g) {
char v3[4 * 3], f[4];
data->read(_name, 64);
_flags = data->readUint32LE();
data->seek(4, SEEK_CUR);
_type = data->readUint32LE();
int meshNum = data->readUint32LE();
if (meshNum < 0)
_mesh = NULL;
else
_mesh = g->_meshes + meshNum;
_depth = READ_LE_UINT32(data + 80);
int parentPtr = READ_LE_UINT32(data + 84);
_numChildren = READ_LE_UINT32(data + 88);
int childPtr = READ_LE_UINT32(data + 92);
int siblingPtr = READ_LE_UINT32(data + 96);
_pivot = Math::Vector3d::get_vector3d(data + 100);
_pos = Math::Vector3d::get_vector3d(data + 112);
_pitch = get_float(data + 124);
_yaw = get_float(data + 128);
_roll = get_float(data + 132);
_depth = data->readUint32LE();
int parentPtr = data->readUint32LE();
_numChildren = data->readUint32LE();
int childPtr = data->readUint32LE();
int siblingPtr = data->readUint32LE();
data->read(v3, 4 * 3);
_pivot = Math::Vector3d::get_vector3d(v3);
data->read(v3, 4 * 3);
_pos = Math::Vector3d::get_vector3d(v3);
data->read(f, 4);
_pitch = get_float(f);
data->read(f, 4);
_yaw = get_float(f);
data->read(f, 4);
_roll = get_float(f);
_animPos.set(0,0,0);
_animPitch = 0;
_animYaw = 0;
_animRoll = 0;
_sprite = NULL;
data += 184;
data->seek(48, SEEK_CUR);
if (parentPtr != 0) {
_parent = hierNodes + READ_LE_UINT32(data);
data += 4;
} else
if (parentPtr != 0)
_parent = hierNodes + data->readUint32LE();
else
_parent = NULL;
if (childPtr != 0) {
_child = hierNodes + READ_LE_UINT32(data);
data += 4;
} else
if (childPtr != 0)
_child = hierNodes + data->readUint32LE();
else
_child = NULL;
if (siblingPtr != 0) {
_sibling = hierNodes + READ_LE_UINT32(data);
data += 4;
} else
if (siblingPtr != 0)
_sibling = hierNodes + data->readUint32LE();
else
_sibling = NULL;
_meshVisible = true;

View File

@ -23,10 +23,13 @@
#ifndef GRIM_MODEL_H
#define GRIM_MODEL_H
#include "common/memstream.h"
#include "engines/grim/object.h"
#include "math/matrix4.h"
namespace Common {
class SeekableReadStream;
}
namespace Grim {
class TextSplitter;
@ -49,10 +52,10 @@ struct Sprite {
class Model : public Object {
public:
// Construct a 3D model from the given data.
Model(const Common::String &filename, const char *data, int len, CMap *cmap, Model *parent = NULL);
void loadBinary(const char *&data, CMap *cmap);
Model(const Common::String &filename, Common::SeekableReadStream *data, CMap *cmap, Model *parent = NULL);
void loadBinary(Common::SeekableReadStream *data, CMap *cmap);
void loadText(TextSplitter *ts, CMap *cmap);
void loadEMI(Common::MemoryReadStream &ms);
void loadEMI(Common::SeekableReadStream *data);
void reload(CMap *cmap);
void draw() const;
Material *findMaterial(const char *name, CMap *cmap) const;
@ -67,7 +70,7 @@ public:
//private:
struct Geoset {
void loadBinary(const char *&data, Material *materials[]);
void loadBinary(Common::SeekableReadStream *data, Material *materials[]);
void loadText(TextSplitter *ts, Material *materials[]);
void changeMaterials(Material *materials[]);
Geoset() : _numMeshes(0) { }
@ -96,7 +99,7 @@ public:
class MeshFace {
public:
int loadBinary(const char *&data, Material *materials[]);
int loadBinary(Common::SeekableReadStream *data, Material *materials[]);
void draw(float *vertices, float *vertNormals, float *textureVerts) const;
void changeMaterial(Material *material);
~MeshFace();
@ -111,7 +114,7 @@ public:
class Mesh {
public:
void loadBinary(const char *&data, Material *materials[]);
void loadBinary(Common::SeekableReadStream *data, Material *materials[]);
void loadText(TextSplitter *ts, Material *materials[]);
void changeMaterials(Material *materials[]);
void draw() const;
@ -142,7 +145,7 @@ class ModelNode {
public:
ModelNode() : _initialized(false) { }
~ModelNode();
void loadBinary(const char *&data, ModelNode *hierNodes, const Model::Geoset *g);
void loadBinary(Common::SeekableReadStream *data, ModelNode *hierNodes, const Model::Geoset *g);
void draw() const;
void getBoundingBox(int *x1, int *y1, int *x2, int *y2) const;
void addChild(ModelNode *child);

View File

@ -82,31 +82,31 @@ Math::Vector4d *readVector4d(Common::ReadStream &ms) {
vec4d->set(x,y,z,w);
return vec4d;
}
void EMIMeshFace::loadFace(Common::MemoryReadStream &ms) {
_flags = ms.readUint32LE();
_hasTexture = ms.readUint32LE();
void EMIMeshFace::loadFace(Common::SeekableReadStream *data) {
_flags = data->readUint32LE();
_hasTexture = data->readUint32LE();
if(_hasTexture > 1) {
warning("We have this many textures: %d", _hasTexture);
}
if(_hasTexture)
_texID = ms.readUint32LE();
_faceLength = ms.readUint32LE();
_texID = data->readUint32LE();
_faceLength = data->readUint32LE();
_faceLength = _faceLength / 3;
short x = 0, y = 0, z = 0;
_indexes = new Vector3int[_faceLength];
int j = 0;
for (int i = 0; i < _faceLength; i ++) {
ms.read((char *)&x, 2);
ms.read((char *)&y, 2);
ms.read((char *)&z, 2);
data->read((char *)&x, 2);
data->read((char *)&y, 2);
data->read((char *)&z, 2);
_indexes[j++].setVal(x,y,z);
}
}
void EMIModel::setTex(int index) {
_mats[index]->select();
}
}
// May be removed when I get through the conversion
void EMIMeshFace::render() {
@ -117,62 +117,61 @@ void EMIMeshFace::render() {
}
//glDrawElements(GL_TRIANGLES, _faceLength * 3, GL_UNSIGNED_INT, _indexes);
}
void EMIModel::loadMesh(Common::MemoryReadStream &ms) {
void EMIModel::loadMesh(Common::SeekableReadStream *data) {
int strLength = 0;
Common::String nameString = readLAString(ms);
Common::String nameString = readLAString(*data);
_sphereData = readVector4d(ms);
_sphereData = readVector4d(*data);
_boxData = readVector3d(ms);
_boxData2 = readVector3d(ms);
_boxData = readVector3d(*data);
_boxData2 = readVector3d(*data);
_numTexSets = ms.readUint32LE();
_setType = ms.readUint32LE();
_numTextures = ms.readUint32LE();
_numTexSets = data->readUint32LE();
_setType = data->readUint32LE();
_numTextures = data->readUint32LE();
_texNames = new Common::String[_numTextures];
for(int i = 0;i < _numTextures; i++) {
_texNames[i] = readLAString(ms);
_texNames[i] = readLAString(*data);
// Every texname seems to be followed by 4 0-bytes (Ref mk1.mesh,
// this is intentional)
ms.skip(4);
data->skip(4);
}
// 4 unknown bytes - usually with value 19
ms.skip(4);
data->skip(4);
_numVertices = ms.readUint32LE();
_numVertices = data->readUint32LE();
float x = 0, y = 0;
int r = 0, g = 0, b = 0, a = 0;
// Vertices
_vertices = readVector3d(ms, _numVertices);
_normals = readVector3d(ms, _numVertices);
_vertices = readVector3d(*data, _numVertices);
_normals = readVector3d(*data, _numVertices);
_colorMap = new EMIColormap[_numVertices];
for (int i = 0; i < _numVertices; ++i) {
_colorMap[i].r = ms.readByte();
_colorMap[i].g = ms.readByte();
_colorMap[i].b = ms.readByte();
_colorMap[i].a = ms.readByte();
_colorMap[i].r = data->readByte();
_colorMap[i].g = data->readByte();
_colorMap[i].b = data->readByte();
_colorMap[i].a = data->readByte();
}
_texVerts = readVector2d(ms, _numVertices);
_texVerts = readVector2d(*data, _numVertices);
// Faces
_numFaces = ms.readUint32LE();
_numFaces = data->readUint32LE();
_faces = new EMIMeshFace[_numFaces];
int faceLength = 0;
for(int j = 0;j < _numFaces; j++) {
_faces[j].setParent(this);
_faces[j].loadFace(ms);
_faces[j].loadFace(data);
}
int hasBones = ms.readUint32LE();
int hasBones = data->readUint32LE();
// TODO add in the bone-stuff, as well as the skeleton
//prepare(); // <- Initialize materials etc.
@ -200,9 +199,9 @@ void EMIModel::draw() {
}
}
EMIModel::EMIModel(const Common::String &filename, const char *data, int len, EMIModel *parent) {
Common::MemoryReadStream ms((const byte *)data, len);
loadMesh(ms);
EMIModel::EMIModel(const Common::String &filename, Common::SeekableReadStream *data, EMIModel *parent) {
loadMesh(data);
delete data;
}
} // end of namespace Grim

View File

@ -23,13 +23,16 @@
#ifndef GRIM_MODELEMI_H
#define GRIM_MODELEMI_H
#include "common/memstream.h"
#include "engines/grim/object.h"
#include "math/matrix4.h"
#include "math/vector2d.h"
#include "math/vector3d.h"
#include "math/vector4d.h"
namespace Common {
class SeekableReadStream;
}
namespace Grim {
class Material;
@ -54,7 +57,7 @@ public:
EMIModel *_parent;
EMIMeshFace() : _numFaces(0), _hasTexture(0), _texID(0), _flags(0) { }
void loadFace(Common::MemoryReadStream &ms);
void loadFace(Common::SeekableReadStream *data);
void setParent(EMIModel *m) { _parent = m; }
void render();
};
@ -86,9 +89,9 @@ public:
int _setType;
public:
EMIModel(const Common::String &filename, const char *data, int len, EMIModel *parent = NULL);
EMIModel(const Common::String &filename, Common::SeekableReadStream *data, EMIModel *parent = NULL);
void setTex(int index);
void loadMesh(Common::MemoryReadStream &ms);
void loadMesh(Common::SeekableReadStream *data);
void prepareForRender();
void prepare();
void draw();

View File

@ -42,7 +42,7 @@ SmushPlayer::SmushPlayer(bool demo) : MoviePlayer(), _demo(demo) {
bool SmushPlayer::loadFile(Common::String filename) {
if (!_demo)
return _videoDecoder->loadStream(g_resourceloader->openNewSubStreamFile(filename.c_str()));
return _videoDecoder->loadStream(g_resourceloader->openNewStreamFile(filename.c_str()));
else
return _videoDecoder->loadFile(filename);
}

View File

@ -36,65 +36,84 @@
#include "engines/grim/skeleton.h"
#include "engines/grim/inputdialog.h"
#include "engines/grim/debug.h"
#include "common/algorithm.h"
#include "gui/message.h"
namespace Grim {
ResourceLoader *g_resourceloader = NULL;
class LabListComperator {
const Common::String _labName;
public:
LabListComperator() {}
LabListComperator(const Common::String &ln) : _labName(ln) {}
bool operator()(const Common::ArchiveMemberPtr &l) {
return _labName.compareToIgnoreCase(l->getName()) == 0;
}
bool operator()(const Common::ArchiveMemberPtr &l, const Common::ArchiveMemberPtr &r) {
return (l->getName().compareToIgnoreCase(r->getName()) > 0);
}
};
ResourceLoader::ResourceLoader() {
int lab_counter = 0;
_cacheDirty = false;
_cacheMemorySize = 0;
Lab *l;
Common::ArchiveMemberList files;
SearchMan.listMatchingMembers(files, "*.lab");
SearchMan.listMatchingMembers(files, "*.m4b");
if (g_grim->getGameType() == GType_GRIM) {
if (g_grim->getGameFlags() & ADGF_DEMO) {
SearchMan.listMatchingMembers(files, "gfdemo01.lab");
SearchMan.listMatchingMembers(files, "grimdemo.mus");
SearchMan.listMatchingMembers(files, "sound001.lab");
SearchMan.listMatchingMembers(files, "voice001.lab");
} else {
SearchMan.listMatchingMembers(files, "data???.lab");
SearchMan.listMatchingMembers(files, "movie??.lab");
SearchMan.listMatchingMembers(files, "vox????.lab");
SearchMan.listMatchingMembers(files, "year?mus.lab");
SearchMan.listMatchingMembers(files, "local.lab");
SearchMan.listMatchingMembers(files, "credits.lab");
//Sort the archives in order to ensure that they are loaded with the correct order
Common::sort(files.begin(), files.end(), LabListComperator());
//Check the presence of datausr.lab and ask the user if he wants to load it.
//In this case put it in the top of the list
Common::ArchiveMemberList::iterator datausr_it = Common::find_if(files.begin(), files.end(), LabListComperator("datausr.lab"));
if (datausr_it != files.end()) {
Grim::InputDialog d("User-patch detected, the Residual-team\n provides no support for using such patches.\n Click OK to load, or Cancel\n to skip the patch.", "OK", false);
int res = d.runModal();
if (res == GUI::kMessageOK)
files.push_front(*datausr_it);
files.erase(datausr_it);
}
}
}
if (g_grim->getGameType() == GType_MONKEY4)
SearchMan.listMatchingMembers(files, "*.m4b");
if (files.empty())
error("Cannot find game data - check configuration file");
int priority = files.size();
for (Common::ArchiveMemberList::const_iterator x = files.begin(); x != files.end(); ++x) {
const Common::String filename = (*x)->getName();
l = new Lab();
Common::String filename = (*x)->getName();
filename.toLowercase();
if (l->open(filename)) {
if (filename.equalsIgnoreCase("datausr.lab")) {
Grim::InputDialog d("User-patch detected, the Residual-team\n provides no support for using such patches.\n Click OK to load, or Cancel\n to skip the patch.", "OK", false);
int res = d.runModal();
if (res) {
warning("Loading %s",filename.c_str());
_labs.push_front(l);
}
}
else if (filename.equalsIgnoreCase("data005.lab"))
_labs.push_front(l);
else
_labs.push_back(l);
lab_counter++;
} else {
l = new Lab();
if (l->open(filename))
_files.add(filename, l, priority--, true);
else
delete l;
}
}
files.clear();
if (g_grim->getGameFlags() & ADGF_DEMO) {
SearchMan.listMatchingMembers(files, "*.mus");
for (Common::ArchiveMemberList::const_iterator x = files.begin(); x != files.end(); ++x) {
const Common::String filename = (*x)->getName();
l = new Lab();
if (l->open(filename)) {
_labs.push_back(l);
lab_counter++;
} else {
delete l;
}
}
}
}
template<typename T>
@ -110,33 +129,25 @@ ResourceLoader::~ResourceLoader() {
for (Common::Array<ResourceCache>::iterator i = _cache.begin(); i != _cache.end(); ++i) {
ResourceCache &r = *i;
delete[] r.fname;
delete r.resPtr;
delete[] r.resPtr;
}
clearList(_labs);
clearList(_models);
clearList(_colormaps);
clearList(_keyframeAnims);
clearList(_lipsyncs);
}
const Lab *ResourceLoader::getLab(const Common::String &filename) const {
for (LabList::const_iterator i = _labs.begin(); i != _labs.end(); ++i)
if ((*i)->getFileExists(filename))
return *i;
return NULL;
}
static int sortCallback(const void *entry1, const void *entry2) {
return scumm_stricmp(((ResourceLoader::ResourceCache *)entry1)->fname, ((ResourceLoader::ResourceCache *)entry2)->fname);
}
Block *ResourceLoader::getFileFromCache(const Common::String &filename) {
Common::SeekableReadStream *ResourceLoader::getFileFromCache(const Common::String &filename) {
ResourceLoader::ResourceCache *entry = getEntryFromCache(filename);
if (entry)
return entry->resPtr;
else
if (!entry)
return NULL;
return new Common::MemoryReadStream(entry->resPtr, entry->len);
}
ResourceLoader::ResourceCache *ResourceLoader::getEntryFromCache(const Common::String &filename) {
@ -154,73 +165,50 @@ ResourceLoader::ResourceCache *ResourceLoader::getEntryFromCache(const Common::S
return (ResourceLoader::ResourceCache *)bsearch(&key, _cache.begin(), _cache.size(), sizeof(ResourceCache), sortCallback);
}
bool ResourceLoader::getFileExists(const Common::String &filename) const {
return getLab(filename) != NULL;
bool ResourceLoader::getFileExists(const Common::String &filename) {
return _files.hasFile(filename);
}
Block *ResourceLoader::getFileBlock(const Common::String &filename) const {
const Lab *l = getLab(filename);
if (!l)
return NULL;
else
return l->getFileBlock(filename);
}
Block *ResourceLoader::getBlock(const Common::String &filename) {
Common::String fname = filename;
fname.toLowercase();
Block *b = getFileFromCache(fname);
if (!b) {
b = getFileBlock(fname);
if (b) {
putIntoCache(fname, b);
}
}
return b;
}
LuaFile *ResourceLoader::openNewStreamLuaFile(const char *filename) const {
const Lab *l = getLab(filename);
if (!l)
return NULL;
else
return l->openNewStreamLua(filename);
}
Common::SeekableReadStream *ResourceLoader::openNewStreamFile(const char *filename) const {
const Lab *l = getLab(filename);
if (!l)
Common::SeekableReadStream *ResourceLoader::loadFile(Common::String &filename) {
if (_files.hasFile(filename))
return _files.createReadStreamForMember(filename);
else if (SearchMan.hasFile(filename))
return SearchMan.createReadStreamForMember(filename);
else
return l->openNewStreamFile(filename);
}
Common::SeekableReadStream *ResourceLoader::openNewSubStreamFile(const char *filename) const {
const Lab *l = getLab(filename);
if (!l)
return NULL;
else
return l->openNewSubStreamFile(filename);
}
int ResourceLoader::getFileLength(const char *filename) const {
const Lab *l = getLab(filename);
if (l)
return l->getFileLength(filename);
else
return 0;
Common::SeekableReadStream *ResourceLoader::openNewStreamFile(const char *filename, bool cache) {
Common::String fname = filename;
Common::SeekableReadStream *s;
fname.toLowercase();
if (cache) {
s = getFileFromCache(fname);
if (!s) {
s = loadFile(fname);
if (!s)
return NULL;
uint32 size = s->size();
byte *buf = new byte[size];
s->read(buf, size);
putIntoCache(fname, buf, size);
return new Common::MemoryReadStream(buf, size);
} else
return s;
}
return loadFile(fname);
}
void ResourceLoader::putIntoCache(const Common::String &fname, Block *res) {
void ResourceLoader::putIntoCache(const Common::String &fname, byte *res, uint32 len) {
ResourceCache entry;
entry.resPtr = res;
entry.len = len;
entry.fname = new char[fname.size() + 1];
strcpy(entry.fname, fname.c_str());
_cacheMemorySize += res->getLen();
_cacheMemorySize += len;
_cache.push_back(entry);
_cacheDirty = true;
}
@ -228,32 +216,25 @@ void ResourceLoader::putIntoCache(const Common::String &fname, Block *res) {
Bitmap *ResourceLoader::loadBitmap(const Common::String &filename) {
Common::String fname = filename;
fname.toLowercase();
Block *b = getFileFromCache(fname);
if (!b) {
b = getFileBlock(fname);
if (!b) { // Grim sometimes asks for non-existant bitmaps (eg, ha_overhead)
warning("Could not find bitmap %s", filename.c_str());
return NULL;
}
putIntoCache(fname, b);
Common::SeekableReadStream *stream = openNewStreamFile(fname.c_str(), true);
if (!stream) { // Grim sometimes asks for non-existant bitmaps (eg, ha_overhead)
warning("Could not find bitmap %s", filename.c_str());
return NULL;
}
Bitmap *result = new Bitmap(filename, b->getData(), b->getLen());
Bitmap *result = new Bitmap(filename, stream);
return result;
}
CMap *ResourceLoader::loadColormap(const Common::String &filename) {
Block *b = getFileFromCache(filename);
if (!b) {
b = getFileBlock(filename);
if (!b) {
error("Could not find colormap %s", filename.c_str());
}
putIntoCache(filename, b);
Common::SeekableReadStream *stream = openNewStreamFile(filename.c_str());
if (!stream) {
error("Could not find colormap %s", filename.c_str());
}
CMap *result = new CMap(filename, b->getData(), b->getLen());
CMap *result = new CMap(filename, stream);
_colormaps.push_back(result);
return result;
@ -278,42 +259,37 @@ static Common::String fixFilename(const Common::String filename, bool append = t
Costume *ResourceLoader::loadCostume(const Common::String &filename, Costume *prevCost) {
Common::String fname = fixFilename(filename);
fname.toLowercase();
Block *b = getFileFromCache(fname);
if (!b) {
b = getFileBlock(fname);
if (!b)
error("Could not find costume \"%s\"", filename.c_str());
putIntoCache(fname, b);
Common::SeekableReadStream *stream = openNewStreamFile(fname.c_str(), true);
if (!stream) {
error("Could not find costume \"%s\"", filename.c_str());
}
Costume *result = new Costume(filename, b->getData(), b->getLen(), prevCost);
Costume *result = new Costume(filename, stream, prevCost);
return result;
}
Font *ResourceLoader::loadFont(const Common::String &filename) {
Block *b = getFileFromCache(filename);
if (!b) {
b = getFileBlock(filename);
if (!b)
error("Could not find font file %s", filename.c_str());
putIntoCache(filename, b);
}
Common::SeekableReadStream *stream;
Font *result = new Font(filename, b->getData(), b->getLen());
stream = openNewStreamFile(filename.c_str(), true);
if(!stream)
error("Could not find font file %s", filename.c_str());
Font *result = new Font(filename, stream);
return result;
}
KeyframeAnim *ResourceLoader::loadKeyframe(const Common::String &filename) {
Block *b = getFileFromCache(filename);
if (!b) {
b = getFileBlock(filename);
if (!b)
error("Could not find keyframe file %s", filename.c_str());
putIntoCache(filename, b);
}
Common::SeekableReadStream *stream;
KeyframeAnim *result = new KeyframeAnim(filename, b->getData(), b->getLen());
stream = openNewStreamFile(filename.c_str());
if(!stream)
error("Could not find keyframe file %s", filename.c_str());
KeyframeAnim *result = new KeyframeAnim(filename, stream);
_keyframeAnims.push_back(result);
return result;
@ -321,25 +297,19 @@ KeyframeAnim *ResourceLoader::loadKeyframe(const Common::String &filename) {
LipSync *ResourceLoader::loadLipSync(const Common::String &filename) {
LipSync *result;
Block *b = getFileFromCache(filename);
bool cached = true;
if (!b) {
b = getFileBlock(filename);
if (!b)
return NULL;
cached = false;
}
Common::SeekableReadStream *stream;
result = new LipSync(filename, b->getData(), b->getLen());
stream = openNewStreamFile(filename.c_str());
if(!stream)
return NULL;
result = new LipSync(filename, stream);
// Some lipsync files have no data
if (result->isValid()) {
if (!cached)
putIntoCache(filename, b);
if (result->isValid())
_lipsyncs.push_back(result);
} else {
else {
delete result;
delete b;
result = NULL;
}
@ -349,70 +319,62 @@ LipSync *ResourceLoader::loadLipSync(const Common::String &filename) {
Material *ResourceLoader::loadMaterial(const Common::String &filename, CMap *c) {
Common::String fname = fixFilename(filename, false);
fname.toLowercase();
Block *b = getFileFromCache(fname);
if (!b) {
b = getFileBlock(fname);
if (!b)
error("Could not find material %s", filename.c_str());
putIntoCache(filename, b);
}
Common::SeekableReadStream *stream;
Material *result = new Material(fname, b->getData(), b->getLen(), c);
stream = openNewStreamFile(fname.c_str(), true);
if(!stream)
error("Could not find material %s", filename.c_str());
Material *result = new Material(fname, stream, c);
return result;
}
Model *ResourceLoader::loadModel(const Common::String &filename, CMap *c, Model *parent) {
Common::String fname = fixFilename(filename);
Block *b = getFileFromCache(fname);
if (!b) {
b = getFileBlock(fname);
if (!b)
error("Could not find model %s", filename.c_str());
putIntoCache(fname, b);
}
Common::SeekableReadStream *stream;
Model *result = new Model(filename, b->getData(), b->getLen(), c, parent);
stream = openNewStreamFile(fname.c_str());
if(!stream)
error("Could not find model %s", filename.c_str());
Model *result = new Model(filename, stream, c, parent);
_models.push_back(result);
return result;
}
EMIModel *ResourceLoader::loadModelEMI(const Common::String &filename, EMIModel *parent) {
Common::String fname = fixFilename(filename);
Block *b = getFileFromCache(fname);
if (!b) {
b = getFileBlock(fname);
if (!b) {
warning("Could not find model %s", filename.c_str());
return NULL;
}
putIntoCache(fname, b);
Common::SeekableReadStream *stream;
stream = openNewStreamFile(fname.c_str());
if(!stream) {
warning("Could not find model %s", filename.c_str());
return NULL;
}
EMIModel *result = new EMIModel(filename, b->getData(), b->getLen(), parent);
EMIModel *result = new EMIModel(filename, stream, parent);
_emiModels.push_back(result);
return result;
}
Skeleton *ResourceLoader::loadSkeleton(const Common::String &filename) {
Common::String fname = fixFilename(filename);
Block *b = getFileFromCache(fname);
if (!b) {
b = getFileBlock(fname);
if (!b) {
warning("Could not find skeleton %s", filename.c_str());
return NULL;
}
putIntoCache(fname, b);
Common::SeekableReadStream *stream;
stream = openNewStreamFile(fname.c_str(), true);
if(!stream) {
warning("Could not find skeleton %s", filename.c_str());
return NULL;
}
Skeleton *result = new Skeleton(filename, b->getData(), b->getLen());
Skeleton *result = new Skeleton(filename, stream);
return result;
}
void ResourceLoader::uncache(const char *filename) {
Common::String fname = filename;
fname.toLowercase();
@ -425,8 +387,8 @@ void ResourceLoader::uncache(const char *filename) {
for (unsigned int i = 0; i < _cache.size(); i++) {
if (fname.compareTo(_cache[i].fname) == 0) {
delete[] _cache[i].fname;
_cacheMemorySize -= _cache[i].resPtr->getLen();
delete _cache[i].resPtr;
_cacheMemorySize -= _cache[i].len;
delete[] _cache[i].resPtr;
_cache.remove_at(i);
_cacheDirty = true;
}

View File

@ -27,6 +27,7 @@
#include "common/file.h"
#include "engines/grim/object.h"
#include "engines/grim/lua/lua.h"
namespace Grim {
@ -42,8 +43,6 @@ class LipSync;
class TrackedObject;
class SaveGame;
class Skeleton;
class Block;
class LuaFile;
class Lab;
typedef ObjectPtr<Material> MaterialPtr;
@ -69,14 +68,9 @@ public:
EMIModel *loadModelEMI(const Common::String &fname, EMIModel *parent = NULL);
LipSync *loadLipSync(const Common::String &fname);
Skeleton *loadSkeleton(const Common::String &fname);
Block *getFileBlock(const Common::String &filename) const;
Block *getBlock(const Common::String &filename);
Common::SeekableReadStream *openNewStreamFile(const char *filename) const;
Common::SeekableReadStream *openNewSubStreamFile(const char *filename) const;
LuaFile *openNewStreamLuaFile(const char *filename) const;
Common::SeekableReadStream *openNewStreamFile(const char *filename, bool cache = false);
void uncache(const char *fname);
bool getFileExists(const Common::String &filename) const;
int getFileLength(const char *filename) const;
bool getFileExists(const Common::String &filename); //TODO: make it const again at next scummvm sync
ModelPtr getModel(const Common::String &fname, CMap *c);
CMapPtr getColormap(const Common::String &fname);
@ -89,17 +83,16 @@ public:
struct ResourceCache {
char *fname;
Block *resPtr;
byte *resPtr;
uint32 len;
};
private:
const Lab *getLab(const Common::String &filename) const;
Block *getFileFromCache(const Common::String &filename);
Common::SeekableReadStream *loadFile(Common::String &filename); //TODO: make it const again at next scummvm sync
Common::SeekableReadStream *getFileFromCache(const Common::String &filename);
ResourceLoader::ResourceCache *getEntryFromCache(const Common::String &filename);
void putIntoCache(const Common::String &fname, Block *res);
void putIntoCache(const Common::String &fname, byte *res, uint32 len);
typedef Common::List<Lab *> LabList;
LabList _labs;
Common::SearchSet _files;
Common::Array<ResourceCache> _cache;

View File

@ -21,7 +21,6 @@
*/
#include "common/util.h"
#include "common/memstream.h"
#include "engines/grim/debug.h"
#include "engines/grim/grim.h"
@ -156,29 +155,29 @@ void Sector::load(TextSplitter &ts) {
_normal /= length;
}
void Sector::loadBinary(Common::MemoryReadStream *ms) {
_numVertices = ms->readUint32LE();
void Sector::loadBinary(Common::SeekableReadStream *data) {
_numVertices = data->readUint32LE();
_vertices = new Math::Vector3d[_numVertices];
for(int i = 0; i < _numVertices; i++) {
ms->read(_vertices[i].getData(), 12);
data->read(_vertices[i].getData(), 12);
}
char name[128];
int nameLength = ms->readUint32LE();
int nameLength = data->readUint32LE();
_name = ms->read(name, nameLength);
_name = data->read(name, nameLength);
_id = ms->readUint32LE();
_id = data->readUint32LE();
_visible = ms->readByte();
_visible = data->readByte();
_type = (SectorType)ms->readUint32LE();
_type = (SectorType)data->readUint32LE();
// this probably does something more than skip bytes, but ATM I don't know what
int skip = ms->readUint32LE();
ms->seek(skip * 4, SEEK_CUR);
int skip = data->readUint32LE();
data->seek(skip * 4, SEEK_CUR);
ms->read(&_height, 4);
data->read(&_height, 4);
}
void Sector::setVisible(bool vis) {

View File

@ -30,7 +30,7 @@
#include "math/line3d.h"
namespace Common {
class MemoryReadStream;
class SeekableReadStream;
}
namespace Grim {
@ -57,7 +57,7 @@ public:
bool restoreState(SaveGame *savedState);
void load(TextSplitter &ts);
void loadBinary(Common::MemoryReadStream *ms);
void loadBinary(Common::SeekableReadStream *data);
void setVisible(bool visible);
void shrink(float radius);
void unshrink();

View File

@ -22,7 +22,6 @@
#define FORBIDDEN_SYMBOL_EXCEPTION_printf
#include "common/memstream.h"
#include "common/foreach.h"
#include "engines/grim/debug.h"
@ -39,17 +38,20 @@
namespace Grim {
Set::Set(const Common::String &sceneName, const char *buf, int len) :
Set::Set(const Common::String &sceneName, Common::SeekableReadStream *data) :
PoolObject<Set, MKTAG('S', 'E', 'T', ' ')>(), _locked(false), _name(sceneName), _enableLights(false),
_lightsConfigured(false) {
if (len >= 7 && memcmp(buf, "section", 7) == 0) {
TextSplitter ts(buf, len);
char header[7];
data->read(header, 7);
data->seek(0, SEEK_SET);
if (memcmp(header, "section", 7) == 0) {
TextSplitter ts(data);
loadText(ts);
} else {
Common::MemoryReadStream ms((const byte *)buf, len);
loadBinary(&ms);
loadBinary(data);
}
delete data;
}
Set::Set() :
@ -76,7 +78,7 @@ Set::~Set() {
}
}
void Set::loadText(TextSplitter &ts){
void Set::loadText(TextSplitter &ts) {
char tempBuf[256];
ts.expectString("section: colormaps");
@ -153,16 +155,15 @@ void Set::loadText(TextSplitter &ts){
}
}
void Set::loadBinary(Common::MemoryReadStream *ms)
{
void Set::loadBinary(Common::SeekableReadStream *data) {
// yes, an array of size 0
_cmaps = NULL;//new CMapPtr[0];
_numSetups = ms->readUint32LE();
_numSetups = data->readUint32LE();
_setups = new Setup[_numSetups];
for (int i = 0; i < _numSetups; i++)
_setups[i].loadBinary(ms);
_setups[i].loadBinary(data);
_currSetup = _setups;
_numSectors = 0;
@ -175,20 +176,20 @@ void Set::loadBinary(Common::MemoryReadStream *ms)
// the rest may or may not be optional. Might be a good idea to check if there is no more data.
_numLights = ms->readUint32LE();
_numLights = data->readUint32LE();
_lights = new Light[_numLights];
for (int i = 0; i < _numLights; i++)
_lights[i].loadBinary(ms);
_lights[i].loadBinary(data);
// bypass light stuff for now
_numLights = 0;
_numSectors = ms->readUint32LE();
_numSectors = data->readUint32LE();
// Allocate and fill an array of sector info
_sectors = new Sector*[_numSectors];
for (int i = 0; i < _numSectors; i++) {
_sectors[i] = new Sector();
_sectors[i]->loadBinary(ms);
_sectors[i]->loadBinary(data);
}
}
@ -391,30 +392,30 @@ void Set::Setup::load(TextSplitter &ts) {
}
}
void Set::Setup::loadBinary(Common::MemoryReadStream *ms) {
void Set::Setup::loadBinary(Common::SeekableReadStream *data) {
char name[128];
ms->read(name, 128);
data->read(name, 128);
_name = Common::String(name);
// Skip an unknown number (this is the stringlength of the following string)
int fNameLen = 0;
fNameLen = ms->readUint32LE();
fNameLen = data->readUint32LE();
char* fileName = new char[fNameLen];
ms->read(fileName,fNameLen);
data->read(fileName,fNameLen);
_bkgndZBm = NULL;
_bkgndBm = g_resourceloader->loadBitmap(fileName);
ms->read(_pos.getData(), 12);
data->read(_pos.getData(), 12);
ms->read(_interest.getData(), 12);
data->read(_interest.getData(), 12);
ms->read(&_roll, 4);
ms->read(&_fov, 4);
ms->read(&_nclip, 4);
ms->read(&_fclip, 4);
data->read(&_roll, 4);
data->read(&_fov, 4);
data->read(&_nclip, 4);
data->read(&_fclip, 4);
}
@ -448,9 +449,9 @@ void Light::load(TextSplitter &ts) {
_enabled = true;
}
void Light::loadBinary(Common::MemoryReadStream *ms) {
void Light::loadBinary(Common::SeekableReadStream *data) {
// skip lights for now
ms->seek(100, SEEK_CUR);
data->seek(100, SEEK_CUR);
}
void Set::Setup::setupCamera() const {

View File

@ -30,7 +30,7 @@
#include "engines/grim/objectstate.h"
namespace Common {
class MemoryReadStream;
class SeekableReadStream;
}
namespace Grim {
@ -40,12 +40,12 @@ class Light;
class Set : public PoolObject<Set, MKTAG('S', 'E', 'T', ' ')> {
public:
Set(const Common::String &name, const char *buf, int len);
Set(const Common::String &name, Common::SeekableReadStream *data);
Set();
~Set();
void loadText(TextSplitter &ts);
void loadBinary(Common::MemoryReadStream *ms);
void loadBinary(Common::SeekableReadStream *data);
void saveState(SaveGame *savedState) const;
bool restoreState(SaveGame *savedState);
@ -107,7 +107,7 @@ public:
struct Setup { // Camera setup data
void load(TextSplitter &ts);
void loadBinary(Common::MemoryReadStream *ms);
void loadBinary(Common::SeekableReadStream *data);
void setupCamera() const;
Common::String _name;
Bitmap::Ptr _bkgndBm, _bkgndZBm;
@ -145,7 +145,7 @@ private:
class Light { // Set lighting data
public:
void load(TextSplitter &ts);
void loadBinary(Common::MemoryReadStream *ms);
void loadBinary(Common::SeekableReadStream *data);
Common::String _name;
Common::String _type;
Math::Vector3d _pos, _dir;

View File

@ -24,12 +24,11 @@
namespace Grim {
Skeleton::Skeleton(const Common::String &filename, const char *data, int len) {
Common::MemoryReadStream ms((const byte *)data, len);
loadSkeleton(ms);
Skeleton::Skeleton(const Common::String &filename, Common::SeekableReadStream *data) {
loadSkeleton(data);
}
void Skeleton::loadSkeleton(Common::MemoryReadStream &ms) {
void Skeleton::loadSkeleton(Common::SeekableReadStream *data) {
}

View File

@ -23,15 +23,18 @@
#ifndef GRIM_SKELETON_H
#define GRIM_SKELETON_H
#include "common/memstream.h"
#include "engines/grim/object.h"
namespace Common {
class SeekableReadStream;
}
namespace Grim {
class Skeleton : public Object {
void loadSkeleton(Common::MemoryReadStream &ms);
void loadSkeleton(Common::SeekableReadStream *data);
public:
Skeleton(const Common::String &filename, const char *data, int len);
Skeleton(const Common::String &filename, Common::SeekableReadStream *data);
};
} // end of namespace Grim

View File

@ -22,6 +22,7 @@
#include "common/util.h"
#include "common/textconsole.h"
#include "common/stream.h"
#include "engines/grim/textsplit.h"
@ -57,12 +58,13 @@ int residual_vsscanf(const char *str, int field_count, const char *format, va_li
f11, f12, f13, f14, f15, f16, f17, f18, f19, f20);
}
TextSplitter::TextSplitter(const char *data, int len) {
TextSplitter::TextSplitter(Common::SeekableReadStream *data) {
char *line;
int i;
uint32 len = data->size();
_stringData = new char[len + 1];
memcpy(_stringData, data, len);
data->read(_stringData, len);
_stringData[len] = '\0';
// Find out how many lines of text there are
_numLines = _lineIndex = 0;

View File

@ -23,6 +23,10 @@
#ifndef GRIM_TEXTSPLIT_HH
#define GRIM_TEXTSPLIT_HH
namespace Common {
class SeekableReadStream;
}
namespace Grim {
// A utility class to help in parsing the text-format files. Splits
@ -31,7 +35,7 @@ namespace Grim {
class TextSplitter {
public:
TextSplitter(const char *data, int len);
TextSplitter(Common::SeekableReadStream *data);
~TextSplitter();
char *nextLine() {