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.cpp190
1 files changed, 181 insertions, 9 deletions
diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp
index af945247ba..2f69d5caa1 100644
--- a/engines/sci/console.cpp
+++ b/engines/sci/console.cpp
@@ -131,6 +131,8 @@ Console::Console(SciEngine *engine) : GUI::Debugger(),
DCmd_Register("al", WRAP_METHOD(Console, cmdAnimateList)); // alias
DCmd_Register("window_list", WRAP_METHOD(Console, cmdWindowList));
DCmd_Register("wl", WRAP_METHOD(Console, cmdWindowList)); // alias
+ DCmd_Register("saved_bits", WRAP_METHOD(Console, cmdSavedBits));
+ DCmd_Register("show_saved_bits", WRAP_METHOD(Console, cmdShowSavedBits));
// Segments
DCmd_Register("segment_table", WRAP_METHOD(Console, cmdPrintSegmentTable));
DCmd_Register("segtable", WRAP_METHOD(Console, cmdPrintSegmentTable)); // alias
@@ -253,7 +255,7 @@ void Console::postEnter() {
videoDecoder = new RobotDecoder(g_system->getMixer(), _engine->getPlatform() == Common::kPlatformMacintosh);
} else if (_videoFile.hasSuffix(".duk")) {
duckMode = true;
- videoDecoder = new Video::AviDecoder(g_system->getMixer());
+ videoDecoder = new Video::AviDecoder(g_system->getMixer());
#endif
} else if (_videoFile.hasSuffix(".avi")) {
videoDecoder = new Video::AviDecoder(g_system->getMixer());
@@ -364,6 +366,8 @@ bool Console::cmdHelp(int argc, const char **argv) {
DebugPrintf(" undither - Enable/disable undithering\n");
DebugPrintf(" play_video - Plays a SEQ, AVI, VMD, RBT or DUK video\n");
DebugPrintf(" animate_object_list / al - Shows the current list of objects in kAnimate's draw list\n");
+ DebugPrintf(" saved_bits - List saved bits on the hunk\n");
+ DebugPrintf(" show_saved_bits - Display saved bits\n");
DebugPrintf("\n");
DebugPrintf("Segments:\n");
DebugPrintf(" segment_table / segtable - Lists all segments\n");
@@ -891,7 +895,7 @@ bool Console::cmdVerifyScripts(int argc, const char **argv) {
return true;
}
-// Same as in sound/drivers/midi.cpp
+// Same as in sound/drivers/midi.cpp
uint8 getGmInstrument(const Mt32ToGmMap &Mt32Ins) {
if (Mt32Ins.gmInstr == MIDI_MAPPED_TO_RHYTHM)
return Mt32Ins.gmRhythmKey + 0x80;
@@ -909,7 +913,7 @@ bool Console::cmdShowInstruments(int argc, const char **argv) {
MidiPlayer *player = MidiPlayer_Midi_create(doSoundVersion);
MidiParser_SCI *parser = new MidiParser_SCI(doSoundVersion, 0);
parser->setMidiDriver(player);
-
+
Common::List<ResourceId> *resources = _engine->getResMan()->listResources(kResourceTypeSound);
Common::sort(resources->begin(), resources->end());
Common::List<ResourceId>::iterator itr = resources->begin();
@@ -980,7 +984,7 @@ bool Console::cmdShowInstruments(int argc, const char **argv) {
if (channel != 15) { // SCI special
byte instrument = *channelData++;
if (!firstOneShown)
- firstOneShown = true;
+ firstOneShown = true;
else
DebugPrintf(",");
@@ -1573,7 +1577,7 @@ bool Console::cmdPlayVideo(int argc, const char **argv) {
Common::String filename = argv[1];
filename.toLowercase();
- if (filename.hasSuffix(".seq") || filename.hasSuffix(".avi") || filename.hasSuffix(".vmd") ||
+ if (filename.hasSuffix(".seq") || filename.hasSuffix(".avi") || filename.hasSuffix(".vmd") ||
filename.hasSuffix(".rbt") || filename.hasSuffix(".duk")) {
_videoFile = filename;
_videoFrameDelay = (argc == 2) ? 10 : atoi(argv[2]);
@@ -1600,6 +1604,174 @@ bool Console::cmdWindowList(int argc, const char **argv) {
return true;
}
+
+bool Console::cmdSavedBits(int argc, const char **argv) {
+ SegManager *segman = _engine->_gamestate->_segMan;
+ SegmentId id = segman->findSegmentByType(SEG_TYPE_HUNK);
+ HunkTable* hunks = (HunkTable*)segman->getSegmentObj(id);
+ if (!hunks) {
+ DebugPrintf("No hunk segment found.\n");
+ return true;
+ }
+
+ Common::Array<reg_t> entries = hunks->listAllDeallocatable(id);
+
+ for (uint i = 0; i < entries.size(); ++i) {
+ uint16 offset = entries[i].offset;
+ const Hunk& h = hunks->_table[offset];
+ if (strcmp(h.type, "SaveBits()") == 0) {
+ byte* memoryPtr = (byte*)h.mem;
+
+ if (memoryPtr) {
+ DebugPrintf("%04x:%04x:", PRINT_REG(entries[i]));
+
+ Common::Rect rect;
+ byte mask;
+ assert(h.size >= sizeof(rect) + sizeof(mask));
+
+ memcpy((void *)&rect, memoryPtr, sizeof(rect));
+ memcpy((void *)&mask, memoryPtr + sizeof(rect), sizeof(mask));
+
+ DebugPrintf(" %d,%d - %d,%d", rect.top, rect.left,
+ rect.bottom, rect.right);
+ if (mask & GFX_SCREEN_MASK_VISUAL)
+ DebugPrintf(" visual");
+ if (mask & GFX_SCREEN_MASK_PRIORITY)
+ DebugPrintf(" priority");
+ if (mask & GFX_SCREEN_MASK_CONTROL)
+ DebugPrintf(" control");
+ if (mask & GFX_SCREEN_MASK_DISPLAY)
+ DebugPrintf(" display");
+ DebugPrintf("\n");
+ }
+ }
+ }
+
+
+ return true;
+}
+
+bool Console::cmdShowSavedBits(int argc, const char **argv) {
+ if (argc < 2) {
+ DebugPrintf("Display saved bits.\n");
+ DebugPrintf("Usage: %s <address>\n", argv[0]);
+ DebugPrintf("Check the \"addresses\" command on how to use addresses\n");
+ return true;
+ }
+
+ reg_t memoryHandle = NULL_REG;
+
+ if (parse_reg_t(_engine->_gamestate, argv[1], &memoryHandle, false)) {
+ DebugPrintf("Invalid address passed.\n");
+ DebugPrintf("Check the \"addresses\" command on how to use addresses\n");
+ return true;
+ }
+
+ if (memoryHandle.isNull()) {
+ DebugPrintf("Invalid address.\n");
+ return true;
+ }
+
+ SegManager *segman = _engine->_gamestate->_segMan;
+ SegmentId id = segman->findSegmentByType(SEG_TYPE_HUNK);
+ HunkTable* hunks = (HunkTable*)segman->getSegmentObj(id);
+ if (!hunks) {
+ DebugPrintf("No hunk segment found.\n");
+ return true;
+ }
+
+ if (memoryHandle.segment != id || !hunks->isValidOffset(memoryHandle.offset)) {
+ DebugPrintf("Invalid address.\n");
+ return true;
+ }
+
+ const Hunk& h = hunks->_table[memoryHandle.offset];
+
+ if (strcmp(h.type, "SaveBits()") != 0) {
+ DebugPrintf("Invalid address.\n");
+ return true;
+ }
+
+ byte *memoryPtr = segman->getHunkPointer(memoryHandle);
+
+ if (!memoryPtr) {
+ DebugPrintf("Invalid or freed bits.\n");
+ return true;
+ }
+
+ // Now we _finally_ know these are valid saved bits
+
+ Common::Rect rect;
+ byte mask;
+ assert(h.size >= sizeof(rect) + sizeof(mask));
+
+ memcpy((void *)&rect, memoryPtr, sizeof(rect));
+ memcpy((void *)&mask, memoryPtr + sizeof(rect), sizeof(mask));
+
+ Common::Point tl(rect.left, rect.top);
+ Common::Point tr(rect.right-1, rect.top);
+ Common::Point bl(rect.left, rect.bottom-1);
+ Common::Point br(rect.right-1, rect.bottom-1);
+
+ DebugPrintf(" %d,%d - %d,%d", rect.top, rect.left,
+ rect.bottom, rect.right);
+ if (mask & GFX_SCREEN_MASK_VISUAL)
+ DebugPrintf(" visual");
+ if (mask & GFX_SCREEN_MASK_PRIORITY)
+ DebugPrintf(" priority");
+ if (mask & GFX_SCREEN_MASK_CONTROL)
+ DebugPrintf(" control");
+ if (mask & GFX_SCREEN_MASK_DISPLAY)
+ DebugPrintf(" display");
+ DebugPrintf("\n");
+
+ if (!_engine->_gfxPaint16 || !_engine->_gfxScreen)
+ return true;
+
+ // We backup all planes, and then flash the saved bits
+ // FIXME: This probably won't work well with hi-res games
+
+ byte bakMask = GFX_SCREEN_MASK_VISUAL | GFX_SCREEN_MASK_PRIORITY | GFX_SCREEN_MASK_CONTROL;
+ int bakSize = _engine->_gfxScreen->bitsGetDataSize(rect, bakMask);
+ reg_t bakScreen = segman->allocateHunkEntry("show_saved_bits backup", bakSize);
+ byte* bakMemory = segman->getHunkPointer(bakScreen);
+ assert(bakMemory);
+ _engine->_gfxScreen->bitsSave(rect, bakMask, bakMemory);
+
+#ifndef USE_TEXT_CONSOLE_FOR_DEBUGGER
+ // If a graphical debugger overlay is used, hide it here, so that the
+ // results can be drawn.
+ g_system->hideOverlay();
+#endif
+
+ const int paintCount = 3;
+ for (int i = 0; i < paintCount; ++i) {
+ _engine->_gfxScreen->bitsRestore(memoryPtr);
+ _engine->_gfxScreen->drawLine(tl, tr, 0, 255, 255);
+ _engine->_gfxScreen->drawLine(tr, br, 0, 255, 255);
+ _engine->_gfxScreen->drawLine(br, bl, 0, 255, 255);
+ _engine->_gfxScreen->drawLine(bl, tl, 0, 255, 255);
+ _engine->_gfxScreen->copyRectToScreen(rect);
+ g_system->updateScreen();
+ g_sci->sleep(500);
+ _engine->_gfxScreen->bitsRestore(bakMemory);
+ _engine->_gfxScreen->copyRectToScreen(rect);
+ g_system->updateScreen();
+ if (i < paintCount - 1)
+ g_sci->sleep(500);
+ }
+
+ _engine->_gfxPaint16->bitsFree(bakScreen);
+
+#ifndef USE_TEXT_CONSOLE_FOR_DEBUGGER
+ // Show the graphical debugger overlay
+ g_system->showOverlay();
+#endif
+
+ return true;
+}
+
+
bool Console::cmdParseGrammar(int argc, const char **argv) {
DebugPrintf("Parse grammar, in strict GNF:\n");
@@ -1657,7 +1829,7 @@ bool Console::cmdPrintSegmentTable(int argc, const char **argv) {
case SEG_TYPE_STRING:
DebugPrintf("T SCI32 strings (%d)", (*(StringTable *)mobj).entries_used);
break;
-#endif
+#endif
default:
DebugPrintf("I Invalid (type = %x)", mobj->getType());
@@ -2782,8 +2954,8 @@ void Console::printKernelCallsFound(int kernelFuncNum, bool showFoundScripts) {
uint16 argc2 = opparams[1];
if (kFuncNum == kernelFuncNum) {
- DebugPrintf("Called from script %d, object %s, method %s(%d) with %d parameters\n",
- itr->getNumber(), objName,
+ DebugPrintf("Called from script %d, object %s, method %s(%d) with %d bytes for arguments\n",
+ itr->getNumber(), objName,
_engine->getKernel()->getSelectorName(obj->getFuncSelector(i)).c_str(), i, argc2);
}
}
@@ -2799,7 +2971,7 @@ void Console::printKernelCallsFound(int kernelFuncNum, bool showFoundScripts) {
// Check for end of function/script
if (offset >= script->getBufSize())
break;
- if (opcode == op_ret)// && offset >= maxJmpOffset)
+ if (opcode == op_ret && offset >= maxJmpOffset)
break;
} // while (true)
} // for (uint16 i = 0; i < obj->getMethodCount(); i++)