[Scummvm-git-logs] scummvm master -> 5e31204c92d316e5c8df10f5394af7a89b4ce8df

mgerhardy martin.gerhardy at gmail.com
Thu Nov 5 17:57:03 UTC 2020


This automated email contains information about 18 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .

Summary:
936cee63d6 TWINE: fixed endianess issue in hqr loading
7079d6d49b TWINE: fixed endian issues in grid data parsing
e513d7de5c TWINE: add resource sizes for sprites
0023dfd5ea TWINE: prepare to use memstreams
aeb8730151 TWINE: endian safe parsing of grid entries
763b99e189 TWINE: added macro to check if the current actor is the hero
590660655d TWINE: extracted into own methods
329e60ea56 TWINE: minor cleanup
59adc94b06 TWINE: changed comment
517248adb8 TWINE: reduced visibility of scene members
c8183e2926 TWINE: fixed wild casting
e498b80bed TWINE: use stream to parse the sprite offsets
36278881ea TWINE: use endian safe short parsing
c5336cd078 TWINE: use stream for endian safe parsing of the body data
5adc5d99aa TWINE: fixed active menu button text changes
1a2ebdc5da TWINE: fixed agressive behaviour type text id in options menu
bac82c726f TWINE: small helper method to match the textid to behaviours
5e31204c92 TWINE: const for palette pointers


Commit: 936cee63d64cb463ea5bbfe31e5bdc2c9949f5db
    https://github.com/scummvm/scummvm/commit/936cee63d64cb463ea5bbfe31e5bdc2c9949f5db
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2020-11-05T18:56:07+01:00

Commit Message:
TWINE: fixed endianess issue in hqr loading

Changed paths:
    engines/twine/hqr.cpp
    engines/twine/resources.cpp


diff --git a/engines/twine/hqr.cpp b/engines/twine/hqr.cpp
index 9ae75ebd3e..63a6277438 100644
--- a/engines/twine/hqr.cpp
+++ b/engines/twine/hqr.cpp
@@ -23,6 +23,7 @@
 #include "twine/hqr.h"
 #include "common/debug.h"
 #include "common/file.h"
+#include "common/memstream.h"
 #include "common/system.h"
 #include "common/textconsole.h"
 
