diff options
Diffstat (limited to 'engines/sci/console.cpp')
-rw-r--r-- | engines/sci/console.cpp | 649 |
1 files changed, 531 insertions, 118 deletions
diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp index e233c4cba4..b20ed3f8be 100644 --- a/engines/sci/console.cpp +++ b/engines/sci/console.cpp @@ -41,9 +41,7 @@ #include "sci/graphics/cache.h" #include "sci/graphics/cursor.h" #include "sci/graphics/screen.h" -#include "sci/graphics/paint.h" #include "sci/graphics/paint16.h" -#include "sci/graphics/paint32.h" #include "sci/graphics/palette.h" #include "sci/graphics/ports.h" #include "sci/graphics/view.h" @@ -54,8 +52,8 @@ #include "sci/video/seq_decoder.h" #ifdef ENABLE_SCI32 #include "sci/graphics/frameout.h" +#include "sci/graphics/paint32.h" #include "video/coktel_decoder.h" -#include "sci/video/robot_decoder.h" #endif #include "common/file.h" @@ -137,8 +135,12 @@ Console::Console(SciEngine *engine) : GUI::Debugger(), registerCmd("wl", WRAP_METHOD(Console, cmdWindowList)); // alias registerCmd("plane_list", WRAP_METHOD(Console, cmdPlaneList)); registerCmd("pl", WRAP_METHOD(Console, cmdPlaneList)); // alias + registerCmd("visible_plane_list", WRAP_METHOD(Console, cmdVisiblePlaneList)); + registerCmd("vpl", WRAP_METHOD(Console, cmdVisiblePlaneList)); // alias registerCmd("plane_items", WRAP_METHOD(Console, cmdPlaneItemList)); registerCmd("pi", WRAP_METHOD(Console, cmdPlaneItemList)); // alias + registerCmd("visible_plane_items", WRAP_METHOD(Console, cmdVisiblePlaneItemList)); + registerCmd("vpi", WRAP_METHOD(Console, cmdVisiblePlaneItemList)); // alias registerCmd("saved_bits", WRAP_METHOD(Console, cmdSavedBits)); registerCmd("show_saved_bits", WRAP_METHOD(Console, cmdShowSavedBits)); // Segments @@ -190,6 +192,7 @@ Console::Console(SciEngine *engine) : GUI::Debugger(), registerCmd("send", WRAP_METHOD(Console, cmdSend)); registerCmd("go", WRAP_METHOD(Console, cmdGo)); registerCmd("logkernel", WRAP_METHOD(Console, cmdLogKernel)); + registerCmd("vocab994", WRAP_METHOD(Console, cmdMapVocab994)); // Breakpoints registerCmd("bp_list", WRAP_METHOD(Console, cmdBreakpointList)); registerCmd("bplist", WRAP_METHOD(Console, cmdBreakpointList)); // alias @@ -209,6 +212,11 @@ Console::Console(SciEngine *engine) : GUI::Debugger(), registerCmd("bpe", WRAP_METHOD(Console, cmdBreakpointFunction)); // alias // VM registerCmd("script_steps", WRAP_METHOD(Console, cmdScriptSteps)); + registerCmd("script_objects", WRAP_METHOD(Console, cmdScriptObjects)); + registerCmd("scro", WRAP_METHOD(Console, cmdScriptObjects)); + registerCmd("script_strings", WRAP_METHOD(Console, cmdScriptStrings)); + registerCmd("scrs", WRAP_METHOD(Console, cmdScriptStrings)); + registerCmd("script_said", WRAP_METHOD(Console, cmdScriptSaid)); registerCmd("vm_varlist", WRAP_METHOD(Console, cmdVMVarlist)); registerCmd("vmvarlist", WRAP_METHOD(Console, cmdVMVarlist)); // alias registerCmd("vl", WRAP_METHOD(Console, cmdVMVarlist)); // alias @@ -257,8 +265,6 @@ void Console::postEnter() { #ifdef ENABLE_SCI32 } else if (_videoFile.hasSuffix(".vmd")) { videoDecoder = new Video::AdvancedVMDDecoder(); - } else if (_videoFile.hasSuffix(".rbt")) { - videoDecoder = new RobotDecoder(_engine->getPlatform() == Common::kPlatformMacintosh); } else if (_videoFile.hasSuffix(".duk")) { duckMode = true; videoDecoder = new Video::AVIDecoder(); @@ -325,6 +331,7 @@ bool Console::cmdHelp(int argc, const char **argv) { debugPrintf("debugflag_list - Lists the available debug flags and their status\n"); debugPrintf("debugflag_enable - Enables a debug flag\n"); debugPrintf("debugflag_disable - Disables a debug flag\n"); + debugPrintf("debuglevel - Shows or sets debug level\n"); debugPrintf("\n"); debugPrintf("Commands\n"); debugPrintf("--------\n"); @@ -375,7 +382,9 @@ bool Console::cmdHelp(int argc, const char **argv) { debugPrintf(" animate_list / al - Shows the current list of objects in kAnimate's draw list (SCI0 - SCI1.1)\n"); debugPrintf(" window_list / wl - Shows a list of all the windows (ports) in the draw list (SCI0 - SCI1.1)\n"); debugPrintf(" plane_list / pl - Shows a list of all the planes in the draw list (SCI2+)\n"); + debugPrintf(" visible_plane_list / vpl - Shows a list of all the planes in the visible draw list (SCI2+)\n"); debugPrintf(" plane_items / pi - Shows a list of all items for a plane (SCI2+)\n"); + debugPrintf(" visible_plane_items / vpi - Shows a list of all items for a plane in the visible draw list (SCI2+)\n"); debugPrintf(" saved_bits - List saved bits on the hunk\n"); debugPrintf(" show_saved_bits - Display saved bits\n"); debugPrintf("\n"); @@ -477,15 +486,19 @@ bool Console::cmdGetVersion(int argc, const char **argv) { debugPrintf("Lofs type: %s\n", getSciVersionDesc(_engine->_features->detectLofsType())); debugPrintf("Move count type: %s\n", (_engine->_features->handleMoveCount()) ? "increment" : "ignore"); debugPrintf("SetCursor type: %s\n", getSciVersionDesc(_engine->_features->detectSetCursorType())); + debugPrintf("PseudoMouse ability: %s\n", _engine->_features->detectPseudoMouseAbility() == kPseudoMouseAbilityTrue ? "yes" : "no"); #ifdef ENABLE_SCI32 - if (getSciVersion() >= SCI_VERSION_2) - debugPrintf("kString type: %s\n", (_engine->_features->detectSci2StringFunctionType() == kSci2StringFunctionOld) ? "SCI2 (old)" : "SCI2.1 (new)"); - if (getSciVersion() == SCI_VERSION_2_1) + if ((getSciVersion() >= SCI_VERSION_2_1_EARLY) && (getSciVersion() <= SCI_VERSION_2_1_LATE)) debugPrintf("SCI2.1 kernel table: %s\n", (_engine->_features->detectSci21KernelType() == SCI_VERSION_2) ? "modified SCI2 (old)" : "SCI2.1 (new)"); #endif debugPrintf("View type: %s\n", viewTypeDesc[g_sci->getResMan()->getViewType()]); - debugPrintf("Uses palette merging: %s\n", g_sci->_gfxPalette->isMerging() ? "yes" : "no"); - debugPrintf("Uses 16 bit color matching: %s\n", g_sci->_gfxPalette->isUsing16bitColorMatch() ? "yes" : "no"); + if (getSciVersion() <= SCI_VERSION_1_1) { + debugPrintf("kAnimate fastCast enabled: %s\n", g_sci->_gfxAnimate->isFastCastEnabled() ? "yes" : "no"); + } + if (getSciVersion() < SCI_VERSION_2) { + debugPrintf("Uses palette merging: %s\n", g_sci->_gfxPalette16->isMerging() ? "yes" : "no"); + debugPrintf("Uses 16 bit color matching: %s\n", g_sci->_gfxPalette16->isUsing16bitColorMatch() ? "yes" : "no"); + } debugPrintf("Resource volume version: %s\n", g_sci->getResMan()->getVolVersionDesc()); debugPrintf("Resource map version: %s\n", g_sci->getResMan()->getMapVersionDesc()); debugPrintf("Contains selector vocabulary (vocab.997): %s\n", hasVocab997 ? "yes" : "no"); @@ -660,10 +673,33 @@ bool Console::cmdRegisters(int argc, const char **argv) { return true; } +bool Console::parseResourceNumber36(const char *userParameter, uint16 &resourceNumber, uint32 &resourceTuple) { + int userParameterLen = strlen(userParameter); + + if (userParameterLen != 10) { + debugPrintf("Audio36/Sync36 resource numbers must be specified as RRRNNVVCCS\n"); + debugPrintf("where RRR is the resource number/map\n"); + debugPrintf(" NN is the noun\n"); + debugPrintf(" VV is the verb\n"); + debugPrintf(" CC is the cond\n"); + debugPrintf(" S is the seq\n"); + return false; + } + + // input: RRRNNVVCCS + resourceNumber = strtol(Common::String(userParameter, 3).c_str(), 0, 36); + uint16 noun = strtol(Common::String(userParameter + 3, 2).c_str(), 0, 36); + uint16 verb = strtol(Common::String(userParameter + 5, 2).c_str(), 0, 36); + uint16 cond = strtol(Common::String(userParameter + 7, 2).c_str(), 0, 36); + uint16 seq = strtol(Common::String(userParameter + 9, 1).c_str(), 0, 36); + resourceTuple = ((noun & 0xff) << 24) | ((verb & 0xff) << 16) | ((cond & 0xff) << 8) | (seq & 0xff); + return true; +} + bool Console::cmdDiskDump(int argc, const char **argv) { - int resNumFrom = 0; - int resNumTo = 0; - int resNumCur = 0; + bool resourceAll = false; + uint16 resourceNumber = 0; + uint32 resourceTuple = 0; if (argc != 3) { debugPrintf("Dumps the specified resource to disk as a patch file\n"); @@ -673,42 +709,90 @@ bool Console::cmdDiskDump(int argc, const char **argv) { return true; } + ResourceType resourceType = parseResourceType(argv[1]); + if (resourceType == kResourceTypeInvalid) { + debugPrintf("Resource type '%s' is not valid\n", argv[1]); + return true; + } + if (strcmp(argv[2], "*") == 0) { - resNumFrom = 0; - resNumTo = 65535; + resourceAll = true; } else { - resNumFrom = atoi(argv[2]); - resNumTo = resNumFrom; + switch (resourceType) { + case kResourceTypeAudio36: + case kResourceTypeSync36: + if (!parseResourceNumber36(argv[2], resourceNumber, resourceTuple)) { + return true; + } + break; + default: + resourceNumber = atoi(argv[2]); + break; + } } - ResourceType res = parseResourceType(argv[1]); - - if (res == kResourceTypeInvalid) + if (resourceType == kResourceTypeInvalid) { debugPrintf("Resource type '%s' is not valid\n", argv[1]); - else { - for (resNumCur = resNumFrom; resNumCur <= resNumTo; resNumCur++) { - Resource *resource = _engine->getResMan()->findResource(ResourceId(res, resNumCur), 0); - if (resource) { - char outFileName[50]; - sprintf(outFileName, "%s.%03d", getResourceTypeName(res), resNumCur); - Common::DumpFile *outFile = new Common::DumpFile(); - outFile->open(outFileName); - resource->writeToStream(outFile); - outFile->finalize(); - outFile->close(); - delete outFile; - debugPrintf("Resource %s.%03d (located in %s) has been dumped to disk\n", argv[1], resNumCur, resource->getResourceLocation().c_str()); - } else { - if (resNumFrom == resNumTo) { - debugPrintf("Resource %s.%03d not found\n", argv[1], resNumCur); - } - } + return true; + } + + if (resourceAll) { + // "*" used, dump everything of that type + Common::List<ResourceId> resources = _engine->getResMan()->listResources(resourceType, -1); + Common::sort(resources.begin(), resources.end()); + + Common::List<ResourceId>::iterator itr; + for (itr = resources.begin(); itr != resources.end(); ++itr) { + resourceNumber = itr->getNumber(); + resourceTuple = itr->getTuple(); + cmdDiskDumpWorker(resourceType, resourceNumber, resourceTuple); } + } else { + // id was given, dump only this resource + cmdDiskDumpWorker(resourceType, resourceNumber, resourceTuple); } return true; } +void Console::cmdDiskDumpWorker(ResourceType resourceType, int resourceNumber, uint32 resourceTuple) { + const char *resourceTypeName = getResourceTypeName(resourceType); + ResourceId resourceId; + Resource *resource = NULL; + char outFileName[50]; + + switch (resourceType) { + case kResourceTypeAudio36: + case kResourceTypeSync36: { + resourceId = ResourceId(resourceType, resourceNumber, resourceTuple); + resource = _engine->getResMan()->findResource(resourceId, 0); + sprintf(outFileName, "%s", resourceId.toPatchNameBase36().c_str()); + // patch filename is: [type:1 char] [map:3 chars] [noun:2 chars] [verb:2 chars] "." [cond: 2 chars] [seq:1 char] + // e.g. "@5EG0000.014" + break; + } + default: + resourceId = ResourceId(resourceType, resourceNumber); + resource = _engine->getResMan()->findResource(resourceId, 0); + sprintf(outFileName, "%s.%03d", resourceTypeName, resourceNumber); + // patch filename is: [resourcetype].[resourcenumber] + // e.g. "Script.0" + break; + } + + if (resource) { + Common::DumpFile *outFile = new Common::DumpFile(); + outFile->open(outFileName); + resource->writeToStream(outFile); + outFile->finalize(); + outFile->close(); + delete outFile; + debugPrintf("Resource %s (located in %s) has been dumped to disk\n", outFileName, resource->getResourceLocation().c_str()); + } else { + debugPrintf("Resource %s not found\n", outFileName); + } +} + bool Console::cmdHexDump(int argc, const char **argv) { if (argc != 3) { debugPrintf("Dumps the specified resource to standard output\n"); @@ -748,6 +832,77 @@ bool Console::cmdResourceId(int argc, const char **argv) { return true; } +bool Console::cmdList(int argc, const char **argv) { + int selectedMapNumber = -1; + Common::List<ResourceId> resources; + Common::List<ResourceId>::iterator itr; + int displayCount = 0; + int currentMap = -1; + + if (argc < 2) { + debugPrintf("Lists all the resources of a given type\n"); + cmdResourceTypes(argc, argv); + return true; + } + + ResourceType resourceType = parseResourceType(argv[1]); + if (resourceType == kResourceTypeInvalid) { + debugPrintf("Unknown resource type: '%s'\n", argv[1]); + return true; + } + + switch (resourceType) { + case kResourceTypeAudio36: + case kResourceTypeSync36: + if (argc != 3) { + debugPrintf("Please specify map number (-1: all maps)\n"); + return true; + } + selectedMapNumber = atoi(argv[2]); + resources = _engine->getResMan()->listResources(resourceType, selectedMapNumber); + Common::sort(resources.begin(), resources.end()); + + for (itr = resources.begin(); itr != resources.end(); ++itr) { + const uint16 map = itr->getNumber(); + const uint32 resourceTuple = itr->getTuple(); + const uint16 noun = (resourceTuple >> 24) & 0xff; + const uint16 verb = (resourceTuple >> 16) & 0xff; + const uint16 cond = (resourceTuple >> 8) & 0xff; + const uint16 seq = resourceTuple & 0xff; + + if (currentMap != map) { + if (displayCount % 3) + debugPrintf("\n"); + debugPrintf("Map %04x (%i):\n", map, map); + currentMap = map; + displayCount = 0; + } + + if (displayCount % 3 == 0) + debugPrintf(" "); + + debugPrintf("%02x %02x %02x %02x (%3i %3i %3i %3i) ", noun, verb, cond, seq, noun, verb, cond, seq); + + if (++displayCount % 3 == 0) + debugPrintf("\n"); + } + break; + default: + resources = _engine->getResMan()->listResources(resourceType); + Common::sort(resources.begin(), resources.end()); + + for (itr = resources.begin(); itr != resources.end(); ++itr) { + debugPrintf("%8i", itr->getNumber()); + if (++displayCount % 10 == 0) + debugPrintf("\n"); + } + break; + } + + debugPrintf("\n"); + return true; +} + bool Console::cmdDissectScript(int argc, const char **argv) { if (argc != 2) { debugPrintf("Examines a script\n"); @@ -849,7 +1004,7 @@ bool Console::cmdHexgrep(int argc, const char **argv) { for (; resNumber <= resMax; resNumber++) { script = _engine->getResMan()->findResource(ResourceId(restype, resNumber), 0); if (script) { - unsigned int seeker = 0, seekerold = 0; + uint32 seeker = 0, seekerold = 0; uint32 comppos = 0; int output_script_name = 0; @@ -899,7 +1054,7 @@ bool Console::cmdVerifyScripts(int argc, const char **argv) { if (!script) debugPrintf("Error: script %d couldn't be loaded\n", itr->getNumber()); - if (getSciVersion() <= SCI_VERSION_2_1) { + if (getSciVersion() <= SCI_VERSION_2_1_LATE) { heap = _engine->getResMan()->findResource(ResourceId(kResourceTypeHeap, itr->getNumber()), false); if (!heap) debugPrintf("Error: script %d doesn't have a corresponding heap\n", itr->getNumber()); @@ -1124,52 +1279,6 @@ bool Console::cmdMapInstrument(int argc, const char **argv) { return true; } -bool Console::cmdList(int argc, const char **argv) { - if (argc < 2) { - debugPrintf("Lists all the resources of a given type\n"); - cmdResourceTypes(argc, argv); - return true; - } - - - ResourceType res = parseResourceType(argv[1]); - if (res == kResourceTypeInvalid) - debugPrintf("Unknown resource type: '%s'\n", argv[1]); - else { - int number = -1; - - if ((res == kResourceTypeAudio36) || (res == kResourceTypeSync36)) { - if (argc != 3) { - debugPrintf("Please specify map number (-1: all maps)\n"); - return true; - } - number = atoi(argv[2]); - } - - Common::List<ResourceId> resources = _engine->getResMan()->listResources(res, number); - Common::sort(resources.begin(), resources.end()); - - int cnt = 0; - Common::List<ResourceId>::iterator itr; - for (itr = resources.begin(); itr != resources.end(); ++itr) { - if (number == -1) { - debugPrintf("%8i", itr->getNumber()); - if (++cnt % 10 == 0) - debugPrintf("\n"); - } else if (number == (int)itr->getNumber()) { - const uint32 tuple = itr->getTuple(); - debugPrintf("(%3i, %3i, %3i, %3i) ", (tuple >> 24) & 0xff, (tuple >> 16) & 0xff, - (tuple >> 8) & 0xff, tuple & 0xff); - if (++cnt % 4 == 0) - debugPrintf("\n"); - } - } - debugPrintf("\n"); - } - - return true; -} - bool Console::cmdSaveGame(int argc, const char **argv) { if (argc != 2) { debugPrintf("Saves the current game state to the hard disk\n"); @@ -1401,7 +1510,7 @@ bool Console::cmdSaid(int argc, const char **argv) { } // TODO: Maybe turn this into a proper said spec compiler - unsigned int len = 0; + uint32 len = 0; for (p++; p < argc; p++) { if (strcmp(argv[p], ",") == 0) { spec[len++] = 0xf0; @@ -1438,7 +1547,7 @@ bool Console::cmdSaid(int argc, const char **argv) { spec[len++] = 0xfe; spec[len++] = 0xf6; } else { - unsigned int s = strtol(argv[p], 0, 16); + uint32 s = strtol(argv[p], 0, 16); if (s >= 0xf0 && s <= 0xff) { spec[len++] = s; } else { @@ -1511,7 +1620,7 @@ bool Console::cmdParserNodes(int argc, const char **argv) { bool Console::cmdSetPalette(int argc, const char **argv) { if (argc < 2) { - debugPrintf("Sets a palette resource\n"); + debugPrintf("Sets a palette resource (SCI16)\n"); debugPrintf("Usage: %s <resourceId>\n", argv[0]); debugPrintf("where <resourceId> is the number of the palette resource to set\n"); return true; @@ -1519,7 +1628,14 @@ bool Console::cmdSetPalette(int argc, const char **argv) { uint16 resourceId = atoi(argv[1]); - _engine->_gfxPalette->kernelSetFromResource(resourceId, true); +#ifdef ENABLE_SCI32 + if (getSciVersion() >= SCI_VERSION_2) { + debugPrintf("This SCI version does not support this command\n"); + return true; + } +#endif + + _engine->_gfxPalette16->kernelSetFromResource(resourceId, true); return true; } @@ -1538,7 +1654,7 @@ bool Console::cmdDrawPic(int argc, const char **argv) { #endif uint16 resourceId = atoi(argv[1]); - _engine->_gfxPaint->kernelDrawPicture(resourceId, 100, false, false, false, 0); + _engine->_gfxPaint16->kernelDrawPicture(resourceId, 100, false, false, false, 0); _engine->_gfxScreen->copyToScreen(); _engine->sleep(2000); @@ -1667,6 +1783,21 @@ bool Console::cmdPlaneList(int argc, const char **argv) { return true; } +bool Console::cmdVisiblePlaneList(int argc, const char **argv) { +#ifdef ENABLE_SCI32 + if (_engine->_gfxFrameout) { + debugPrintf("Visible plane list:\n"); + _engine->_gfxFrameout->printVisiblePlaneList(this); + } else { + debugPrintf("This SCI version does not have a list of planes\n"); + } +#else + debugPrintf("SCI32 isn't included in this compiled executable\n"); +#endif + return true; +} + + bool Console::cmdPlaneItemList(int argc, const char **argv) { if (argc != 2) { debugPrintf("Shows the list of items for a plane\n"); @@ -1695,6 +1826,34 @@ bool Console::cmdPlaneItemList(int argc, const char **argv) { return true; } +bool Console::cmdVisiblePlaneItemList(int argc, const char **argv) { + if (argc != 2) { + debugPrintf("Shows the list of items for a plane\n"); + debugPrintf("Usage: %s <plane address>\n", argv[0]); + return true; + } + + reg_t planeObject = NULL_REG; + + if (parse_reg_t(_engine->_gamestate, argv[1], &planeObject, false)) { + debugPrintf("Invalid address passed.\n"); + debugPrintf("Check the \"addresses\" command on how to use addresses\n"); + return true; + } + +#ifdef ENABLE_SCI32 + if (_engine->_gfxFrameout) { + debugPrintf("Visible plane item list:\n"); + _engine->_gfxFrameout->printVisiblePlaneItemList(this, planeObject); + } else { + debugPrintf("This SCI version does not have a list of plane items\n"); + } +#else + debugPrintf("SCI32 isn't included in this compiled executable\n"); +#endif + return true; +} + bool Console::cmdSavedBits(int argc, const char **argv) { SegManager *segman = _engine->_gamestate->_segMan; SegmentId id = segman->findSegmentByType(SEG_TYPE_HUNK); @@ -1708,7 +1867,7 @@ bool Console::cmdSavedBits(int argc, const char **argv) { for (uint i = 0; i < entries.size(); ++i) { uint16 offset = entries[i].getOffset(); - const Hunk& h = hunks->_table[offset]; + const Hunk& h = hunks->at(offset); if (strcmp(h.type, "SaveBits()") == 0) { byte* memoryPtr = (byte *)h.mem; @@ -1775,7 +1934,7 @@ bool Console::cmdShowSavedBits(int argc, const char **argv) { return true; } - const Hunk& h = hunks->_table[memoryHandle.getOffset()]; + const Hunk& h = hunks->at(memoryHandle.getOffset()); if (strcmp(h.type, "SaveBits()") != 0) { debugPrintf("Invalid address.\n"); @@ -1919,6 +2078,10 @@ bool Console::cmdPrintSegmentTable(int argc, const char **argv) { case SEG_TYPE_STRING: debugPrintf("T SCI32 strings (%d)", (*(StringTable *)mobj).entries_used); break; + + case SEG_TYPE_BITMAP: + debugPrintf("T SCI32 bitmaps (%d)", (*(BitmapTable *)mobj).entries_used); + break; #endif default: @@ -1991,32 +2154,32 @@ bool Console::segmentInfo(int nr) { break; case SEG_TYPE_CLONES: { - CloneTable *ct = (CloneTable *)mobj; + CloneTable &ct = *(CloneTable *)mobj; debugPrintf("clones\n"); - for (uint i = 0; i < ct->_table.size(); i++) - if (ct->isValidEntry(i)) { + for (uint i = 0; i < ct.size(); i++) + if (ct.isValidEntry(i)) { reg_t objpos = make_reg(nr, i); debugPrintf(" [%04x] %s; copy of ", i, _engine->_gamestate->_segMan->getObjectName(objpos)); // Object header - const Object *obj = _engine->_gamestate->_segMan->getObject(ct->_table[i].getPos()); + const Object *obj = _engine->_gamestate->_segMan->getObject(ct[i].getPos()); if (obj) - debugPrintf("[%04x:%04x] %s : %3d vars, %3d methods\n", PRINT_REG(ct->_table[i].getPos()), - _engine->_gamestate->_segMan->getObjectName(ct->_table[i].getPos()), + debugPrintf("[%04x:%04x] %s : %3d vars, %3d methods\n", PRINT_REG(ct[i].getPos()), + _engine->_gamestate->_segMan->getObjectName(ct[i].getPos()), obj->getVarCount(), obj->getMethodCount()); } } break; case SEG_TYPE_LISTS: { - ListTable *lt = (ListTable *)mobj; + ListTable < = *(ListTable *)mobj; debugPrintf("lists\n"); - for (uint i = 0; i < lt->_table.size(); i++) - if (lt->isValidEntry(i)) { + for (uint i = 0; i < lt.size(); i++) + if (lt.isValidEntry(i)) { debugPrintf(" [%04x]: ", i); - printList(&(lt->_table[i])); + printList(<[i]); } } break; @@ -2027,13 +2190,13 @@ bool Console::segmentInfo(int nr) { } case SEG_TYPE_HUNK: { - HunkTable *ht = (HunkTable *)mobj; + HunkTable &ht = *(HunkTable *)mobj; - debugPrintf("hunk (total %d)\n", ht->entries_used); - for (uint i = 0; i < ht->_table.size(); i++) - if (ht->isValidEntry(i)) { + debugPrintf("hunk (total %d)\n", ht.entries_used); + for (uint i = 0; i < ht.size(); i++) + if (ht.isValidEntry(i)) { debugPrintf(" [%04x] %d bytes at %p, type=%s\n", - i, ht->_table[i].size, ht->_table[i].mem, ht->_table[i].type); + i, ht[i].size, ht[i].mem, ht[i].type); } } break; @@ -2053,6 +2216,9 @@ bool Console::segmentInfo(int nr) { case SEG_TYPE_ARRAY: debugPrintf("SCI32 arrays\n"); break; + case SEG_TYPE_BITMAP: + debugPrintf("SCI32 bitmaps\n"); + break; #endif default : @@ -2172,6 +2338,7 @@ bool Console::cmdStartSound(int argc, const char **argv) { return true; } + // TODO: Maybe also add a playBed option. g_sci->_soundCmd->startNewSound(number); return cmdExit(0, 0); } @@ -2198,9 +2365,10 @@ bool Console::cmdToggleSound(int argc, const char **argv) { Common::String newState = argv[2]; newState.toLowercase(); - if (newState == "play") - g_sci->_soundCmd->processPlaySound(id); - else if (newState == "stop") + if (newState == "play") { + // Maybe also have a 'playbed' option. (Second argument to processPlaySound.) + g_sci->_soundCmd->processPlaySound(id, false); + } else if (newState == "stop") g_sci->_soundCmd->processStopSound(id, false); else debugPrintf("New state can either be 'play' or 'stop'"); @@ -2410,9 +2578,14 @@ bool Console::cmdVMVars(int argc, const char **argv) { case 1: case 2: case 3: { - // for global, local, temp and param, we need an index if (argc < 3) { - debugPrintf("Variable number must be specified for requested type\n"); + for (int i = 0; i < s->variablesMax[varType]; ++i) { + curValue = &s->variables[varType][i]; + debugPrintf("%s var %d == %04x:%04x", varNames[varType], i, PRINT_REG(*curValue)); + printBasicVarInfo(*curValue); + debugPrintf("\n"); + } + return true; } if (argc > 4) { @@ -2647,6 +2820,12 @@ bool Console::cmdViewReference(int argc, const char **argv) { hexDumpReg(array->getRawData(), array->getSize(), 4, 0, true); break; } + case SEG_TYPE_BITMAP: { + debugPrintf("SCI32 bitmap:\n"); + const SciBitmap *bitmap = _engine->_gamestate->_segMan->lookupBitmap(reg); + Common::hexdump((const byte *) bitmap->getRawData(), bitmap->getRawSize(), 16, 0); + break; + } #endif default: { const SegmentRef block = _engine->_gamestate->_segMan->dereference(reg); @@ -2730,6 +2909,186 @@ bool Console::cmdScriptSteps(int argc, const char **argv) { return true; } +bool Console::cmdScriptObjects(int argc, const char **argv) { + int curScriptNr = -1; + + if (argc < 2) { + debugPrintf("Shows all objects inside a specified script.\n"); + debugPrintf("Usage: %s <script number>\n", argv[0]); + debugPrintf("Example: %s 999\n", argv[0]); + debugPrintf("<script number> may be * to show objects inside all loaded scripts\n"); + return true; + } + + if (strcmp(argv[1], "*") == 0) { + // get said-strings of all currently loaded scripts + curScriptNr = -1; + } else { + curScriptNr = atoi(argv[1]); + } + + printOffsets(curScriptNr, SCI_SCR_OFFSET_TYPE_OBJECT); + return true; +} + +bool Console::cmdScriptStrings(int argc, const char **argv) { + int curScriptNr = -1; + + if (argc < 2) { + debugPrintf("Shows all strings inside a specified script.\n"); + debugPrintf("Usage: %s <script number>\n", argv[0]); + debugPrintf("Example: %s 999\n", argv[0]); + debugPrintf("<script number> may be * to show strings inside all loaded scripts\n"); + return true; + } + + if (strcmp(argv[1], "*") == 0) { + // get strings of all currently loaded scripts + curScriptNr = -1; + } else { + curScriptNr = atoi(argv[1]); + } + + printOffsets(curScriptNr, SCI_SCR_OFFSET_TYPE_STRING); + return true; +} + +bool Console::cmdScriptSaid(int argc, const char **argv) { + int curScriptNr = -1; + + if (argc < 2) { + debugPrintf("Shows all said-strings inside a specified script.\n"); + debugPrintf("Usage: %s <script number>\n", argv[0]); + debugPrintf("Example: %s 999\n", argv[0]); + debugPrintf("<script number> may be * to show said-strings inside all loaded scripts\n"); + return true; + } + + if (strcmp(argv[1], "*") == 0) { + // get said-strings of all currently loaded scripts + curScriptNr = -1; + } else { + curScriptNr = atoi(argv[1]); + } + + printOffsets(curScriptNr, SCI_SCR_OFFSET_TYPE_SAID); + return true; +} + +void Console::printOffsets(int scriptNr, uint16 showType) { + SegManager *segMan = _engine->_gamestate->_segMan; + Vocabulary *vocab = _engine->_vocabulary; + SegmentId curSegmentNr; + Common::List<SegmentId> segmentNrList; + + SegmentType curSegmentType = SEG_TYPE_INVALID; + SegmentObj *curSegmentObj = NULL; + Script *curScriptObj = NULL; + const byte *curScriptData = NULL; + + segmentNrList.clear(); + if (scriptNr < 0) { + // get offsets of all currently loaded scripts + for (curSegmentNr = 0; curSegmentNr < segMan->_heap.size(); curSegmentNr++) { + curSegmentObj = segMan->_heap[curSegmentNr]; + if (curSegmentObj && curSegmentObj->getType() == SEG_TYPE_SCRIPT) { + segmentNrList.push_back(curSegmentNr); + } + } + + } else { + curSegmentNr = segMan->getScriptSegment(scriptNr); + if (!curSegmentNr) { + debugPrintf("Script %d is currently not loaded/available\n", scriptNr); + return; + } + segmentNrList.push_back(curSegmentNr); + } + + const offsetLookupArrayType *scriptOffsetLookupArray; + offsetLookupArrayType::const_iterator arrayIterator; + int showTypeCount = 0; + + reg_t objectPos; + const char *objectNamePtr = NULL; + const byte *stringPtr = NULL; + const byte *saidPtr = NULL; + + Common::List<SegmentId>::iterator it; + const Common::List<SegmentId>::iterator end = segmentNrList.end(); + + for (it = segmentNrList.begin(); it != end; it++) { + curSegmentNr = *it; + // get object of this segment + curSegmentObj = segMan->getSegmentObj(curSegmentNr); + if (!curSegmentObj) + continue; + + curSegmentType = curSegmentObj->getType(); + if (curSegmentType != SEG_TYPE_SCRIPT) // safety check + continue; + + curScriptObj = (Script *)curSegmentObj; + debugPrintf("=== SCRIPT %d inside Segment %d ===\n", curScriptObj->getScriptNumber(), curSegmentNr); + debugN("=== SCRIPT %d inside Segment %d ===\n", curScriptObj->getScriptNumber(), curSegmentNr); + + // now print the list + scriptOffsetLookupArray = curScriptObj->getOffsetArray(); + curScriptData = curScriptObj->getBuf(); + showTypeCount = 0; + + for (arrayIterator = scriptOffsetLookupArray->begin(); arrayIterator != scriptOffsetLookupArray->end(); arrayIterator++) { + if (arrayIterator->type == showType) { + switch (showType) { + case SCI_SCR_OFFSET_TYPE_OBJECT: + objectPos = make_reg(curSegmentNr, arrayIterator->offset); + objectNamePtr = segMan->getObjectName(objectPos); + debugPrintf(" %03d:%04x: %s\n", arrayIterator->id, arrayIterator->offset, objectNamePtr); + debugN(" %03d:%04x: %s\n", arrayIterator->id, arrayIterator->offset, objectNamePtr); + break; + case SCI_SCR_OFFSET_TYPE_STRING: + stringPtr = curScriptData + arrayIterator->offset; + debugPrintf(" %03d:%04x: '%s' (size %d)\n", arrayIterator->id, arrayIterator->offset, stringPtr, arrayIterator->stringSize); + debugN(" %03d:%04x: '%s' (size %d)\n", arrayIterator->id, arrayIterator->offset, stringPtr, arrayIterator->stringSize); + break; + case SCI_SCR_OFFSET_TYPE_SAID: + saidPtr = curScriptData + arrayIterator->offset; + debugPrintf(" %03d:%04x:\n", arrayIterator->id, arrayIterator->offset); + debugN(" %03d:%04x: ", arrayIterator->id, arrayIterator->offset); + vocab->debugDecipherSaidBlock(saidPtr); + debugN("\n"); + break; + default: + break; + } + showTypeCount++; + } + } + + if (showTypeCount == 0) { + switch (showType) { + case SCI_SCR_OFFSET_TYPE_OBJECT: + debugPrintf(" no objects\n"); + debugN(" no objects\n"); + break; + case SCI_SCR_OFFSET_TYPE_STRING: + debugPrintf(" no strings\n"); + debugN(" no strings\n"); + break; + case SCI_SCR_OFFSET_TYPE_SAID: + debugPrintf(" no said-strings\n"); + debugN(" no said-strings\n"); + break; + default: + break; + } + } + + debugPrintf("\n"); + debugN("\n"); + } +} + bool Console::cmdBacktrace(int argc, const char **argv) { debugPrintf("Call stack (current base: 0x%x):\n", _engine->_gamestate->executionStackBase); Common::List<ExecStack>::const_iterator iter; @@ -2755,7 +3114,10 @@ bool Console::cmdBacktrace(int argc, const char **argv) { break; case EXEC_STACK_TYPE_KERNEL: // Kernel function - debugPrintf(" %x:[%x] k%s(", i, call.debugOrigin, _engine->getKernel()->getKernelName(call.debugSelector).c_str()); + if (call.debugKernelSubFunction == -1) + debugPrintf(" %x:[%x] k%s(", i, call.debugOrigin, _engine->getKernel()->getKernelName(call.debugKernelFunction).c_str()); + else + debugPrintf(" %x:[%x] k%s(", i, call.debugOrigin, _engine->getKernel()->getKernelName(call.debugKernelFunction, call.debugKernelSubFunction).c_str()); break; case EXEC_STACK_TYPE_VARSELECTOR: @@ -3209,6 +3571,7 @@ bool Console::cmdSend(int argc, const char **argv) { // We call run_engine explictly so we can restore the value of r_acc // after execution. run_vm(_engine->_gamestate); + _engine->_gamestate->xs = old_xstack; } @@ -3619,6 +3982,55 @@ bool Console::cmdSfx01Track(int argc, const char **argv) { return true; } +bool Console::cmdMapVocab994(int argc, const char **argv) { + EngineState *s = _engine->_gamestate; // for the several defines in this function + reg_t reg; + + if (argc != 4) { + debugPrintf("Attempts to map a range of vocab.994 entries to a given class\n"); + debugPrintf("Usage: %s <class addr> <first> <last>\n", argv[0]); + return true; + } + + if (parse_reg_t(_engine->_gamestate, argv[1], ®, false)) { + debugPrintf("Invalid address passed.\n"); + debugPrintf("Check the \"addresses\" command on how to use addresses\n"); + return true; + } + + Resource *resource = _engine->_resMan->findResource(ResourceId(kResourceTypeVocab, 994), 0); + const Object *obj = s->_segMan->getObject(reg); + uint16 *data = (uint16 *) resource->data; + uint32 first = atoi(argv[2]); + uint32 last = atoi(argv[3]); + Common::Array<bool> markers; + + markers.resize(_engine->getKernel()->getSelectorNamesSize()); + if (!obj->isClass() && getSciVersion() != SCI_VERSION_3) + obj = s->_segMan->getObject(obj->getSuperClassSelector()); + + first = MIN(first, (uint32) (resource->size / 2 - 2)); + last = MIN(last, (uint32) (resource->size / 2 - 2)); + + for (uint32 i = first; i <= last; ++i) { + uint16 ofs = data[i]; + + if (obj && ofs < obj->getVarCount()) { + uint16 varSelector = obj->getVarSelector(ofs); + debugPrintf("%d: property at index %04x of %s is %s %s\n", i, ofs, + s->_segMan->derefString(obj->getNameSelector()), + _engine->getKernel()->getSelectorName(varSelector).c_str(), + markers[varSelector] ? "(repeat!)" : ""); + markers[varSelector] = true; + } + else { + debugPrintf("%d: property at index %04x doesn't match up with %s\n", i, ofs, + s->_segMan->derefString(obj->getNameSelector())); + } + } + + return true; +} bool Console::cmdQuit(int argc, const char **argv) { if (argc != 2) { } @@ -3977,7 +4389,7 @@ void Console::printList(List *list) { return; } - node = &(nt->_table[pos.getOffset()]); + node = &nt->at(pos.getOffset()); debugPrintf("\t%04x:%04x : %04x:%04x -> %04x:%04x\n", PRINT_REG(pos), PRINT_REG(node->key), PRINT_REG(node->value)); @@ -4007,7 +4419,7 @@ int Console::printNode(reg_t addr) { return 1; } - list = &(lt->_table[addr.getOffset()]); + list = <->at(addr.getOffset()); debugPrintf("%04x:%04x : first x last = (%04x:%04x, %04x:%04x)\n", PRINT_REG(addr), PRINT_REG(list->first), PRINT_REG(list->last)); } else { @@ -4026,7 +4438,7 @@ int Console::printNode(reg_t addr) { debugPrintf("Address does not contain a node\n"); return 1; } - node = &(nt->_table[addr.getOffset()]); + node = &nt->at(addr.getOffset()); debugPrintf("%04x:%04x : prev x next = (%04x:%04x, %04x:%04x); maps %04x:%04x -> %04x:%04x\n", PRINT_REG(addr), PRINT_REG(node->pred), PRINT_REG(node->succ), PRINT_REG(node->key), PRINT_REG(node->value)); @@ -4057,7 +4469,8 @@ int Console::printObject(reg_t pos) { debugPrintf(" "); if (var_container && i < var_container->getVarCount()) { uint16 varSelector = var_container->getVarSelector(i); - debugPrintf("[%03x] %s = ", varSelector, _engine->getKernel()->getSelectorName(varSelector).c_str()); + // Times two commented out for now for easy parsing of vocab.994 + debugPrintf("(%04x) [%03x] %s = ", i /* *2 */, varSelector, _engine->getKernel()->getSelectorName(varSelector).c_str()); } else debugPrintf("p#%x = ", i); |