/* 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. * * $URL$ * $Id$ * */ // Console module #include "sci/sci.h" #include "sci/console.h" #include "sci/resource.h" #include "sci/vocabulary.h" #include "sci/engine/savegame.h" #include "sci/engine/state.h" #include "sci/engine/gc.h" #include "sci/engine/kernel_types.h" // for determine_reg_type #include "sci/gfx/gfx_gui.h" // for sciw_set_status_bar #include "sci/gfx/gfx_state_internal.h" #include "sci/gfx/gfx_widgets.h" // for getPort #include "sci/sfx/songlib.h" // for songlib_t #include "sci/sfx/iterator.h" // for SCI_SONG_ITERATOR_TYPE_SCI0 #include "sci/sfx/sci_midi.h" #include "sci/vocabulary.h" #include "common/savefile.h" namespace Sci { extern EngineState *g_EngineState; int debug_sleeptime_factor = 1; int _kdebug_cheap_event_hack = 0; bool _kdebug_track_mouse_clicks = false; int _weak_validations = 1; // Some validation errors are reduced to warnings if non-0 Console::Console(SciEngine *vm) : GUI::Debugger() { _vm = vm; // Kernel // DCmd_Register("classes", WRAP_METHOD(Console, cmdClasses)); // TODO DCmd_Register("opcodes", WRAP_METHOD(Console, cmdOpcodes)); DCmd_Register("selectors", WRAP_METHOD(Console, cmdSelectors)); DCmd_Register("kernel_names", WRAP_METHOD(Console, cmdKernelNames)); DCmd_Register("registers", WRAP_METHOD(Console, cmdRegisters)); DCmd_Register("weak_validations", WRAP_METHOD(Console, cmdWeakValidations)); // Parser DCmd_Register("suffixes", WRAP_METHOD(Console, cmdSuffixes)); DCmd_Register("parse_grammar", WRAP_METHOD(Console, cmdParseGrammar)); DCmd_Register("parser_nodes", WRAP_METHOD(Console, cmdParserNodes)); DCmd_Register("parser_words", WRAP_METHOD(Console, cmdParserWords)); // Resources DCmd_Register("hexdump", WRAP_METHOD(Console, cmdHexDump)); DCmd_Register("resource_id", WRAP_METHOD(Console, cmdResourceId)); DCmd_Register("resource_size", WRAP_METHOD(Console, cmdResourceSize)); DCmd_Register("resource_types", WRAP_METHOD(Console, cmdResourceTypes)); DCmd_Register("list", WRAP_METHOD(Console, cmdList)); DCmd_Register("hexgrep", WRAP_METHOD(Console, cmdHexgrep)); // Game DCmd_Register("save_game", WRAP_METHOD(Console, cmdSaveGame)); DCmd_Register("restore_game", WRAP_METHOD(Console, cmdRestoreGame)); DCmd_Register("restart_game", WRAP_METHOD(Console, cmdRestartGame)); DCmd_Register("version", WRAP_METHOD(Console, cmdGetVersion)); DCmd_Register("room", WRAP_METHOD(Console, cmdRoomNumber)); // Graphics DCmd_Register("sci0_palette", WRAP_METHOD(Console, cmdSci0Palette)); DCmd_Register("clear_screen", WRAP_METHOD(Console, cmdClearScreen)); DCmd_Register("redraw_screen", WRAP_METHOD(Console, cmdRedrawScreen)); DCmd_Register("class_table", WRAP_METHOD(Console, cmdClassTable)); DCmd_Register("sentence_fragments", WRAP_METHOD(Console, cmdSentenceFragments)); DCmd_Register("draw_pic", WRAP_METHOD(Console, cmdDrawPic)); DCmd_Register("draw_rect", WRAP_METHOD(Console, cmdDrawRect)); DCmd_Register("draw_cel", WRAP_METHOD(Console, cmdDrawCel)); DCmd_Register("view_info", WRAP_METHOD(Console, cmdViewInfo)); DCmd_Register("update_zone", WRAP_METHOD(Console, cmdUpdateZone)); DCmd_Register("propagate_zone", WRAP_METHOD(Console, cmdPropagateZone)); DCmd_Register("fill_screen", WRAP_METHOD(Console, cmdFillScreen)); DCmd_Register("current_port", WRAP_METHOD(Console, cmdCurrentPort)); DCmd_Register("print_port", WRAP_METHOD(Console, cmdPrintPort)); DCmd_Register("visual_state", WRAP_METHOD(Console, cmdVisualState)); DCmd_Register("flush_visual", WRAP_METHOD(Console, cmdFlushPorts)); DCmd_Register("dynamic_views", WRAP_METHOD(Console, cmdDynamicViews)); DCmd_Register("dropped_views", WRAP_METHOD(Console, cmdDroppedViews)); DCmd_Register("priority_bands", WRAP_METHOD(Console, cmdPriorityBands)); DCmd_Register("status_bar", WRAP_METHOD(Console, cmdStatusBarColors)); DCmd_Register("show_map", WRAP_METHOD(Console, cmdShowMap)); // Events DCmd_Register("simkey", WRAP_METHOD(Console, cmdSimulateKey)); DCmd_Register("track_mouse", WRAP_METHOD(Console, cmdTrackMouse)); // Segments DCmd_Register("segment_table", WRAP_METHOD(Console, cmdPrintSegmentTable)); DCmd_Register("segment_info", WRAP_METHOD(Console, cmdSegmentInfo)); DCmd_Register("segment_kill", WRAP_METHOD(Console, cmdKillSegment)); // Garbage collection DCmd_Register("gc", WRAP_METHOD(Console, cmdGCInvoke)); DCmd_Register("gc_objects", WRAP_METHOD(Console, cmdGCObjects)); DCmd_Register("gc_interval", WRAP_METHOD(Console, cmdGCInterval)); DCmd_Register("gc_reachable", WRAP_METHOD(Console, cmdGCShowReachable)); DCmd_Register("gc_freeable", WRAP_METHOD(Console, cmdGCShowFreeable)); DCmd_Register("gc_normalize", WRAP_METHOD(Console, cmdGCNormalize)); // Music/SFX DCmd_Register("songlib", WRAP_METHOD(Console, cmdSongLib)); DCmd_Register("is_sample", WRAP_METHOD(Console, cmdIsSample)); DCmd_Register("sfx01_header", WRAP_METHOD(Console, cmdSfx01Header)); DCmd_Register("sfx01_track", WRAP_METHOD(Console, cmdSfx01Track)); DCmd_Register("stop_sfx", WRAP_METHOD(Console, cmdStopSfx)); // Script DCmd_Register("addresses", WRAP_METHOD(Console, cmdAddresses)); DCmd_Register("dissect_script", WRAP_METHOD(Console, cmdDissectScript)); DCmd_Register("script_steps", WRAP_METHOD(Console, cmdScriptSteps)); DCmd_Register("set_acc", WRAP_METHOD(Console, cmdSetAccumulator)); DCmd_Register("bp_list", WRAP_METHOD(Console, cmdBreakpointList)); DCmd_Register("bp_del", WRAP_METHOD(Console, cmdBreakpointDelete)); // VM DCmd_Register("vm_varlist", WRAP_METHOD(Console, cmdVMVarlist)); DCmd_Register("stack", WRAP_METHOD(Console, cmdStack)); DCmd_Register("value_type", WRAP_METHOD(Console, cmdValueType)); DCmd_Register("view_object", WRAP_METHOD(Console, cmdViewListNode)); DCmd_Register("view_object", WRAP_METHOD(Console, cmdViewObject)); DCmd_Register("active_object", WRAP_METHOD(Console, cmdViewActiveObject)); DCmd_Register("acc_object", WRAP_METHOD(Console, cmdViewAccumulatorObject)); DCmd_Register("sleep_factor", WRAP_METHOD(Console, cmdSleepFactor)); DCmd_Register("exit", WRAP_METHOD(Console, cmdExit)); // These were in sci.cpp /* con_hook_int(&(gfx_options.buffer_pics_nr), "buffer_pics_nr", "Number of pics to buffer in LRU storage\n"); con_hook_int(&(gfx_options.pic0_dither_mode), "pic0_dither_mode", "Mode to use for pic0 dithering\n"); con_hook_int(&(gfx_options.pic0_dither_pattern), "pic0_dither_pattern", "Pattern to use for pic0 dithering\n"); con_hook_int(&(gfx_options.pic0_unscaled), "pic0_unscaled", "Whether pic0 should be drawn unscaled\n"); con_hook_int(&(gfx_options.dirty_frames), "dirty_frames", "Dirty frames management\n"); */ } Console::~Console() { } static ResourceType parseResourceType(const char *resid) { // Gets the resource number of a resource string, or returns -1 ResourceType res = kResourceTypeInvalid; for (int i = 0; i < kResourceTypeInvalid; i++) if (strcmp(getResourceTypeName((ResourceType)i), resid) == 0) res = (ResourceType)i; return res; } bool Console::cmdGetVersion(int argc, const char **argv) { int ver = _vm->getVersion(); DebugPrintf("Resource file version: %s\n", sci_version_types[_vm->getResMgr()->_sciVersion]); DebugPrintf("Emulated interpreter version: %s\n", versionNames[ver]); return true; } bool Console::cmdOpcodes(int argc, const char **argv) { DebugPrintf("Opcode names in numeric order [index: type name]:\n"); for (uint seeker = 0; seeker < g_EngineState->_kernel->getOpcodesSize(); seeker++) { opcode op = g_EngineState->_kernel->getOpcode(seeker); DebugPrintf("%03x: %03x %20s | ", seeker, op.type, op.name.c_str()); if ((seeker % 3) == 2) DebugPrintf("\n"); } DebugPrintf("\n"); return true; } bool Console::cmdSelectors(int argc, const char **argv) { DebugPrintf("Selector names in numeric order:\n"); for (uint seeker = 0; seeker < g_EngineState->_kernel->getSelectorNamesSize(); seeker++) { DebugPrintf("%03x: %20s | ", seeker, g_EngineState->_kernel->getSelectorName(seeker).c_str()); if ((seeker % 3) == 2) DebugPrintf("\n"); } DebugPrintf("\n"); return true; } bool Console::cmdKernelNames(int argc, const char **argv) { DebugPrintf("Selector names in numeric order:\n"); for (uint seeker = 0; seeker < g_EngineState->_kernel->getKernelNamesSize(); seeker++) { DebugPrintf("%03x: %20s | ", seeker, g_EngineState->_kernel->getKernelName(seeker).c_str()); if ((seeker % 3) == 2) DebugPrintf("\n"); } DebugPrintf("\n"); return true; } bool Console::cmdSuffixes(int argc, const char **argv) { g_EngineState->_vocabulary->printSuffixes(); return true; } bool Console::cmdParserWords(int argc, const char **argv) { g_EngineState->_vocabulary->printParserWords(); return true; } bool Console::cmdRegisters(int argc, const char **argv) { DebugPrintf("Current register values:\n"); #if 0 // TODO: p_restadjust DebugPrintf("acc=%04x:%04x prev=%04x:%04x &rest=%x\n", PRINT_REG(g_EngineState->r_acc), PRINT_REG(g_EngineState->r_prev), *p_restadjust); #endif if (!g_EngineState->_executionStack.empty()) { #if 0 // TODO: p_pc, p_objp, p_pp, p_sp DebugPrintf("pc=%04x:%04x obj=%04x:%04x fp=ST:%04x sp=ST:%04x\n", PRINT_REG(*p_pc), PRINT_REG(*p_objp), PRINT_STK(*p_pp), PRINT_STK(*p_sp)); #endif } else DebugPrintf("\n"); return true; } bool Console::cmdHexDump(int argc, const char **argv) { if (argc != 3) { DebugPrintf("Usage: %s \n", argv[0]); cmdResourceTypes(argc, argv); return true; } int resNum = atoi(argv[2]); if (resNum == 0) { DebugPrintf("The resource number specified is not a number"); return true; } ResourceType res = parseResourceType(argv[1]); if (res == kResourceTypeInvalid) DebugPrintf("Resource type '%s' is not valid\n", argv[1]); else { Resource *resource = _vm->getResMgr()->findResource(res, resNum, 0); if (resource) { Common::hexdump(resource->data, resource->size, 16, 0); DebugPrintf("Resource %s.%03d has been dumped to standard output\n", argv[1], resNum); } else { DebugPrintf("Resource %s.%03d not found\n", argv[1], resNum); } } return true; } bool Console::cmdResourceId(int argc, const char **argv) { if (argc != 2) { DebugPrintf("Identifies a resource number by splitting it up in resource type and resource number\n"); DebugPrintf("Usage: %s \n", argv[0]); return true; } int id = atoi(argv[1]); DebugPrintf("%s.%d (0x%x)\n", getResourceTypeName((ResourceType)(id >> 11)), id & 0x7ff, id & 0x7ff); return true; } bool Console::cmdDissectScript(int argc, const char **argv) { if (argc != 2) { DebugPrintf("Examines a script\n"); DebugPrintf("Usage: %s