diff options
| -rw-r--r-- | engines/sci/console.cpp | 9 | ||||
| -rw-r--r-- | engines/sci/engine/seg_manager.cpp | 17 | ||||
| -rw-r--r-- | engines/sci/engine/seg_manager.h | 3 | ||||
| -rw-r--r-- | engines/sci/engine/segment.cpp | 84 | ||||
| -rw-r--r-- | engines/sci/engine/segment.h | 30 | 
5 files changed, 89 insertions, 54 deletions
| diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp index e88efe4f31..0f651709b9 100644 --- a/engines/sci/console.cpp +++ b/engines/sci/console.cpp @@ -1951,7 +1951,8 @@ bool Console::cmdViewReference(int argc, const char **argv) {  			break;  		case KSIG_REF: {  			int size; -			byte *block = _vm->_gamestate->segMan->dereference(reg, &size); +			const SegmentRef block = _vm->_gamestate->segMan->dereference(reg); +			size = block.maxSize;  			DebugPrintf("raw data\n"); @@ -1966,7 +1967,7 @@ bool Console::cmdViewReference(int argc, const char **argv) {  			if (reg_end.segment != 0)  				DebugPrintf("Block size less than or equal to %d\n", size); -			Common::hexdump(block, size, 16, 0); +			Common::hexdump(block.raw, size, 16, 0);  			}  			break;  		case KSIG_ARITHMETIC: @@ -2248,8 +2249,8 @@ bool Console::cmdDissassembleAddress(int argc, const char **argv) {  		return true;  	} -	_vm->_gamestate->segMan->dereference(vpc, &size); -	size += vpc.offset; // total segment size +	SegmentRef ref = _vm->_gamestate->segMan->dereference(vpc); +	size = ref.maxSize + vpc.offset; // total segment size  	for (int i = 2; i < argc; i++) {  		if (!scumm_stricmp(argv[i], "bwt")) diff --git a/engines/sci/engine/seg_manager.cpp b/engines/sci/engine/seg_manager.cpp index 6449272bdc..e7e8d4197b 100644 --- a/engines/sci/engine/seg_manager.cpp +++ b/engines/sci/engine/seg_manager.cpp @@ -863,29 +863,30 @@ Hunk *SegManager::alloc_Hunk(reg_t *addr) {  	return &(table->_table[offset]);  } -byte *SegManager::dereference(reg_t pointer, int *size) { +SegmentRef SegManager::dereference(reg_t pointer) { +	SegmentRef ret; +  	if (!pointer.segment || (pointer.segment >= _heap.size()) || !_heap[pointer.segment]) {  		// This occurs in KQ5CD when interacting with certain objects  		warning("Attempt to dereference invalid pointer %04x:%04x", PRINT_REG(pointer)); -		return NULL; /* Invalid */ +		return ret; /* Invalid */  	}  	SegmentObj *mobj = _heap[pointer.segment]; -	return mobj->dereference(pointer, size); +	return mobj->dereference(pointer);  }  static void *_kernel_dereference_pointer(SegManager *segMan, reg_t pointer, int entries) { -	int maxsize; -	void *retval = segMan->dereference(pointer, &maxsize); +	SegmentRef ret = segMan->dereference(pointer); -	if (!retval) +	if (!ret.raw)  		return NULL; -	if (entries > maxsize) { +	if (entries > ret.maxSize) {  		warning("Trying to dereference pointer %04x:%04x beyond end of segment", PRINT_REG(pointer));  		return NULL;  	} -	return retval; +	return ret.raw;  } diff --git a/engines/sci/engine/seg_manager.h b/engines/sci/engine/seg_manager.h index 8c6676d0ec..61b0c76e2e 100644 --- a/engines/sci/engine/seg_manager.h +++ b/engines/sci/engine/seg_manager.h @@ -279,10 +279,9 @@ public:  	/**  	 * Dereferences a raw memory pointer  	 * @param[in]  reg	The reference to dereference -	 * @param[out] size	(optional) The theoretical maximum size  	 * @return			The data block referenced  	 */ -	byte *dereference(reg_t reg, int *size); +	SegmentRef dereference(reg_t pointer);  	/**  	 * Dereferences a heap pointer pointing to raw memory. diff --git a/engines/sci/engine/segment.cpp b/engines/sci/engine/segment.cpp index 80027dbb39..7d2889aefc 100644 --- a/engines/sci/engine/segment.cpp +++ b/engines/sci/engine/segment.cpp @@ -214,79 +214,97 @@ int16 Script::getHeap(uint16 offset) const {  //	return (_buf[offset] | (_buf[offset+1]) << 8);  } -byte *SegmentObj::dereference(reg_t pointer, int *size) { +SegmentRef SegmentObj::dereference(reg_t pointer) {  	error("Error: Trying to dereference pointer %04x:%04x to inappropriate segment",  		          PRINT_REG(pointer)); -	return NULL; +	return SegmentRef();  }  bool Script::isValidOffset(uint16 offset) const {  	return offset < _bufSize;  } -byte *Script::dereference(reg_t pointer, int *size) { +SegmentRef Script::dereference(reg_t pointer) {  	if (pointer.offset > _bufSize) { -		warning("Attempt to dereference invalid pointer %04x:%04x into script segment (script size=%d)\n", +		warning("Attempt to dereference invalid pointer %04x:%04x into script segment (script size=%d)",  				  PRINT_REG(pointer), (uint)_bufSize); -		return NULL; +		return SegmentRef();  	} -	if (size) -		*size = _bufSize - pointer.offset; -	return _buf + pointer.offset; + +	SegmentRef ret; +	ret.isRaw = true; +	ret.maxSize = _bufSize - pointer.offset; +	ret.raw = _buf + pointer.offset; +	return ret;  }  bool LocalVariables::isValidOffset(uint16 offset) const {  	return offset < _locals.size() * sizeof(reg_t);  } -byte *LocalVariables::dereference(reg_t pointer, int *size) { -	if (size) -		*size = _locals.size() * sizeof(reg_t); - +SegmentRef LocalVariables::dereference(reg_t pointer) {  	// FIXME: The following doesn't seem to be endian safe.  	// To fix this, we'd have to always treat the reg_t  	// values stored here as in the little endian format. -	byte *base = (byte *)&_locals[0]; -	return base + pointer.offset; +	// Anyway, generate a warning for now to see if this ever +	// happens. +	// One has to wonder whether we return the right value anyway. +	// Here are three potential options: +	//   1:  ((byte *)&_locals[0]) + pointer.offset +	//   2:  ((byte *)&_locals[pointer.offset/2]) + (pointer.offset % 2) +	//   3:  ((byte *)&_locals[pointer.offset]) +	// So which one is correct? :) +	if (pointer.offset & 1) +		warning("LocalVariables::dereference: Odd offset in pointer  %04x:%04x", PRINT_REG(pointer)); + +	SegmentRef ret; +	ret.isRaw = false;	// reg_t based data! +	ret.maxSize = _locals.size() * sizeof(reg_t); +	ret.raw = (byte *)&_locals[0] + pointer.offset; +	return ret;  }  bool DataStack::isValidOffset(uint16 offset) const {  	return offset < _capacity * sizeof(reg_t);  } -byte *DataStack::dereference(reg_t pointer, int *size) { -	if (size) -		*size = _capacity * sizeof(reg_t); - -	byte *base = (byte *)_entries; -	return base + pointer.offset; +SegmentRef DataStack::dereference(reg_t pointer) { +	SegmentRef ret; +	ret.isRaw = false;	// reg_t based data! +	ret.maxSize = _capacity * sizeof(reg_t); +	// FIXME: Is this correct? See comment in LocalVariables::dereference +	ret.raw = (byte *)_entries + pointer.offset; +	return ret;  }  bool DynMem::isValidOffset(uint16 offset) const {  	return offset < _size;  } -byte *DynMem::dereference(reg_t pointer, int *size) { -	if (size) -		*size = _size; - -	byte *base = (byte *)_buf; -	return base + pointer.offset; +SegmentRef DynMem::dereference(reg_t pointer) { +	SegmentRef ret; +	ret.isRaw = true; +	ret.maxSize = _size; +	ret.raw = _buf + pointer.offset; +	return ret;  }  bool SystemStrings::isValidOffset(uint16 offset) const {  	return offset < SYS_STRINGS_MAX && !strings[offset]._name.empty();  } -byte *SystemStrings::dereference(reg_t pointer, int *size) { -	if (size) -		*size = strings[pointer.offset].max_size; +SegmentRef SystemStrings::dereference(reg_t pointer) { +	SegmentRef ret; +	ret.isRaw = false;	// FIXME: Raw or not raw? the sys strings code is totally incoherent in this regard +	ret.maxSize = strings[pointer.offset].max_size;  	if (isValidOffset(pointer.offset)) -		return (byte *)(strings[pointer.offset].value); +		ret.raw = (byte *)(strings[pointer.offset].value); +	else { +		// This occurs in KQ5CD when interacting with certain objects +		warning("Attempt to dereference invalid pointer %04x:%04x", PRINT_REG(pointer)); +	} -	// This occurs in KQ5CD when interacting with certain objects -	warning("Attempt to dereference invalid pointer %04x:%04x", PRINT_REG(pointer)); -	return NULL; +	return ret;  } diff --git a/engines/sci/engine/segment.h b/engines/sci/engine/segment.h index 81da9c2488..1f446957d5 100644 --- a/engines/sci/engine/segment.h +++ b/engines/sci/engine/segment.h @@ -34,6 +34,23 @@  namespace Sci { +struct SegmentRef { +	bool isRaw;	///! true if data is raw, false if it is a reg_t sequence +	union { +		byte *raw; +		reg_t *reg; +	}; +	int maxSize;	///! number of available bytes +	// TODO: Add this? +	//reg_t pointer;	// Original pointer + +	// TODO: Add this? +	//SegmentType type; + +	SegmentRef() : isRaw(true), raw(0), maxSize(0) {} +}; + +  enum SegmentType {  	SEG_TYPE_INVALID = 0,  	SEG_TYPE_SCRIPT = 1, @@ -73,10 +90,9 @@ public:  	/**  	 * Dereferences a raw memory pointer.  	 * @param reg	reference to dereference -	 * @param size	if not NULL, set to the theoretical maximum size of the referenced data block  	 * @return		the data block referenced  	 */ -	virtual byte *dereference(reg_t pointer, int *size); +	virtual SegmentRef dereference(reg_t pointer);  	/**  	 * Finds the canonic address associated with sub_reg. @@ -161,7 +177,7 @@ public:  	}  	virtual bool isValidOffset(uint16 offset) const; -	virtual byte *dereference(reg_t pointer, int *size); +	virtual SegmentRef dereference(reg_t pointer);  	virtual void saveLoadWithSerializer(Common::Serializer &ser);  }; @@ -176,7 +192,7 @@ public:  	}  	virtual bool isValidOffset(uint16 offset) const; -	virtual byte *dereference(reg_t pointer, int *size); +	virtual SegmentRef dereference(reg_t pointer);  	virtual reg_t findCanonicAddress(SegManager *segMan, reg_t sub_addr);  	virtual void listAllOutgoingReferences(reg_t object, void *param, NoteCallback note); @@ -309,7 +325,7 @@ public:  	bool init(int script_nr, ResourceManager *resMan);  	virtual bool isValidOffset(uint16 offset) const; -	virtual byte *dereference(reg_t pointer, int *size); +	virtual SegmentRef dereference(reg_t pointer);  	virtual reg_t findCanonicAddress(SegManager *segMan, reg_t sub_addr);  	virtual void freeAtAddress(SegManager *segMan, reg_t sub_addr);  	virtual void listAllDeallocatable(SegmentId segId, void *param, NoteCallback note); @@ -467,7 +483,7 @@ public:  	}  	virtual bool isValidOffset(uint16 offset) const; -	virtual byte *dereference(reg_t pointer, int *size); +	virtual SegmentRef dereference(reg_t pointer);  	virtual reg_t findCanonicAddress(SegManager *segMan, reg_t sub_addr);  	virtual void listAllOutgoingReferences(reg_t object, void *param, NoteCallback note); @@ -624,7 +640,7 @@ public:  	}  	virtual bool isValidOffset(uint16 offset) const; -	virtual byte *dereference(reg_t pointer, int *size); +	virtual SegmentRef dereference(reg_t pointer);  	virtual reg_t findCanonicAddress(SegManager *segMan, reg_t sub_addr);  	virtual void listAllDeallocatable(SegmentId segId, void *param, NoteCallback note); | 
