diff options
| -rw-r--r-- | engines/sci/engine/scriptdebug.cpp | 186 | ||||
| -rw-r--r-- | engines/sci/engine/vm.cpp | 188 | 
2 files changed, 189 insertions, 185 deletions
diff --git a/engines/sci/engine/scriptdebug.cpp b/engines/sci/engine/scriptdebug.cpp index 76490217c3..857b074678 100644 --- a/engines/sci/engine/scriptdebug.cpp +++ b/engines/sci/engine/scriptdebug.cpp @@ -281,8 +281,7 @@ reg_t disassemble(EngineState *s, reg_t pos, bool printBWTag, bool printBytecode  	return retval;  } -bool isJumpOpcode(EngineState *s, reg_t pos, reg_t& jumpTarget) -{ +bool isJumpOpcode(EngineState *s, reg_t pos, reg_t& jumpTarget) {  	SegmentObj *mobj = s->_segMan->getSegment(pos.segment, SEG_TYPE_SCRIPT);  	if (!mobj)  		return false; @@ -571,4 +570,187 @@ void Kernel::dissectScript(int scriptNumber, Vocabulary *vocab) {  	debugN("Script ends without terminator\n");  } +bool SciEngine::checkSelectorBreakpoint(BreakpointType breakpointType, reg_t send_obj, int selector) { +	Common::String methodName = _gamestate->_segMan->getObjectName(send_obj); +	methodName += ("::" + getKernel()->getSelectorName(selector)); + +	Common::List<Breakpoint>::const_iterator bpIter; +	for (bpIter = _debugState._breakpoints.begin(); bpIter != _debugState._breakpoints.end(); ++bpIter) { +		if ((*bpIter).type == breakpointType && (*bpIter).name == methodName) { +			_console->DebugPrintf("Break on %s (in [%04x:%04x])\n", methodName.c_str(), PRINT_REG(send_obj)); +			_debugState.debugging = true; +			_debugState.breakpointWasHit = true; +			return true; +		} +	} +	return false; +} + +bool SciEngine::checkExportBreakpoint(uint16 script, uint16 pubfunct) { +	if (_debugState._activeBreakpointTypes & BREAK_EXPORT) { +		uint32 bpaddress = (script << 16 | pubfunct); + +		Common::List<Breakpoint>::const_iterator bp; +		for (bp = _debugState._breakpoints.begin(); bp != _debugState._breakpoints.end(); ++bp) { +			if (bp->type == BREAK_EXPORT && bp->address == bpaddress) { +				_console->DebugPrintf("Break on script %d, export %d\n", script, pubfunct); +				_debugState.debugging = true; +				_debugState.breakpointWasHit = true; +				return true; +			} +		} +	} + +	return false; +} + +void debugSelectorCall(reg_t send_obj, Selector selector, int argc, StackPtr argp, ObjVarRef &varp, reg_t funcp, SegManager *segMan, SelectorType selectorType) { +	int activeBreakpointTypes = g_sci->_debugState._activeBreakpointTypes; +	const char *objectName = segMan->getObjectName(send_obj); +	const char *selectorName = g_sci->getKernel()->getSelectorName(selector).c_str(); +	Console *con = g_sci->getSciDebugger(); + +#ifdef VM_DEBUG_SEND +		debugN("Send to %04x:%04x (%s), selector %04x (%s):", PRINT_REG(send_obj),  +			s->_segMan->getObjectName(send_obj), selector,  +			g_sci->getKernel()->getSelectorName(selector).c_str()); +#endif // VM_DEBUG_SEND + +	switch (selectorType) { +	case kSelectorNone: +		break; +	case kSelectorVariable: +#ifdef VM_DEBUG_SEND +		if (argc) +			debugN("Varselector: Write %04x:%04x\n", PRINT_REG(argp[1])); +		else +			debugN("Varselector: Read\n"); +#endif // VM_DEBUG_SEND + +		// argc == 0: read selector +		// argc == 1: write selector +		// argc can be bigger than 1 in some cases, because of a script bug. +		// Usually, these aren't fatal. +		if ((activeBreakpointTypes & BREAK_SELECTORREAD) || +			(activeBreakpointTypes & BREAK_SELECTORWRITE) || +			argc > 1) { + +			reg_t selectorValue = *varp.getPointer(segMan); +			if (!argc && (activeBreakpointTypes & BREAK_SELECTORREAD)) { +				if (g_sci->checkSelectorBreakpoint(BREAK_SELECTORREAD, send_obj, selector)) +					con->DebugPrintf("Read from selector (%s:%s): %04x:%04x\n",  +							objectName, selectorName, +							PRINT_REG(selectorValue)); +			} else if (argc && (activeBreakpointTypes & BREAK_SELECTORWRITE)) { +				if (g_sci->checkSelectorBreakpoint(BREAK_SELECTORWRITE, send_obj, selector)) +					con->DebugPrintf("Write to selector (%s:%s): change %04x:%04x to %04x:%04x\n",  +							objectName, selectorName, +							PRINT_REG(selectorValue), PRINT_REG(argp[1])); +			} + +			if (argc > 1) +				debug(kDebugLevelScripts, "Write to selector (%s:%s): change %04x:%04x to %04x:%04x, argc == %d\n",  +							objectName, selectorName, +							PRINT_REG(selectorValue), PRINT_REG(argp[1]), argc); +		} +		break; +	case kSelectorMethod: +#ifndef VM_DEBUG_SEND +			if (activeBreakpointTypes & BREAK_SELECTOREXEC) { +				if (g_sci->checkSelectorBreakpoint(BREAK_SELECTOREXEC, send_obj, selector)) { +#else +			if (true) { +				if (true) { +#endif +					con->DebugPrintf("%s::%s(", objectName, selectorName); +					for (int i = 0; i < argc; i++) { +						con->DebugPrintf("%04x:%04x", PRINT_REG(argp[i+1])); +						if (i + 1 < argc) +							con->DebugPrintf(", "); +					} +					con->DebugPrintf(") at %04x:%04x\n", PRINT_REG(funcp)); +				} +			} +		break; +	}	// switch +} + +void logKernelCall(const KernelFunction *kernelCall, const KernelSubFunction *kernelSubCall, EngineState *s, int argc, reg_t *argv, reg_t result) { +	Kernel *kernel = g_sci->getKernel(); +	if (!kernelSubCall) { +		debugN("k%s: ", kernelCall->name); +	} else { +		int callNameLen = strlen(kernelCall->name); +		if (strncmp(kernelCall->name, kernelSubCall->name, callNameLen) == 0) { +			const char *subCallName = kernelSubCall->name + callNameLen; +			debugN("k%s(%s): ", kernelCall->name, subCallName); +		} else { +			debugN("k%s(%s): ", kernelCall->name, kernelSubCall->name); +		} +	} +	for (int parmNr = 0; parmNr < argc; parmNr++) { +		if (parmNr) +			debugN(", "); +		uint16 regType = kernel->findRegType(argv[parmNr]); +		if (regType & SIG_TYPE_NULL) +			debugN("0"); +		else if (regType & SIG_TYPE_UNINITIALIZED) +			debugN("UNINIT"); +		else if (regType & SIG_IS_INVALID) +			debugN("INVALID"); +		else if (regType & SIG_TYPE_INTEGER) +			debugN("%d", argv[parmNr].offset); +		else { +			debugN("%04x:%04x", PRINT_REG(argv[parmNr])); +			switch (regType) { +			case SIG_TYPE_OBJECT: +				debugN(" (%s)", s->_segMan->getObjectName(argv[parmNr])); +				break; +			case SIG_TYPE_REFERENCE: +			{ +				SegmentObj *mobj = s->_segMan->getSegmentObj(argv[parmNr].segment); +				switch (mobj->getType()) { +				case SEG_TYPE_HUNK: +				{ +					HunkTable *ht = (HunkTable*)mobj; +					int index = argv[parmNr].offset; +					if (ht->isValidEntry(index)) { +						// NOTE: This ", deleted" isn't as useful as it could +						// be because it prints the status _after_ the kernel +						// call. +						debugN(" ('%s' hunk%s)", ht->_table[index].type, ht->_table[index].mem ? "" : ", deleted"); +					} else +						debugN(" (INVALID hunk ref)"); +					break; +				} +				default: +					// TODO: Any other segment types which could +					// use special handling? + +					if (kernelCall->function == kSaid) { +						SegmentRef saidSpec = s->_segMan->dereference(argv[parmNr]); +						if (saidSpec.isRaw) { +							debugN(" ('"); +							g_sci->getVocabulary()->debugDecipherSaidBlock(saidSpec.raw); +							debugN("')"); +						} else { +							debugN(" (non-raw said-spec)"); +						} +					} else { +						debugN(" ('%s')", s->_segMan->getString(argv[parmNr]).c_str()); +					} +					break; +				} +			} +			default: +				break; +			} +		} +	} +	if (result.isPointer()) +		debugN(" = %04x:%04x\n", PRINT_REG(result)); +	else +		debugN(" = %d\n", result.offset); +} +  } // End of namespace Sci diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index 89e8ed787f..f1e1980064 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -257,112 +257,6 @@ ExecStack *execute_method(EngineState *s, uint16 script, uint16 pubfunct, StackP  	return &(s->_executionStack.back());  } -bool SciEngine::checkSelectorBreakpoint(BreakpointType breakpointType, reg_t send_obj, int selector) { -	Common::String methodName = _gamestate->_segMan->getObjectName(send_obj); -	methodName += ("::" + getKernel()->getSelectorName(selector)); - -	Common::List<Breakpoint>::const_iterator bpIter; -	for (bpIter = _debugState._breakpoints.begin(); bpIter != _debugState._breakpoints.end(); ++bpIter) { -		if ((*bpIter).type == breakpointType && (*bpIter).name == methodName) { -			_console->DebugPrintf("Break on %s (in [%04x:%04x])\n", methodName.c_str(), PRINT_REG(send_obj)); -			_debugState.debugging = true; -			_debugState.breakpointWasHit = true; -			return true; -		} -	} -	return false; -} - -bool SciEngine::checkExportBreakpoint(uint16 script, uint16 pubfunct) { -	if (_debugState._activeBreakpointTypes & BREAK_EXPORT) { -		uint32 bpaddress = (script << 16 | pubfunct); - -		Common::List<Breakpoint>::const_iterator bp; -		for (bp = _debugState._breakpoints.begin(); bp != _debugState._breakpoints.end(); ++bp) { -			if (bp->type == BREAK_EXPORT && bp->address == bpaddress) { -				_console->DebugPrintf("Break on script %d, export %d\n", script, pubfunct); -				_debugState.debugging = true; -				_debugState.breakpointWasHit = true; -				return true; -			} -		} -	} - -	return false; -} - -void debugSelectorCall(reg_t send_obj, Selector selector, int argc, StackPtr argp, ObjVarRef &varp, reg_t funcp, SegManager *segMan, SelectorType selectorType) { -	int activeBreakpointTypes = g_sci->_debugState._activeBreakpointTypes; -	const char *objectName = segMan->getObjectName(send_obj); -	const char *selectorName = g_sci->getKernel()->getSelectorName(selector).c_str(); -	Console *con = g_sci->getSciDebugger(); - -#ifdef VM_DEBUG_SEND -		debugN("Send to %04x:%04x (%s), selector %04x (%s):", PRINT_REG(send_obj),  -			s->_segMan->getObjectName(send_obj), selector,  -			g_sci->getKernel()->getSelectorName(selector).c_str()); -#endif // VM_DEBUG_SEND - -	switch (selectorType) { -	case kSelectorNone: -		break; -	case kSelectorVariable: -#ifdef VM_DEBUG_SEND -		if (argc) -			debugN("Varselector: Write %04x:%04x\n", PRINT_REG(argp[1])); -		else -			debugN("Varselector: Read\n"); -#endif // VM_DEBUG_SEND - -		// argc == 0: read selector -		// argc == 1: write selector -		// argc can be bigger than 1 in some cases, because of a script bug. -		// Usually, these aren't fatal. -		if ((activeBreakpointTypes & BREAK_SELECTORREAD) || -			(activeBreakpointTypes & BREAK_SELECTORWRITE) || -			argc > 1) { - -			reg_t selectorValue = *varp.getPointer(segMan); -			if (!argc && (activeBreakpointTypes & BREAK_SELECTORREAD)) { -				if (g_sci->checkSelectorBreakpoint(BREAK_SELECTORREAD, send_obj, selector)) -					con->DebugPrintf("Read from selector (%s:%s): %04x:%04x\n",  -							objectName, selectorName, -							PRINT_REG(selectorValue)); -			} else if (argc && (activeBreakpointTypes & BREAK_SELECTORWRITE)) { -				if (g_sci->checkSelectorBreakpoint(BREAK_SELECTORWRITE, send_obj, selector)) -					con->DebugPrintf("Write to selector (%s:%s): change %04x:%04x to %04x:%04x\n",  -							objectName, selectorName, -							PRINT_REG(selectorValue), PRINT_REG(argp[1])); -			} - -			if (argc > 1) -				debug(kDebugLevelScripts, "Write to selector (%s:%s): change %04x:%04x to %04x:%04x, argc == %d\n",  -							objectName, selectorName, -							PRINT_REG(selectorValue), PRINT_REG(argp[1]), argc); -		} -		break; -	case kSelectorMethod: -#ifndef VM_DEBUG_SEND -			if (activeBreakpointTypes & BREAK_SELECTOREXEC) { -				if (g_sci->checkSelectorBreakpoint(BREAK_SELECTOREXEC, send_obj, selector)) { -#else -			if (true) { -				if (true) { -#endif -					con->DebugPrintf("%s::%s(", objectName, selectorName); -					for (int i = 0; i < argc; i++) { -						con->DebugPrintf("%04x:%04x", PRINT_REG(argp[i+1])); -						if (i + 1 < argc) -							con->DebugPrintf(", "); -					} -					con->DebugPrintf(") at %04x:%04x\n", PRINT_REG(funcp)); -				} -			} -		break; -	}	// switch -} - -  static void _exec_varselectors(EngineState *s) {  	// Executes all varselector read/write ops on the TOS  	while (!s->_executionStack.empty() && s->_executionStack.back().type == EXEC_STACK_TYPE_VARSELECTOR) { @@ -382,6 +276,9 @@ static void _exec_varselectors(EngineState *s) {  	}  } +// from scriptdebug.cpp +extern void debugSelectorCall(reg_t send_obj, Selector selector, int argc, StackPtr argp, ObjVarRef &varp, reg_t funcp, SegManager *segMan, SelectorType selectorType); +  ExecStack *send_selector(EngineState *s, reg_t send_obj, reg_t work_obj, StackPtr sp, int framesize, StackPtr argp) {  	// send_obj and work_obj are equal for anything but 'super'  	// Returns a pointer to the TOS exec_stack element @@ -453,83 +350,8 @@ static void addKernelCallToExecStack(EngineState *s, int kernelCallNr, int argc,  	s->_executionStack.push_back(xstack);  } -static void	logKernelCall(const KernelFunction *kernelCall, const KernelSubFunction *kernelSubCall, EngineState *s, int argc, reg_t *argv, reg_t result) { -	Kernel *kernel = g_sci->getKernel(); -	if (!kernelSubCall) { -		debugN("k%s: ", kernelCall->name); -	} else { -		int callNameLen = strlen(kernelCall->name); -		if (strncmp(kernelCall->name, kernelSubCall->name, callNameLen) == 0) { -			const char *subCallName = kernelSubCall->name + callNameLen; -			debugN("k%s(%s): ", kernelCall->name, subCallName); -		} else { -			debugN("k%s(%s): ", kernelCall->name, kernelSubCall->name); -		} -	} -	for (int parmNr = 0; parmNr < argc; parmNr++) { -		if (parmNr) -			debugN(", "); -		uint16 regType = kernel->findRegType(argv[parmNr]); -		if (regType & SIG_TYPE_NULL) -			debugN("0"); -		else if (regType & SIG_TYPE_UNINITIALIZED) -			debugN("UNINIT"); -		else if (regType & SIG_IS_INVALID) -			debugN("INVALID"); -		else if (regType & SIG_TYPE_INTEGER) -			debugN("%d", argv[parmNr].offset); -		else { -			debugN("%04x:%04x", PRINT_REG(argv[parmNr])); -			switch (regType) { -			case SIG_TYPE_OBJECT: -				debugN(" (%s)", s->_segMan->getObjectName(argv[parmNr])); -				break; -			case SIG_TYPE_REFERENCE: -			{ -				SegmentObj *mobj = s->_segMan->getSegmentObj(argv[parmNr].segment); -				switch (mobj->getType()) { -				case SEG_TYPE_HUNK: -				{ -					HunkTable *ht = (HunkTable*)mobj; -					int index = argv[parmNr].offset; -					if (ht->isValidEntry(index)) { -						// NOTE: This ", deleted" isn't as useful as it could -						// be because it prints the status _after_ the kernel -						// call. -						debugN(" ('%s' hunk%s)", ht->_table[index].type, ht->_table[index].mem ? "" : ", deleted"); -					} else -						debugN(" (INVALID hunk ref)"); -					break; -				} -				default: -					// TODO: Any other segment types which could -					// use special handling? - -					if (kernelCall->function == kSaid) { -						SegmentRef saidSpec = s->_segMan->dereference(argv[parmNr]); -						if (saidSpec.isRaw) { -							debugN(" ('"); -							g_sci->getVocabulary()->debugDecipherSaidBlock(saidSpec.raw); -							debugN("')"); -						} else { -							debugN(" (non-raw said-spec)"); -						} -					} else { -						debugN(" ('%s')", s->_segMan->getString(argv[parmNr]).c_str()); -					} -					break; -				} -			} -			default: -				break; -			} -		} -	} -	if (result.isPointer()) -		debugN(" = %04x:%04x\n", PRINT_REG(result)); -	else -		debugN(" = %d\n", result.offset); -} +// from scriptdebug.cpp +extern void logKernelCall(const KernelFunction *kernelCall, const KernelSubFunction *kernelSubCall, EngineState *s, int argc, reg_t *argv, reg_t result);  static void callKernelFunc(EngineState *s, int kernelCallNr, int argc) {  	Kernel *kernel = g_sci->getKernel();  | 
