mirror of
https://github.com/libretro/scummvm.git
synced 2025-02-12 06:00:48 +00:00
Merge pull request #447 from YakBizzarro/resource-enhance3
Enhance resource loading
This commit is contained in:
commit
1a0ed0c852
@ -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();
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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() {
|
||||
|
@ -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; }
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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
|
||||
|
@ -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; }
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
};
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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:
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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() {
|
||||
|
@ -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 {
|
||||
|
@ -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");
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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) {
|
||||
|
@ -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();
|
||||
|
@ -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 {
|
||||
|
@ -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;
|
||||
|
@ -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) {
|
||||
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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() {
|
||||
|
Loading…
x
Reference in New Issue
Block a user