aboutsummaryrefslogtreecommitdiff
path: root/engines/sci/console.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'engines/sci/console.cpp')
-rw-r--r--engines/sci/console.cpp503
1 files changed, 425 insertions, 78 deletions
diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp
index cbc6dfaf74..f1bb8d3e7f 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,9 @@
#include "sci/video/seq_decoder.h"
#ifdef ENABLE_SCI32
#include "sci/graphics/frameout.h"
+#include "sci/graphics/paint32.h"
+#include "sci/graphics/palette32.h"
#include "video/coktel_decoder.h"
-#include "sci/video/robot_decoder.h"
#endif
#include "common/file.h"
@@ -141,6 +140,8 @@ Console::Console(SciEngine *engine) : GUI::Debugger(),
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
@@ -192,6 +193,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
@@ -199,6 +201,8 @@ Console::Console(SciEngine *engine) : GUI::Debugger(),
registerCmd("bp_del", WRAP_METHOD(Console, cmdBreakpointDelete));
registerCmd("bpdel", WRAP_METHOD(Console, cmdBreakpointDelete)); // alias
registerCmd("bc", WRAP_METHOD(Console, cmdBreakpointDelete)); // alias
+ registerCmd("bp_address", WRAP_METHOD(Console, cmdBreakpointAddress));
+ registerCmd("bpa", WRAP_METHOD(Console, cmdBreakpointAddress)); // alias
registerCmd("bp_method", WRAP_METHOD(Console, cmdBreakpointMethod));
registerCmd("bpx", WRAP_METHOD(Console, cmdBreakpointMethod)); // alias
registerCmd("bp_read", WRAP_METHOD(Console, cmdBreakpointRead));
@@ -227,6 +231,8 @@ Console::Console(SciEngine *engine) : GUI::Debugger(),
registerCmd("view_listnode", WRAP_METHOD(Console, cmdViewListNode));
registerCmd("view_reference", WRAP_METHOD(Console, cmdViewReference));
registerCmd("vr", WRAP_METHOD(Console, cmdViewReference)); // alias
+ registerCmd("dump_reference", WRAP_METHOD(Console, cmdDumpReference));
+ registerCmd("dr", WRAP_METHOD(Console, cmdDumpReference)); // alias
registerCmd("view_object", WRAP_METHOD(Console, cmdViewObject));
registerCmd("vo", WRAP_METHOD(Console, cmdViewObject)); // alias
registerCmd("active_object", WRAP_METHOD(Console, cmdViewActiveObject));
@@ -264,8 +270,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();
@@ -385,6 +389,7 @@ bool Console::cmdHelp(int argc, const char **argv) {
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");
@@ -432,6 +437,7 @@ bool Console::cmdHelp(int argc, const char **argv) {
debugPrintf("Breakpoints:\n");
debugPrintf(" bp_list / bplist / bl - Lists the current breakpoints\n");
debugPrintf(" bp_del / bpdel / bc - Deletes a breakpoint with the specified index\n");
+ debugPrintf(" bp_address / bpa - Sets a breakpoint on a script address\n");
debugPrintf(" bp_method / bpx - Sets a breakpoint on the execution of a specified method/selector\n");
debugPrintf(" bp_read / bpr - Sets a breakpoint on reading of a specified selector\n");
debugPrintf(" bp_write / bpw - Sets a breakpoint on writing to a specified selector\n");
@@ -446,6 +452,7 @@ bool Console::cmdHelp(int argc, const char **argv) {
debugPrintf(" value_type - Determines the type of a value\n");
debugPrintf(" view_listnode - Examines the list node at the given address\n");
debugPrintf(" view_reference / vr - Examines an arbitrary reference\n");
+ debugPrintf(" dump_reference / dr - Dumps an arbitrary reference to disk\n");
debugPrintf(" view_object / vo - Examines the object at the given address\n");
debugPrintf(" active_object - Shows information on the currently active object or class\n");
debugPrintf(" acc_object - Shows information on the object or class at the address indexed by the accumulator\n");
@@ -486,6 +493,7 @@ 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_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)");
@@ -494,8 +502,10 @@ bool Console::cmdGetVersion(int argc, const char **argv) {
if (getSciVersion() <= SCI_VERSION_1_1) {
debugPrintf("kAnimate fastCast enabled: %s\n", g_sci->_gfxAnimate->isFastCastEnabled() ? "yes" : "no");
}
- 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");
+ 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");
@@ -672,7 +682,7 @@ bool Console::cmdRegisters(int argc, const char **argv) {
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");
@@ -757,7 +767,7 @@ void Console::cmdDiskDumpWorker(ResourceType resourceType, int resourceNumber, u
ResourceId resourceId;
Resource *resource = NULL;
char outFileName[50];
-
+
switch (resourceType) {
case kResourceTypeAudio36:
case kResourceTypeSync36: {
@@ -874,7 +884,7 @@ bool Console::cmdList(int argc, const char **argv) {
currentMap = map;
displayCount = 0;
}
-
+
if (displayCount % 3 == 0)
debugPrintf(" ");
@@ -1001,7 +1011,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;
@@ -1507,7 +1517,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;
@@ -1544,7 +1554,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 {
@@ -1617,7 +1627,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;
@@ -1625,6 +1635,13 @@ bool Console::cmdSetPalette(int argc, const char **argv) {
uint16 resourceId = atoi(argv[1]);
+#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;
}
@@ -1644,7 +1661,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);
@@ -1816,6 +1833,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);
@@ -1829,7 +1874,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;
@@ -1896,7 +1941,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");
@@ -2037,8 +2082,8 @@ bool Console::cmdPrintSegmentTable(int argc, const char **argv) {
debugPrintf("A SCI32 arrays (%d)", (*(ArrayTable *)mobj).entries_used);
break;
- case SEG_TYPE_STRING:
- debugPrintf("T SCI32 strings (%d)", (*(StringTable *)mobj).entries_used);
+ case SEG_TYPE_BITMAP:
+ debugPrintf("T SCI32 bitmaps (%d)", (*(BitmapTable *)mobj).entries_used);
break;
#endif
@@ -2112,32 +2157,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 &lt = *(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(lt[i]);
}
}
break;
@@ -2148,13 +2193,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;
@@ -2168,12 +2213,27 @@ bool Console::segmentInfo(int nr) {
break;
#ifdef ENABLE_SCI32
- case SEG_TYPE_STRING:
- debugPrintf("SCI32 strings\n");
- break;
- case SEG_TYPE_ARRAY:
+ case SEG_TYPE_ARRAY: {
+ ArrayTable &table = *(ArrayTable *)mobj;
debugPrintf("SCI32 arrays\n");
+ for (uint i = 0; i < table.size(); ++i) {
+ if (table.isValidEntry(i)) {
+ debugPrintf(" [%04x] %s\n", i, table[i].toDebugString().c_str());
+ }
+ }
break;
+ }
+
+ case SEG_TYPE_BITMAP: {
+ BitmapTable &table = *(BitmapTable *)mobj;
+ debugPrintf("SCI32 bitmaps (total %d)\n", table.entries_used);
+ for (uint i = 0; i < table.size(); ++i) {
+ if (table.isValidEntry(i)) {
+ debugPrintf(" [%04x] %s\n", i, table[i].toString().c_str());
+ }
+ }
+ break;
+ }
#endif
default :
@@ -2533,9 +2593,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) {
@@ -2736,16 +2801,8 @@ bool Console::cmdViewReference(int argc, const char **argv) {
switch (type) {
case 0:
break;
- case SIG_TYPE_LIST: {
- List *list = _engine->_gamestate->_segMan->lookupList(reg);
-
- debugPrintf("list\n");
-
- if (list)
- printList(list);
- else
- debugPrintf("Invalid list.\n");
- }
+ case SIG_TYPE_LIST:
+ printList(reg);
break;
case SIG_TYPE_NODE:
debugPrintf("list node\n");
@@ -2758,16 +2815,12 @@ bool Console::cmdViewReference(int argc, const char **argv) {
case SIG_TYPE_REFERENCE: {
switch (_engine->_gamestate->_segMan->getSegmentType(reg.getSegment())) {
#ifdef ENABLE_SCI32
- case SEG_TYPE_STRING: {
- debugPrintf("SCI32 string\n");
- const SciString *str = _engine->_gamestate->_segMan->lookupString(reg);
- Common::hexdump((const byte *) str->getRawData(), str->getSize(), 16, 0);
+ case SEG_TYPE_ARRAY: {
+ printArray(reg);
break;
}
- case SEG_TYPE_ARRAY: {
- debugPrintf("SCI32 array:\n");
- const SciArray<reg_t> *array = _engine->_gamestate->_segMan->lookupArray(reg);
- hexDumpReg(array->getRawData(), array->getSize(), 4, 0, true);
+ case SEG_TYPE_BITMAP: {
+ printBitmap(reg);
break;
}
#endif
@@ -2812,6 +2865,125 @@ bool Console::cmdViewReference(int argc, const char **argv) {
return true;
}
+bool Console::cmdDumpReference(int argc, const char **argv) {
+ if (argc < 2) {
+ debugPrintf("Dumps an arbitrary reference to disk.\n");
+ debugPrintf("Usage: %s <start address> [<end address>]\n", argv[0]);
+ debugPrintf("Where <start address> is the starting address to dump\n");
+ debugPrintf("<end address>, if provided, is the address where the dump ends\n");
+ debugPrintf("Check the \"addresses\" command on how to use addresses\n");
+ return true;
+ }
+
+ reg_t reg = NULL_REG;
+ reg_t reg_end = NULL_REG;
+
+ if (parse_reg_t(_engine->_gamestate, argv[1], &reg, false)) {
+ debugPrintf("Invalid address passed.\n");
+ debugPrintf("Check the \"addresses\" command on how to use addresses\n");
+ return true;
+ }
+
+ if (argc > 2) {
+ if (parse_reg_t(_engine->_gamestate, argv[2], &reg_end, false)) {
+ debugPrintf("Invalid address passed.\n");
+ debugPrintf("Check the \"addresses\" command on how to use addresses\n");
+ return true;
+ }
+ }
+
+ if (reg.getSegment() == 0 && reg.getOffset() == 0) {
+ debugPrintf("Register is null.\n");
+ return true;
+ }
+
+ if (g_sci->getKernel()->findRegType(reg) != SIG_TYPE_REFERENCE) {
+ debugPrintf("%04x:%04x is not a reference\n", PRINT_REG(reg));
+ return true;
+ }
+
+ if (reg_end.getSegment() != reg.getSegment() && reg_end != NULL_REG) {
+ debugPrintf("Ending segment different from starting segment. Assuming no bound on dump.\n");
+ reg_end = NULL_REG;
+ }
+
+ Common::DumpFile out;
+ Common::String outFileName;
+ uint32 bytesWritten;
+
+ switch (_engine->_gamestate->_segMan->getSegmentType(reg.getSegment())) {
+#ifdef ENABLE_SCI32
+ case SEG_TYPE_BITMAP: {
+ outFileName = Common::String::format("%04x_%04x.tga", PRINT_REG(reg));
+ out.open(outFileName);
+ SciBitmap &bitmap = *_engine->_gamestate->_segMan->lookupBitmap(reg);
+ const Color *color = g_sci->_gfxPalette32->getCurrentPalette().colors;
+ const uint16 numColors = ARRAYSIZE(g_sci->_gfxPalette32->getCurrentPalette().colors);
+
+ out.writeByte(0); // image id length
+ out.writeByte(1); // color map type (present)
+ out.writeByte(1); // image type (uncompressed color-mapped)
+ out.writeSint16LE(0); // index of first color map entry
+ out.writeSint16LE(numColors); // number of color map entries
+ out.writeByte(24); // number of bits per color entry (RGB24)
+ out.writeSint16LE(0); // bottom-left x-origin
+ out.writeSint16LE(bitmap.getHeight() - 1); // bottom-left y-origin
+ out.writeSint16LE(bitmap.getWidth()); // width
+ out.writeSint16LE(bitmap.getHeight()); // height
+ out.writeByte(8); // bits per pixel
+ out.writeByte(1 << 5); // origin of pixel data (top-left)
+
+ bytesWritten = 18;
+
+ for (int i = 0; i < numColors; ++i) {
+ out.writeByte(color->b);
+ out.writeByte(color->g);
+ out.writeByte(color->r);
+ ++color;
+ }
+
+ bytesWritten += numColors * 3;
+ bytesWritten += out.write(bitmap.getPixels(), bitmap.getWidth() * bitmap.getHeight());
+ break;
+ }
+#endif
+
+ default: {
+ const SegmentRef block = _engine->_gamestate->_segMan->dereference(reg);
+ uint32 size = block.maxSize;
+
+ if (size == 0) {
+ debugPrintf("Size of reference is zero.\n");
+ return true;
+ }
+
+ if (reg_end.getSegment() != 0 && (size < reg_end.getOffset() - reg.getOffset())) {
+ debugPrintf("Block end out of bounds (size %d). Resetting.\n", size);
+ reg_end = NULL_REG;
+ }
+
+ if (reg_end.getSegment() != 0 && (size >= reg_end.getOffset() - reg.getOffset())) {
+ size = reg_end.getOffset() - reg.getOffset();
+ }
+
+ if (reg_end.getSegment() != 0) {
+ debugPrintf("Block size less than or equal to %d\n", size);
+ }
+
+ outFileName = Common::String::format("%04x_%04x.dmp", PRINT_REG(reg));
+ out.open(outFileName);
+ bytesWritten = out.write(block.raw, size);
+ break;
+ }
+ }
+
+ out.finalize();
+ out.close();
+
+ debugPrintf("Wrote %u bytes to %s\n", bytesWritten, outFileName.c_str());
+ return true;
+}
+
bool Console::cmdViewObject(int argc, const char **argv) {
if (argc != 2) {
debugPrintf("Examines the object at the given address.\n");
@@ -2863,7 +3035,7 @@ bool Console::cmdScriptObjects(int argc, const char **argv) {
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;
@@ -2885,7 +3057,7 @@ bool Console::cmdScriptStrings(int argc, const char **argv) {
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;
@@ -2907,7 +3079,7 @@ bool Console::cmdScriptSaid(int argc, const char **argv) {
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;
@@ -3058,7 +3230,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:
@@ -3237,7 +3412,7 @@ bool Console::cmdDisassemble(int argc, const char **argv) {
farthestTarget = jumpTarget;
}
// TODO: Use a true 32-bit reg_t for the position (addr)
- addr = disassemble(_engine->_gamestate, make_reg32(addr.getSegment(), addr.getOffset()), printBWTag, printBytecode);
+ addr = disassemble(_engine->_gamestate, make_reg32(addr.getSegment(), addr.getOffset()), objAddr, printBWTag, printBytecode);
if (addr.isNull() && prevAddr < farthestTarget)
addr = prevAddr + 1; // skip past the ret
} while (addr.getOffset() > 0);
@@ -3286,7 +3461,7 @@ bool Console::cmdDisassembleAddress(int argc, const char **argv) {
do {
// TODO: Use a true 32-bit reg_t for the position (vpc)
- vpc = disassemble(_engine->_gamestate, make_reg32(vpc.getSegment(), vpc.getOffset()), printBWTag, printBytes);
+ vpc = disassemble(_engine->_gamestate, make_reg32(vpc.getSegment(), vpc.getOffset()), NULL_REG, printBWTag, printBytes);
} while ((vpc.getOffset() > 0) && (vpc.getOffset() + 6 < size) && (--opCount));
return true;
@@ -3581,6 +3756,8 @@ bool Console::cmdBreakpointList(int argc, const char **argv) {
bpdata = bp->address;
debugPrintf("Execute script %d, export %d\n", bpdata >> 16, bpdata & 0xFFFF);
break;
+ case BREAK_ADDRESS:
+ debugPrintf("Execute address %04x:%04x\n", PRINT_REG(bp->regAddress));
}
i++;
@@ -3719,7 +3896,7 @@ bool Console::cmdBreakpointKernel(int argc, const char **argv) {
bool Console::cmdBreakpointFunction(int argc, const char **argv) {
if (argc != 3) {
debugPrintf("Sets a breakpoint on the execution of the specified exported function.\n");
- debugPrintf("Usage: %s <script number> <export number\n", argv[0]);
+ debugPrintf("Usage: %s <script number> <export number>\n", argv[0]);
return true;
}
@@ -3737,6 +3914,31 @@ bool Console::cmdBreakpointFunction(int argc, const char **argv) {
return true;
}
+bool Console::cmdBreakpointAddress(int argc, const char **argv) {
+ if (argc != 2) {
+ debugPrintf("Sets a breakpoint on the execution of the specified code address.\n");
+ debugPrintf("Usage: %s <address>\n", argv[0]);
+ return true;
+ }
+
+ reg_t addr;
+
+ if (parse_reg_t(_engine->_gamestate, argv[1], &addr, false)) {
+ debugPrintf("Invalid address passed.\n");
+ debugPrintf("Check the \"addresses\" command on how to use addresses\n");
+ return true;
+ }
+
+ Breakpoint bp;
+ bp.type = BREAK_ADDRESS;
+ bp.regAddress = make_reg32(addr.getSegment(), addr.getOffset());
+
+ _debugState._breakpoints.push_back(bp);
+ _debugState._activeBreakpointTypes |= BREAK_ADDRESS;
+
+ return true;
+}
+
bool Console::cmdSfx01Header(int argc, const char **argv) {
if (argc != 2) {
debugPrintf("Dumps the header of a SCI01 song\n");
@@ -3923,6 +4125,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], &reg, 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) {
}
@@ -4265,8 +4516,28 @@ void Console::printBasicVarInfo(reg_t variable) {
debugPrintf(" IS INVALID!");
}
-void Console::printList(List *list) {
- reg_t pos = list->first;
+void Console::printList(reg_t reg) {
+ SegmentObj *mobj = _engine->_gamestate->_segMan->getSegment(reg.getSegment(), SEG_TYPE_LISTS);
+
+ if (!mobj) {
+ debugPrintf("list:\nCould not find list segment.\n");
+ return;
+ }
+
+ ListTable *table = static_cast<ListTable *>(mobj);
+
+ if (!table->isValidEntry(reg.getOffset())) {
+ debugPrintf("list:\nAddress does not contain a valid list.\n");
+ return;
+ }
+
+ const List &list = table->at(reg.getOffset());
+ debugPrintf("list:\n");
+ printList(list);
+}
+
+void Console::printList(const List &list) {
+ reg_t pos = list.first;
reg_t my_prev = NULL_REG;
debugPrintf("\t<\n");
@@ -4276,26 +4547,24 @@ void Console::printList(List *list) {
NodeTable *nt = (NodeTable *)_engine->_gamestate->_segMan->getSegment(pos.getSegment(), SEG_TYPE_NODES);
if (!nt || !nt->isValidEntry(pos.getOffset())) {
- debugPrintf(" WARNING: %04x:%04x: Doesn't contain list node!\n",
- PRINT_REG(pos));
+ debugPrintf(" WARNING: %04x:%04x: Doesn't contain list node!\n", PRINT_REG(pos));
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));
if (my_prev != node->pred)
- debugPrintf(" WARNING: current node gives %04x:%04x as predecessor!\n",
- PRINT_REG(node->pred));
+ debugPrintf(" WARNING: current node gives %04x:%04x as predecessor!\n", PRINT_REG(node->pred));
my_prev = pos;
pos = node->succ;
}
- if (my_prev != list->last)
+ if (my_prev != list.last)
debugPrintf(" WARNING: Last node was expected to be %04x:%04x, was %04x:%04x!\n",
- PRINT_REG(list->last), PRINT_REG(my_prev));
+ PRINT_REG(list.last), PRINT_REG(my_prev));
debugPrintf("\t>\n");
}
@@ -4311,7 +4580,7 @@ int Console::printNode(reg_t addr) {
return 1;
}
- list = &(lt->_table[addr.getOffset()]);
+ list = &lt->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 {
@@ -4330,7 +4599,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));
@@ -4339,6 +4608,83 @@ int Console::printNode(reg_t addr) {
return 0;
}
+#ifdef ENABLE_SCI32
+void Console::printArray(reg_t reg) {
+ SegmentObj *mobj = _engine->_gamestate->_segMan->getSegment(reg.getSegment(), SEG_TYPE_ARRAY);
+
+ if (!mobj) {
+ debugPrintf("SCI32 array:\nCould not find array segment.\n");
+ return;
+ }
+
+ ArrayTable *table = static_cast<ArrayTable *>(mobj);
+
+ if (!table->isValidEntry(reg.getOffset())) {
+ debugPrintf("SCI32 array:\nAddress does not contain a valid array.\n");
+ return;
+ }
+
+ const SciArray &array = table->at(reg.getOffset());
+
+ const char *arrayType;
+ switch (array.getType()) {
+ case kArrayTypeID:
+ arrayType = "reg_t";
+ break;
+ case kArrayTypeByte:
+ arrayType = "byte";
+ break;
+ case kArrayTypeInt16:
+ arrayType = "int16 (as reg_t)";
+ break;
+ case kArrayTypeString:
+ arrayType = "string";
+ break;
+ default:
+ arrayType = "invalid";
+ break;
+ }
+ debugPrintf("SCI32 %s array (%u entries):\n", arrayType, array.size());
+ switch (array.getType()) {
+ case kArrayTypeInt16:
+ case kArrayTypeID: {
+ hexDumpReg((const reg_t *)array.getRawData(), array.size(), 4, 0, true);
+ break;
+ }
+ case kArrayTypeByte:
+ case kArrayTypeString: {
+ Common::hexdump((const byte *)array.getRawData(), array.size(), 16, 0);
+ break;
+ }
+ default:
+ break;
+ }
+}
+
+void Console::printBitmap(reg_t reg) {
+ SegmentObj *mobj = _engine->_gamestate->_segMan->getSegment(reg.getSegment(), SEG_TYPE_BITMAP);
+
+ if (!mobj) {
+ debugPrintf("SCI32 bitmap:\nCould not find bitmap segment.\n");
+ return;
+ }
+
+ BitmapTable *table = static_cast<BitmapTable *>(mobj);
+
+ if (!table->isValidEntry(reg.getOffset())) {
+ debugPrintf("SCI32 bitmap:\nAddress does not contain a valid bitmap.\n");
+ return;
+ }
+
+ const SciBitmap &bitmap = table->at(reg.getOffset());
+
+ debugPrintf("SCI32 bitmap (%s):\n", bitmap.toString().c_str());
+
+ Common::hexdump((const byte *) bitmap.getRawData(), bitmap.getRawSize(), 16, 0);
+}
+
+#endif
+
int Console::printObject(reg_t pos) {
EngineState *s = _engine->_gamestate; // for the several defines in this function
const Object *obj = s->_segMan->getObject(pos);
@@ -4346,7 +4692,7 @@ int Console::printObject(reg_t pos) {
uint i;
if (!obj) {
- debugPrintf("[%04x:%04x]: Not an object.", PRINT_REG(pos));
+ debugPrintf("[%04x:%04x]: Not an object.\n", PRINT_REG(pos));
return 1;
}
@@ -4361,7 +4707,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);