diff --git a/engines/stark/xrc.cpp b/engines/stark/xrc.cpp index 6d0457e43db..6ac7475a62a 100644 --- a/engines/stark/xrc.cpp +++ b/engines/stark/xrc.cpp @@ -32,6 +32,7 @@ XRCNode::XRCNode() : _dataType(0), _nodeOrder(0), _unknown1(0), + _dataLength(0), _unknown3(0), _parent(nullptr) { } @@ -52,6 +53,9 @@ XRCNode *XRCNode::read(Common::ReadStream *stream) { // Create a new node XRCNode *node; switch (dataType) { + case kScript: + node = new ScriptXRCNode(); + break; default: node = new UnimplementedXRCNode(); break; @@ -72,14 +76,14 @@ void XRCNode::readCommon(Common::ReadStream *stream) { _unknown1 = stream->readByte(); _nodeOrder = stream->readUint16LE(); - // Read the resource name length - uint16 nameLength = stream->readUint16LE(); - // Read the resource name - char *name = new char[nameLength]; - stream->read(name, nameLength); - _name = Common::String(name, nameLength); - delete[] name; + _name = readString(stream); + + // Read the data length + _dataLength = stream->readUint32LE(); + + // Show a first batch of information + debugC(10, kDebugXRC, "Stark::XRCNode: Type 0x%02X, Name: \"%s\", %d bytes", _dataType, _name.c_str(), _dataLength); } void XRCNode::readChildren(Common::ReadStream *stream) { @@ -105,6 +109,34 @@ void XRCNode::readChildren(Common::ReadStream *stream) { } } +Common::String XRCNode::readString(Common::ReadStream *stream) { + // Read the string length + uint16 length = stream->readUint16LE(); + + // Read the string + char *data = new char[length]; + stream->read(data, length); + Common::String string(data, length); + delete[] data; + + return string; +} + +XRCNode::DataMap XRCNode::readMap(Common::ReadStream *stream) { + // TODO: Is this really a map? + Common::HashMap map; + + uint32 size = stream->readUint32LE(); + for (uint i = 0; i < size; i++) { + byte b = stream->readByte(); + uint16 w = stream->readUint16LE(); + + map[b] = w; + } + + return map; +} + void XRCNode::print(uint depth) { // Display value for the node type Common::String type(getTypeName()); @@ -178,7 +210,6 @@ Common::String XRCNode::getArchive() { UnimplementedXRCNode::UnimplementedXRCNode() : XRCNode(), - _dataLength(0), _data(nullptr) { } @@ -188,12 +219,6 @@ UnimplementedXRCNode::~UnimplementedXRCNode() { } void UnimplementedXRCNode::readData(Common::ReadStream *stream) { - // Read the data length - _dataLength = stream->readUint32LE(); - - // Show a first batch of information - debugC(10, kDebugXRC, "Stark::XRCNode: Type 0x%02X, Name: \"%s\", %d bytes", _dataType, _name.c_str(), _dataLength); - // Read the data if (_dataLength) { _data = new byte[_dataLength]; @@ -213,4 +238,64 @@ void UnimplementedXRCNode::printData() { } } +ScriptXRCNode::~ScriptXRCNode() { +} + +ScriptXRCNode::ScriptXRCNode() { +} + +void ScriptXRCNode::readData(Common::ReadStream* stream) { + uint32 count = stream->readUint32LE(); + for (uint i = 0; i < count; i++) { + Argument argument; + argument.type = stream->readUint32LE(); + + switch (argument.type) { + case Argument::kTypeInteger1: + case Argument::kTypeInteger2: + argument.intValue = stream->readUint32LE(); + break; + + case Argument::kTypeDataMap: + argument.mapValue = readMap(stream); + break; + case Argument::kTypeString: + argument.stringValue = readString(stream); + break; + default: + error("Unknown argument type %d", argument.type); + } + + _arguments.push_back(argument); + } +} + +void ScriptXRCNode::printData() { + for (uint i = 0; i < _arguments.size(); i++) { + switch (_arguments[i].type) { + case Argument::kTypeInteger1: + case Argument::kTypeInteger2: + debug("%d: %d", i, _arguments[i].intValue); + break; + + case Argument::kTypeDataMap: { + Common::String desc; + + DataMap map = _arguments[i].mapValue; + for (DataMap::const_iterator it = map.begin(); it != map.end(); it++) { + desc += Common::String::format("(%d => %d) ", it->_key, it->_value); + } + + debug("%d: %s", i, desc.c_str()); + } + break; + case Argument::kTypeString: + debug("%d: %s", i, _arguments[i].stringValue.c_str()); + break; + default: + error("Unknown argument type %d", _arguments[i].type); + } + } +} + } // End of namespace Stark diff --git a/engines/stark/xrc.h b/engines/stark/xrc.h index 19685a6e10b..8e25fdc19d3 100644 --- a/engines/stark/xrc.h +++ b/engines/stark/xrc.h @@ -24,6 +24,7 @@ #define STARK_XRC_H #include "common/array.h" +#include "common/hashmap.h" #include "common/str.h" #include "common/stream.h" @@ -33,7 +34,8 @@ class XRCNode { public: enum Type { kLevel = 2, - kRoom = 3 + kRoom = 3, + kScript = 22 }; virtual ~XRCNode(); @@ -59,6 +61,11 @@ protected: virtual void readData(Common::ReadStream *stream) = 0; void readChildren(Common::ReadStream *stream); + typedef Common::HashMap DataMap; + + static Common::String readString(Common::ReadStream *stream); + static DataMap readMap(Common::ReadStream *stream); + virtual void printData() = 0; const char *getTypeName(); @@ -67,6 +74,9 @@ protected: byte _unknown1; uint16 _nodeOrder; // Node order inside the parent node Common::String _name; + + uint32 _dataLength; + uint16 _unknown3; XRCNode *_parent; @@ -85,12 +95,40 @@ protected: void readData(Common::ReadStream *stream) override; void printData() override; - uint32 _dataLength; byte *_data; friend class XRCNode; }; +class ScriptXRCNode : public XRCNode { +public: + virtual ~ScriptXRCNode(); + + struct Argument { + enum Type { + kTypeInteger1 = 1, + kTypeInteger2 = 2, + kTypeDataMap = 3, + kTypeString = 4 + }; + + uint32 type; + uint32 intValue; + Common::String stringValue; + DataMap mapValue; + }; + +protected: + ScriptXRCNode(); + + void readData(Common::ReadStream *stream) override; + void printData() override; + + Common::Array _arguments; + + friend class XRCNode; +}; + } // End of namespace Stark #endif // STARK_XRC_H