@@ -39,18 +40,19 @@ namespace HQR {
 /**
  * Decompress entry based in Yaz0r and Zink decompression code
  * @param dst destination pointer where will be the decompressed entry
- * @param src compressed data pointer
+ * @param compBuf compressed data pointer
+ * @param compSize @p compBuf buffer size
  * @param decompsize real file size after decompression
  * @param mode compression mode used
  */
-static void decompressEntry(uint8 *dst, const uint8 *src, int32 decompsize, int32 mode) {
+static void decompressEntry(uint8 *dst, const uint8 *compBuf, uint32 compSize, int32 decompsize, int32 mode) {
+	Common::MemoryReadStream stream(compBuf, compSize);
 	do {
-		uint8 b = *(src++);
+		uint8 b = stream.readByte();
 		for (int32 d = 0; d < 8; d++) {
 			int32 length;
 			if (!(b & (1 << d))) {
-				const uint16 offset = *(const uint16 *)(src);
-				src += 2;
+				const uint16 offset = stream.readUint16LE();
 				length = (offset & 0x0F) + (mode + 1);
 				const uint8 *ptr = dst - (offset >> 4) - 1;
 				for (int32 i = 0; i < length; i++) {
@@ -58,7 +60,7 @@ static void decompressEntry(uint8 *dst, const uint8 *src, int32 decompsize, int3
 				}
 			} else {
 				length = 1;
-				*(dst++) = *(src++);
+				*(dst++) = stream.readByte();
 			}
 			decompsize -= length;
 			if (decompsize <= 0) {
@@ -147,7 +149,7 @@ int32 getEntry(uint8 *ptr, const char *filename, int32 index) {
 	else if (mode == 1 || mode == 2) {
 		uint8 *compDataPtr = (uint8 *)malloc(compSize);
 		wrap(file.read(compDataPtr, compSize))
-		decompressEntry(ptr, compDataPtr, realSize, mode);
+		decompressEntry(ptr, compDataPtr, compSize, realSize, mode);
 		free(compDataPtr);
 	}
 
@@ -258,7 +260,7 @@ int32 getVoxEntry(uint8 *ptr, const char *filename, int32 index, int32 hiddenInd
 	else if (mode == 1 || mode == 2) {
 		uint8 *compDataPtr = (uint8 *)malloc(compSize);
 		wrap(file.read(compDataPtr, compSize))
-		decompressEntry(ptr, compDataPtr, realSize, mode);
+		decompressEntry(ptr, compDataPtr, compSize, realSize, mode);
 		free(compDataPtr);
 	}
 
diff --git a/engines/twine/resources.cpp b/engines/twine/resources.cpp
index d65c6fc435..8a213b9129 100644
--- a/engines/twine/resources.cpp
+++ b/engines/twine/resources.cpp
@@ -97,9 +97,9 @@ void Resources::preloadSamples() {
 			continue;
 		}
 		// Fix incorrect sample files first byte
-		if (*samplesTable[i] != 'C') {
+		if (*(samplesTable[i]) != 'C') {
 			debug(0, "Sample %i has incorrect magic id", i);
-			*samplesTable[i] = 'C';
+			*(samplesTable[i]) = 'C';
 		}
 	}
 }


Commit: 7079d6d49bde254412adfc9d3d84735f4a50b3b3
    https://github.com/scummvm/scummvm/commit/7079d6d49bde254412adfc9d3d84735f4a50b3b3
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2020-11-05T18:56:07+01:00

Commit Message:
TWINE: fixed endian issues in grid data parsing

Changed paths:
    engines/twine/grid.cpp


diff --git a/engines/twine/grid.cpp b/engines/twine/grid.cpp
index 6b549e1472..4752510a91 100644
--- a/engines/twine/grid.cpp
+++ b/engines/twine/grid.cpp
@@ -21,6 +21,7 @@
  */
 
 #include "twine/grid.h"
+#include "common/endian.h"
 #include "common/textconsole.h"
 #include "twine/actor.h"
 #include "twine/collision.h"
@@ -56,8 +57,9 @@ void Grid::copyGridMask(int32 index, int32 x, int32 y, const uint8 *buffer) {
 	int32 right = *ptr + left - 1;
 	int32 bottom = *(ptr + 1) + top - 1;
 
-	if (left > _engine->_interface->textWindowRight || right < _engine->_interface->textWindowLeft || bottom < _engine->_interface->textWindowTop || top > _engine->_interface->textWindowBottom)
+	if (left > _engine->_interface->textWindowRight || right < _engine->_interface->textWindowLeft || bottom < _engine->_interface->textWindowTop || top > _engine->_interface->textWindowBottom) {
 		return;
+	}
 
 	ptr += 4;
 
@@ -66,8 +68,9 @@ void Grid::copyGridMask(int32 index, int32 x, int32 y, const uint8 *buffer) {
 
 	int32 vSize = (bottom - top) + 1;
 
-	if (vSize <= 0)
+	if (vSize <= 0) {
 		return;
+	}
 
 	int32 offset = -((right - left) - SCREEN_WIDTH) - 1;
 
@@ -79,8 +82,9 @@ void Grid::copyGridMask(int32 index, int32 x, int32 y, const uint8 *buffer) {
 		int numOfLineToRemove = _engine->_interface->textWindowTop - absY;
 
 		vSize -= numOfLineToRemove;
-		if (vSize <= 0)
+		if (vSize <= 0) {
 			return;
+		}
 
 		absY += numOfLineToRemove;
 
@@ -95,8 +99,9 @@ void Grid::copyGridMask(int32 index, int32 x, int32 y, const uint8 *buffer) {
 	// reduce the vSize to remove lines on bottom
 	if (absY + vSize - 1 > _engine->_interface->textWindowBottom) {
 		vSize = _engine->_interface->textWindowBottom - absY + 1;
-		if (vSize <= 0)
+		if (vSize <= 0) {
 			return;
+		}
 	}
 
 	uint8 *outPtr = (uint8 *)_engine->frontVideoBuffer.getPixels() + _engine->screenLookupTable[absY] + left;
@@ -113,8 +118,9 @@ void Grid::copyGridMask(int32 index, int32 x, int32 y, const uint8 *buffer) {
 			absX += temp;
 
 			vc3--;
-			if (!vc3)
+			if (!vc3) {
 				break;
+			}
 
 			temp = *(ptr++); // copy size
 
@@ -176,9 +182,9 @@ void Grid::drawOverSpriteActor(int32 x, int32 y, int32 z) {
 
 int Grid::processGridMask(const uint8 *buffer, uint8 *ptr) {
 	const uint32 *ptrSave = (const uint32 *)ptr;
-	int32 ebx = *((const uint32 *)buffer); // brick flag
+	int32 ebx = READ_UINT32(buffer); // brick flag
 	buffer += 4;
-	*((uint32 *)ptr) = ebx;
+	WRITE_LE_UINT32(ptr, (uint32)ebx);
 	ptr += 4;
 
 	uint8 bh = (ebx & 0x0000FF00) >> 8;
@@ -252,7 +258,7 @@ void Grid::createGridMask() {
 }
 
 void Grid::getSpriteSize(int32 offset, int32 *width, int32 *height, const uint8 *spritePtr) {
-	spritePtr += *((const int32 *)(spritePtr + offset * 4));
+	spritePtr += READ_LE_INT32(spritePtr + offset * 4);
 
 	*width = *spritePtr;
 	*height = *(spritePtr + 1);
@@ -276,7 +282,7 @@ int32 Grid::loadGridBricks(int32 gridSize) {
 		uint8 currentBitMask = 1 << (7 - (i & 7));
 
 		if (currentBitByte & currentBitMask) {
-			uint32 currentBllOffset = *((const uint32 *)(currentBll + currentBllEntryIdx));
+			uint32 currentBllOffset = READ_LE_UINT32(currentBll + currentBllEntryIdx);
 			const uint8 *currentBllPtr = currentBll + currentBllOffset;
 
 			uint32 bllSizeX = currentBllPtr[0];
@@ -288,7 +294,7 @@ int32 Grid::loadGridBricks(int32 gridSize) {
 			const uint8 *bllDataPtr = currentBllPtr + 5;
 
 			for (uint32 j = 0; j < bllSize; j++) {
-				uint32 brickIdx = *((const int16 *)(bllDataPtr));
+				uint32 brickIdx = READ_LE_INT16(bllDataPtr);
 
 				if (brickIdx) {
 					brickIdx--;
@@ -394,7 +400,7 @@ void Grid::createGridMap() {
 		int32 gridIdx = z << 6;
 
 		for (int32 x = 0; x < GRID_SIZE_X; x++) {
-			int32 gridOffset = *((const uint16 *)(currentGrid + 2 * (x + gridIdx)));
+			int32 gridOffset = READ_LE_UINT16(currentGrid + 2 * (x + gridIdx));
 			createGridColumn(currentGrid + gridOffset, blockBuffer + blockOffset);
 			blockOffset += 50;
 		}
@@ -411,7 +417,7 @@ void Grid::createCellingGridMap(const uint8 *gridPtr) {
 		const uint8 *tempGridPtr = gridPtr + currGridOffset;
 
 		for (int32 x = 0; x < GRID_SIZE_X; x++) {
-			int gridOffset = *((const uint16 *)tempGridPtr);
+			int gridOffset = READ_LE_UINT16(tempGridPtr);
 			tempGridPtr += 2;
 			createCellingGridColumn(gridPtr + gridOffset, blockBuffer + blockOffset);
 			blockOffset += 50;
@@ -436,7 +442,7 @@ bool Grid::initGrid(int32 index) {
 
 	createGridMask();
 
-	numberOfBll = (*((const uint32 *)currentBll) >> 2);
+	numberOfBll = READ_LE_INT32(currentBll) >> 2;
 
 	createGridMap();
 
@@ -470,7 +476,7 @@ void Grid::drawSprite(int32 index, int32 posX, int32 posY, const uint8 *ptr) {
 // WARNING: Rewrite this function to have better performance
 void Grid::drawBrickSprite(int32 index, int32 posX, int32 posY, const uint8 *ptr, bool isSprite) {
 	if (isSprite) {
-		ptr = ptr + *((const uint32 *)(ptr + index * 4));
+		ptr = ptr + READ_LE_INT32(ptr + index * 4);
 	}
 
 	int32 left = posX + *(ptr + 2);
@@ -547,7 +553,7 @@ const uint8* Grid::getBlockBufferGround(int32 x, int32 y, int32 z, int16 &ground
 	const uint8 *ptr = blockBuffer + tempY * 2 + tempX * GRID_SIZE_Y * 2 + (tempZ << 6) * GRID_SIZE_Y * 2;
 
 	while (tempY) {
-		if (*(const int16 *)ptr) { // found the ground
+		if (READ_LE_INT16(ptr)) { // found the ground
 			break;
 		}
 		tempY--;
@@ -561,7 +567,7 @@ const uint8* Grid::getBlockBufferGround(int32 x, int32 y, int32 z, int16 &ground
 }
 
 const uint8 *Grid::getBlockLibrary(int32 index) {
-	const int32 offset = *((const uint32 *)(currentBll + 4 * index));
+	const int32 offset = READ_LE_UINT32(currentBll + 4 * index);
 	return (const uint8 *)(currentBll + offset);
 }
 
@@ -575,7 +581,7 @@ void Grid::drawColumnGrid(int32 blockIdx, int32 brickBlockIdx, int32 x, int32 y,
 
 	const uint8 brickShape = *((const uint8 *)(blockPtr + 0));
 	const uint8 brickSound = *((const uint8 *)(blockPtr + 1));
-	const uint16 brickIdx = *((const uint16 *)(blockPtr + 2));
+	const uint16 brickIdx = READ_LE_UINT16(blockPtr + 2);
 	if (!brickIdx) {
 		return;
 	}
@@ -674,7 +680,7 @@ int32 Grid::getBrickShape(int32 x, int32 y, int32 z) {
 	if (blockIdx) {
 		const uint8 *blockPtr = currentBll;
 
-		blockPtr += *(const uint32 *)(blockPtr + blockIdx * 4 - 4);
+		blockPtr += READ_LE_UINT32(blockPtr + blockIdx * 4 - 4);
 		blockPtr += 3;
 
 		const uint8 tmpBrickIdx = *(blockBufferPtr + 1);
@@ -716,7 +722,7 @@ int32 Grid::getBrickShapeFull(int32 x, int32 y, int32 z, int32 y2) {
 	if (blockIdx) {
 		const uint8 *blockPtr = currentBll;
 
-		blockPtr += *(const uint32 *)(blockPtr + blockIdx * 4 - 4);
+		blockPtr += READ_LE_UINT32(blockPtr + blockIdx * 4 - 4);
 		blockPtr += 3;
 
 		uint8 tmpBrickIdx = *(blockBufferPtr + 1);
@@ -735,7 +741,7 @@ int32 Grid::getBrickShapeFull(int32 x, int32 y, int32 z, int32 y2) {
 			blockBufferPtr += 2;
 			currY++;
 
-			if (*(const int16 *)(blockBufferPtr) != 0) {
+			if (READ_LE_INT16(blockBufferPtr) != 0) {
 				return 1;
 			}
 		}
@@ -755,7 +761,7 @@ int32 Grid::getBrickShapeFull(int32 x, int32 y, int32 z, int32 y2) {
 		blockBufferPtr += 2;
 		currY++;
 
-		if (*(const int16 *)(blockBufferPtr) != 0) {
+		if (READ_LE_INT16(blockBufferPtr) != 0) {
 			return 1;
 		}
 	}
@@ -788,14 +794,14 @@ int32 Grid::getBrickSoundType(int32 x, int32 y, int32 z) { // getPos2
 	if (blockIdx) {
 		const uint8 *blockPtr = currentBll;
 
-		blockPtr += *(const uint32 *)(blockPtr + blockIdx * 4 - 4);
+		blockPtr += READ_LE_UINT32(blockPtr + blockIdx * 4 - 4);
 		blockPtr += 3;
 
 		uint8 tmpBrickIdx = *(blockBufferPtr + 1);
 		blockPtr = blockPtr + tmpBrickIdx * 4;
 		blockPtr++;
 
-		return *((const int16 *)blockPtr);
+		return READ_LE_INT16(blockPtr);
 	}
 
 	return 0xF0;


Commit: e513d7de5c61d29d756634751ac05a69308c48e6
    https://github.com/scummvm/scummvm/commit/e513d7de5c61d29d756634751ac05a69308c48e6
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2020-11-05T18:56:07+01:00

Commit Message:
TWINE: add resource sizes for sprites

Changed paths:
    engines/twine/resources.cpp
    engines/twine/resources.h


diff --git a/engines/twine/resources.cpp b/engines/twine/resources.cpp
index 8a213b9129..1c2f93ca97 100644
--- a/engines/twine/resources.cpp
+++ b/engines/twine/resources.cpp
@@ -127,11 +127,13 @@ void Resources::initResources() {
 	_engine->_text->setFontColor(14);
 	_engine->_text->setTextCrossColor(136, 143, 2);
 
-	if (HQR::getAllocEntry(&spriteShadowPtr, Resources::HQR_RESS_FILE, RESSHQR_SPRITESHADOW) == 0) {
+	spriteShadowSize = HQR::getAllocEntry(&spriteShadowPtr, Resources::HQR_RESS_FILE, RESSHQR_SPRITESHADOW);
+	if (spriteShadowSize == 0) {
 		error("Failed to load sprite shadow");
 	}
 
-	if (HQR::getAllocEntry(&spriteBoundingBoxPtr, Resources::HQR_RESS_FILE, RESSHQR_SPRITEBOXDATA) == 0) {
+	spriteBoundingBoxSize = HQR::getAllocEntry(&spriteBoundingBoxPtr, Resources::HQR_RESS_FILE, RESSHQR_SPRITEBOXDATA);
+	if (spriteBoundingBoxSize == 0) {
 		error("Failed to load actors bounding box data");
 	}
 
diff --git a/engines/twine/resources.h b/engines/twine/resources.h
index 64621f5eaa..ccfd4f13d8 100644
--- a/engines/twine/resources.h
+++ b/engines/twine/resources.h
@@ -142,7 +142,9 @@ public:
 	/** Font buffer pointer */
 	uint8 *fontPtr = nullptr;
 
+	uint32 spriteShadowSize = 0;
 	uint8 *spriteShadowPtr = nullptr;
+	uint32 spriteBoundingBoxSize = 0;
 	uint8 *spriteBoundingBoxPtr = nullptr;
 
 	/** Initialize resource pointers */


Commit: 0023dfd5ea62767715a140b9938dad7b9431f28e
    https://github.com/scummvm/scummvm/commit/0023dfd5ea62767715a140b9938dad7b9431f28e
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2020-11-05T18:56:07+01:00

Commit Message:
TWINE: prepare to use memstreams

Changed paths:
    engines/twine/grid.cpp
    engines/twine/grid.h


diff --git a/engines/twine/grid.cpp b/engines/twine/grid.cpp
index 4752510a91..413f1a0682 100644
--- a/engines/twine/grid.cpp
+++ b/engines/twine/grid.cpp
@@ -36,7 +36,8 @@
 namespace TwinE {
 
 Grid::Grid(TwinEEngine *engine) : _engine(engine) {
-	blockBuffer = (uint8 *)malloc(GRID_SIZE_X * GRID_SIZE_Z * GRID_SIZE_Y * 2 * sizeof(uint8));
+	blockBufferSize = GRID_SIZE_X * GRID_SIZE_Z * GRID_SIZE_Y * 2 * sizeof(uint8);
+	blockBuffer = (uint8 *)malloc(blockBufferSize);
 }
 
 Grid::~Grid() {
@@ -329,7 +330,7 @@ int32 Grid::loadGridBricks(int32 gridSize) {
 	return 1;
 }
 
-void Grid::createGridColumn(const uint8 *gridEntry, uint8 *dest) {
+void Grid::createGridColumn(const uint8 *gridEntry, uint32 gridEntrySize, uint8 *dest, uint32 destSize) {
 	int32 brickCount = *(gridEntry++);
 
 	do {
@@ -360,7 +361,7 @@ void Grid::createGridColumn(const uint8 *gridEntry, uint8 *dest) {
 	} while (--brickCount);
 }
 
-void Grid::createCellingGridColumn(const uint8 *gridEntry, uint8 *dest) {
+void Grid::createCellingGridColumn(const uint8 *gridEntry, uint32 gridEntrySize, uint8 *dest, uint32 destSize) {
 	int32 brickCount = *(gridEntry++);
 
 	do {
@@ -401,14 +402,14 @@ void Grid::createGridMap() {
 
 		for (int32 x = 0; x < GRID_SIZE_X; x++) {
 			int32 gridOffset = READ_LE_UINT16(currentGrid + 2 * (x + gridIdx));
-			createGridColumn(currentGrid + gridOffset, blockBuffer + blockOffset);
+			createGridColumn(currentGrid + gridOffset, currentGridSize - gridOffset, blockBuffer + blockOffset, blockBufferSize - blockOffset);
 			blockOffset += 50;
 		}
 		currOffset += 3200;
 	}
 }
 
-void Grid::createCellingGridMap(const uint8 *gridPtr) {
+void Grid::createCellingGridMap(const uint8 *gridPtr, int32 gridPtrSize) {
 	int32 currGridOffset = 0;
 	int32 currOffset = 0;
 
@@ -419,7 +420,7 @@ void Grid::createCellingGridMap(const uint8 *gridPtr) {
 		for (int32 x = 0; x < GRID_SIZE_X; x++) {
 			int gridOffset = READ_LE_UINT16(tempGridPtr);
 			tempGridPtr += 2;
-			createCellingGridColumn(gridPtr + gridOffset, blockBuffer + blockOffset);
+			createCellingGridColumn(gridPtr + gridOffset, gridPtrSize - gridOffset, blockBuffer + blockOffset, blockBufferSize - blockOffset);
 			blockOffset += 50;
 		}
 		currGridOffset += 128;
@@ -429,8 +430,8 @@ void Grid::createCellingGridMap(const uint8 *gridPtr) {
 
 bool Grid::initGrid(int32 index) {
 	// load grids from file
-	const int32 gridSize = HQR::getAllocEntry(&currentGrid, Resources::HQR_LBA_GRI_FILE, index);
-	if (gridSize == 0) {
+	currentGridSize = HQR::getAllocEntry(&currentGrid, Resources::HQR_LBA_GRI_FILE, index);
+	if (currentGridSize == 0) {
 		warning("Failed to load grid index: %i", index);
 		return false;
 	}
@@ -438,7 +439,7 @@ bool Grid::initGrid(int32 index) {
 	// load layouts from file
 	HQR::getAllocEntry(&currentBll, Resources::HQR_LBA_BLL_FILE, index);
 
-	loadGridBricks(gridSize);
+	loadGridBricks(currentGridSize);
 
 	createGridMask();
 
@@ -454,12 +455,13 @@ bool Grid::initCellingGrid(int32 index) {
 
 	// load grids from file
 	const int realIndex = index + CELLING_GRIDS_START_INDEX;
-	if (HQR::getAllocEntry(&gridPtr, Resources::HQR_LBA_GRI_FILE, realIndex) == 0) {
+	const int32 gridSize = HQR::getAllocEntry(&gridPtr, Resources::HQR_LBA_GRI_FILE, realIndex);
+	if (gridSize == 0) {
 		warning("Failed to load grid index %i", realIndex);
 		return false;
 	}
 
-	createCellingGridMap(gridPtr);
+	createCellingGridMap(gridPtr, gridSize);
 	free(gridPtr);
 	_engine->_redraw->reqBgRedraw = true;
 	return true;
diff --git a/engines/twine/grid.h b/engines/twine/grid.h
index e0cb2afe7c..66298ddec2 100644
--- a/engines/twine/grid.h
+++ b/engines/twine/grid.h
@@ -113,19 +113,19 @@ private:
 	 * Create celling grid map from celling grid to block library buffer
 	 * @param gridPtr celling grid buffer pointer
 	 */
-	void createCellingGridMap(const uint8 *gridPtr);
+	void createCellingGridMap(const uint8 *gridPtr, int32 gridPtrSize);
 	/**
 	 * Create grid Y column in block buffer
 	 * @param gridEntry current grid index
 	 * @param dest destination block buffer
 	 */
-	void createCellingGridColumn(const uint8 *gridEntry, uint8 *dest);
+	void createCellingGridColumn(const uint8 *gridEntry, uint32 gridEntrySize, uint8 *dest, uint32 destSize);
 	/**
 	 * Create grid Y column in block buffer
 	 * @param gridEntry current grid index
 	 * @param dest destination block buffer
 	 */
-	void createGridColumn(const uint8 *gridEntry, uint8 *dest);
+	void createGridColumn(const uint8 *gridEntry, uint32 gridEntrySize, uint8 *dest, uint32 destSize);
 	/**
 	 * Load grid bricks according with block librarie usage
 	 * @param gridSize size of the current grid
@@ -159,6 +159,7 @@ private:
 	uint8 brickUsageTable[NUM_BRICKS]{0};
 
 	/** Current grid pointer */
+	int32 currentGridSize = 0;
 	uint8 *currentGrid = nullptr;
 	/** Current block library pointer */
 	uint8 *currentBll = nullptr;
@@ -176,6 +177,7 @@ private:
 	int32 brickPixelPosY = 0;
 
 	/** Celling grid brick block buffer */
+	int32 blockBufferSize = 0;
 	uint8 *blockBuffer = nullptr;
 
 public:


Commit: aeb87301512cc38b3026f8f0a15d08e8aa2c108f
    https://github.com/scummvm/scummvm/commit/aeb87301512cc38b3026f8f0a15d08e8aa2c108f
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2020-11-05T18:56:07+01:00

Commit Message:
TWINE: endian safe parsing of grid entries

Changed paths:
    engines/twine/grid.cpp


diff --git a/engines/twine/grid.cpp b/engines/twine/grid.cpp
index 413f1a0682..789fd425f5 100644
--- a/engines/twine/grid.cpp
+++ b/engines/twine/grid.cpp
@@ -22,6 +22,7 @@
 
 #include "twine/grid.h"
 #include "common/endian.h"
+#include "common/memstream.h"
 #include "common/textconsole.h"
 #include "twine/actor.h"
 #include "twine/collision.h"
@@ -331,65 +332,58 @@ int32 Grid::loadGridBricks(int32 gridSize) {
 }
 
 void Grid::createGridColumn(const uint8 *gridEntry, uint32 gridEntrySize, uint8 *dest, uint32 destSize) {
-	int32 brickCount = *(gridEntry++);
+	Common::MemoryReadStream stream(gridEntry, gridEntrySize);
+	Common::MemoryWriteStream outstream(dest, destSize);
+	int32 brickCount = stream.readByte();
 
 	do {
-		int32 flag = *(gridEntry++);
-		int32 blockCount = (flag & 0x3F) + 1;
-
-		const uint16 *gridBuffer = (const uint16 *)gridEntry;
-		uint16 *blockByffer = (uint16 *)dest;
+		const int32 flag = stream.readByte();
+		const int32 blockCount = (flag & 0x3F) + 1;
 
 		if (!(flag & 0xC0)) {
 			for (int32 i = 0; i < blockCount; i++) {
-				*(blockByffer++) = 0;
+				outstream.writeUint16LE(0);
 			}
 		} else if (flag & 0x40) {
 			for (int32 i = 0; i < blockCount; i++) {
-				*(blockByffer++) = *(gridBuffer++);
+				outstream.writeUint16LE(stream.readUint16LE());
 			}
 		} else {
-			int32 gridIdx = *(gridBuffer++);
+			int32 gridIdx = stream.readUint16LE();
 			for (int32 i = 0; i < blockCount; i++) {
-				*(blockByffer++) = gridIdx;
+				outstream.writeUint16LE(gridIdx);
 			}
 		}
-
-		gridEntry = (const uint8 *)gridBuffer;
-		dest = (uint8 *)blockByffer;
-
+		assert(!outstream.err());
+		assert(!stream.err());
 	} while (--brickCount);
 }
 
 void Grid::createCellingGridColumn(const uint8 *gridEntry, uint32 gridEntrySize, uint8 *dest, uint32 destSize) {
-	int32 brickCount = *(gridEntry++);
+	Common::MemoryReadStream stream(gridEntry, gridEntrySize);
+	Common::SeekableMemoryWriteStream outstream(dest, destSize);
+	int32 brickCount = stream.readByte();
 
 	do {
-		int32 flag = *(gridEntry++);
-
-		int32 blockCount = (flag & 0x3F) + 1;
-
-		const uint16 *gridBuffer = (const uint16 *)gridEntry;
-		uint16 *blockByffer = (uint16 *)dest;
+		const int32 flag = stream.readByte();
+		const int32 blockCount = (flag & 0x3F) + 1;
 
 		if (!(flag & 0xC0)) {
 			for (int32 i = 0; i < blockCount; i++) {
-				blockByffer++;
+				outstream.seek(outstream.pos() + 2);
 			}
 		} else if (flag & 0x40) {
 			for (int32 i = 0; i < blockCount; i++) {
-				*(blockByffer++) = *(gridBuffer++);
+				outstream.writeUint16LE(stream.readUint16LE());
 			}
 		} else {
-			int32 gridIdx = *(gridBuffer++);
+			int32 gridIdx = stream.readUint16LE();
 			for (int32 i = 0; i < blockCount; i++) {
-				*(blockByffer++) = gridIdx;
+				outstream.writeUint16LE(gridIdx);
 			}
 		}
-
-		gridEntry = (const uint8 *)gridBuffer;
-		dest = (uint8 *)blockByffer;
-
+		assert(!outstream.err());
+		assert(!stream.err());
 	} while (--brickCount);
 }
 


Commit: 763b99e189ae627190433b961aa088e5af076911
    https://github.com/scummvm/scummvm/commit/763b99e189ae627190433b961aa088e5af076911
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2020-11-05T18:56:07+01:00

Commit Message:
TWINE: added macro to check if the current actor is the hero

Changed paths:
    engines/twine/scene.cpp
    engines/twine/scene.h


diff --git a/engines/twine/scene.cpp b/engines/twine/scene.cpp
index 0b93ab2f69..c7669023da 100644
--- a/engines/twine/scene.cpp
+++ b/engines/twine/scene.cpp
@@ -419,7 +419,7 @@ void Scene::processActorZones(int32 actorIdx) {
 	actor->zone = -1;
 	int32 tmpCellingGrid = 0;
 
-	if (!actorIdx) {
+	if (IS_HERO(actorIdx)) {
 		currentActorInZone = actorIdx;
 	}
 
@@ -432,7 +432,7 @@ void Scene::processActorZones(int32 actorIdx) {
 		    (currentZ >= zone->bottomLeft.z && currentZ <= zone->topRight.z)) {
 			switch (zone->type) {
 			case kCube:
-				if (!actorIdx && actor->life > 0) {
+				if (IS_HERO(actorIdx) && actor->life > 0) {
 					needChangeScene = zone->infoData.ChangeScene.newSceneIdx;
 					zoneHeroX = actor->x - zone->bottomLeft.x + zone->infoData.ChangeScene.x;
 					zoneHeroY = actor->y - zone->bottomLeft.y + zone->infoData.ChangeScene.y;
@@ -470,13 +470,13 @@ void Scene::processActorZones(int32 actorIdx) {
 				}
 				break;
 			case kObject:
-				if (!actorIdx && _engine->_movements->heroAction) {
+				if (IS_HERO(actorIdx) && _engine->_movements->heroAction) {
 					_engine->_animations->initAnim(kAction, 1, 0, 0);
 					processZoneExtraBonus(zone);
 				}
 				break;
 			case kText:
-				if (!actorIdx && _engine->_movements->heroAction) {
+				if (IS_HERO(actorIdx) && _engine->_movements->heroAction) {
 					_engine->freezeTime();
 					_engine->_text->setFontCrossColor(zone->infoData.DisplayText.textColor);
 					talkingActor = actorIdx;
@@ -486,7 +486,7 @@ void Scene::processActorZones(int32 actorIdx) {
 				}
 				break;
 			case kLadder:
-				if (!actorIdx && _engine->_actor->heroBehaviour != kProtoPack && (actor->anim == kForward || actor->anim == kTopLadder || actor->anim == kClimbLadder)) {
+				if (IS_HERO(actorIdx) && _engine->_actor->heroBehaviour != kProtoPack && (actor->anim == kForward || actor->anim == kTopLadder || actor->anim == kClimbLadder)) {
 					_engine->_movements->rotateActor(actor->boudingBox.x.bottomLeft, actor->boudingBox.z.bottomLeft, actor->angle + 0x580);
 					_engine->_renderer->destX += _engine->_movements->processActorX;
 					_engine->_renderer->destZ += _engine->_movements->processActorZ;
diff --git a/engines/twine/scene.h b/engines/twine/scene.h
index 9716a66828..ebab6b7d69 100644
--- a/engines/twine/scene.h
+++ b/engines/twine/scene.h
@@ -224,6 +224,7 @@ enum LBA1SceneId {
 };
 
 #define OWN_ACTOR_SCENE_INDEX 0
+#define IS_HERO(x) (x) == OWN_ACTOR_SCENE_INDEX
 
 class TwinEEngine;
 class Scene {


Commit: 590660655d8c3ca9e2a9f87dfda10d1f2db523f9
    https://github.com/scummvm/scummvm/commit/590660655d8c3ca9e2a9f87dfda10d1f2db523f9
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2020-11-05T18:56:07+01:00

Commit Message:
TWINE: extracted into own methods

Changed paths:
    engines/twine/movements.cpp
    engines/twine/movements.h


diff --git a/engines/twine/movements.cpp b/engines/twine/movements.cpp
index 474f06b5c4..75162af9bd 100644
--- a/engines/twine/movements.cpp
+++ b/engines/twine/movements.cpp
@@ -30,6 +30,7 @@
 #include "twine/input.h"
 #include "twine/renderer.h"
 #include "twine/scene.h"
+#include "twine/text.h"
 #include "twine/twine.h"
 
 namespace TwinE {
@@ -228,233 +229,252 @@ void Movements::update() {
 	loopCursorKeys = _engine->_input->cursorKeys;
 }
 
-void Movements::processActorMovements(int32 actorIdx) {
+void Movements::processManualAction(int actorIdx) {
 	ActorStruct *actor = _engine->_scene->getActor(actorIdx);
-	if (actor->entity == -1) {
-		return;
-	}
+	// take this out when we want to give manual movements to other characters than Hero
+	if (actor == _engine->_scene->sceneHero) {
+		heroAction = false;
 
-	if (actor->dynamicFlags.bIsFalling) {
-		if (actor->controlMode != ControlMode::kManual) {
-			return;
+		// If press W for action
+		if (_engine->_input->toggleActionIfActive(TwinEActionType::SpecialAction)) {
+			heroAction = true;
 		}
 
-		int16 tempAngle = 0;
-		if (_engine->_input->isActionActive(TwinEActionType::TurnLeft)) {
-			tempAngle = 0x100;
-		} else if (_engine->_input->isActionActive(TwinEActionType::TurnRight)) {
-			tempAngle = -0x100;
+		// Process hero actions
+		if (_engine->_input->isActionActive(TwinEActionType::ExecuteBehaviourAction)) {
+			switch (_engine->_actor->heroBehaviour) {
+			case kNormal:
+				heroAction = true;
+				break;
+			case kAthletic:
+				_engine->_animations->initAnim(kJump, 1, 0, actorIdx);
+				break;
+			case kAggressive:
+				if (_engine->_actor->autoAgressive) {
+					heroMoved = true;
+					actor->angle = getRealAngle(&actor->move);
+					// TODO: previousLoopActionKey must be handled properly
+					if (!previousLoopActionKey || !actor->anim) {
+						const int32 aggresiveMode = _engine->getRandomNumber(3);
+
+						switch (aggresiveMode) {
+						case 0:
+							_engine->_animations->initAnim(kKick, 1, 0, actorIdx);
+							break;
+						case 1:
+							_engine->_animations->initAnim(kRightPunch, 1, 0, actorIdx);
+							break;
+						case 2:
+							_engine->_animations->initAnim(kLeftPunch, 1, 0, actorIdx);
+							break;
+						}
+					}
+				} else {
+					if (_engine->_input->isActionActive(TwinEActionType::TurnLeft)) {
+						_engine->_animations->initAnim(kLeftPunch, 1, 0, actorIdx);
+					} else if (_engine->_input->isActionActive(TwinEActionType::TurnRight)) {
+						_engine->_animations->initAnim(kRightPunch, 1, 0, actorIdx);
+					}
+
+					if (_engine->_input->toggleActionIfActive(TwinEActionType::MoveForward)) {
+						_engine->_animations->initAnim(kKick, 1, 0, actorIdx);
+					}
+				}
+				break;
+			case kDiscrete:
+					_engine->_animations->initAnim(kHide, 0, 255, actorIdx);
+				break;
+			case kProtoPack:
+				break;
+			}
 		}
+	}
 
-		moveActor(actor->angle, actor->angle + tempAngle, actor->speed, &actor->move);
+	if (_engine->_input->isActionActive(TwinEActionType::ThrowMagicBall) && !_engine->_gameState->gameFlags[GAMEFLAG_INVENTORY_DISABLED]) {
+		if (_engine->_gameState->usingSabre == 0) { // Use Magic Ball
+			if (_engine->_gameState->gameFlags[InventoryItems::kiMagicBall]) {
+				if (_engine->_gameState->magicBallIdx == -1) {
+					_engine->_animations->initAnim(kThrowBall, 1, 0, actorIdx);
+				}
 
-		heroPressedKey = heroActionKey;
-	} else {
-		if (!actor->staticFlags.bIsSpriteActor) {
-			if (actor->controlMode != ControlMode::kManual) {
+				heroMoved = true;
 				actor->angle = getRealAngle(&actor->move);
 			}
+		} else if (_engine->_gameState->gameFlags[InventoryItems::kiUseSabre]) {
+			if (actor->body != InventoryItems::kiUseSabre) {
+				_engine->_actor->initModelActor(InventoryItems::kiUseSabre, actorIdx);
+			}
+
+			_engine->_animations->initAnim(kSabreAttack, 1, 0, actorIdx);
+
+			heroMoved = true;
+			actor->angle = getRealAngle(&actor->move);
 		}
+	}
 
-		switch (actor->controlMode) {
-		case kNoMove:
-			break;
-		case kManual:
-			// take this out when we want to give manual movements to other characters than Hero
-			if (actor == _engine->_scene->sceneHero) {
-				heroAction = false;
-
-				// If press W for action
-				if (_engine->_input->isActionActive(TwinEActionType::SpecialAction)) {
-					heroAction = true;
-				}
+	// TODO: remove loopCursorKeys here
+	if (!loopCursorKeys || heroAction) {
+		// if continue walking
+		if (_engine->_input->isActionActive(TwinEActionType::MoveForward) || _engine->_input->isActionActive(TwinEActionType::MoveBackward)) {
+			heroMoved = false; // don't break animation
+		}
 
-				// Process hero actions
-				switch (_engine->_actor->heroBehaviour) {
-				case kNormal:
-					if (_engine->_input->isActionActive(TwinEActionType::ExecuteBehaviourAction)) {
-						heroAction = true;
-					}
-					break;
-				case kAthletic:
-					if (_engine->_input->isActionActive(TwinEActionType::ExecuteBehaviourAction)) {
-						_engine->_animations->initAnim(kJump, 1, 0, actorIdx);
-					}
-					break;
-				case kAggressive:
-					if (_engine->_input->isActionActive(TwinEActionType::ExecuteBehaviourAction)) {
-						if (_engine->_actor->autoAgressive) {
-							heroMoved = true;
-							actor->angle = getRealAngle(&actor->move);
-							// TODO: previousLoopActionKey must be handled properly
-							if (!previousLoopActionKey || !actor->anim) {
-								const int32 aggresiveMode = _engine->getRandomNumber(3);
-
-								switch (aggresiveMode) {
-								case 0:
-									_engine->_animations->initAnim(kKick, 1, 0, actorIdx);
-									break;
-								case 1:
-									_engine->_animations->initAnim(kRightPunch, 1, 0, actorIdx);
-									break;
-								case 2:
-									_engine->_animations->initAnim(kLeftPunch, 1, 0, actorIdx);
-									break;
-								}
-							}
-						} else {
-							if (_engine->_input->isActionActive(TwinEActionType::TurnLeft)) {
-								_engine->_animations->initAnim(kLeftPunch, 1, 0, actorIdx);
-							} else if (_engine->_input->isActionActive(TwinEActionType::TurnRight)) {
-								_engine->_animations->initAnim(kRightPunch, 1, 0, actorIdx);
-							}
-
-							if (_engine->_input->toggleActionIfActive(TwinEActionType::MoveForward)) {
-								_engine->_animations->initAnim(kKick, 1, 0, actorIdx);
-							}
-						}
-					}
-					break;
-				case kDiscrete:
-					if (_engine->_input->isActionActive(TwinEActionType::ExecuteBehaviourAction)) {
-						_engine->_animations->initAnim(kHide, 0, 255, actorIdx);
-					}
-					break;
-				case kProtoPack:
-					break;
-				}
+		if (heroActionKey != heroPressedKey || loopCursorKeys != heroPressedKey2) {
+			if (heroMoved) {
+				_engine->_animations->initAnim(kStanding, 0, 255, actorIdx);
 			}
+		}
 
-			if (_engine->_input->isActionActive(TwinEActionType::ThrowMagicBall) && !_engine->_gameState->gameFlags[GAMEFLAG_INVENTORY_DISABLED]) {
-				if (_engine->_gameState->usingSabre == 0) { // Use Magic Ball
-					if (_engine->_gameState->gameFlags[InventoryItems::kiMagicBall]) {
-						if (_engine->_gameState->magicBallIdx == -1) {
-							_engine->_animations->initAnim(kThrowBall, 1, 0, actorIdx);
-						}
-
-						heroMoved = true;
-						actor->angle = getRealAngle(&actor->move);
-					}
-				} else if (_engine->_gameState->gameFlags[InventoryItems::kiUseSabre]) {
-					if (actor->body != InventoryItems::kiUseSabre) {
-						_engine->_actor->initModelActor(InventoryItems::kiUseSabre, actorIdx);
-					}
+		heroMoved = false;
 
-					_engine->_animations->initAnim(kSabreAttack, 1, 0, actorIdx);
+		if (_engine->_input->isActionActive(TwinEActionType::MoveForward)) {
+			if (!_engine->_scene->currentActorInZone) {
+				_engine->_animations->initAnim(kForward, 0, 255, actorIdx);
+			}
+			heroMoved = true;
+		} else if (_engine->_input->isActionActive(TwinEActionType::MoveBackward)) {
+			_engine->_animations->initAnim(kBackward, 0, 255, actorIdx);
+			heroMoved = true;
+		}
 
-					heroMoved = true;
+		if (_engine->_input->isActionActive(TwinEActionType::TurnLeft)) {
+			heroMoved = true;
+			if (actor->anim == 0) {
+				_engine->_animations->initAnim(kTurnLeft, 0, 255, actorIdx);
+			} else {
+				if (!actor->dynamicFlags.bIsRotationByAnim) {
 					actor->angle = getRealAngle(&actor->move);
 				}
 			}
-
-			// TODO: remove loopCursorKeys here
-			if (!loopCursorKeys || heroAction) {
-				// if continue walking
-				if (_engine->_input->isActionActive(TwinEActionType::MoveForward) || _engine->_input->isActionActive(TwinEActionType::MoveBackward)) {
-					heroMoved = false; // don't break animation
-				}
-
-				if (heroActionKey != heroPressedKey || loopCursorKeys != heroPressedKey2) {
-					if (heroMoved) {
-						_engine->_animations->initAnim(kStanding, 0, 255, actorIdx);
-					}
+		} else if (_engine->_input->isActionActive(TwinEActionType::TurnRight)) {
+			heroMoved = true;
+			if (actor->anim == 0) {
+				_engine->_animations->initAnim(kTurnRight, 0, 255, actorIdx);
+			} else {
+				if (!actor->dynamicFlags.bIsRotationByAnim) {
+					actor->angle = getRealAngle(&actor->move);
 				}
+			}
+		}
+	}
 
-				heroMoved = false;
+	int16 tempAngle;
+	if (_engine->_input->isActionActive(TwinEActionType::TurnLeft)) {
+		tempAngle = 0x100;
+	} else if (_engine->_input->isActionActive(TwinEActionType::TurnRight)) {
+		tempAngle = -0x100;
+	} else {
+		tempAngle = 0;
+	}
 
-				if (_engine->_input->isActionActive(TwinEActionType::MoveForward)) {
-					if (!_engine->_scene->currentActorInZone) {
-						_engine->_animations->initAnim(kForward, 0, 255, actorIdx);
-					}
-					heroMoved = true;
-				} else if (_engine->_input->isActionActive(TwinEActionType::MoveBackward)) {
-					_engine->_animations->initAnim(kBackward, 0, 255, actorIdx);
-					heroMoved = true;
-				}
+	moveActor(actor->angle, actor->angle + tempAngle, actor->speed, &actor->move);
 
-				if (_engine->_input->isActionActive(TwinEActionType::TurnLeft)) {
-					heroMoved = true;
-					if (actor->anim == 0) {
-						_engine->_animations->initAnim(kTurnLeft, 0, 255, actorIdx);
-					} else {
-						if (!actor->dynamicFlags.bIsRotationByAnim) {
-							actor->angle = getRealAngle(&actor->move);
-						}
-					}
-				} else if (_engine->_input->isActionActive(TwinEActionType::TurnRight)) {
-					heroMoved = true;
-					if (actor->anim == 0) {
-						_engine->_animations->initAnim(kTurnRight, 0, 255, actorIdx);
-					} else {
-						if (!actor->dynamicFlags.bIsRotationByAnim) {
-							actor->angle = getRealAngle(&actor->move);
-						}
-					}
-				}
-			}
+	heroPressedKey = heroActionKey;
+	heroPressedKey2 = loopCursorKeys;
+}
 
-			int16 tempAngle;
-			if (_engine->_input->isActionActive(TwinEActionType::TurnLeft)) {
-				tempAngle = 0x100;
-			} else if (_engine->_input->isActionActive(TwinEActionType::TurnRight)) {
-				tempAngle = -0x100;
-			} else {
-				tempAngle = 0;
-			}
+void Movements::processFollowAction(int actorIdx) {
+	ActorStruct *actor = _engine->_scene->getActor(actorIdx);
+	const ActorStruct* followedActor = _engine->_scene->getActor(actor->followedActor);
+	int32 newAngle = getAngleAndSetTargetActorDistance(actor->x, actor->z, followedActor->x, followedActor->z);
+	if (actor->staticFlags.bIsSpriteActor) {
+		actor->angle = newAngle;
+	} else {
+		moveActor(actor->angle, newAngle, actor->speed, &actor->move);
+	}
+}
 
-			moveActor(actor->angle, actor->angle + tempAngle, actor->speed, &actor->move);
+void Movements::processRandomAction(int actorIdx) {
+	ActorStruct *actor = _engine->_scene->getActor(actorIdx);
+	if (actor->dynamicFlags.bIsRotationByAnim) {
+		return;
+	}
 
-			heroPressedKey = heroActionKey;
-			heroPressedKey2 = loopCursorKeys;
+	if (actor->brickShape & 0x80) {
+		moveActor(actor->angle, (((_engine->getRandomNumber() & 0x100) + (actor->angle - 0x100)) & 0x3FF), actor->speed, &actor->move);
+		actor->info0 = _engine->getRandomNumber(300) + _engine->lbaTime + 300;
+		_engine->_animations->initAnim(kStanding, 0, 255, actorIdx);
+	}
 
-			break;
-		case kFollow: {
-			const ActorStruct* followedActor = _engine->_scene->getActor(actor->followedActor);
-			int32 newAngle = getAngleAndSetTargetActorDistance(actor->x, actor->z, followedActor->x, followedActor->z);
-			if (actor->staticFlags.bIsSpriteActor) {
-				actor->angle = newAngle;
-			} else {
-				moveActor(actor->angle, newAngle, actor->speed, &actor->move);
-			}
-			break;
+	if (!actor->move.numOfStep) {
+		_engine->_animations->initAnim(kForward, 0, 255, actorIdx);
+		if (_engine->lbaTime > actor->info0) {
+			moveActor(actor->angle, (((_engine->getRandomNumber() & 0x100) + (actor->angle - 0x100)) & 0x3FF), actor->speed, &actor->move);
+			actor->info0 = _engine->getRandomNumber(300) + _engine->lbaTime + 300;
 		}
-		case kTrack:
-			if (actor->positionInMoveScript == -1) {
-				actor->positionInMoveScript = 0;
-			}
-			break;
-		case kFollow2:     // unused
-		case kTrackAttack: // unused
-			break;
-		case kSameXZ: {
-			const ActorStruct* followedActor = _engine->_scene->getActor(actor->followedActor);
-			actor->x = followedActor->x;
-			actor->z = followedActor->z;
-			break;
+	}
+}
+
+void Movements::processTrackAction(int actorIdx) {
+	ActorStruct *actor = _engine->_scene->getActor(actorIdx);
+	if (actor->positionInMoveScript == -1) {
+		actor->positionInMoveScript = 0;
+	}
+}
+
+void Movements::processSameXZAction(int actorIdx) {
+	ActorStruct *actor = _engine->_scene->getActor(actorIdx);
+	const ActorStruct* followedActor = _engine->_scene->getActor(actor->followedActor);
+	actor->x = followedActor->x;
+	actor->z = followedActor->z;
+}
+
+void Movements::processActorMovements(int32 actorIdx) {
+	ActorStruct *actor = _engine->_scene->getActor(actorIdx);
+	if (actor->entity == -1) {
+		return;
+	}
+
+	if (actor->dynamicFlags.bIsFalling) {
+		if (actor->controlMode != ControlMode::kManual) {
+			return;
 		}
-		case kRandom: {
-			if (!actor->dynamicFlags.bIsRotationByAnim) {
-				if (actor->brickShape & 0x80) {
-					moveActor(actor->angle, (((_engine->getRandomNumber() & 0x100) + (actor->angle - 0x100)) & 0x3FF), actor->speed, &actor->move);
-					actor->info0 = _engine->getRandomNumber(300) + _engine->lbaTime + 300;
-					_engine->_animations->initAnim(kStanding, 0, 255, actorIdx);
-				}
 
-				if (!actor->move.numOfStep) {
-					_engine->_animations->initAnim(kForward, 0, 255, actorIdx);
-					if (_engine->lbaTime > actor->info0) {
-						moveActor(actor->angle, (((_engine->getRandomNumber() & 0x100) + (actor->angle - 0x100)) & 0x3FF), actor->speed, &actor->move);
-						actor->info0 = _engine->getRandomNumber(300) + _engine->lbaTime + 300;
-					}
-				}
-			}
-			break;
+		int16 tempAngle = 0;
+		if (_engine->_input->isActionActive(TwinEActionType::TurnLeft)) {
+			tempAngle = 0x100;
+		} else if (_engine->_input->isActionActive(TwinEActionType::TurnRight)) {
+			tempAngle = -0x100;
 		}
-		default:
-			warning("Unknown Control mode %d\n", actor->controlMode);
-			break;
+
+		moveActor(actor->angle, actor->angle + tempAngle, actor->speed, &actor->move);
+
+		heroPressedKey = heroActionKey;
+		return;
+	}
+	if (!actor->staticFlags.bIsSpriteActor) {
+		if (actor->controlMode != ControlMode::kManual) {
+			actor->angle = getRealAngle(&actor->move);
 		}
 	}
-} // namespace TwinE
+
+	switch (actor->controlMode) {
+	case kNoMove:
+		break;
+	case kManual:
+		processManualAction(actorIdx);
+		break;
+	case kFollow:
+		processFollowAction(actorIdx);
+		break;
+	case kTrack:
+		processTrackAction(actorIdx);
+		break;
+	case kFollow2:     // unused
+	case kTrackAttack: // unused
+		break;
+	case kSameXZ: {
+		processSameXZAction(actorIdx);
+		break;
+	}
+	case kRandom: {
+		processRandomAction(actorIdx);
+		break;
+	}
+	default:
+		warning("Unknown Control mode %d\n", actor->controlMode);
+		break;
+	}
+}
 
 } // namespace TwinE
diff --git a/engines/twine/movements.h b/engines/twine/movements.h
index 63a3e000ef..4918579f97 100644
--- a/engines/twine/movements.h
+++ b/engines/twine/movements.h
@@ -45,6 +45,12 @@ private:
 	// cursor keys
 	int32 previousLoopActionKey = 0;
 
+	void processManualAction(int actorIdx);
+	void processFollowAction(int actorIdx);
+	void processRandomAction(int actorIdx);
+	void processTrackAction(int actorIdx);
+	void processSameXZAction(int actorIdx);
+
 public:
 	Movements(TwinEEngine *engine);
 


Commit: 329e60ea56d0bafc49dd5123fc8ec1813e8009fb
    https://github.com/scummvm/scummvm/commit/329e60ea56d0bafc49dd5123fc8ec1813e8009fb
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2020-11-05T18:56:07+01:00

Commit Message:
TWINE: minor cleanup

Changed paths:
    engines/twine/movements.cpp


diff --git a/engines/twine/movements.cpp b/engines/twine/movements.cpp
index 75162af9bd..6818ca9761 100644
--- a/engines/twine/movements.cpp
+++ b/engines/twine/movements.cpp
@@ -450,6 +450,8 @@ void Movements::processActorMovements(int32 actorIdx) {
 
 	switch (actor->controlMode) {
 	case kNoMove:
+	case kFollow2:     // unused
+	case kTrackAttack: // unused
 		break;
 	case kManual:
 		processManualAction(actorIdx);
@@ -460,17 +462,12 @@ void Movements::processActorMovements(int32 actorIdx) {
 	case kTrack:
 		processTrackAction(actorIdx);
 		break;
-	case kFollow2:     // unused
-	case kTrackAttack: // unused
-		break;
-	case kSameXZ: {
+	case kSameXZ:
 		processSameXZAction(actorIdx);
 		break;
-	}
-	case kRandom: {
+	case kRandom:
 		processRandomAction(actorIdx);
 		break;
-	}
 	default:
 		warning("Unknown Control mode %d\n", actor->controlMode);
 		break;


Commit: 59adc94b06a925267f18da305bb4007930bb193f
    https://github.com/scummvm/scummvm/commit/59adc94b06a925267f18da305bb4007930bb193f
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2020-11-05T18:56:07+01:00

Commit Message:
TWINE: changed comment

Changed paths:
    engines/twine/movements.h
    engines/twine/script_life_v1.cpp


diff --git a/engines/twine/movements.h b/engines/twine/movements.h
index 4918579f97..8c713eb4d6 100644
--- a/engines/twine/movements.h
+++ b/engines/twine/movements.h
@@ -58,8 +58,10 @@ public:
 
 	/** Hero moved */
 	bool heroMoved = false; // twinsenMove
-	/** Hero Action */
-	bool heroAction = false; // action
+	/**
+	 * Hero executes the current action of the trigger zone
+	 */
+	bool heroAction = false;
 
 	/** Process actor.x coordinate */
 	int16 processActorX = 0;
diff --git a/engines/twine/script_life_v1.cpp b/engines/twine/script_life_v1.cpp
index 4a4872dda1..4b07841902 100644
--- a/engines/twine/script_life_v1.cpp
+++ b/engines/twine/script_life_v1.cpp
@@ -258,7 +258,8 @@ static int32 processLifeConditions(TwinEEngine *engine, LifeScriptContext &ctx)
 		} else {
 			engine->_scene->currentScriptValue = MAX_TARGET_ACTOR_DISTANCE;
 		}
-	} break;
+		break;
+	}
 	case kcHIT_BY:
 		engine->_scene->currentScriptValue = ctx.actor->hitBy;
 		break;


Commit: 517248adb8ef172caf1ec3e2631d86cc3bcb5d84
    https://github.com/scummvm/scummvm/commit/517248adb8ef172caf1ec3e2631d86cc3bcb5d84
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2020-11-05T18:56:08+01:00

Commit Message:
TWINE: reduced visibility of scene members

Changed paths:
    engines/twine/gamestate.cpp
    engines/twine/scene.cpp
    engines/twine/scene.h


diff --git a/engines/twine/gamestate.cpp b/engines/twine/gamestate.cpp
index 041b67658a..f2b7bfaa01 100644
--- a/engines/twine/gamestate.cpp
+++ b/engines/twine/gamestate.cpp
@@ -83,29 +83,12 @@ void GameState::initSceneVars() {
 		inventoryFlags[i] = 0;
 	}
 
-	_engine->_scene->sampleAmbiance[0] = -1;
-	_engine->_scene->sampleAmbiance[1] = -1;
-	_engine->_scene->sampleAmbiance[2] = -1;
-	_engine->_scene->sampleAmbiance[3] = -1;
-
-	_engine->_scene->sampleRepeat[0] = 0;
-	_engine->_scene->sampleRepeat[1] = 0;
-	_engine->_scene->sampleRepeat[2] = 0;
-	_engine->_scene->sampleRepeat[3] = 0;
-
-	_engine->_scene->sampleRound[0] = 0;
-	_engine->_scene->sampleRound[1] = 0;
-	_engine->_scene->sampleRound[2] = 0;
-	_engine->_scene->sampleRound[3] = 0;
+	_engine->_scene->initSceneVars();
 
 	for (int32 i = 0; i < ARRAYSIZE(holomapFlags); i++) {
 		holomapFlags[i] = 0;
 	}
 
-	_engine->_scene->sceneNumActors = 0;
-	_engine->_scene->sceneNumZones = 0;
-	_engine->_scene->sceneNumTracks = 0;
-
 	_engine->_actor->currentPositionInBodyPtrTab = 0;
 }
 
diff --git a/engines/twine/scene.cpp b/engines/twine/scene.cpp
index c7669023da..a1a3a38af7 100644
--- a/engines/twine/scene.cpp
+++ b/engines/twine/scene.cpp
@@ -277,10 +277,10 @@ void Scene::changeScene() {
 	// TODO: treat holomap trajectories
 
 	if (needChangeScene == LBA1SceneId::Citadel_Island_end_sequence_1 || needChangeScene == LBA1SceneId::Citadel_Island_end_sequence_2) {
-		_engine->_scene->sceneTextBank = TextBankId::Tippet_Island;
+		sceneTextBank = TextBankId::Tippet_Island;
 	}
 
-	_engine->_text->initTextBank(_engine->_scene->sceneTextBank + 3);
+	_engine->_text->initTextBank(sceneTextBank + 3);
 	_engine->_grid->initGrid(needChangeScene);
 
 	if (heroPositionType == ScenePositionType::kZone) {
@@ -346,6 +346,27 @@ ActorStruct *Scene::getActor(int32 actorIdx) {
 	return &_sceneActors[actorIdx];
 }
 
+void Scene::initSceneVars() {
+	sampleAmbiance[0] = -1;
+	sampleAmbiance[1] = -1;
+	sampleAmbiance[2] = -1;
+	sampleAmbiance[3] = -1;
+
+	sampleRepeat[0] = 0;
+	sampleRepeat[1] = 0;
+	sampleRepeat[2] = 0;
+	sampleRepeat[3] = 0;
+
+	sampleRound[0] = 0;
+	sampleRound[1] = 0;
+	sampleRound[2] = 0;
+	sampleRound[3] = 0;
+
+	sceneNumActors = 0;
+	sceneNumZones = 0;
+	sceneNumTracks = 0;
+}
+
 void Scene::processEnvironmentSound() {
 	if (_engine->lbaTime >= sampleAmbienceTime) {
 		int16 currentAmb = _engine->getRandomNumber(4); // random ambiance
diff --git a/engines/twine/scene.h b/engines/twine/scene.h
index ebab6b7d69..15ab840690 100644
--- a/engines/twine/scene.h
+++ b/engines/twine/scene.h
@@ -231,7 +231,7 @@ class Scene {
 private:
 	TwinEEngine *_engine;
 
-/** Process zone extra bonus */
+	/** Process zone extra bonus */
 	void processZoneExtraBonus(ZoneStruct *zone);
 	void setActorStaticFlags(int32 actorIdx, uint16 staticFlags);
 	bool loadSceneLBA1();
@@ -244,23 +244,8 @@ private:
 	ActorStruct _sceneActors[NUM_MAX_ACTORS];
 	int32 _currentSceneSize = 0;
 
-public:
-	Scene(TwinEEngine *engine) : _engine(engine) {}
-
-	uint8 *currentScene = nullptr;
-
-	int32 needChangeScene = LBA1SceneId::Citadel_Island_Prison;
-	int32 currentSceneIdx = LBA1SceneId::Citadel_Island_Prison;
-	int32 previousSceneIdx = LBA1SceneId::Citadel_Island_Prison;
-
-	int32 sceneTextBank = TextBankId::None;
-	int32 currentGameOverScene = 0;
-	int32 alphaLight = 0;
-	int32 betaLight = 0;
-
 	/** Timer for the next sample ambience in scene */
 	int32 sampleAmbienceTime = 0;
-
 	int16 sampleAmbiance[4] {0};
 	int16 sampleRepeat[4] {0};
 	int16 sampleRound[4] {0};
@@ -275,13 +260,27 @@ public:
 	int16 sceneHeroY = 0; // newTwinsenYByScene
 	int16 sceneHeroZ = 0; // newTwinsenZByScene
 
-	int16 newHeroX = 0; // newTwinsenX
-	int16 newHeroY = 0; // newTwinsenY
-	int16 newHeroZ = 0; // newTwinsenZ
-
 	int16 zoneHeroX = 0; // newTwinsenXByZone
 	int16 zoneHeroY = 0; // newTwinsenYByZone
 	int16 zoneHeroZ = 0; // newTwinsenZByZone
+	int32 currentGameOverScene = 0;
+
+public:
+	Scene(TwinEEngine *engine) : _engine(engine) {}
+
+	uint8 *currentScene = nullptr;
+
+	int32 needChangeScene = LBA1SceneId::Citadel_Island_Prison;
+	int32 currentSceneIdx = LBA1SceneId::Citadel_Island_Prison;
+	int32 previousSceneIdx = LBA1SceneId::Citadel_Island_Prison;
+
+	int32 sceneTextBank = TextBankId::None;
+	int32 alphaLight = 0;
+	int32 betaLight = 0;
+
+	int16 newHeroX = 0; // newTwinsenX
+	int16 newHeroY = 0; // newTwinsenY
+	int16 newHeroZ = 0; // newTwinsenZ
 
 	/** Hero Y coordinate before fall */
 	int16 heroYBeforeFall = 0;
@@ -325,6 +324,7 @@ public:
 
 	/** Process scene environment sound */
 	void processEnvironmentSound();
+	void initSceneVars();
 
 	/**
 	 * Process actor zones


Commit: c8183e292667a758511ff25e57a8d4fd30bf8772
    https://github.com/scummvm/scummvm/commit/c8183e292667a758511ff25e57a8d4fd30bf8772
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2020-11-05T18:56:08+01:00

Commit Message:
TWINE: fixed wild casting

Changed paths:
    engines/twine/redraw.cpp


diff --git a/engines/twine/redraw.cpp b/engines/twine/redraw.cpp
index ed8635b9e9..95de44426d 100644
--- a/engines/twine/redraw.cpp
+++ b/engines/twine/redraw.cpp
@@ -237,7 +237,7 @@ void Redraw::redrawEngineActions(int32 bgRedraw) { // fullRedraw
 		ActorStruct *actor = _engine->_scene->getActor(modelActorPos);
 		actor->dynamicFlags.bIsVisible = 0; // reset visible state
 
-		if (_engine->_grid->useCellingGrid == -1 || actor->y <= (*(const int16 *)(_engine->_grid->cellingGridIdx * 24 + (const int8 *)_engine->_scene->sceneZones + 8))) {
+		if (_engine->_grid->useCellingGrid == -1 || actor->y <= _engine->_scene->sceneZones[_engine->_grid->cellingGridIdx].topRight.y) {
 			// no redraw required
 			if (actor->staticFlags.bIsBackgrounded && bgRedraw == 0) {
 				// get actor position on screen


Commit: e498b80bedebc263e1f3cd7c9871fa13060266d6
    https://github.com/scummvm/scummvm/commit/e498b80bedebc263e1f3cd7c9871fa13060266d6
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2020-11-05T18:56:08+01:00

Commit Message:
TWINE: use stream to parse the sprite offsets

Changed paths:
    engines/twine/redraw.cpp


diff --git a/engines/twine/redraw.cpp b/engines/twine/redraw.cpp
index 95de44426d..4a4204d5a3 100644
--- a/engines/twine/redraw.cpp
+++ b/engines/twine/redraw.cpp
@@ -21,6 +21,7 @@
  */
 
 #include "twine/redraw.h"
+#include "common/memstream.h"
 #include "common/textconsole.h"
 #include "graphics/surface.h"
 #include "twine/actor.h"
@@ -448,8 +449,10 @@ void Redraw::redrawEngineActions(int32 bgRedraw) { // fullRedraw
 				_engine->_grid->getSpriteSize(0, &spriteWidth, &spriteHeight, spritePtr);
 
 				// calculate sprite position on screen
-				renderLeft = _engine->_renderer->projPosX + *((const int16 *)(_engine->_resources->spriteBoundingBoxPtr + (actor2->entity * 16)));
-				renderTop = _engine->_renderer->projPosY + *((const int16 *)(_engine->_resources->spriteBoundingBoxPtr + (actor2->entity * 16) + 2));
+				Common::MemoryReadStream stream(_engine->_resources->spriteBoundingBoxPtr, _engine->_resources->spriteBoundingBoxSize);
+				stream.seek(actor2->entity * 16);
+				renderLeft = _engine->_renderer->projPosX + stream.readSint16LE();
+				renderTop = _engine->_renderer->projPosY + stream.readSint16LE();
 				renderRight = renderLeft + spriteWidth;
 				renderBottom = renderTop + spriteHeight;
 
@@ -500,8 +503,10 @@ void Redraw::redrawEngineActions(int32 bgRedraw) { // fullRedraw
 					_engine->_grid->getSpriteSize(0, &spriteWidth, &spriteHeight, _engine->_resources->spriteTable[extra->info0]);
 
 					// calculate sprite position on screen
-					renderLeft = _engine->_renderer->projPosX + *(const int16 *)(_engine->_resources->spriteBoundingBoxPtr + extra->info0 * 16);
-					renderTop = _engine->_renderer->projPosY + *(const int16 *)(_engine->_resources->spriteBoundingBoxPtr + extra->info0 * 16 + 2);
+					Common::MemoryReadStream stream(_engine->_resources->spriteBoundingBoxPtr, _engine->_resources->spriteBoundingBoxSize);
+					stream.seek(extra->info0 * 16);
+					renderLeft = _engine->_renderer->projPosX + stream.readSint16LE();
+					renderTop = _engine->_renderer->projPosY + stream.readSint16LE();
 					renderRight = renderLeft + spriteWidth;
 					renderBottom = renderTop + spriteHeight;
 
@@ -567,8 +572,10 @@ void Redraw::redrawEngineActions(int32 bgRedraw) { // fullRedraw
 				int32 spriteWidth, spriteHeight;
 				_engine->_grid->getSpriteSize(0, &spriteWidth, &spriteHeight, spritePtr);
 
-				const int16 offsetX = *((const int16 *)(_engine->_resources->spriteBoundingBoxPtr + (overlay->info0 * 16)));
-				const int16 offsetY = *((const int16 *)(_engine->_resources->spriteBoundingBoxPtr + (overlay->info0 * 16) + 2));
+				Common::MemoryReadStream stream(_engine->_resources->spriteBoundingBoxPtr, _engine->_resources->spriteBoundingBoxSize);
+				stream.seek(overlay->info0 * 16);
+				const int16 offsetX = stream.readSint16LE();
+				const int16 offsetY = stream.readSint16LE();
 
 				renderLeft = offsetX + overlay->x;
 				renderTop = offsetY + overlay->y;


Commit: 36278881ea4a2c526f43cf3d5bb4b80a530f2986
    https://github.com/scummvm/scummvm/commit/36278881ea4a2c526f43cf3d5bb4b80a530f2986
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2020-11-05T18:56:08+01:00

Commit Message:
TWINE: use endian safe short parsing

Changed paths:
    engines/twine/actor.cpp


diff --git a/engines/twine/actor.cpp b/engines/twine/actor.cpp
index 461b9b9b82..8ca1dc3385 100644
--- a/engines/twine/actor.cpp
+++ b/engines/twine/actor.cpp
@@ -21,6 +21,7 @@
  */
 
 #include "twine/actor.h"
+#include "common/memstream.h"
 #include "common/system.h"
 #include "common/textconsole.h"
 #include "twine/animations.h"
@@ -163,15 +164,17 @@ void Actor::initSpriteActor(int32 actorIdx) {
 	ActorStruct *localActor = _engine->_scene->getActor(actorIdx);
 
 	if (localActor->staticFlags.bIsSpriteActor && localActor->sprite != -1 && localActor->entity != localActor->sprite) {
-		const int16 *ptr = (const int16 *)(_engine->_resources->spriteBoundingBoxPtr + localActor->sprite * 16 + 4);
+		Common::MemoryReadStream stream(_engine->_resources->spriteBoundingBoxPtr, _engine->_resources->spriteBoundingBoxSize);
+		stream.seek(localActor->sprite * 16);
+		stream.skip(4);
 
 		localActor->entity = localActor->sprite;
-		localActor->boudingBox.x.bottomLeft = *(ptr++);
-		localActor->boudingBox.x.topRight = *(ptr++);
-		localActor->boudingBox.y.bottomLeft = *(ptr++);
-		localActor->boudingBox.y.topRight = *(ptr++);
-		localActor->boudingBox.z.bottomLeft = *(ptr++);
-		localActor->boudingBox.z.topRight = *(ptr++);
+		localActor->boudingBox.x.bottomLeft = stream.readSint16LE();
+		localActor->boudingBox.x.topRight = stream.readSint16LE();
+		localActor->boudingBox.y.bottomLeft = stream.readSint16LE();
+		localActor->boudingBox.y.topRight = stream.readSint16LE();
+		localActor->boudingBox.z.bottomLeft = stream.readSint16LE();
+		localActor->boudingBox.z.topRight = stream.readSint16LE();
 	}
 }
 


Commit: c5336cd078098fe822b7bdae74397d367d786869
    https://github.com/scummvm/scummvm/commit/c5336cd078098fe822b7bdae74397d367d786869
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2020-11-05T18:56:08+01:00

Commit Message:
TWINE: use stream for endian safe parsing of the body data

Changed paths:
    engines/twine/actor.cpp
    engines/twine/actor.h


diff --git a/engines/twine/actor.cpp b/engines/twine/actor.cpp
index 8ca1dc3385..cf70cecf18 100644
--- a/engines/twine/actor.cpp
+++ b/engines/twine/actor.cpp
@@ -180,81 +180,61 @@ void Actor::initSpriteActor(int32 actorIdx) {
 
 int32 Actor::initBody(int32 bodyIdx, int32 actorIdx) {
 	ActorStruct *localActor = _engine->_scene->getActor(actorIdx);
-	uint8 *bodyPtr = localActor->entityDataPtr;
-
+	Common::MemorySeekableReadWriteStream stream(localActor->entityDataPtr, localActor->entityDataSize);
 	do {
-		uint8 var1 = *(bodyPtr++);
-
-		if (var1 == 0xFF) {
+		const uint8 type = stream.readByte();
+		if (type == 0xFF) {
 			return -1;
 		}
 
-		uint8 *bodyPtr2 = bodyPtr + 1;
+		uint8 idx = stream.readByte();
+		const int32 pos = stream.pos();
+		const uint8 size = stream.readByte();
+		if (type == 1) { // 1 = body data - 3 is animdata
+			if (idx == bodyIdx) {
+				const int16 bodyIndex = stream.readUint16LE();
 
-		if (var1 == 1) {
-			uint8 var2 = *(bodyPtr);
-
-			if (var2 == bodyIdx) {
 				int32 index;
-				uint8 *bodyPtr3 = bodyPtr2 + 1;
-				int16 flag = *((uint16 *)bodyPtr3);
-
-				if (!(flag & 0x8000)) {
-					if (bodyTable[currentPositionInBodyPtrTab]) {
-						free(bodyTable[currentPositionInBodyPtrTab]);
+				if (!(bodyIndex & 0x8000)) {
+					index = currentPositionInBodyPtrTab;
+					currentPositionInBodyPtrTab++;
+					if (bodyTable[index]) {
+						free(bodyTable[index]);
 					}
-					HQR::getAllocEntry(&bodyTable[currentPositionInBodyPtrTab], Resources::HQR_BODY_FILE, flag & 0xFFFF);
-
-					if (!bodyTable[currentPositionInBodyPtrTab]) {
+					bodyTableSize[index] = HQR::getAllocEntry(&bodyTable[index], Resources::HQR_BODY_FILE, bodyIndex & 0xFFFF);
+					if (bodyTableSize[index] == 0) {
 						error("HQR ERROR: Loading body entities");
 					}
-					_engine->_renderer->prepareIsoModel(bodyTable[currentPositionInBodyPtrTab]);
-					*((uint16 *)bodyPtr3) = currentPositionInBodyPtrTab + 0x8000;
-					index = currentPositionInBodyPtrTab;
-					currentPositionInBodyPtrTab++;
+					_engine->_renderer->prepareIsoModel(bodyTable[index]);
+					stream.seek(stream.pos() - sizeof(uint16));
+					stream.writeUint16LE(index + 0x8000);
 				} else {
-					flag &= 0x7FFF;
-					index = flag;
+					index = bodyIndex & 0x7FFF;
 				}
 
-				bodyPtr3 += 2;
 				bottomLeftX = -32000;
 
-				uint8 *bodyPtr4 = bodyPtr3;
-				bodyPtr3++;
-
-				if (!*bodyPtr4) {
+				const bool hasBox = stream.readByte();
+				if (!hasBox) {
 					return index;
 				}
 
-				bodyPtr4 = bodyPtr3;
-				bodyPtr3++;
-
-				if (*bodyPtr4 != 14) {
+				if (stream.readByte() != 14) {
 					return index;
 				}
 
-				// bodyPtr5 = (int16 *) bodyPtr3;
-
-				bottomLeftX = *((uint16 *)bodyPtr3);
-				bodyPtr3 += 2;
-				bottomLeftY = *((uint16 *)bodyPtr3);
-				bodyPtr3 += 2;
-				bottomLeftZ = *((uint16 *)bodyPtr3);
-				bodyPtr3 += 2;
+				bottomLeftX = stream.readUint16LE();
+				bottomLeftY = stream.readUint16LE();
+				bottomLeftZ = stream.readUint16LE();
 
-				topRightX = *((uint16 *)bodyPtr3);
-				bodyPtr3 += 2;
-				topRightY = *((uint16 *)bodyPtr3);
-				bodyPtr3 += 2;
-				topRightZ = *((uint16 *)bodyPtr3);
-				bodyPtr3 += 2;
+				topRightX = stream.readUint16LE();
+				topRightY = stream.readUint16LE();
+				topRightZ = stream.readUint16LE();
 
 				return index;
 			}
 		}
-
-		bodyPtr = *bodyPtr2 + bodyPtr2;
+		stream.seek(pos + size);
 	} while (1);
 }
 
diff --git a/engines/twine/actor.h b/engines/twine/actor.h
index 6c9c4b3c9b..ce71dd79a2 100644
--- a/engines/twine/actor.h
+++ b/engines/twine/actor.h
@@ -307,6 +307,7 @@ public:
 
 	/** Actors 3D body table - size of NUM_BODIES */
 	uint8 *bodyTable[NUM_BODIES]{nullptr};
+	int32 bodyTableSize[NUM_BODIES]{0};
 
 	/** Current position in body table */
 	int32 currentPositionInBodyPtrTab;


Commit: 5adc5d99aaee291f7a974d046d20dccb0dfd6aa9
    https://github.com/scummvm/scummvm/commit/5adc5d99aaee291f7a974d046d20dccb0dfd6aa9
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2020-11-05T18:56:08+01:00

Commit Message:
TWINE: fixed active menu button text changes

Changed paths:
    engines/twine/menu.h


diff --git a/engines/twine/menu.h b/engines/twine/menu.h
index 272ad03af3..623072a034 100644
--- a/engines/twine/menu.h
+++ b/engines/twine/menu.h
@@ -81,6 +81,7 @@ public:
 
 	void setButtonTextId(int16 buttonIdx, int16 textIndex) {
 		_settings[MenuSettings_FirstButton + buttonIdx * 2] = textIndex;
+		_buttonTexts[buttonIdx].clear();
 	}
 
 	int16 getActiveButtonTextId() const {


Commit: 1a2ebdc5da5fa422c12c179b55fd67eefcae8c4f
    https://github.com/scummvm/scummvm/commit/1a2ebdc5da5fa422c12c179b55fd67eefcae8c4f
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2020-11-05T18:56:08+01:00

Commit Message:
TWINE: fixed agressive behaviour type text id in options menu

Changed paths:
    engines/twine/actor.h
    engines/twine/menu.cpp


diff --git a/engines/twine/actor.h b/engines/twine/actor.h
index ce71dd79a2..25087d2506 100644
--- a/engines/twine/actor.h
+++ b/engines/twine/actor.h
@@ -42,6 +42,8 @@ namespace TwinE {
  * 			UP / RIGHT / LEFT will manually select
  * 			different punch/kick options
  * <li> DISCREET: Kneel down to hide
+ *
+ * @note The values must match the @c TextId indices
  */
 enum HeroBehaviourType {
 	kNormal = 0,
diff --git a/engines/twine/menu.cpp b/engines/twine/menu.cpp
index 082118b50a..61930fd365 100644
--- a/engines/twine/menu.cpp
+++ b/engines/twine/menu.cpp
@@ -376,9 +376,9 @@ int32 Menu::processMenu(MenuSettings *menuSettings) {
 					_engine->_actor->autoAgressive = !_engine->_actor->autoAgressive;
 				}
 				if (_engine->_actor->autoAgressive) {
-					menuSettings->setActiveButtonTextId(TextId::kBehaviourAgressiveManual);
-				} else {
 					menuSettings->setActiveButtonTextId(TextId::kBehaviourAgressiveAuto);
+				} else {
+					menuSettings->setActiveButtonTextId(TextId::kBehaviourAgressiveManual);
 				}
 				break;
 			case MenuButtonTypes::kPolygonDetails:
@@ -798,7 +798,7 @@ void Menu::drawBehaviour(HeroBehaviourType behaviour, int32 angle, int16 cantDra
 
 		char dialText[256];
 		if (_engine->_actor->heroBehaviour == kAggressive && _engine->_actor->autoAgressive) {
-			_engine->_text->getMenuText(4, dialText, sizeof(dialText));
+			_engine->_text->getMenuText(TextId::kBehaviourAgressiveAuto, dialText, sizeof(dialText));
 		} else {
 			_engine->_text->getMenuText(_engine->_actor->heroBehaviour, dialText, sizeof(dialText));
 		}


Commit: bac82c726f43f6b2b43f74c1a6374f323305d1bb
    https://github.com/scummvm/scummvm/commit/bac82c726f43f6b2b43f74c1a6374f323305d1bb
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2020-11-05T18:56:08+01:00

Commit Message:
TWINE: small helper method to match the textid to behaviours

Changed paths:
    engines/twine/actor.cpp
    engines/twine/actor.h
    engines/twine/menu.cpp


diff --git a/engines/twine/actor.cpp b/engines/twine/actor.cpp
index cf70cecf18..869dfe4a6f 100644
--- a/engines/twine/actor.cpp
+++ b/engines/twine/actor.cpp
@@ -178,6 +178,14 @@ void Actor::initSpriteActor(int32 actorIdx) {
 	}
 }
 
+int32 Actor::getTextIdForBehaviour() const {
+	if (_engine->_actor->heroBehaviour == kAggressive && _engine->_actor->autoAgressive) {
+		return TextId::kBehaviourAgressiveAuto;
+	}
+	// the other values are matching the text ids
+	return _engine->_actor->heroBehaviour;
+}
+
 int32 Actor::initBody(int32 bodyIdx, int32 actorIdx) {
 	ActorStruct *localActor = _engine->_scene->getActor(actorIdx);
 	Common::MemorySeekableReadWriteStream stream(localActor->entityDataPtr, localActor->entityDataSize);
diff --git a/engines/twine/actor.h b/engines/twine/actor.h
index 25087d2506..80816337ba 100644
--- a/engines/twine/actor.h
+++ b/engines/twine/actor.h
@@ -320,6 +320,8 @@ public:
 	/** Load hero 3D body and animations */
 	void loadHeroEntities();
 
+	int32 getTextIdForBehaviour() const;
+
 	/**
 	 * Set hero behaviour
 	 * @param behaviour behaviour value to set
diff --git a/engines/twine/menu.cpp b/engines/twine/menu.cpp
index 61930fd365..8151777bca 100644
--- a/engines/twine/menu.cpp
+++ b/engines/twine/menu.cpp
@@ -797,11 +797,7 @@ void Menu::drawBehaviour(HeroBehaviourType behaviour, int32 angle, int16 cantDra
 		_engine->_text->setFontColor(15);
 
 		char dialText[256];
-		if (_engine->_actor->heroBehaviour == kAggressive && _engine->_actor->autoAgressive) {
-			_engine->_text->getMenuText(TextId::kBehaviourAgressiveAuto, dialText, sizeof(dialText));
-		} else {
-			_engine->_text->getMenuText(_engine->_actor->heroBehaviour, dialText, sizeof(dialText));
-		}
+		_engine->_text->getMenuText(_engine->_actor->getTextIdForBehaviour(), dialText, sizeof(dialText));
 
 		_engine->_text->drawText((650 - _engine->_text->getTextSize(dialText)) / 2, 240, dialText);
 	}


Commit: 5e31204c92d316e5c8df10f5394af7a89b4ce8df
    https://github.com/scummvm/scummvm/commit/5e31204c92d316e5c8df10f5394af7a89b4ce8df
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2020-11-05T18:56:08+01:00

Commit Message:
TWINE: const for palette pointers

Changed paths:
    engines/twine/actor.cpp
    engines/twine/screens.cpp
    engines/twine/screens.h


diff --git a/engines/twine/actor.cpp b/engines/twine/actor.cpp
index 869dfe4a6f..280214a018 100644
--- a/engines/twine/actor.cpp
+++ b/engines/twine/actor.cpp
@@ -187,8 +187,8 @@ int32 Actor::getTextIdForBehaviour() const {
 }
 
 int32 Actor::initBody(int32 bodyIdx, int32 actorIdx) {
-	ActorStruct *localActor = _engine->_scene->getActor(actorIdx);
-	Common::MemorySeekableReadWriteStream stream(localActor->entityDataPtr, localActor->entityDataSize);
+	ActorStruct *actor = _engine->_scene->getActor(actorIdx);
+	Common::MemorySeekableReadWriteStream stream(actor->entityDataPtr, actor->entityDataSize);
 	do {
 		const uint8 type = stream.readByte();
 		if (type == 0xFF) {
@@ -272,6 +272,7 @@ void Actor::initModelActor(int32 bodyIdx, int16 actorIdx) {
 		localActor->body = bodyIdx;
 		int currentIndex = localActor->entity;
 
+		// -32000 means no bounding box in the entity data
 		if (bottomLeftX == -32000) {
 			uint16 *ptr = (uint16 *)bodyTable[localActor->entity];
 			ptr++;
diff --git a/engines/twine/screens.cpp b/engines/twine/screens.cpp
index 2e58140e57..38615caa07 100644
--- a/engines/twine/screens.cpp
+++ b/engines/twine/screens.cpp
@@ -195,7 +195,7 @@ void Screens::adjustCrossPalette(const uint32 *pal1, const uint32 *pal2) {
 	} while (intensity <= 100);
 }
 
-void Screens::fadeToBlack(uint32 *pal) {
+void Screens::fadeToBlack(const uint32 *pal) {
 	if (palResetted) {
 		return;
 	}
@@ -208,7 +208,7 @@ void Screens::fadeToBlack(uint32 *pal) {
 	palResetted = true;
 }
 
-void Screens::fadeToPal(uint32 *pal) {
+void Screens::fadeToPal(const uint32 *pal) {
 	for (int32 i = 0; i <= 100; i += 3) {
 		adjustPalette(0, 0, 0, pal, i);
 		_engine->_system->delayMillis(1000 / 50);
@@ -238,14 +238,14 @@ void Screens::setBackPal() {
 	palResetted = true;
 }
 
-void Screens::fadePalRed(uint32 *pal) {
+void Screens::fadePalRed(const uint32 *pal) {
 	for (int32 i = 100; i >= 0; i -= 2) {
 		adjustPalette(0xFF, 0, 0, pal, i);
 		_engine->_system->delayMillis(1000 / 50);
 	}
 }
 
-void Screens::fadeRedPal(uint32 *pal) {
+void Screens::fadeRedPal(const uint32 *pal) {
 	for (int32 i = 0; i <= 100; i += 2) {
 		adjustPalette(0xFF, 0, 0, pal, i);
 		_engine->_system->delayMillis(1000 / 50);
diff --git a/engines/twine/screens.h b/engines/twine/screens.h
index b73bce29e9..fd5a7eb838 100644
--- a/engines/twine/screens.h
+++ b/engines/twine/screens.h
@@ -136,13 +136,13 @@ public:
 	 * Fade image to black
 	 * @param palette current palette to fade
 	 */
-	void fadeToBlack(uint32 *palette);
+	void fadeToBlack(const uint32 *palette);
 
 	/**
 	 * Fade image with another palette source
 	 * @param palette current palette to fade
 	 */
-	void fadeToPal(uint32 *palette);
+	void fadeToPal(const uint32 *palette);
 
 	/** Fade black palette to white palette */
 	void blackToWhite();
@@ -154,13 +154,13 @@ public:
 	 * Fade palette to red palette
 	 * @param palette current palette to fade
 	 */
-	void fadePalRed(uint32 *palette);
+	void fadePalRed(const uint32 *palette);
 
 	/**
 	 * Fade red to palette
 	 * @param palette current palette to fade
 	 */
-	void fadeRedPal(uint32 *palette);
+	void fadeRedPal(const uint32 *palette);
 
 	/**
 	 * Copy a determinate screen buffer to another




More information about the Scummvm-git-logs mailing list