diff options
| -rw-r--r-- | engines/sci/console.cpp | 55 | ||||
| -rw-r--r-- | engines/sci/console.h | 2 | ||||
| -rw-r--r-- | engines/sci/debug.h | 6 | ||||
| -rw-r--r-- | engines/sci/engine/vm.cpp | 112 | ||||
| -rw-r--r-- | engines/sci/sci.h | 2 | 
5 files changed, 115 insertions, 62 deletions
diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp index 7acbe56a12..6246754ec4 100644 --- a/engines/sci/console.cpp +++ b/engines/sci/console.cpp @@ -178,6 +178,10 @@ Console::Console(SciEngine *engine) : GUI::Debugger(),  	DCmd_Register("bc",					WRAP_METHOD(Console, cmdBreakpointDelete));			// alias  	DCmd_Register("bp_method",			WRAP_METHOD(Console, cmdBreakpointMethod));  	DCmd_Register("bpx",				WRAP_METHOD(Console, cmdBreakpointMethod));			// alias +	DCmd_Register("bp_read",			WRAP_METHOD(Console, cmdBreakpointRead)); +	DCmd_Register("bpr",				WRAP_METHOD(Console, cmdBreakpointRead));			// alias +	DCmd_Register("bp_write",			WRAP_METHOD(Console, cmdBreakpointWrite)); +	DCmd_Register("bpw",				WRAP_METHOD(Console, cmdBreakpointWrite));			// alias  	DCmd_Register("bp_kernel",			WRAP_METHOD(Console, cmdBreakpointKernel));  	DCmd_Register("bpk",				WRAP_METHOD(Console, cmdBreakpointKernel));			// alias  	DCmd_Register("bp_function",		WRAP_METHOD(Console, cmdBreakpointFunction)); @@ -389,7 +393,9 @@ 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_method / bpx - Sets a breakpoint on the execution or access of a specified method/selector\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");  	DebugPrintf(" bp_kernel / bpk - Sets a breakpoint on execution of a kernel function\n");  	DebugPrintf(" bp_function / bpe - Sets a breakpoint on the execution of the specified exported function\n");  	DebugPrintf("\n"); @@ -2741,9 +2747,15 @@ bool Console::cmdBreakpointList(int argc, const char **argv) {  	for (; bp != end; ++bp) {  		DebugPrintf("  #%i: ", i);  		switch (bp->type) { -		case BREAK_SELECTOR: +		case BREAK_SELECTOREXEC:  			DebugPrintf("Execute %s\n", bp->name.c_str());  			break; +		case BREAK_SELECTORREAD: +			DebugPrintf("Read %s\n", bp->name.c_str()); +			break; +		case BREAK_SELECTORWRITE: +			DebugPrintf("Write %s\n", bp->name.c_str()); +			break;  		case BREAK_EXPORT:  			bpdata = bp->address;  			DebugPrintf("Execute script %d, export %d\n", bpdata >> 16, bpdata & 0xFFFF); @@ -2803,7 +2815,7 @@ bool Console::cmdBreakpointDelete(int argc, const char **argv) {  bool Console::cmdBreakpointMethod(int argc, const char **argv) {  	if (argc != 2) { -		DebugPrintf("Sets a breakpoint on execution/access of a specified method/selector.\n"); +		DebugPrintf("Sets a breakpoint on execution of a specified method/selector.\n");  		DebugPrintf("Usage: %s <name>\n", argv[0]);  		DebugPrintf("Example: %s ego::doit\n", argv[0]);  		DebugPrintf("May also be used to set a breakpoint that applies whenever an object\n"); @@ -2815,12 +2827,45 @@ bool Console::cmdBreakpointMethod(int argc, const char **argv) {  	   Thus, we can't check whether the command argument is a valid method name.  	   A breakpoint set on an invalid method name will just never trigger. */  	Breakpoint bp; -	bp.type = BREAK_SELECTOR; +	bp.type = BREAK_SELECTOREXEC;  	bp.name = argv[1];  	_debugState._breakpoints.push_back(bp); -	_debugState._activeBreakpointTypes |= BREAK_SELECTOR; +	_debugState._activeBreakpointTypes |= BREAK_SELECTOREXEC; +	return true; +} +bool Console::cmdBreakpointRead(int argc, const char **argv) { +	if (argc != 2) { +		DebugPrintf("Sets a breakpoint on reading of a specified selector.\n"); +		DebugPrintf("Usage: %s <name>\n", argv[0]); +		DebugPrintf("Example: %s ego::view\n", argv[0]); +		return true; +	} + +	Breakpoint bp; +	bp.type = BREAK_SELECTORREAD; +	bp.name = argv[1]; + +	_debugState._breakpoints.push_back(bp); +	_debugState._activeBreakpointTypes |= BREAK_SELECTORREAD; +	return true; +} + +bool Console::cmdBreakpointWrite(int argc, const char **argv) { +	if (argc != 2) { +		DebugPrintf("Sets a breakpoint on writing of a specified selector.\n"); +		DebugPrintf("Usage: %s <name>\n", argv[0]); +		DebugPrintf("Example: %s ego::view\n", argv[0]); +		return true; +	} + +	Breakpoint bp; +	bp.type = BREAK_SELECTORWRITE; +	bp.name = argv[1]; + +	_debugState._breakpoints.push_back(bp); +	_debugState._activeBreakpointTypes |= BREAK_SELECTORWRITE;  	return true;  } diff --git a/engines/sci/console.h b/engines/sci/console.h index 60599ea783..444443154c 100644 --- a/engines/sci/console.h +++ b/engines/sci/console.h @@ -135,6 +135,8 @@ private:  	bool cmdBreakpointList(int argc, const char **argv);  	bool cmdBreakpointDelete(int argc, const char **argv);  	bool cmdBreakpointMethod(int argc, const char **argv); +	bool cmdBreakpointRead(int argc, const char **argv); +	bool cmdBreakpointWrite(int argc, const char **argv);  	bool cmdBreakpointKernel(int argc, const char **argv);  	bool cmdBreakpointFunction(int argc, const char **argv);  	// VM diff --git a/engines/sci/debug.h b/engines/sci/debug.h index 5cf0e38fbc..d9959f0b7f 100644 --- a/engines/sci/debug.h +++ b/engines/sci/debug.h @@ -37,13 +37,15 @@ enum BreakpointType {  	 * Break when selector is executed. data contains (char *) selector name  	 * (in the format Object::Method)  	 */ -	BREAK_SELECTOR = 1, +	BREAK_SELECTOREXEC = 1 << 0, // break when selector gets executed +	BREAK_SELECTORREAD = 1 << 1, // break when selector gets executed +	BREAK_SELECTORWRITE = 1 << 2, // break when selector gets executed  	/**  	 * Break when an exported function is called. data contains  	 * script_no << 16 | export_no.  	 */ -	BREAK_EXPORT = 2 +	BREAK_EXPORT = 1 << 3  };  struct Breakpoint { diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index e841a3877f..39d919f333 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -366,27 +366,24 @@ struct CallsStruct {  	int type; /**< Same as ExecStack.type */  }; -bool SciEngine::checkSelectorBreakpoint(reg_t send_obj, int selector) { -	if (_debugState._activeBreakpointTypes & BREAK_SELECTOR) { -		char method_name[256]; - -		sprintf(method_name, "%s::%s", _gamestate->_segMan->getObjectName(send_obj), getKernel()->getSelectorName(selector).c_str()); - -		Common::List<Breakpoint>::const_iterator bp; -		for (bp = _debugState._breakpoints.begin(); bp != _debugState._breakpoints.end(); ++bp) { -			int cmplen = bp->name.size(); -			if (bp->name.lastChar() != ':') -				cmplen = 256; - -			if (bp->type == BREAK_SELECTOR && !strncmp(bp->name.c_str(), method_name, cmplen)) { -				_console->DebugPrintf("Break on %s (in [%04x:%04x])\n", method_name, PRINT_REG(send_obj)); -				_debugState.debugging = true; -				_debugState.breakpointWasHit = true; -				return true; -			} +bool SciEngine::checkSelectorBreakpoint(BreakpointType breakpointType, reg_t send_obj, int selector) { +	char method_name[256]; + +	sprintf(method_name, "%s::%s", _gamestate->_segMan->getObjectName(send_obj), getKernel()->getSelectorName(selector).c_str()); + +	Common::List<Breakpoint>::const_iterator bp; +	for (bp = _debugState._breakpoints.begin(); bp != _debugState._breakpoints.end(); ++bp) { +		int cmplen = bp->name.size(); +		if (bp->name.lastChar() != ':') +			cmplen = 256; + +		if (bp->type == breakpointType && !strncmp(bp->name.c_str(), method_name, cmplen)) { +			_console->DebugPrintf("Break on %s (in [%04x:%04x])\n", method_name, PRINT_REG(send_obj)); +			_debugState.debugging = true; +			_debugState.breakpointWasHit = true; +			return true;  		}  	} -  	return false;  } @@ -399,12 +396,13 @@ ExecStack *send_selector(EngineState *s, reg_t send_obj, reg_t work_obj, StackPt  	int selector;  	int argc;  	int origin = s->_executionStack.size()-1; // Origin: Used for debugging -	bool printSendActions = false;  	// We return a pointer to the new active ExecStack  	// The selector calls we catch are stored below:  	Common::Stack<CallsStruct> sendCalls; +	int activeBreakpointTypes = g_sci->_debugState._activeBreakpointTypes; +  	while (framesize > 0) {  		selector = validate_arithmetic(*argp++);  		argc = validate_arithmetic(*argp); @@ -413,9 +411,6 @@ ExecStack *send_selector(EngineState *s, reg_t send_obj, reg_t work_obj, StackPt  			error("send_selector(): More than 0x800 arguments to function call");  		} -		// Check if a breakpoint is set on this method -		printSendActions = g_sci->checkSelectorBreakpoint(send_obj, selector); -  #ifdef VM_DEBUG_SEND  		printf("Send to %04x:%04x (%s), selector %04x (%s):", PRINT_REG(send_obj),   			s->_segMan->getObjectName(send_obj), selector,  @@ -439,18 +434,23 @@ ExecStack *send_selector(EngineState *s, reg_t send_obj, reg_t work_obj, StackPt  			// argc == 0: read selector  			// argc != 0: write selector -			if (printSendActions && !argc) {	// read selector -				debug("[read selector]\n"); -				printSendActions = false; -			} - -			if (printSendActions && argc) { -				reg_t oldReg = *varp.getPointer(s->_segMan); -				reg_t newReg = argp[1]; -				warning("[write to selector (%s:%s): change %04x:%04x to %04x:%04x]\n",  -					s->_segMan->getObjectName(send_obj), g_sci->getKernel()->getSelectorName(selector).c_str(),  -					PRINT_REG(oldReg), PRINT_REG(newReg)); -				printSendActions = false; +			if (!argc) { +				// read selector +				if (activeBreakpointTypes & BREAK_SELECTORREAD) { +					if (g_sci->checkSelectorBreakpoint(BREAK_SELECTORREAD, send_obj, selector)) +						debug("[read selector]\n"); +				} +			} else { +				// write selector +				if (activeBreakpointTypes & BREAK_SELECTORWRITE) { +					if (g_sci->checkSelectorBreakpoint(BREAK_SELECTORWRITE, send_obj, selector)) { +						reg_t oldReg = *varp.getPointer(s->_segMan); +						reg_t newReg = argp[1]; +						warning("[write to selector (%s:%s): change %04x:%04x to %04x:%04x]\n",  +							s->_segMan->getObjectName(send_obj), g_sci->getKernel()->getSelectorName(selector).c_str(),  +							PRINT_REG(oldReg), PRINT_REG(newReg)); +					} +				}  			}  			if (argc > 1) { @@ -483,6 +483,8 @@ ExecStack *send_selector(EngineState *s, reg_t send_obj, reg_t work_obj, StackPt  		case kSelectorMethod:  #ifdef VM_DEBUG_SEND +			if (_debugState._activeBreakpointTypes & BREAK_SELECTOREXEC) +				g_sci->checkSelectorBreakpoint(BREAK_SELECTOREXEC, send_obj, selector);  			printf("Funcselector(");  			for (int i = 0; i < argc; i++) {  				printf("%04x:%04x", PRINT_REG(argp[i+1])); @@ -491,30 +493,32 @@ ExecStack *send_selector(EngineState *s, reg_t send_obj, reg_t work_obj, StackPt  			}  			printf(") at %04x:%04x\n", PRINT_REG(funcp));  #endif // VM_DEBUG_SEND -			if (printSendActions) { -				printf("[invoke selector]");  #ifndef VM_DEBUG_SEND -				int displaySize = 0; -				for (int argNr = 1; argNr <= argc; argNr++) { -					if (argNr == 1) -						printf(" - "); -					reg_t curParam = argp[argNr]; -					if (curParam.segment) { -						printf("[%04x:%04x] ", PRINT_REG(curParam)); -						displaySize += 12; -					} else { -						printf("[%04x] ", curParam.offset); -						displaySize += 7; -					} -					if (displaySize > 50) { -						if (argNr < argc) -							printf("..."); -						break; +			if (activeBreakpointTypes & BREAK_SELECTOREXEC) { +				if (g_sci->checkSelectorBreakpoint(BREAK_SELECTOREXEC, send_obj, selector)) { +					printf("[execute selector]"); + +					int displaySize = 0; +					for (int argNr = 1; argNr <= argc; argNr++) { +						if (argNr == 1) +							printf(" - "); +						reg_t curParam = argp[argNr]; +						if (curParam.segment) { +							printf("[%04x:%04x] ", PRINT_REG(curParam)); +							displaySize += 12; +						} else { +							printf("[%04x] ", curParam.offset); +							displaySize += 7; +						} +						if (displaySize > 50) { +							if (argNr < argc) +								printf("..."); +							break; +						}  					}  				}  #endif  				printf("\n"); -				printSendActions = false;  			}  			{ diff --git a/engines/sci/sci.h b/engines/sci/sci.h index a620f6cd09..7239abad17 100644 --- a/engines/sci/sci.h +++ b/engines/sci/sci.h @@ -260,7 +260,7 @@ public:  	void scriptDebug();  	bool checkExportBreakpoint(uint16 script, uint16 pubfunct); -	bool checkSelectorBreakpoint(reg_t send_obj, int selector); +	bool checkSelectorBreakpoint(BreakpointType breakpointType, reg_t send_obj, int selector);  	void patchGameSaveRestore(SegManager *segMan);  | 
