mirror of
https://github.com/libretro/scummvm.git
synced 2024-12-26 19:55:44 +00:00
47f6c2e9b9
GUI: Support double quoted debugger parameters
375 lines
10 KiB
C++
375 lines
10 KiB
C++
/* ScummVM - Graphic Adventure Engine
|
|
*
|
|
* ScummVM is the legal property of its developers, whose names
|
|
* are too numerous to list here. Please refer to the COPYRIGHT
|
|
* file distributed with this source distribution.
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version 2
|
|
* of the License, or (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
*
|
|
*/
|
|
|
|
#include "titanic/debugger.h"
|
|
#include "titanic/core/node_item.h"
|
|
#include "titanic/core/room_item.h"
|
|
#include "titanic/core/tree_item.h"
|
|
#include "titanic/core/view_item.h"
|
|
#include "titanic/game_manager.h"
|
|
#include "titanic/game/movie_tester.h"
|
|
#include "titanic/main_game_window.h"
|
|
#include "titanic/pet_control/pet_control.h"
|
|
#include "titanic/support/movie.h"
|
|
#include "titanic/titanic.h"
|
|
#include "common/str-array.h"
|
|
|
|
namespace Titanic {
|
|
|
|
Debugger::Debugger(TitanicEngine *vm) : GUI::Debugger(), _vm(vm) {
|
|
registerCmd("continue", WRAP_METHOD(Debugger, cmdExit));
|
|
registerCmd("dump", WRAP_METHOD(Debugger, cmdDump));
|
|
registerCmd("room", WRAP_METHOD(Debugger, cmdRoom));
|
|
registerCmd("pet", WRAP_METHOD(Debugger, cmdPET));
|
|
registerCmd("item", WRAP_METHOD(Debugger, cmdItem));
|
|
registerCmd("movie", WRAP_METHOD(Debugger, cmdMovie));
|
|
registerCmd("sound", WRAP_METHOD(Debugger, cmdSound));
|
|
registerCmd("cheat", WRAP_METHOD(Debugger, cmdCheat));
|
|
registerCmd("frame", WRAP_METHOD(Debugger, cmdFrame));
|
|
}
|
|
|
|
int Debugger::strToInt(const char *s) {
|
|
if (!*s)
|
|
// No string at all
|
|
return 0;
|
|
else if (toupper(s[strlen(s) - 1]) != 'H')
|
|
// Standard decimal string
|
|
return atoi(s);
|
|
|
|
// Hexadecimal string
|
|
uint tmp = 0;
|
|
int read = sscanf(s, "%xh", &tmp);
|
|
if (read < 1)
|
|
error("strToInt failed on string \"%s\"", s);
|
|
return (int)tmp;
|
|
}
|
|
|
|
CRoomItem *Debugger::findRoom(const char *name) {
|
|
CTreeItem *root = g_vm->_window->_gameManager->_project;
|
|
CRoomItem *roomItem = dynamic_cast<CRoomItem *>(root->findByName(name));
|
|
if (roomItem)
|
|
return roomItem;
|
|
|
|
int roomNumber = strToInt(name);
|
|
for (CTreeItem *treeItem = root; treeItem; treeItem = treeItem->scan(root)) {
|
|
roomItem = dynamic_cast<CRoomItem *>(treeItem);
|
|
if (roomItem && roomItem->_roomNumber == roomNumber)
|
|
return roomItem;
|
|
}
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
CNodeItem *Debugger::findNode(CRoomItem *room, const char *name) {
|
|
CNodeItem *nodeItem = dynamic_cast<CNodeItem *>(room->findByName(name));
|
|
if (nodeItem)
|
|
return nodeItem;
|
|
|
|
int nodeNumber = strToInt(name);
|
|
nodeItem = dynamic_cast<CNodeItem *>(room->findChildInstanceOf(CNodeItem::_type));
|
|
while (nodeItem) {
|
|
if (nodeItem->_nodeNumber == nodeNumber)
|
|
return nodeItem;
|
|
|
|
nodeItem = dynamic_cast<CNodeItem *>(room->findNextInstanceOf(CNodeItem::_type, nodeItem));
|
|
}
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
CViewItem *Debugger::findView(CNodeItem *node, const char *name) {
|
|
CViewItem *viewItem = dynamic_cast<CViewItem *>(node->findByName(name));
|
|
if (viewItem)
|
|
return viewItem;
|
|
|
|
int viewNumber = strToInt(name);
|
|
viewItem = dynamic_cast<CViewItem *>(node->findChildInstanceOf(CViewItem::_type));
|
|
while (viewItem) {
|
|
if (viewItem->_viewNumber == viewNumber)
|
|
return viewItem;
|
|
|
|
viewItem = dynamic_cast<CViewItem *>(node->findNextInstanceOf(CViewItem::_type, viewItem));
|
|
}
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
void Debugger::listRooms() {
|
|
CGameManager &gm = *g_vm->_window->_gameManager;
|
|
CTreeItem *root = gm._project;
|
|
CViewItem *view = gm._gameState._gameLocation.getView();
|
|
CNodeItem *node = gm._gameState._gameLocation.getNode();
|
|
CRoomItem *room = gm._gameState._gameLocation.getRoom();
|
|
debugPrintf("Current location: %s, %s, %s\n", room->getName().c_str(),
|
|
node->getName().c_str(), view->getName().c_str());
|
|
|
|
debugPrintf("Available rooms:\n");
|
|
for (CTreeItem *treeItem = root; treeItem; treeItem = treeItem->scan(root)) {
|
|
CRoomItem *roomItem = dynamic_cast<CRoomItem *>(treeItem);
|
|
if (roomItem)
|
|
debugPrintf("%d - %s\n", roomItem->_roomNumber, roomItem->_name.c_str());
|
|
}
|
|
}
|
|
|
|
void Debugger::listRoom(CRoomItem *room) {
|
|
for (CTreeItem *treeItem = room; treeItem; treeItem = treeItem->scan(room)) {
|
|
CNodeItem *nodeItem = dynamic_cast<CNodeItem *>(treeItem);
|
|
if (nodeItem)
|
|
debugPrintf("%s\n", nodeItem->_name.c_str());
|
|
}
|
|
}
|
|
|
|
void Debugger::listNode(CNodeItem *node) {
|
|
for (CTreeItem *treeItem = node; treeItem; treeItem = treeItem->scan(node)) {
|
|
CViewItem *viewItem = dynamic_cast<CViewItem *>(treeItem);
|
|
if (viewItem)
|
|
debugPrintf("%s\n", viewItem->_name.c_str());
|
|
}
|
|
}
|
|
|
|
bool Debugger::cmdDump(int argc, const char **argv) {
|
|
// Get the starting node
|
|
CTreeItem *root = g_vm->_window->_gameManager->_project;
|
|
if (argc == 2)
|
|
root = root->findByName(argv[1]);
|
|
|
|
if (root == nullptr) {
|
|
debugPrintf("Could not find item\n");
|
|
} else {
|
|
root->dump(0);
|
|
debugPrintf("Item and it's content were dumped to stdout\n");
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool Debugger::cmdRoom(int argc, const char **argv) {
|
|
if (argc == 1) {
|
|
listRooms();
|
|
} else if (argc >= 2) {
|
|
CRoomItem *roomItem = findRoom(argv[1]);
|
|
|
|
if (!roomItem && argc == 2) {
|
|
// Presume it's a full view specified
|
|
CProjectItem *project = g_vm->_window->_project;
|
|
CViewItem *view = project->parseView(argv[1]);
|
|
|
|
if (view) {
|
|
project->changeView(argv[1]);
|
|
return false;
|
|
} else {
|
|
debugPrintf("Could not find view - %s\n", argv[1]);
|
|
}
|
|
} else if (argc == 2)
|
|
listRoom(roomItem);
|
|
else {
|
|
CNodeItem *nodeItem = findNode(roomItem, argv[2]);
|
|
|
|
if (!nodeItem)
|
|
debugPrintf("Could not find node - %s\n", argv[2]);
|
|
else if (argc == 3)
|
|
listNode(nodeItem);
|
|
else {
|
|
CViewItem *viewItem = findView(nodeItem, argv[3]);
|
|
|
|
if (!viewItem) {
|
|
debugPrintf("Could not find view - %s\n", argv[3]);
|
|
} else {
|
|
// Change to the specified view
|
|
g_vm->_window->_gameManager->_gameState.changeView(viewItem, nullptr);
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool Debugger::cmdPET(int argc, const char **argv) {
|
|
CGameManager &gameManager = *g_vm->_window->_gameManager;
|
|
CGameState &gameState = gameManager._gameState;
|
|
|
|
if (argc == 2) {
|
|
CString s(argv[1]);
|
|
s.toLowercase();
|
|
|
|
if (s == "on") {
|
|
gameState._petActive = true;
|
|
gameManager.markAllDirty();
|
|
debugPrintf("PET is now on\n");
|
|
return true;
|
|
} else if (s == "off") {
|
|
gameState._petActive = false;
|
|
gameManager.update();
|
|
debugPrintf("PET is now off\n");
|
|
return true;
|
|
}
|
|
}
|
|
|
|
debugPrintf("%s [on | off]\n", argv[0]);
|
|
return true;
|
|
}
|
|
|
|
bool Debugger::cmdItem(int argc, const char **argv) {
|
|
CGameManager &gameManager = *g_vm->_window->_gameManager;
|
|
CGameState &gameState = gameManager._gameState;
|
|
|
|
if (argc == 1) {
|
|
// No parameters, so list the available items
|
|
debugPrintf("item [<name> [ add ]]\n");
|
|
for (int idx = 0; idx < 40; ++idx)
|
|
debugPrintf("%s\n", g_vm->_itemIds[idx].c_str());
|
|
} else {
|
|
// Ensure the specified name is a valid inventory item
|
|
int itemIndex;
|
|
for (itemIndex = 0; itemIndex < 40; ++itemIndex) {
|
|
if (g_vm->_itemIds[itemIndex] == argv[1])
|
|
break;
|
|
}
|
|
if (itemIndex == 40) {
|
|
debugPrintf("Could not find item with that name\n");
|
|
return true;
|
|
}
|
|
|
|
// Get the item
|
|
CCarry *item = dynamic_cast<CCarry *>(
|
|
g_vm->_window->_project->findByName(argv[1]));
|
|
assert(item);
|
|
|
|
if (argc == 2) {
|
|
// List it's details
|
|
CTreeItem *treeItem = item;
|
|
CString fullName;
|
|
while ((treeItem = treeItem->getParent()) != nullptr) {
|
|
if (!treeItem->getName().empty())
|
|
fullName = treeItem->getName() + "." + fullName;
|
|
}
|
|
|
|
debugPrintf("Current location: %s\n", fullName.c_str());
|
|
} else if (CString(argv[2]) == "add") {
|
|
// Ensure the PET is active and add the item to the inventory
|
|
gameState._petActive = true;
|
|
gameManager.markAllDirty();
|
|
item->petAddToInventory();
|
|
|
|
return false;
|
|
} else {
|
|
debugPrintf("Unknown command\n");
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool Debugger::cmdMovie(int argc, const char **argv) {
|
|
if (argc < 2) {
|
|
debugPrintf("movie filename.avi [startFrame endFrame]\n");
|
|
return true;
|
|
}
|
|
|
|
CViewItem *view = g_vm->_window->_gameManager->getView();
|
|
CMovieTester *tester = static_cast<CMovieTester *>(
|
|
view->findChildInstanceOf(CMovieTester::_type));
|
|
if (!tester) {
|
|
// No movie tester present, so create one
|
|
tester = new CMovieTester();
|
|
tester->addUnder(view);
|
|
}
|
|
|
|
CString filename(argv[1]);
|
|
|
|
if (filename == "reverse" || filename == "doubletake") {
|
|
// Tests reverse playback transparency frames
|
|
tester->loadMovie("y457.avi");
|
|
if (filename == "reverse") {
|
|
tester->playMovie(436, 0, MOVIE_STOP_PREVIOUS);
|
|
} else {
|
|
tester->playMovie(436, 432, MOVIE_STOP_PREVIOUS);
|
|
tester->playMovie(432, 436, 0);
|
|
tester->playMovie(436, 432, 0);
|
|
tester->playMovie(432, 436, 0);
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
if (!filename.hasSuffix(".avi"))
|
|
filename += ".avi";
|
|
tester->loadMovie(filename);
|
|
|
|
if (argc == 2) {
|
|
tester->playMovie(MOVIE_STOP_PREVIOUS);
|
|
} else {
|
|
uint startFrame = strToInt(argv[2]);
|
|
uint endFrame = (argc == 3) ? startFrame : strToInt(argv[3]);
|
|
tester->playMovie(startFrame, endFrame, MOVIE_STOP_PREVIOUS);
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool Debugger::cmdSound(int argc, const char **argv) {
|
|
if (argc == 2) {
|
|
Common::String name = argv[1];
|
|
if (!name.contains("#"))
|
|
name = "z#" + name;
|
|
|
|
CGameManager *gameManager = g_vm->_window->_gameManager;
|
|
CProximity prox;
|
|
gameManager->_sound.playSound(name, prox);
|
|
return false;
|
|
} else {
|
|
debugPrintf("sound <name>\n");
|
|
return true;
|
|
}
|
|
}
|
|
|
|
bool Debugger::cmdCheat(int argc, const char **argv) {
|
|
CGameManager *gameManager = g_vm->_window->_gameManager;
|
|
CProjectItem *project = g_vm->_window->_project;
|
|
|
|
CViewItem *newView = project->parseView("Cheat Room.Node 1.Cheat Rooms View");
|
|
gameManager->_gameState.changeView(newView, nullptr);
|
|
return false;
|
|
}
|
|
|
|
bool Debugger::cmdFrame(int argc, const char **argv) {
|
|
if (argc == 3) {
|
|
CGameObject *obj = dynamic_cast<CGameObject *>(
|
|
g_vm->_window->_project->findByName(argv[1]));
|
|
|
|
if (obj) {
|
|
obj->loadFrame(strToInt(argv[2]));
|
|
return false;
|
|
} else {
|
|
debugPrintf("Object not found\n");
|
|
return true;
|
|
}
|
|
} else {
|
|
debugPrintf("frame <object> <frame number>");
|
|
return true;
|
|
}
|
|
}
|
|
|
|
} // End of namespace Titanic
|