diff --git a/engines/grim/costume.cpp b/engines/grim/costume.cpp index 00205da74b6..23c39c771fd 100644 --- a/engines/grim/costume.cpp +++ b/engines/grim/costume.cpp @@ -761,11 +761,7 @@ void SoundComponent::reset() { Costume::Costume(const char *fname, const char *data, int len, Costume *prevCost) : Object() { - load(fname, data, len, prevCost); -} - -void Costume::load(const char *filename, const char *data, int len, Costume *prevCost) { - _fname = filename; + _fname = fname; _head.maxPitch = 0; _head.joint1 = -1; _head.joint2 = -1; @@ -776,9 +772,16 @@ void Costume::load(const char *filename, const char *data, int len, Costume *pre _headYaw = 0; _headPitch = 0; _prevCostume = prevCost; + if (g_grim->getGameType() == GType_MONKEY4) { + Common::MemoryReadStream ms((const byte *)data, len); + loadEMI(ms, prevCost); + } else { + TextSplitter ts(data, len); + loadGRIM(ts, prevCost); + } +} - TextSplitter ts(data, len); - +void Costume::loadGRIM(TextSplitter &ts, Costume *prevCost) { ts.expectString("costume v0.1"); ts.expectString("section tags"); int numTags; @@ -863,6 +866,68 @@ void Costume::load(const char *filename, const char *data, int len, Costume *pre } } +void Costume::loadEMI(Common::MemoryReadStream &ms, Costume *prevCost) { + Common::Listcomponents; + + _numChores = ms.readUint32LE(); + _chores = new Chore[_numChores]; + for (int i = 0; i < _numChores; i++) { + uint32 nameLength; + nameLength = ms.readUint32LE(); + ms.read(_chores[i]._name, nameLength); + float length; + ms.read(&length, 4); + _chores[i]._length = (int)length; + + _chores[i]._owner = this; + _chores[i]._numTracks = ms.readUint32LE(); + _chores[i]._tracks = new ChoreTrack[_chores[i]._numTracks]; + + for (int k = 0; k < _chores[i]._numTracks; k++) { + int componentNameLength = ms.readUint32LE(); + assert(componentNameLength < 64); + + char name[64]; + ms.read(name, componentNameLength); + + int trackID = ms.readUint32LE(); + int parent = ms.readUint32LE(); + assert(parent == -1); + + Component *component = loadComponentEMI(name, parent); + + components.push_back(component); + + ChoreTrack &track = _chores[i]._tracks[k]; + track.numKeys = ms.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); + track.keys[j].time = time; + track.keys[j].value = value; + } + } + _chores[i]._tracks->compID; + } + + _numComponents = components.size(); + _components = new Component *[_numComponents]; + int i = 0; + for (Common::List::iterator it = components.begin(); it != components.end(); ++it, ++i) { + _components[i] = *it; + if (!_components[i]) + continue; + _components[i]->setCostume(this); + _components[i]->init(); + _components[i]->setFade(1.f); + } +} + Costume::~Costume() { if (_chores) { stopChores(); @@ -1116,6 +1181,46 @@ Costume::Component *Costume::loadComponent (tag32 tag, Costume::Component *paren return NULL; } +Costume::Component *Costume::loadComponentEMI(const char *name, int parentID) { + // some have an exclimation mark, this could mean something. + assert(name[0] == '!'); + ++name; + + char type[5]; + memcpy(type, name, 4); + type[4] = 0; + + name += 4; + + if (strcmp(type, "mesh") == 0) + return new MainModelComponent(0, parentID, name, 0, 0); + /*if (FROM_BE_32(tag) == MKTAG('M','M','D','L')) + return new MainModelComponent(parent, parentID, name, prevComponent, tag); + else if (FROM_BE_32(tag) == MKTAG('M','O','D','L')) + return new ModelComponent(parent, parentID, name, prevComponent, tag); + else if (FROM_BE_32(tag) == MKTAG('C','M','A','P')) + return new ColormapComponent(parent, parentID, name, tag); + else if (FROM_BE_32(tag) == MKTAG('K','E','Y','F')) + return new KeyframeComponent(parent, parentID, name, tag); + else if (FROM_BE_32(tag) == MKTAG('M','E','S','H')) + return new MeshComponent(parent, parentID, name, tag); + else if (FROM_BE_32(tag) == MKTAG('L','U','A','V')) + return new LuaVarComponent(parent, parentID, name, tag); + else if (FROM_BE_32(tag) == MKTAG('I','M','L','S')) + return new SoundComponent(parent, parentID, name, tag); + else if (FROM_BE_32(tag) == MKTAG('B','K','N','D')) + return new BitmapComponent(parent, parentID, name, tag); + else if (FROM_BE_32(tag) == MKTAG('M','A','T',' ')) + return new MaterialComponent(parent, parentID, name, tag); + else if (FROM_BE_32(tag) == MKTAG('S','P','R','T')) + return NULL;// new SpriteComponent(parent, parentID, name); + + char t[4]; + memcpy(t, &tag, sizeof(tag32)); + warning("loadComponent: Unknown tag '%c%c%c%c', name '%s'", t[0], t[1], t[2], t[3], name);*/ + return NULL; +} + Model::HierNode *Costume::getModelNodes() { for (int i = 0; i < _numComponents; i++) { if (!_components[i]) @@ -1147,6 +1252,7 @@ void Costume::playChore(const char *name) { warning("Costume::playChore: Could not find chore: %s", name); return; } + void Costume::playChore(int num) { if (num < 0 || num >= _numChores) { if (gDebugLevel == DEBUG_CHORES || gDebugLevel == DEBUG_WARN || gDebugLevel == DEBUG_ALL) diff --git a/engines/grim/costume.h b/engines/grim/costume.h index 5fff2029efe..5b2f1b84c87 100644 --- a/engines/grim/costume.h +++ b/engines/grim/costume.h @@ -26,6 +26,8 @@ #ifndef GRIM_COSTUME_H #define GRIM_COSTUME_H +#include "common/memstream.h" + #include "engines/grim/model.h" #include "engines/grim/object.h" #include "engines/grim/colormap.h" @@ -41,7 +43,8 @@ public: Costume(const char *filename, const char *data, int len, Costume *prevCost); Costume() : Object() { _chores = 0; } - void load(const char *filename, const char *data, int len, Costume *prevCost); + void loadGRIM(TextSplitter &ts, Costume *prevCost); + void loadEMI(Common::MemoryReadStream &ms, Costume *prevCost); virtual ~Costume(); @@ -113,7 +116,7 @@ public: private: Component *loadComponent(tag32 tag, Component *parent, int parentID, const char *name, Component *prevComponent); - + Component *loadComponentEMI(const char *name, int parentID); Common::String _fname; Costume *_prevCostume; diff --git a/engines/grim/model.cpp b/engines/grim/model.cpp index 73f9db4655b..092923c7fdc 100644 --- a/engines/grim/model.cpp +++ b/engines/grim/model.cpp @@ -40,7 +40,10 @@ Model::Model(const char *filename, const char *data, int len, CMap *cmap) : _fname = filename; _headNode = NULL; - if (len >= 4 && READ_BE_UINT32(data) == MKTAG('L','D','O','M')) + 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')) loadBinary(data, cmap); else { TextSplitter ts(data, len); @@ -62,6 +65,30 @@ void Model::reload(CMap *cmap) { delete[] materials; } +void Model::loadEMI(Common::MemoryReadStream &ms) { + char name[64]; + + int nameLength = ms.readUint32LE(); + assert(nameLength < 64); + + ms.read(name, nameLength); + + _numMaterials = ms.readUint32LE(); + _materials = new MaterialPtr[_numMaterials]; + _materialNames = new char[_numMaterials][32]; + for (int i = 0; i < _numMaterials; i++) { + nameLength = ms.readUint32LE(); + assert(nameLength < 32); + + ms.read(_materialNames[i], nameLength); + _materials[i] = g_resourceloader->getMaterial(_materialNames[i], 0); + ms.seek(4, SEEK_CUR); + } + + ms.seek(4, SEEK_CUR); + + +} void Model::loadBinary(const char *&data, CMap *cmap) { _numMaterials = READ_LE_UINT32(data + 4); data += 8; diff --git a/engines/grim/model.h b/engines/grim/model.h index e59052f8532..94e3d80758e 100644 --- a/engines/grim/model.h +++ b/engines/grim/model.h @@ -26,6 +26,8 @@ #ifndef GRIM_MODEL_H #define GRIM_MODEL_H +#include "common/memstream.h" + #include "engines/grim/resource.h" #include "engines/grim/object.h" #include "graphics/matrix4.h" @@ -40,6 +42,7 @@ public: Model(const char *filename, const char *data, int len, CMap *cmap); void loadBinary(const char *&data, CMap *cmap); void loadText(TextSplitter *ts, CMap *cmap); + void loadEMI(Common::MemoryReadStream &ms); void reload(CMap *cmap); void draw() const; diff --git a/engines/grim/resource.cpp b/engines/grim/resource.cpp index 22de014ab23..49026bb74c8 100644 --- a/engines/grim/resource.cpp +++ b/engines/grim/resource.cpp @@ -245,9 +245,30 @@ CMap *ResourceLoader::loadColormap(const char *filename) { return result; } -Costume *ResourceLoader::loadCostume(const char *filename, Costume *prevCost) { - Common::String fname = filename; +static Common::String fixFilename(const char *filename) { + Common::String fname; + if (g_grim->getGameType() == GType_MONKEY4) { + char str[128]; + int len = strlen(filename); + for (int i = 0; i < len; i++) { + str[i] = filename[i]; + // Fix paths + if (str[i] == '\\') + str[i] = '/'; + } + // Append b to end of filename for EMI + str[len] = 'b'; + str[len + 1] = '\0'; + fname = str; + } else { + fname = filename; + } fname.toLowercase(); + return fname; +} + +Costume *ResourceLoader::loadCostume(const char *filename, Costume *prevCost) { + Common::String fname = fixFilename(filename); Block *b = getFileFromCache(fname.c_str()); if (!b) { b = getFileBlock(fname.c_str()); @@ -337,8 +358,7 @@ Material *ResourceLoader::loadMaterial(const char *filename, CMap *c) { } Model *ResourceLoader::loadModel(const char *filename, CMap *c) { - Common::String fname = filename; - fname.toLowercase(); + Common::String fname = fixFilename(filename); Block *b = getFileFromCache(fname.c_str()); if (!b) { b = getFileBlock(fname.c_str());