diff options
Diffstat (limited to 'engines/sci/console.cpp')
-rw-r--r-- | engines/sci/console.cpp | 190 |
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++) |