diff options
Diffstat (limited to 'engines/cine/object.cpp')
| -rw-r--r-- | engines/cine/object.cpp | 75 | 
1 files changed, 59 insertions, 16 deletions
diff --git a/engines/cine/object.cpp b/engines/cine/object.cpp index 7666f05352..c02e01c8ce 100644 --- a/engines/cine/object.cpp +++ b/engines/cine/object.cpp @@ -99,21 +99,36 @@ int removeOverlay(uint16 objIdx, uint16 param) {  /*! \brief Add new overlay sprite to the list   * \param objIdx Associate the overlay with this object - * \param param Type of new overlay + * \param type Type of new overlay   * \todo Why are x, y, width and color left uninitialized?   */ -void addOverlay(uint16 objIdx, uint16 param) { +void addOverlay(uint16 objIdx, uint16 type) {  	Common::List<overlay>::iterator it;  	overlay tmp;  	for (it = overlayList.begin(); it != overlayList.end(); ++it) { +		// This is done for both Future Wars and Operation Stealth  		if (objectTable[it->objIdx].mask >= objectTable[objIdx].mask) {  			break;  		} + +		// There are additional checks in Operation Stealth's implementation +		if (g_cine->getGameType() == Cine::GType_OS && (it->type == 2 || it->type == 3)) { +			break; +		} +	} + +	// In Operation Stealth's implementation we might bail out early +	if (g_cine->getGameType() == Cine::GType_OS && it != overlayList.end() && it->objIdx == objIdx && it->type == type) { +		return;  	}  	tmp.objIdx = objIdx; -	tmp.type = param; +	tmp.type = type; +	tmp.x = 0; +	tmp.y = 0; +	tmp.width = 0; +	tmp.color = 0;  	overlayList.insert(it, tmp);  } @@ -122,24 +137,22 @@ void addOverlay(uint16 objIdx, uint16 param) {   * \param objIdx Associate the overlay with this object   * \param param source background index   */ -void addGfxElementA0(int16 objIdx, int16 param) { +void addGfxElement(int16 objIdx, int16 param, int16 type) {  	Common::List<overlay>::iterator it;  	overlay tmp;  	for (it = overlayList.begin(); it != overlayList.end(); ++it) { -		// wtf?! -		if (objectTable[it->objIdx].mask == objectTable[objIdx].mask && -			(it->type == 2 || it->type == 3)) { +		if (objectTable[it->objIdx].mask >= objectTable[objIdx].mask || it->type == 2 || it->type == 3) {  			break;  		}  	} -	if (it != overlayList.end() && it->objIdx == objIdx && it->type == 20 && it->x == param) { +	if (it != overlayList.end() && it->objIdx == objIdx && it->type == type && it->x == param) {  		return;  	}  	tmp.objIdx = objIdx; -	tmp.type = 20; +	tmp.type = type;  	tmp.x = param;  	tmp.y = 0;  	tmp.width = 0; @@ -153,11 +166,11 @@ void addGfxElementA0(int16 objIdx, int16 param) {   * \param param Remove overlay using this background   * \todo Check that it works   */ -void removeGfxElementA0(int16 objIdx, int16 param) { +void removeGfxElement(int16 objIdx, int16 param, int16 type) {  	Common::List<overlay>::iterator it;  	for (it = overlayList.begin(); it != overlayList.end(); ++it) { -		if (it->objIdx == objIdx && it->type == 20 && it->x == param) { +		if (it->objIdx == objIdx && it->type == type && it->x == param) {  			overlayList.erase(it);  			return;  		} @@ -170,8 +183,12 @@ void setupObject(byte objIdx, uint16 param1, uint16 param2, uint16 param3, uint1  	objectTable[objIdx].mask = param3;  	objectTable[objIdx].frame = param4; -	if (removeOverlay(objIdx, 0)) { -		addOverlay(objIdx, 0); +	if (g_cine->getGameType() == Cine::GType_OS) { +		resetGfxEntityEntry(objIdx); +	} else { // Future Wars +		if (removeOverlay(objIdx, 0)) { +			addOverlay(objIdx, 0); +		}  	}  } @@ -199,9 +216,12 @@ void modifyObjectParam(byte objIdx, byte paramIdx, int16 newValue) {  	case 3:  		objectTable[objIdx].mask = newValue; -		// TODO: Check this part against disassembly -		if (removeOverlay(objIdx, 0)) { -			addOverlay(objIdx, 0); +		if (g_cine->getGameType() == Cine::GType_OS) { // Operation Stealth specific +			resetGfxEntityEntry(objIdx); +		} else { // Future Wars specific +			if (removeOverlay(objIdx, 0)) { +				addOverlay(objIdx, 0); +			}  		}  		break;  	case 4: @@ -221,6 +241,29 @@ void modifyObjectParam(byte objIdx, byte paramIdx, int16 newValue) {  	}  } +/** + * Check if at least one of the range B's endpoints is inside range A, + * not counting the starting and ending points of range A. + * Used at least by Operation Stealth's opcode 0x8D i.e. 141. + */ +bool compareRanges(uint16 aStart, uint16 aEnd, uint16 bStart, uint16 bEnd) { +	return (bStart > aStart && bStart < aEnd) || (bEnd > aStart && bEnd < aEnd); +} + +uint16 compareObjectParamRanges(uint16 objIdx1, uint16 xAdd1, uint16 yAdd1, uint16 maskAdd1, uint16 objIdx2, uint16 xAdd2, uint16 yAdd2, uint16 maskAdd2) { +	assert(objIdx1 < NUM_MAX_OBJECT && objIdx2 < NUM_MAX_OBJECT); +	const objectStruct &obj1 = objectTable[objIdx1]; +	const objectStruct &obj2 = objectTable[objIdx2]; + +	if (compareRanges(obj1.x,    obj1.x    + xAdd1,    obj2.x,    obj2.x    + xAdd2) && +		compareRanges(obj1.y,    obj1.y    + yAdd1,    obj2.y,    obj2.y    + yAdd2) && +		compareRanges(obj1.mask, obj1.mask + maskAdd1, obj2.mask, obj2.mask + maskAdd2)) { +		return kCmpEQ; +	} else { +		return 0; +	} +} +  uint16 compareObjectParam(byte objIdx, byte type, int16 value) {  	uint16 compareResult = 0;  	int16 objectParam = getObjectParam(objIdx, type);  | 
