STARK: Add a debug command allowing to list the game's rooms
This commit is contained in:
parent
ff9cd31820
commit
63f88fd167
4 changed files with 144 additions and 12 deletions
|
@ -31,6 +31,7 @@ namespace Stark {
|
||||||
Console::Console(StarkEngine *vm) : GUI::Debugger(), _vm(vm) {
|
Console::Console(StarkEngine *vm) : GUI::Debugger(), _vm(vm) {
|
||||||
registerCmd("dumpArchive", WRAP_METHOD(Console, Cmd_DumpArchive));
|
registerCmd("dumpArchive", WRAP_METHOD(Console, Cmd_DumpArchive));
|
||||||
registerCmd("dumpScript", WRAP_METHOD(Console, Cmd_DumpScript));
|
registerCmd("dumpScript", WRAP_METHOD(Console, Cmd_DumpScript));
|
||||||
|
registerCmd("listRooms", WRAP_METHOD(Console, Cmd_ListRooms));
|
||||||
}
|
}
|
||||||
|
|
||||||
Console::~Console() {
|
Console::~Console() {
|
||||||
|
@ -41,7 +42,7 @@ bool Console::Cmd_DumpArchive(int argc, const char **argv) {
|
||||||
debugPrintf("Extract all the files from a game archive.\n");
|
debugPrintf("Extract all the files from a game archive.\n");
|
||||||
debugPrintf("The destination folder, named 'dump', must exist.\n");
|
debugPrintf("The destination folder, named 'dump', must exist.\n");
|
||||||
debugPrintf("Usage :\n");
|
debugPrintf("Usage :\n");
|
||||||
debugPrintf("dumpArchive [file name]\n");
|
debugPrintf("dumpArchive [archive name]\n");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,26 +86,81 @@ bool Console::Cmd_DumpScript(int argc, const char **argv) {
|
||||||
if (argc != 2) {
|
if (argc != 2) {
|
||||||
debugPrintf("Print the scripts from an archive.\n");
|
debugPrintf("Print the scripts from an archive.\n");
|
||||||
debugPrintf("Usage :\n");
|
debugPrintf("Usage :\n");
|
||||||
debugPrintf("dumpScript [file name]\n");
|
debugPrintf("dumpScript [archive name]\n");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
XARCArchive xarc;
|
XRCNode *node = loadXARCScripts(argv[1]);
|
||||||
if (!xarc.open(argv[1])) {
|
if (node == nullptr) {
|
||||||
debugPrintf("Can't open archive with name '%s'\n", argv[1]);
|
debugPrintf("Can't open archive with name '%s'\n", argv[1]);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
node->print();
|
||||||
|
delete node;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
XRCNode *Console::loadXARCScripts(Common::String archive) {
|
||||||
|
XARCArchive xarc;
|
||||||
|
if (!xarc.open(archive)) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
Common::ArchiveMemberList members;
|
Common::ArchiveMemberList members;
|
||||||
xarc.listMatchingMembers(members, "*.xrc");
|
xarc.listMatchingMembers(members, "*.xrc");
|
||||||
|
|
||||||
for (Common::ArchiveMemberList::const_iterator it = members.begin(); it != members.end(); it++) {
|
if (members.size() == 0) {
|
||||||
debugPrintf("Dumping script '%s'\n", it->get()->getName().c_str());
|
error("No scripts in archive '%s'", archive.c_str());
|
||||||
XRCNode *node = XRCNode::read(xarc.createReadStreamForMember(it->get()->getName()));
|
|
||||||
node->print();
|
|
||||||
delete node;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (members.size() > 1) {
|
||||||
|
error("Too many scripts in archive '%s'", archive.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
return XRCNode::read(xarc.createReadStreamForMember(members.front()->getName()));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Console::Cmd_ListRooms(int argc, const char **argv) {
|
||||||
|
XRCNode *root = loadXARCScripts("x.xarc");
|
||||||
|
if (root == nullptr) {
|
||||||
|
debugPrintf("Can't open archive 'x.xarc'\n");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Loop over the levels
|
||||||
|
for (uint i = 0; i < root->getChildren().size(); i++) {
|
||||||
|
XRCNode *level = root->getChildren()[i];
|
||||||
|
|
||||||
|
// Only consider levels
|
||||||
|
if (level->getType() != XRCNode::kLevel) continue;
|
||||||
|
|
||||||
|
Common::String levelArchive = level->getArchive();
|
||||||
|
debugPrintf("%s - %s\n", levelArchive.c_str(), level->getName().c_str());
|
||||||
|
|
||||||
|
// Load the detailed level archive
|
||||||
|
level = loadXARCScripts(levelArchive);
|
||||||
|
|
||||||
|
if (!level)
|
||||||
|
error("Unable to load archive '%s'", levelArchive.c_str());
|
||||||
|
|
||||||
|
// Loop over the rooms
|
||||||
|
for (uint j = 0; j < level->getChildren().size(); j++) {
|
||||||
|
XRCNode *room = level->getChildren()[j];
|
||||||
|
|
||||||
|
// Only consider rooms
|
||||||
|
if (room->getType() != XRCNode::kRoom) continue;
|
||||||
|
|
||||||
|
Common::String roomArchive = room->getArchive();
|
||||||
|
debugPrintf("%s - %s\n", roomArchive.c_str(), room->getName().c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
delete level;
|
||||||
|
}
|
||||||
|
|
||||||
|
delete root;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -31,6 +31,8 @@
|
||||||
|
|
||||||
namespace Stark {
|
namespace Stark {
|
||||||
|
|
||||||
|
class XRCNode;
|
||||||
|
|
||||||
class Console : public GUI::Debugger {
|
class Console : public GUI::Debugger {
|
||||||
public:
|
public:
|
||||||
Console(StarkEngine *vm);
|
Console(StarkEngine *vm);
|
||||||
|
@ -41,6 +43,9 @@ private:
|
||||||
|
|
||||||
bool Cmd_DumpArchive(int argc, const char **argv);
|
bool Cmd_DumpArchive(int argc, const char **argv);
|
||||||
bool Cmd_DumpScript(int argc, const char **argv);
|
bool Cmd_DumpScript(int argc, const char **argv);
|
||||||
|
bool Cmd_ListRooms(int argc, const char** argv);
|
||||||
|
|
||||||
|
XRCNode *loadXARCScripts(Common::String archive);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // End of namespace Stark
|
} // End of namespace Stark
|
||||||
|
|
|
@ -28,7 +28,9 @@
|
||||||
|
|
||||||
namespace Stark {
|
namespace Stark {
|
||||||
|
|
||||||
XRCNode::XRCNode() : _data(NULL) {
|
XRCNode::XRCNode() :
|
||||||
|
_data(nullptr),
|
||||||
|
_parent(nullptr) {
|
||||||
}
|
}
|
||||||
|
|
||||||
XRCNode::~XRCNode() {
|
XRCNode::~XRCNode() {
|
||||||
|
@ -109,6 +111,9 @@ bool XRCNode::readInternal(Common::ReadStream *stream) {
|
||||||
if (!child)
|
if (!child)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
// Set the child's parent to the current node
|
||||||
|
child->_parent = this;
|
||||||
|
|
||||||
// Save all children read correctly
|
// Save all children read correctly
|
||||||
_children.push_back(child);
|
_children.push_back(child);
|
||||||
}
|
}
|
||||||
|
@ -117,12 +122,18 @@ bool XRCNode::readInternal(Common::ReadStream *stream) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void XRCNode::print(uint depth) {
|
void XRCNode::print(uint depth) {
|
||||||
|
// Display value for the node type
|
||||||
|
Common::String type(getTypeName());
|
||||||
|
if (type.empty()) {
|
||||||
|
type = Common::String::format("%d", _dataType);
|
||||||
|
}
|
||||||
|
|
||||||
// Build the node description
|
// Build the node description
|
||||||
Common::String description;
|
Common::String description;
|
||||||
for (uint i = 0; i < depth; i++) {
|
for (uint i = 0; i < depth; i++) {
|
||||||
description += "-";
|
description += "-";
|
||||||
}
|
}
|
||||||
description += Common::String::format(" %s - (%d) - (unk1=%d, order=%d)", _name.c_str(), _dataType, _unknown1, _nodeOrder);
|
description += Common::String::format(" %s - (%s) - (unk1=%d, order=%x)", _name.c_str(), type.c_str(), _unknown1, _nodeOrder);
|
||||||
|
|
||||||
// Print tge node description
|
// Print tge node description
|
||||||
debug(description.c_str());
|
debug(description.c_str());
|
||||||
|
@ -138,4 +149,49 @@ void XRCNode::print(uint depth) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char *XRCNode::getTypeName() {
|
||||||
|
static const struct {
|
||||||
|
Type type;
|
||||||
|
const char *name;
|
||||||
|
} typeNames[] {
|
||||||
|
{ kLevel, "Level" },
|
||||||
|
{ kRoom, "Room" }
|
||||||
|
};
|
||||||
|
|
||||||
|
for (uint i = 0; i < ARRAYSIZE(typeNames); i++) {
|
||||||
|
if (typeNames[i].type == _dataType) {
|
||||||
|
return typeNames[i].name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
Common::String XRCNode::getArchive() {
|
||||||
|
Common::String archive;
|
||||||
|
|
||||||
|
switch (getType()) {
|
||||||
|
case kLevel:
|
||||||
|
switch (_unknown1) {
|
||||||
|
case 1:
|
||||||
|
archive = Common::String::format("%s/%s.xarc", _name.c_str(), _name.c_str());
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
archive = Common::String::format("%02x/%02x.xarc", _nodeOrder, _nodeOrder);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
error("Unknown level archive type %d", _unknown1);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case kRoom:
|
||||||
|
assert(_parent);
|
||||||
|
archive = Common::String::format("%02x/%02x/%02x.xarc", _parent->_nodeOrder, _nodeOrder, _nodeOrder);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
error("This type of node cannot load children %d", _dataType);
|
||||||
|
}
|
||||||
|
|
||||||
|
return archive;
|
||||||
|
}
|
||||||
|
|
||||||
} // End of namespace Stark
|
} // End of namespace Stark
|
||||||
|
|
|
@ -34,18 +34,31 @@ private:
|
||||||
XRCNode();
|
XRCNode();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
enum Type {
|
||||||
|
kLevel = 2,
|
||||||
|
kRoom = 3
|
||||||
|
};
|
||||||
|
|
||||||
~XRCNode();
|
~XRCNode();
|
||||||
|
|
||||||
static XRCNode *read(Common::ReadStream *stream);
|
static XRCNode *read(Common::ReadStream *stream);
|
||||||
|
|
||||||
Common::String getName() const { return _name; }
|
Common::String getName() const { return _name; }
|
||||||
|
Type getType() const {return (Type) _dataType; }
|
||||||
const byte *getData() const { return _data; }
|
const byte *getData() const { return _data; }
|
||||||
Common::Array<XRCNode *> getChildren() const { return _children; }
|
Common::Array<XRCNode *> getChildren() const { return _children; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the archive file name containing the data for this node.
|
||||||
|
* Only Levels and Rooms have archives.
|
||||||
|
*/
|
||||||
|
Common::String getArchive();
|
||||||
|
|
||||||
void print(uint depth = 0);
|
void print(uint depth = 0);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool readInternal(Common::ReadStream *stream);
|
bool readInternal(Common::ReadStream *stream);
|
||||||
|
const char *getTypeName();
|
||||||
|
|
||||||
byte _dataType;
|
byte _dataType;
|
||||||
byte _unknown1;
|
byte _unknown1;
|
||||||
|
@ -53,8 +66,10 @@ protected:
|
||||||
Common::String _name;
|
Common::String _name;
|
||||||
uint32 _dataLength;
|
uint32 _dataLength;
|
||||||
byte *_data;
|
byte *_data;
|
||||||
Common::Array<XRCNode *> _children;
|
|
||||||
uint16 _unknown3;
|
uint16 _unknown3;
|
||||||
|
|
||||||
|
XRCNode *_parent;
|
||||||
|
Common::Array<XRCNode *> _children;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // End of namespace Stark
|
} // End of namespace Stark
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue