[Scummvm-git-logs] scummvm master -> 31ed2761be50e99765583ccf3b162e488581e585

mgerhardy martin.gerhardy at gmail.com
Tue Oct 27 17:16:14 UTC 2020


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

Summary:
0c129988ed TWINE: cleanup move script
20ef91ee28 TWINE: renamed source files
6bd38bd0ae TWINE: script and gamestate cleanup
c767b26557 TWINE: cleanup
3b3de0ec91 TWINE: activate shadows by default
238deaa377 TWINE: use streams
78eb7e6d29 TWINE: const
40b049ca59 TWINE: reduced visibility
716313db75 TWINE: hide the blockBuffer member and fixed a memory leak
11fda12409 TWINE: plug a memory leak and reduced visiblity
e5fe47d542 TWINE: plug memory leaks
a3927197d1 TWINE: const
156d6ca14d TWINE: moved spriteTable into Resources class
0e9bc030f1 TWINE: moved animTable into Resources class
7d2991aa0b TWINE: moved more cached resources into the Resources class
c34239c7fc TWINE: moved latest cache entries into Resources class
1b143bca5c TWINE: missing mean breaks
8626b873ce TWINE: use the cached sound samples
3b0b130a0a TWINE: plug memory leaks
26c6a63ac1 TWINE: plug memory leaks
1d3fa8e950 TWINE: fixed segfault and plug mem leak
f9bcdaae46 TWINE: allow to quit from menus
9671ab083a TWINE: implemented options
b7aa562484 TWINE: replaced magic numbers with text ids
f5273eef64 TWINE: debug command to list menu texts
10571de5aa TWINE: reduced visibility and return value checks
444dfc18ee TWINE: doesn't make sense to use delaySkip for 1ms
191eed29c3 TWINE: debug command to toggle the debug mode of the game
5f7c967481 TWINE: fixed toggleAbortAction to reset all states
0bef6c419d TWINE: according to the manual you don't have to hold down shift
68c0eff29a TWINE: persist some ui-changable settings via ConfMan
0e16c3f09e TWINE: small comment about the language index
3b73ba9c37 TWINE: comments and grouping of members in ConfigFile struct
31b6aecaba TWINE: copy vox comments
117cf827ee TWINE: reduced scope and cleanup in text rendering
e14950077d TWINE: missing inventory item constants
caeb854b0a TWINE: reduced scope and visibility
83610de2eb TWINE: convert comment into code
31ed2761be TWINE: fixed button states on menu initialization


Commit: 0c129988edcdf958a3e9a0f7b96614b298217a2b
    https://github.com/scummvm/scummvm/commit/0c129988edcdf958a3e9a0f7b96614b298217a2b
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2020-10-27T17:14:04+01:00

Commit Message:
TWINE: cleanup move script

Changed paths:
    engines/twine/script_move.cpp


diff --git a/engines/twine/script_move.cpp b/engines/twine/script_move.cpp
index 651ac4bf7d..eb26399aba 100644
--- a/engines/twine/script_move.cpp
+++ b/engines/twine/script_move.cpp
@@ -35,7 +35,6 @@
 namespace TwinE {
 
 static uint8 *scriptPtr = nullptr;
-static int32 continueMove = 0;
 static int32 scriptPosition = 0;
 static ActorMoveStruct *move = nullptr;
 static int32 numRepeatSample = 1;
@@ -56,9 +55,8 @@ struct ScriptMoveFunction {
 
 /*0x00*/
 static int32 mEND(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
-	continueMove = 0;
 	actor->positionInMoveScript = -1;
-	return 0;
+	return 1;
 }
 
 /*0x01*/
@@ -81,7 +79,7 @@ static int32 mANIM(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
 		actor->positionInMoveScript++;
 	} else {
 		actor->positionInMoveScript = scriptPosition;
-		continueMove = 0;
+		return 1;
 	}
 	return 0;
 }
@@ -105,8 +103,8 @@ static int32 mGOTO_POINT(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor
 	}
 
 	if (engine->_movements->targetActorDistance > 500) {
-		continueMove = 0;
 		actor->positionInMoveScript -= 2;
+		return 1;
 	}
 
 	return 0;
@@ -114,13 +112,12 @@ static int32 mGOTO_POINT(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor
 
 /*0x05*/
 static int32 mWAIT_ANIM(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
-	continueMove = 0;
 	if (!actor->dynamicFlags.bAnimEnded) {
 		actor->positionInMoveScript--;
 	} else {
 		engine->_movements->clearRealAngle(actor);
 	}
-	return 0;
+	return 1;
 }
 
 /*0x06*/
@@ -143,9 +140,8 @@ static int32 mANGLE(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
 		engine->_movements->clearRealAngle(actor);
 		return 0;
 	}
-	continueMove = 0;
 	actor->positionInMoveScript -= 3;
-	return 0;
+	return 1;
 }
 
 /*0x08*/
@@ -185,9 +181,8 @@ static int32 mGOTO(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
 
 /*0x0B*/
 static int32 mSTOP(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
-	continueMove = 0;
 	actor->positionInMoveScript = -1;
-	return 0;
+	return 1;
 }
 
 /*0x0C*/
@@ -209,8 +204,8 @@ static int32 mGOTO_SYM_POINT(TwinEEngine *engine, int32 actorIdx, ActorStruct *a
 	}
 
 	if (engine->_movements->targetActorDistance > 500) {
-		continueMove = 0;
 		actor->positionInMoveScript -= 2;
+		return 1;
 	}
 
 	return 0;
@@ -220,6 +215,7 @@ static int32 mGOTO_SYM_POINT(TwinEEngine *engine, int32 actorIdx, ActorStruct *a
 static int32 mWAIT_NUM_ANIM(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
 	actor->positionInMoveScript += 2;
 
+	bool abortMove = 0;
 	if (actor->dynamicFlags.bAnimEnded) {
 		int32 animPos, animRepeats;
 
@@ -231,19 +227,19 @@ static int32 mWAIT_NUM_ANIM(TwinEEngine *engine, int32 actorIdx, ActorStruct *ac
 		if (animPos == animRepeats) {
 			animPos = 0;
 		} else {
-			continueMove = 0;
+			abortMove = 1;
 		}
 
 		*(scriptPtr + 1) = animPos;
 	} else {
-		continueMove = 0;
+		abortMove = 1;
 	}
 
-	if (continueMove == 0) {
+	if (abortMove == 1) {
 		actor->positionInMoveScript -= 3;
 	}
 
-	return 0;
+	return abortMove;
 }
 
 /*0x0E*/
@@ -273,8 +269,8 @@ static int32 mGOTO_POINT_3D(TwinEEngine *engine, int32 actorIdx, ActorStruct *ac
 	actor->animType = engine->_movements->getAngleAndSetTargetActorDistance(actor->y, 0, sp.y, engine->_movements->targetActorDistance);
 
 	if (engine->_movements->targetActorDistance > 100) {
-		continueMove = 0;
 		actor->positionInMoveScript -= 2;
+		return 1;
 	} else {
 		actor->x = sp.x;
 		actor->y = sp.y;
@@ -332,8 +328,8 @@ static int32 mWAIT_NUM_SECOND(TwinEEngine *engine, int32 actorIdx, ActorStruct *
 	}
 
 	if (engine->lbaTime < currentTime) {
-		continueMove = 0;
 		actor->positionInMoveScript -= 6;
+		return 1;
 	} else {
 		*((int32 *)scriptPtr) = 0;
 	}
@@ -428,8 +424,8 @@ static int32 mCLOSE(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
 static int32 mWAIT_DOOR(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
 	if (actor->staticFlags.bIsSpriteActor && actor->staticFlags.bUsesClipping) {
 		if (actor->speed) {
-			continueMove = 0;
 			actor->positionInMoveScript--;
+			return 1;
 		}
 	}
 	return 0;
@@ -498,8 +494,8 @@ static int32 mFACE_HERO(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor)
 	}
 
 	if (actor->angle != engine->_scene->currentScriptValue) {
-		continueMove = 0;
 		actor->positionInMoveScript -= 3;
+		return 1;
 	} else {
 		engine->_movements->clearRealAngle(actor);
 		*((int16 *)scriptPtr) = -1;
@@ -531,8 +527,8 @@ static int32 mANGLE_RND(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor)
 	}
 
 	if (actor->angle != engine->_scene->currentScriptValue) {
-		continueMove = 0;
 		actor->positionInMoveScript -= 5;
+		return 1;
 	} else {
 		engine->_movements->clearRealAngle(actor);
 		*((int16 *)scriptPtr + 2) = -1;
@@ -579,17 +575,17 @@ static const ScriptMoveFunction function_map[] = {
 
 ScriptMove::ScriptMove(TwinEEngine *engine) : _engine(engine) {
 	scriptPtr = nullptr;
-	continueMove = 0;
 	scriptPosition = 0;
 	move = nullptr;
 	numRepeatSample = 1;
 }
 
 void ScriptMove::processMoveScript(int32 actorIdx) {
-	continueMove = 1;
 	ActorStruct *actor = _engine->_scene->getActor(actorIdx);
 	move = &actor->move;
 
+	int32 end = -2;
+
 	do {
 		scriptPosition = actor->positionInMoveScript;
 		// TODO: use Common::MemoryReadStream for the script parsing
@@ -599,13 +595,15 @@ void ScriptMove::processMoveScript(int32 actorIdx) {
 		actor->positionInMoveScript++;
 
 		if (scriptOpcode >= 0 && scriptOpcode < ARRAYSIZE(function_map)) {
-			if (function_map[scriptOpcode].function(_engine, actorIdx, actor) < 0) {
-				warning("Actor %d Move script [%s] not implemented", actorIdx, function_map[scriptOpcode].name);
-			}
+			end = function_map[scriptOpcode].function(_engine, actorIdx, actor);
 		} else {
 			error("Actor %d with wrong offset/opcode - Offset: %d (opcode: %i)", actorIdx, actor->positionInLifeScript, scriptOpcode);
 		}
-	} while (continueMove);
+
+		if (end < 0) { // show error message
+			warning("Actor %d Life script [%s] not implemented", actorIdx, function_map[scriptOpcode].name);
+		}
+	} while (end != 1);
 }
 
 } // namespace TwinE


Commit: 20ef91ee28410c1a95d8ef31934a2babde86dc07
    https://github.com/scummvm/scummvm/commit/20ef91ee28410c1a95d8ef31934a2babde86dc07
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2020-10-27T17:14:04+01:00

Commit Message:
TWINE: renamed source files

Changed paths:
  A engines/twine/script_life_v1.cpp
  A engines/twine/script_life_v1.h
  A engines/twine/script_move_v1.cpp
  A engines/twine/script_move_v1.h
  R engines/twine/script_life.cpp
  R engines/twine/script_life.h
  R engines/twine/script_move.cpp
  R engines/twine/script_move.h
    engines/twine/module.mk
    engines/twine/twine.cpp


diff --git a/engines/twine/module.mk b/engines/twine/module.mk
index 2716de5512..f3afd43fc9 100644
--- a/engines/twine/module.mk
+++ b/engines/twine/module.mk
@@ -27,8 +27,8 @@ MODULE_OBJS := \
 	resources.o \
 	scene.o \
 	screens.o \
-	script_life.o \
-	script_move.o \
+	script_life_v1.o \
+	script_move_v1.o \
 	sound.o \
 	text.o \
 	twine.o
diff --git a/engines/twine/script_life.cpp b/engines/twine/script_life_v1.cpp
similarity index 99%
rename from engines/twine/script_life.cpp
rename to engines/twine/script_life_v1.cpp
index 01e4bba953..0e341c88fc 100644
--- a/engines/twine/script_life.cpp
+++ b/engines/twine/script_life_v1.cpp
@@ -20,7 +20,7 @@
  *
  */
 
-#include "twine/script_life.h"
+#include "twine/script_life_v1.h"
 #include "common/stream.h"
 #include "twine/actor.h"
 #include "twine/animations.h"
diff --git a/engines/twine/script_life.h b/engines/twine/script_life_v1.h
similarity index 100%
rename from engines/twine/script_life.h
rename to engines/twine/script_life_v1.h
diff --git a/engines/twine/script_move.cpp b/engines/twine/script_move_v1.cpp
similarity index 99%
rename from engines/twine/script_move.cpp
rename to engines/twine/script_move_v1.cpp
index eb26399aba..d966360bef 100644
--- a/engines/twine/script_move.cpp
+++ b/engines/twine/script_move_v1.cpp
@@ -20,7 +20,7 @@
  *
  */
 
-#include "twine/script_move.h"
+#include "twine/script_move_v1.h"
 #include "common/textconsole.h"
 #include "common/util.h"
 #include "twine/actor.h"
@@ -583,6 +583,7 @@ ScriptMove::ScriptMove(TwinEEngine *engine) : _engine(engine) {
 void ScriptMove::processMoveScript(int32 actorIdx) {
 	ActorStruct *actor = _engine->_scene->getActor(actorIdx);
 	move = &actor->move;
+	numRepeatSample = 1;
 
 	int32 end = -2;
 
diff --git a/engines/twine/script_move.h b/engines/twine/script_move_v1.h
similarity index 100%
rename from engines/twine/script_move.h
rename to engines/twine/script_move_v1.h
diff --git a/engines/twine/twine.cpp b/engines/twine/twine.cpp
index a6d2a1000e..ad3146adac 100644
--- a/engines/twine/twine.cpp
+++ b/engines/twine/twine.cpp
@@ -63,8 +63,8 @@
 #include "twine/resources.h"
 #include "twine/scene.h"
 #include "twine/screens.h"
-#include "twine/script_life.h"
-#include "twine/script_move.h"
+#include "twine/script_life_v1.h"
+#include "twine/script_move_v1.h"
 #include "twine/sound.h"
 #include "twine/text.h"
 


Commit: 6bd38bd0aee15a33010f5e69906cd01e35610632
    https://github.com/scummvm/scummvm/commit/6bd38bd0aee15a33010f5e69906cd01e35610632
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2020-10-27T17:14:04+01:00

Commit Message:
TWINE: script and gamestate cleanup

converted error to warning

Changed paths:
    engines/twine/gamestate.cpp
    engines/twine/script_life_v1.cpp


diff --git a/engines/twine/gamestate.cpp b/engines/twine/gamestate.cpp
index 97a460b015..3e408158e8 100644
--- a/engines/twine/gamestate.cpp
+++ b/engines/twine/gamestate.cpp
@@ -276,12 +276,6 @@ bool GameState::saveGame(Common::OutSaveFile* file) {
 }
 
 void GameState::processFoundItem(int32 item) {
-	int32 itemX, itemY, itemZ; // object2XYZ
-	int32 boxTopLeftX, boxTopLeftY, boxBottomRightX, boxBottomRightY;
-	int32 textState, quitItem, currentAnimState;
-	uint8 *currentAnim;
-	AnimTimerDataStruct tmpAnimTimer;
-
 	_engine->_grid->newCameraX = (_engine->_scene->sceneHero->x + 0x100) >> 9;
 	_engine->_grid->newCameraY = (_engine->_scene->sceneHero->y + 0x100) >> 8;
 	_engine->_grid->newCameraZ = (_engine->_scene->sceneHero->z + 0x100) >> 9;
@@ -293,19 +287,19 @@ void GameState::processFoundItem(int32 item) {
 
 	_engine->_screens->copyScreen(_engine->frontVideoBuffer, _engine->workVideoBuffer);
 
-	int32 itemCameraX = _engine->_grid->newCameraX << 9;
-	int32 itemCameraY = _engine->_grid->newCameraY << 8;
-	int32 itemCameraZ = _engine->_grid->newCameraZ << 9;
+	const int32 itemCameraX = _engine->_grid->newCameraX << 9;
+	const int32 itemCameraY = _engine->_grid->newCameraY << 8;
+	const int32 itemCameraZ = _engine->_grid->newCameraZ << 9;
 
 	_engine->_renderer->renderIsoModel(_engine->_scene->sceneHero->x - itemCameraX, _engine->_scene->sceneHero->y - itemCameraY, _engine->_scene->sceneHero->z - itemCameraZ, 0, 0x80, 0, _engine->_actor->bodyTable[_engine->_scene->sceneHero->entity]);
 	_engine->_interface->setClip(_engine->_redraw->renderLeft, _engine->_redraw->renderTop, _engine->_redraw->renderRight, _engine->_redraw->renderBottom);
 
-	itemX = (_engine->_scene->sceneHero->x + 0x100) >> 9;
-	itemY = _engine->_scene->sceneHero->y >> 8;
+	const int32 itemX = (_engine->_scene->sceneHero->x + 0x100) >> 9;
+	int32 itemY = _engine->_scene->sceneHero->y >> 8;
 	if (_engine->_scene->sceneHero->brickShape & 0x7F) {
 		itemY++;
 	}
-	itemZ = (_engine->_scene->sceneHero->z + 0x100) >> 9;
+	const int32 itemZ = (_engine->_scene->sceneHero->z + 0x100) >> 9;
 
 	_engine->_grid->drawOverModelActor(itemX, itemY, itemZ);
 	_engine->flip();
@@ -313,11 +307,10 @@ void GameState::processFoundItem(int32 item) {
 	_engine->_renderer->projectPositionOnScreen(_engine->_scene->sceneHero->x - itemCameraX, _engine->_scene->sceneHero->y - itemCameraY, _engine->_scene->sceneHero->z - itemCameraZ);
 	_engine->_renderer->projPosY -= 150;
 
-	boxTopLeftX = _engine->_renderer->projPosX - 65;
-	boxTopLeftY = _engine->_renderer->projPosY - 65;
-
-	boxBottomRightX = _engine->_renderer->projPosX + 65;
-	boxBottomRightY = _engine->_renderer->projPosY + 65;
+	const int32 boxTopLeftX = _engine->_renderer->projPosX - 65;
+	const int32 boxTopLeftY = _engine->_renderer->projPosY - 65;
+	const int32 boxBottomRightX = _engine->_renderer->projPosX + 65;
+	const int32 boxBottomRightY = _engine->_renderer->projPosY + 65;
 
 	_engine->_sound->playSample(41);
 
@@ -329,21 +322,21 @@ void GameState::processFoundItem(int32 item) {
 	_engine->_text->initText(item);
 	_engine->_text->initDialogueBox();
 
-	textState = 1;
-	quitItem = 0;
+	int32 textState = 1;
+	int32 quitItem = 0;
 
 	_engine->_text->initVoxToPlay(item);
 
-	currentAnim = _engine->_animations->animTable[_engine->_animations->getBodyAnimIndex(kFoundItem, 0)];
+	uint8 *currentAnim = _engine->_animations->animTable[_engine->_animations->getBodyAnimIndex(kFoundItem, 0)];
 
-	tmpAnimTimer = _engine->_scene->sceneHero->animTimerData;
+	AnimTimerDataStruct tmpAnimTimer = _engine->_scene->sceneHero->animTimerData;
 
 	_engine->_animations->animBuffer2 += _engine->_animations->stockAnimation(_engine->_animations->animBuffer2, _engine->_actor->bodyTable[_engine->_scene->sceneHero->entity], &_engine->_scene->sceneHero->animTimerData);
 	if (_engine->_animations->animBuffer1 + 4488 < _engine->_animations->animBuffer2) {
 		_engine->_animations->animBuffer2 = _engine->_animations->animBuffer1;
 	}
 
-	currentAnimState = 0;
+	int32 currentAnimState = 0;
 
 	_engine->_renderer->prepareIsoModel(_engine->_resources->inventoryTable[item]);
 	_engine->_redraw->numOfRedrawBox = 0;
@@ -465,12 +458,16 @@ void GameState::processGameoverAnimation() { // makeGameOver
 	_engine->_hqrdepack->hqrGetEntry(gameOverPtr, Resources::HQR_RESS_FILE, RESSHQR_GAMEOVERMDL);
 
 	if (gameOverPtr) {
+		const int32 left = 120;
+		const int32 top = 120;
+		const int32 right = 519;
+		const int32 bottom = 359;
 		_engine->_renderer->prepareIsoModel(gameOverPtr);
 		_engine->_sound->stopSamples();
 		_engine->_music->stopMidiMusic(); // stop fade music
 		_engine->_renderer->setCameraPosition(320, 240, 128, 200, 200);
 		int32 startLbaTime = _engine->lbaTime;
-		_engine->_interface->setClip(120, 120, 519, 359);
+		_engine->_interface->setClip(left, top, right, bottom);
 
 		while (!_engine->_input->toggleAbortAction() && (_engine->lbaTime - startLbaTime) <= 500) {
 			_engine->readKeys();
@@ -478,22 +475,23 @@ void GameState::processGameoverAnimation() { // makeGameOver
 				return;
 			}
 
-			int32 avg = _engine->_collision->getAverageValue(40000, 3200, 500, _engine->lbaTime - startLbaTime);
-			int32 cdot = _engine->_screens->crossDot(1, 1024, 100, (_engine->lbaTime - startLbaTime) % 0x64);
-			_engine->_interface->blitBox(120, 120, 519, 359, (int8 *)_engine->workVideoBuffer.getPixels(), 120, 120, (int8 *)_engine->frontVideoBuffer.getPixels());
+			const int32 avg = _engine->_collision->getAverageValue(40000, 3200, 500, _engine->lbaTime - startLbaTime);
+			const int32 cdot = _engine->_screens->crossDot(1, 1024, 100, (_engine->lbaTime - startLbaTime) % 0x64);
+
+			_engine->_interface->blitBox(left, top, right, bottom, (int8 *)_engine->workVideoBuffer.getPixels(), 120, 120, (int8 *)_engine->frontVideoBuffer.getPixels());
 			_engine->_renderer->setCameraAngle(0, 0, 0, 0, -cdot, 0, avg);
 			_engine->_renderer->renderIsoModel(0, 0, 0, 0, 0, 0, gameOverPtr);
-			_engine->copyBlockPhys(120, 120, 519, 359);
+			_engine->copyBlockPhys(left, top, right, bottom);
 
 			_engine->lbaTime++;
 			_engine->_system->delayMillis(15);
 		}
 
 		_engine->_sound->playSample(37, _engine->getRandomNumber(2000) + 3096);
-		_engine->_interface->blitBox(120, 120, 519, 359, (int8 *)_engine->workVideoBuffer.getPixels(), 120, 120, (int8 *)_engine->frontVideoBuffer.getPixels());
+		_engine->_interface->blitBox(left, top, right, bottom, (int8 *)_engine->workVideoBuffer.getPixels(), 120, 120, (int8 *)_engine->frontVideoBuffer.getPixels());
 		_engine->_renderer->setCameraAngle(0, 0, 0, 0, 0, 0, 3200);
 		_engine->_renderer->renderIsoModel(0, 0, 0, 0, 0, 0, gameOverPtr);
-		_engine->copyBlockPhys(120, 120, 519, 359);
+		_engine->copyBlockPhys(left, top, right, bottom);
 
 		_engine->delaySkip(2000);
 
diff --git a/engines/twine/script_life_v1.cpp b/engines/twine/script_life_v1.cpp
index 0e341c88fc..3c637e87c0 100644
--- a/engines/twine/script_life_v1.cpp
+++ b/engines/twine/script_life_v1.cpp
@@ -353,7 +353,7 @@ static int32 processLifeConditions(TwinEEngine *engine, ActorStruct *actor) {
 		0 - Condition false
 		1 - Condition true */
 static int32 processLifeOperators(TwinEEngine *engine, int32 valueSize) {
-	int32 operatorCode = *(scriptPtr++);
+	const int32 operatorCode = *(scriptPtr++);
 
 	int32 conditionValue;
 	if (valueSize == 1) {
@@ -398,7 +398,7 @@ static int32 processLifeOperators(TwinEEngine *engine, int32 valueSize) {
 		}
 		break;
 	default:
-		error("Actor operator opcode %d\n", operatorCode);
+		warning("Unknown life script operator opcode %d", operatorCode);
 		break;
 	}
 
@@ -426,9 +426,9 @@ static int32 lNOP(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
 
 /*0x02*/
 static int32 lSNIF(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
-	int32 valueSize = processLifeConditions(engine, actor);
+	const int32 valueSize = processLifeConditions(engine, actor);
 	if (!processLifeOperators(engine, valueSize)) {
-		*opcodePtr = 13; // SWIF
+		*opcodePtr = 0x0D; // SWIF
 	}
 	scriptPtr = actor->lifeScript + *((int16 *)scriptPtr); // condition offset
 	return 0;
@@ -483,7 +483,7 @@ static int32 lSWIF(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
 		scriptPtr = actor->lifeScript + *((int16 *)scriptPtr); // condition offset
 	} else {
 		scriptPtr += 2;
-		*opcodePtr = 2; // SNIF
+		*opcodePtr = 0x02; // SNIF
 	}
 
 	return 0;
@@ -496,7 +496,7 @@ static int32 lONEIF(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
 		scriptPtr = actor->lifeScript + *((int16 *)scriptPtr); // condition offset
 	} else {
 		scriptPtr += 2;
-		*opcodePtr = 4; // NEVERIF
+		*opcodePtr = 0x04; // NEVERIF
 	}
 
 	return 0;
@@ -571,7 +571,7 @@ static int32 lSET_TRACK_OBJ(TwinEEngine *engine, int32 actorIdx, ActorStruct *ac
 
 /*0x19*/
 static int32 lMESSAGE(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
-	int32 textIdx = *((int16 *)scriptPtr);
+	const int32 textIdx = *((int16 *)scriptPtr);
 	scriptPtr += 2;
 
 	engine->freezeTime();
@@ -589,14 +589,14 @@ static int32 lMESSAGE(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
 
 /*0x1A*/
 static int32 lFALLABLE(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
-	int32 flag = *(scriptPtr++);
+	const int32 flag = *(scriptPtr++);
 	actor->staticFlags.bCanFall = flag & 1;
 	return 0;
 }
 
 /*0x1B*/
 static int32 lSET_DIRMODE(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
-	int32 controlMode = *(scriptPtr++);
+	const int32 controlMode = *(scriptPtr++);
 
 	actor->controlMode = (ControlMode)controlMode;
 	if (actor->controlMode == ControlMode::kFollow) {
@@ -608,8 +608,8 @@ static int32 lSET_DIRMODE(TwinEEngine *engine, int32 actorIdx, ActorStruct *acto
 
 /*0x1C*/
 static int32 lSET_DIRMODE_OBJ(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
-	int32 otherActorIdx = *(scriptPtr++);
-	int32 controlMode = *(scriptPtr++);
+	const int32 otherActorIdx = *(scriptPtr++);
+	const int32 controlMode = *(scriptPtr++);
 
 	ActorStruct *otherActor = engine->_scene->getActor(otherActorIdx);
 	otherActor->controlMode = (ControlMode)controlMode;
@@ -622,7 +622,7 @@ static int32 lSET_DIRMODE_OBJ(TwinEEngine *engine, int32 actorIdx, ActorStruct *
 
 /*0x1D*/
 static int32 lCAM_FOLLOW(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
-	int32 followedActorIdx = *(scriptPtr++);
+	const int32 followedActorIdx = *(scriptPtr++);
 
 	if (engine->_scene->currentlyFollowedActor != followedActorIdx) {
 		const ActorStruct *followedActor = engine->_scene->getActor(followedActorIdx);
@@ -639,7 +639,7 @@ static int32 lCAM_FOLLOW(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor
 
 /*0x1E*/
 static int32 lSET_BEHAVIOUR(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
-	int32 behavior = *(scriptPtr++);
+	const int32 behavior = *(scriptPtr++);
 
 	engine->_animations->initAnim(kStanding, 0, 255, 0);
 	engine->_actor->setBehaviour(behavior);
@@ -649,8 +649,8 @@ static int32 lSET_BEHAVIOUR(TwinEEngine *engine, int32 actorIdx, ActorStruct *ac
 
 /*0x1F*/
 static int32 lSET_FLAG_CUBE(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
-	int32 flagIdx = *(scriptPtr++);
-	int32 flagValue = *(scriptPtr++);
+	const int32 flagIdx = *(scriptPtr++);
+	const int32 flagValue = *(scriptPtr++);
 
 	engine->_scene->sceneFlags[flagIdx] = flagValue;
 
@@ -672,7 +672,7 @@ static int32 lSET_COMPORTEMENT(TwinEEngine *engine, int32 actorIdx, ActorStruct
 
 /*0x22*/
 static int32 lSET_COMPORTEMENT_OBJ(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
-	int32 otherActorIdx = *(scriptPtr++);
+	const int32 otherActorIdx = *(scriptPtr++);
 
 	engine->_scene->getActor(otherActorIdx)->positionInLifeScript = *((int16 *)scriptPtr);
 	scriptPtr += 2;
@@ -687,8 +687,8 @@ static int32 lEND_COMPORTEMENT(TwinEEngine *engine, int32 actorIdx, ActorStruct
 
 /*0x24*/
 static int32 lSET_FLAG_GAME(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
-	int32 flagIdx = *(scriptPtr++);
-	int32 flagValue = *(scriptPtr++);
+	const int32 flagIdx = *(scriptPtr++);
+	const int32 flagValue = *(scriptPtr++);
 
 	engine->_gameState->gameFlags[flagIdx] = flagValue;
 
@@ -697,13 +697,14 @@ static int32 lSET_FLAG_GAME(TwinEEngine *engine, int32 actorIdx, ActorStruct *ac
 
 /*0x25*/
 static int32 lKILL_OBJ(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
-	int32 otherActorIdx = *(scriptPtr++);
+	const int32 otherActorIdx = *(scriptPtr++);
 
 	engine->_actor->processActorCarrier(otherActorIdx);
-	engine->_scene->getActor(otherActorIdx)->dynamicFlags.bIsDead = 1;
-	engine->_scene->getActor(otherActorIdx)->entity = -1;
-	engine->_scene->getActor(otherActorIdx)->zone = -1;
-	engine->_scene->getActor(otherActorIdx)->life = 0;
+	ActorStruct* otherActor = engine->_scene->getActor(otherActorIdx);
+	otherActor->dynamicFlags.bIsDead = 1;
+	otherActor->entity = -1;
+	otherActor->zone = -1;
+	otherActor->life = 0;
 
 	return 0;
 }
@@ -734,12 +735,9 @@ static int32 lUSE_ONE_LITTLE_KEY(TwinEEngine *engine, int32 actorIdx, ActorStruc
 
 /*0x28*/
 static int32 lGIVE_GOLD_PIECES(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
-	int16 kashes, i, hideRange;
 	int16 oldNumKashes = engine->_gameState->inventoryNumKashes;
-
-	hideRange = 0;
-
-	kashes = *((int16 *)scriptPtr);
+	int16 hideRange = 0;
+	int16 kashes = *((int16 *)scriptPtr);
 	scriptPtr += 2;
 
 	engine->_gameState->inventoryNumKashes -= kashes;
@@ -749,7 +747,7 @@ static int32 lGIVE_GOLD_PIECES(TwinEEngine *engine, int32 actorIdx, ActorStruct
 
 	engine->_redraw->addOverlay(koSprite, SPRITEHQR_KASHES, 10, 15, 0, koNormal, 3);
 
-	for (i = 0; i < OVERLAY_MAX_ENTRIES; i++) {
+	for (int16 i = 0; i < OVERLAY_MAX_ENTRIES; i++) {
 		OverlayListStruct *overlay = &engine->_redraw->overlayList[i];
 		if (overlay->info0 != -1 && overlay->type == koNumberRange) {
 			overlay->info0 = engine->_collision->getAverageValue(overlay->info1, overlay->info0, 100, overlay->lifeTime - engine->lbaTime - 50);
@@ -788,8 +786,8 @@ static int32 lRESTORE_L_TRACK(TwinEEngine *engine, int32 actorIdx, ActorStruct *
 
 /*0x2C*/
 static int32 lMESSAGE_OBJ(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
-	int32 otherActorIdx = *(scriptPtr++);
-	int32 textIdx = *((int16 *)scriptPtr);
+	const int32 otherActorIdx = *(scriptPtr++);
+	const int32 textIdx = *((int16 *)scriptPtr);
 	scriptPtr += 2;
 
 	engine->freezeTime();
@@ -813,7 +811,7 @@ static int32 lINC_CHAPTER(TwinEEngine *engine, int32 actorIdx, ActorStruct *acto
 
 /*0x2E*/
 static int32 lFOUND_OBJECT(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
-	int32 item = *(scriptPtr++);
+	const int32 item = *(scriptPtr++);
 
 	engine->freezeTime();
 	engine->_gameState->processFoundItem(item);


Commit: c767b26557b8295b69bf23a6ba7578e5ccbed322
    https://github.com/scummvm/scummvm/commit/c767b26557b8295b69bf23a6ba7578e5ccbed322
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2020-10-27T17:14:04+01:00

Commit Message:
TWINE: cleanup

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


diff --git a/engines/twine/actor.cpp b/engines/twine/actor.cpp
index 604bd169d9..0d64e5feec 100644
--- a/engines/twine/actor.cpp
+++ b/engines/twine/actor.cpp
@@ -71,28 +71,28 @@ void Actor::loadHeroEntities() {
 		error("Failed to load actor athletic 3d data");
 	}
 	_engine->_scene->sceneHero->entityDataPtr = heroEntityATHLETIC;
-	heroAnimIdxATHLETIC = _engine->_animations->getBodyAnimIndex(0, 0);
+	heroAnimIdxATHLETIC = _engine->_animations->getBodyAnimIndex(AnimationTypes::kStanding);
 
 	heroEntityAGGRESSIVESize = _engine->_hqrdepack->hqrGetallocEntry(&heroEntityAGGRESSIVE, Resources::HQR_FILE3D_FILE, FILE3DHQR_HEROAGGRESSIVE);
 	if (heroEntityAGGRESSIVESize == 0) {
 		error("Failed to load actor aggressive 3d data");
 	}
 	_engine->_scene->sceneHero->entityDataPtr = heroEntityAGGRESSIVE;
-	heroAnimIdxAGGRESSIVE = _engine->_animations->getBodyAnimIndex(0, 0);
+	heroAnimIdxAGGRESSIVE = _engine->_animations->getBodyAnimIndex(AnimationTypes::kStanding);
 
 	heroEntityDISCRETESize = _engine->_hqrdepack->hqrGetallocEntry(&heroEntityDISCRETE, Resources::HQR_FILE3D_FILE, FILE3DHQR_HERODISCRETE);
 	if (heroEntityDISCRETESize == 0) {
 		error("Failed to load actor discrete 3d data");
 	}
 	_engine->_scene->sceneHero->entityDataPtr = heroEntityDISCRETE;
-	heroAnimIdxDISCRETE = _engine->_animations->getBodyAnimIndex(0, 0);
+	heroAnimIdxDISCRETE = _engine->_animations->getBodyAnimIndex(AnimationTypes::kStanding);
 
 	heroEntityPROTOPACKSize = _engine->_hqrdepack->hqrGetallocEntry(&heroEntityPROTOPACK, Resources::HQR_FILE3D_FILE, FILE3DHQR_HEROPROTOPACK);
 	if (heroEntityPROTOPACKSize == 0) {
 		error("Failed to load actor protopack 3d data");
 	}
 	_engine->_scene->sceneHero->entityDataPtr = heroEntityPROTOPACK;
-	heroAnimIdxPROTOPACK = _engine->_animations->getBodyAnimIndex(0, 0);
+	heroAnimIdxPROTOPACK = _engine->_animations->getBodyAnimIndex(AnimationTypes::kStanding);
 
 	heroEntityNORMALSize = _engine->_hqrdepack->hqrGetallocEntry(&heroEntityNORMAL, Resources::HQR_FILE3D_FILE, FILE3DHQR_HERONORMAL);
 	if (heroEntityNORMALSize == 0) {
@@ -100,7 +100,7 @@ void Actor::loadHeroEntities() {
 	}
 	_engine->_scene->sceneHero->entityDataPtr = heroEntityNORMAL;
 	_engine->_scene->sceneHero->entityDataSize = heroEntityNORMALSize;
-	heroAnimIdxNORMAL = _engine->_animations->getBodyAnimIndex(0, 0);
+	heroAnimIdxNORMAL = _engine->_animations->getBodyAnimIndex(AnimationTypes::kStanding);
 
 	_engine->_scene->sceneHero->animExtraPtr = _engine->_animations->currentActorAnimExtraPtr;
 }
diff --git a/engines/twine/animations.cpp b/engines/twine/animations.cpp
index 397765b40a..8d558f862b 100644
--- a/engines/twine/animations.cpp
+++ b/engines/twine/animations.cpp
@@ -353,33 +353,28 @@ int32 Animations::setModelAnimation(int32 animState, uint8 *animPtr, uint8 *body
 	return 0;
 }
 
-int32 Animations::getBodyAnimIndex(int32 animIdx, int32 actorIdx) {
-	int8 type;
-	uint16 realAnimIdx;
-	uint8 *bodyPtr;
-	uint8 *ptr, *ptr2;
+int32 Animations::getBodyAnimIndex(AnimationTypes animIdx, int32 actorIdx) {
 	uint8 *costumePtr = NULL;
-	ActorStruct *actor;
 
-	actor = _engine->_scene->getActor(actorIdx);
-	bodyPtr = actor->entityDataPtr;
+	ActorStruct *actor = _engine->_scene->getActor(actorIdx);
+	uint8 *bodyPtr = actor->entityDataPtr;
 
 	do {
-		type = *(bodyPtr++);
+		int8 type = *(bodyPtr++);
 
 		if (type == -1) {
 			currentActorAnimExtraPtr = NULL;
 			return -1;
 		}
 
-		ptr = (bodyPtr + 1);
+		uint8 *ptr = (bodyPtr + 1);
 
 		if (type == 3) {
 			if (animIdx == *bodyPtr) {
 				ptr++;
-				realAnimIdx = *(int16 *)(ptr);
+				uint16 realAnimIdx = *(int16 *)(ptr);
 				ptr += 2;
-				ptr2 = ptr;
+				uint8 *ptr2 = ptr;
 				ptr++;
 				if (*ptr2 != 0) {
 					costumePtr = ptr - 1;
@@ -397,37 +392,28 @@ int32 Animations::getBodyAnimIndex(int32 animIdx, int32 actorIdx) {
 }
 
 int32 Animations::stockAnimation(uint8 *animPtr, uint8 *bodyPtr, AnimTimerDataStruct *animTimerDataPtr) {
-	int32 playAnim;
-	uint8 *ptr;
-	int32 *edi;
-	int32 *esi;
-	int32 var0;
-	int32 var1;
-	int32 var2;
-	int32 counter;
-
-	playAnim = *(int16 *)(bodyPtr);
+	int32 playAnim = *(int16 *)(bodyPtr);
 
 	if (playAnim & 2) {
-		ptr = (bodyPtr + 0x10);
+		uint8 *ptr = (bodyPtr + 0x10);
 
 		animTimerDataPtr->time = _engine->lbaTime;
 		animTimerDataPtr->ptr = animPtr;
 
-		var0 = *(int16 *)(ptr - 2);
+		int32 var0 = *(int16 *)(ptr - 2);
 		ptr = ptr + var0;
 
-		var1 = *(int16 *)(ptr);
+		int32 var1 = *(int16 *)(ptr);
 		var1 = var1 + var1 * 2;
 
 		ptr = ptr + var1 * 2 + 2;
 
-		var2 = *(int16 *)(ptr);
-		counter = var2;
+		int32 var2 = *(int16 *)(ptr);
+		int32 counter = var2;
 		var2 = (var2 * 8) + 8;
 
-		edi = (int32 *)(animPtr + 8);
-		esi = (int32 *)(ptr + 10);
+		int32* edi = (int32 *)(animPtr + 8);
+		int32* esi = (int32 *)(ptr + 10);
 
 		do {
 			*(edi++) = *(esi++);
@@ -442,29 +428,16 @@ int32 Animations::stockAnimation(uint8 *animPtr, uint8 *bodyPtr, AnimTimerDataSt
 }
 
 int32 Animations::verifyAnimAtKeyframe(int32 animIdx, uint8 *animPtr, uint8 *bodyPtr, AnimTimerDataStruct *animTimerDataPtr) {
-	int16 bodyHeader;
-
-	uint8 *ebx;
-	int32 ebp;
-	int32 eax;
-	int32 keyFrameLength;
-	int32 numOfPointInAnim = -1;
-	uint8 *keyFramePtrOld;
-
-	numOfPointInAnim = *(int16 *)(animPtr + 2);
-
+	int32 numOfPointInAnim = *(int16 *)(animPtr + 2);
 	keyFramePtr = ((numOfPointInAnim * 8 + 8) * animIdx) + animPtr + 8;
-
-	keyFrameLength = *(int16 *)(keyFramePtr);
-
-	bodyHeader = *(int16 *)(bodyPtr);
-
+	int32 keyFrameLength = *(int16 *)(keyFramePtr);
+	int16 bodyHeader = *(int16 *)(bodyPtr);
 	if (!(bodyHeader & 2)) {
 		return 0;
 	}
 
-	ebx = animTimerDataPtr->ptr;
-	ebp = animTimerDataPtr->time;
+	uint8 *ebx = animTimerDataPtr->ptr;
+	int32 ebp = animTimerDataPtr->time;
 
 	if (!ebx) {
 		ebx = keyFramePtr;
@@ -473,7 +446,7 @@ int32 Animations::verifyAnimAtKeyframe(int32 animIdx, uint8 *animPtr, uint8 *bod
 
 	lastKeyFramePtr = ebx;
 
-	eax = _engine->lbaTime - ebp;
+	int32 eax = _engine->lbaTime - ebp;
 
 	if (eax >= keyFrameLength) {
 		animTimerDataPtr->ptr = keyFramePtr;
@@ -488,7 +461,7 @@ int32 Animations::verifyAnimAtKeyframe(int32 animIdx, uint8 *animPtr, uint8 *bod
 
 		return 1;
 	}
-	keyFramePtrOld = keyFramePtr;
+	uint8 *keyFramePtrOld = keyFramePtr;
 
 	lastKeyFramePtr += 8;
 	keyFramePtr += 8;
@@ -795,7 +768,7 @@ int32 Animations::initAnim(AnimationTypes newAnim, int16 animType, uint8 animExt
 	int32 animIndex = getBodyAnimIndex(newAnim, actorIdx);
 
 	if (animIndex == -1) {
-		animIndex = getBodyAnimIndex(0, actorIdx);
+		animIndex = getBodyAnimIndex(AnimationTypes::kStanding, actorIdx);
 	}
 
 	if (animType != 4 && actor->animType == 2) {
@@ -1008,8 +981,8 @@ void Animations::processActorAnimations(int32 actorIdx) { // DoAnim
 						actor->previousAnimIdx = getBodyAnimIndex(actor->anim, actorIdx);
 
 						if (actor->previousAnimIdx == -1) {
-							actor->previousAnimIdx = getBodyAnimIndex(0, actorIdx);
-							actor->anim = kStanding;
+							actor->previousAnimIdx = getBodyAnimIndex(AnimationTypes::kStanding, actorIdx);
+							actor->anim = AnimationTypes::kStanding;
 						}
 
 						actor->animExtraPtr = currentActorAnimExtraPtr;
diff --git a/engines/twine/animations.h b/engines/twine/animations.h
index a820681c79..73819238ef 100644
--- a/engines/twine/animations.h
+++ b/engines/twine/animations.h
@@ -25,6 +25,7 @@
 
 #include "common/scummsys.h"
 #include "twine/actor.h"
+#include "twine/scene.h"
 
 namespace TwinE {
 
@@ -106,7 +107,7 @@ public:
 	 * @param animIdx Entity animation index
 	 * @param actorIdx Actor index
 	 */
-	int32 getBodyAnimIndex(int32 animIdx, int32 actorIdx);
+	int32 getBodyAnimIndex(AnimationTypes animIdx, int32 actorIdx = OWN_ACTOR_SCENE_INDEX);
 
 	/**
 	 * Stock animation - copy the next keyFrame from a different buffer
diff --git a/engines/twine/gamestate.cpp b/engines/twine/gamestate.cpp
index 3e408158e8..1790842fbf 100644
--- a/engines/twine/gamestate.cpp
+++ b/engines/twine/gamestate.cpp
@@ -327,7 +327,8 @@ void GameState::processFoundItem(int32 item) {
 
 	_engine->_text->initVoxToPlay(item);
 
-	uint8 *currentAnim = _engine->_animations->animTable[_engine->_animations->getBodyAnimIndex(kFoundItem, 0)];
+	const int32 bodyAnimIdx = _engine->_animations->getBodyAnimIndex(AnimationTypes::kFoundItem);
+	uint8 *currentAnim = _engine->_animations->animTable[bodyAnimIdx];
 
 	AnimTimerDataStruct tmpAnimTimer = _engine->_scene->sceneHero->animTimerData;
 


Commit: 3b3de0ec91d5634a88a0bc51bfb3a003e5b325ec
    https://github.com/scummvm/scummvm/commit/3b3de0ec91d5634a88a0bc51bfb3a003e5b325ec
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2020-10-27T17:14:05+01:00

Commit Message:
TWINE: activate shadows by default

Changed paths:
    engines/twine/twine.cpp


diff --git a/engines/twine/twine.cpp b/engines/twine/twine.cpp
index ad3146adac..56a160f7e6 100644
--- a/engines/twine/twine.cpp
+++ b/engines/twine/twine.cpp
@@ -271,7 +271,7 @@ void TwinEEngine::initConfigurations() {
 	cfgfile.Debug = ConfGetIntOrDefault("Debug", 0) == 1;
 	cfgfile.UseAutoSaving = ConfGetIntOrDefault("UseAutoSaving", 0);
 	_actor->autoAgressive = ConfGetIntOrDefault("CombatAuto", 1) == 1;
-	cfgfile.ShadowMode = ConfGetIntOrDefault("Shadow", 0);
+	cfgfile.ShadowMode = ConfGetIntOrDefault("Shadow", 2);
 	cfgfile.SceZoom = ConfGetIntOrDefault("SceZoom", 0) == 0;
 	cfgfile.WallCollision = ConfGetIntOrDefault("WallCollision", 0);
 }


Commit: 238deaa377614b4de28f3bb11ed77ae2b835da30
    https://github.com/scummvm/scummvm/commit/238deaa377614b4de28f3bb11ed77ae2b835da30
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2020-10-27T17:14:05+01:00

Commit Message:
TWINE: use streams

Changed paths:
    engines/twine/animations.cpp


diff --git a/engines/twine/animations.cpp b/engines/twine/animations.cpp
index 8d558f862b..af6fd9596c 100644
--- a/engines/twine/animations.cpp
+++ b/engines/twine/animations.cpp
@@ -21,6 +21,8 @@
  */
 
 #include "twine/animations.h"
+#include "common/memstream.h"
+#include "common/stream.h"
 #include "common/system.h"
 #include "common/textconsole.h"
 #include "common/util.h"
@@ -82,8 +84,9 @@ int32 Animations::setAnimAtKeyframe(int32 keyframeIdx, uint8 *animPtr, uint8 *bo
 
 	numOfKeyframeInAnim = *(int16 *)(animPtr);
 
-	if (keyframeIdx >= numOfKeyframeInAnim)
+	if (keyframeIdx >= numOfKeyframeInAnim) {
 		return numOfKeyframeInAnim;
+	}
 
 	numOfBonesInAnim = *(int16 *)(animPtr + 2);
 
@@ -91,8 +94,9 @@ int32 Animations::setAnimAtKeyframe(int32 keyframeIdx, uint8 *animPtr, uint8 *bo
 
 	bodyHeader = *(int16 *)(bodyPtr);
 
-	if (!(bodyHeader & 2))
+	if (!(bodyHeader & 2)) {
 		return 0;
+	}
 
 	ptrToBodyData = bodyPtr + 14;
 
@@ -222,35 +226,22 @@ int32 Animations::getAnimMode(uint8 **ptr) {
 }
 
 int32 Animations::setModelAnimation(int32 animState, uint8 *animPtr, uint8 *bodyPtr, AnimTimerDataStruct *animTimerDataPtr) {
-	int16 animOpcode;
-
-	int16 bodyHeader;
-
-	uint8 *edi;
-	uint8 *ebx;
-	int32 ebp;
-	int32 eax;
-	int32 keyFrameLength;
-	int32 numOfPointInBody;
-	int32 numOfPointInAnim;
-	uint8 *keyFramePtrOld;
-
-	numOfPointInAnim = *(int16 *)(animPtr + 2);
+	int32 numOfPointInAnim = *(int16 *)(animPtr + 2);
 
 	keyFramePtr = ((numOfPointInAnim * 8 + 8) * animState) + animPtr + 8;
 
-	keyFrameLength = *(int16 *)(keyFramePtr);
+	int32 keyFrameLength = *(int16 *)(keyFramePtr);
 
-	bodyHeader = *(int16 *)(bodyPtr);
+	int16 bodyHeader = *(int16 *)(bodyPtr);
 
 	if (!(bodyHeader & 2)) {
 		return 0;
 	}
 
-	edi = bodyPtr + 16;
+	uint8 *edi = bodyPtr + 16;
 
-	ebx = animTimerDataPtr->ptr;
-	ebp = animTimerDataPtr->time;
+	uint8 *ebx = animTimerDataPtr->ptr;
+	int32 ebp = animTimerDataPtr->time;
 
 	if (!ebx) {
 		ebx = keyFramePtr;
@@ -259,14 +250,14 @@ int32 Animations::setModelAnimation(int32 animState, uint8 *animPtr, uint8 *body
 
 	lastKeyFramePtr = ebx;
 
-	eax = *(int16 *)(edi - 2);
+	int32 eax = *(int16 *)(edi - 2);
 	edi += eax;
 
 	eax = *(int16 *)(edi);
 	eax = eax + eax * 2;
 	edi = edi + eax * 2 + 12;
 
-	numOfPointInBody = *(int16 *)(edi - 10);
+	int32 numOfPointInBody = *(int16 *)(edi - 10);
 
 	if (numOfPointInAnim > numOfPointInBody) {
 		numOfPointInAnim = numOfPointInBody;
@@ -299,7 +290,7 @@ int32 Animations::setModelAnimation(int32 animState, uint8 *animPtr, uint8 *body
 
 		return 1;
 	}
-	keyFramePtrOld = keyFramePtr;
+	uint8 *keyFramePtrOld = keyFramePtr;
 
 	lastKeyFramePtr += 8;
 	keyFramePtr += 8;
@@ -316,7 +307,7 @@ int32 Animations::setModelAnimation(int32 animState, uint8 *animPtr, uint8 *body
 		int16 tmpNumOfPoints = numOfPointInAnim;
 
 		do {
-			animOpcode = getAnimMode(&edi);
+			int16 animOpcode = getAnimMode(&edi);
 
 			switch (animOpcode) {
 			case 0: { // allow global rotate
@@ -394,37 +385,37 @@ int32 Animations::getBodyAnimIndex(AnimationTypes animIdx, int32 actorIdx) {
 int32 Animations::stockAnimation(uint8 *animPtr, uint8 *bodyPtr, AnimTimerDataStruct *animTimerDataPtr) {
 	int32 playAnim = *(int16 *)(bodyPtr);
 
-	if (playAnim & 2) {
-		uint8 *ptr = (bodyPtr + 0x10);
+	if (!(playAnim & 2)) {
+		return 0;
+	}
+	uint8 *ptr = (bodyPtr + 0x10);
 
-		animTimerDataPtr->time = _engine->lbaTime;
-		animTimerDataPtr->ptr = animPtr;
+	animTimerDataPtr->time = _engine->lbaTime;
+	animTimerDataPtr->ptr = animPtr;
 
-		int32 var0 = *(int16 *)(ptr - 2);
-		ptr = ptr + var0;
+	int32 var0 = *(int16 *)(ptr - 2);
+	ptr = ptr + var0;
 
-		int32 var1 = *(int16 *)(ptr);
-		var1 = var1 + var1 * 2;
+	int32 var1 = *(int16 *)(ptr);
+	var1 = var1 + var1 * 2;
 
-		ptr = ptr + var1 * 2 + 2;
+	ptr = ptr + var1 * 2 + 2;
 
-		int32 var2 = *(int16 *)(ptr);
-		int32 counter = var2;
-		var2 = (var2 * 8) + 8;
+	int32 var2 = *(int16 *)(ptr);
+	int32 counter = var2;
+	var2 = (var2 * 8) + 8;
 
-		int32* edi = (int32 *)(animPtr + 8);
-		int32* esi = (int32 *)(ptr + 10);
+	int32 *edi = (int32 *)(animPtr + 8);
+	int32 *esi = (int32 *)(ptr + 10);
 
-		do {
-			*(edi++) = *(esi++);
-			*(edi++) = *(esi++);
+	do {
+		*(edi++) = *(esi++);
+		*(edi++) = *(esi++);
 
-			esi = (int32 *)(((int8 *)esi) + 30);
-		} while (counter--);
+		esi = (int32 *)(((int8 *)esi) + 30);
+	} while (counter--);
 
-		return var2;
-	}
-	return 0;
+	return var2;
 }
 
 int32 Animations::verifyAnimAtKeyframe(int32 animIdx, uint8 *animPtr, uint8 *bodyPtr, AnimTimerDataStruct *animTimerDataPtr) {
@@ -479,272 +470,232 @@ int32 Animations::verifyAnimAtKeyframe(int32 animIdx, uint8 *animPtr, uint8 *bod
 	return 0;
 }
 
-struct DataReader {
-	uint8 *ptr;
-};
-
-int8 readByte(DataReader *data) {
-	return *(data->ptr++);
-}
-
-int16 readWord(DataReader *data) {
-	int16 result;
-	result = *(int16 *)(data->ptr);
-	data->ptr += 2;
-	return result;
-}
-
-void skipBytes(DataReader *data, int n) {
-	data->ptr += n;
-}
-
 void Animations::processAnimActions(int32 actorIdx) {
 	int32 index = 0, endAnimEntityIdx, actionType, animPos;
-	ActorStruct *actor;
-	DataReader *data;
 
-	actor = _engine->_scene->getActor(actorIdx);
+	ActorStruct *actor = _engine->_scene->getActor(actorIdx);
 	if (!actor->animExtraPtr) {
 		return; // avoid null pointers
 	}
 
-	data = (DataReader *)malloc(sizeof(DataReader));
-	if (!data) {
-		error("Failed to allocate memory for the animation actions");
-	}
-	data->ptr = actor->animExtraPtr;
+	Common::MemoryReadStream stream(actor->animExtraPtr, 1000000);
 
-	endAnimEntityIdx = readByte(data);
+	endAnimEntityIdx = stream.readByte();
 	while (index++ < endAnimEntityIdx) {
-		actionType = readByte(data) - 5;
-		if (actionType >= ACTION_LAST)
+		actionType = stream.readByte() - 5;
+		if (actionType >= ACTION_LAST) {
 			return;
+		}
 
 		switch (actionType) {
 		case ACTION_HITTING: {
-			int8 strength;
-
-			animPos = readByte(data) - 1;
-			strength = readByte(data);
+			animPos = stream.readByte() - 1;
+			int8 strength = stream.readByte();
 
 			if (animPos == actor->animPosition) {
 				actor->strengthOfHit = strength;
 				actor->dynamicFlags.bIsHitting = 1;
 			}
-		} break;
+			break;
+		}
 		case ACTION_SAMPLE: {
-			int16 sampleIdx;
+			animPos = stream.readByte();
+			int16 sampleIdx = stream.readSint16LE();
 
-			animPos = readByte(data);
-			sampleIdx = readWord(data);
-
-			if (animPos == actor->animPosition)
+			if (animPos == actor->animPosition) {
 				_engine->_sound->playSample(sampleIdx, 0x1000, 1, actor->x, actor->y, actor->z, actorIdx);
-		} break;
+			}
+			break;
+		}
 		case ACTION_SAMPLE_FREQ: {
-			int16 sampleIdx, frequency;
-
-			animPos = readByte(data);
-			sampleIdx = readWord(data);
-			frequency = readWord(data);
+			animPos = stream.readByte();
+			int16 sampleIdx = stream.readSint16LE();
+			int16 frequency = stream.readSint16LE();
 
 			if (animPos == actor->animPosition) {
 				frequency = _engine->getRandomNumber(frequency) + 0x1000 - (ABS(frequency) >> 1);
 				_engine->_sound->playSample(sampleIdx, frequency, 1, actor->x, actor->y, actor->z, actorIdx);
 			}
-		} break;
+			break;
+		}
 		case ACTION_THROW_EXTRA_BONUS: {
-			int32 yHeight, var_C, var_24, var_14, cx, dx, var;
-
-			animPos = readByte(data);
-			yHeight = readWord(data);
-			var_C = readByte(data);
-			cx = readWord(data);
-			dx = actor->angle + readWord(data);
-			var_24 = readWord(data);
-			var_14 = readByte(data);
-			var = readByte(data);
-
-			if (animPos == actor->animPosition)
+			animPos = stream.readByte();
+			int32 yHeight = stream.readSint16LE();
+			int32 var_C = stream.readByte();
+			int32 cx = stream.readSint16LE();
+			int32 dx = actor->angle + stream.readSint16LE();
+			int32 var_24 = stream.readSint16LE();
+			int32 var_14 = stream.readByte();
+			int32 var = stream.readByte();
+
+			if (animPos == actor->animPosition) {
 				_engine->_extra->addExtraThrow(actorIdx, actor->x, actor->y + yHeight, actor->z, var_C, cx, dx, var_24, var_14, var);
-		} break;
+			}
+			break;
+		}
 		case ACTION_THROW_MAGIC_BALL: {
-			int32 var_8, dx, var_24, var_14;
-
-			animPos = readByte(data);
-			var_8 = readWord(data);
-			dx = readWord(data);
-			var_24 = readWord(data);
-			var_14 = readByte(data);
+			animPos = stream.readByte();
+			int32 var_8 = stream.readSint16LE();
+			int32 dx = stream.readSint16LE();
+			int32 var_24 = stream.readSint16LE();
+			int32 var_14 = stream.readByte();
 
-			if (_engine->_gameState->magicBallIdx == -1 && animPos == actor->animPosition)
+			if (_engine->_gameState->magicBallIdx == -1 && animPos == actor->animPosition) {
 				_engine->_extra->addExtraThrowMagicball(actor->x, actor->y + var_8, actor->z, dx, actor->angle, var_24, var_14);
-		} break;
+			}
+			break;
+		}
 		case ACTION_SAMPLE_REPEAT: {
-			int16 sampleIdx, repeat;
+			animPos = stream.readByte();
+			int16 sampleIdx = stream.readSint16LE();
+			int16 repeat = stream.readSint16LE();
 
-			animPos = readByte(data);
-			sampleIdx = readWord(data);
-			repeat = readWord(data);
-
-			if (animPos == actor->animPosition)
+			if (animPos == actor->animPosition) {
 				_engine->_sound->playSample(sampleIdx, 0x1000, repeat, actor->x, actor->y, actor->z, actorIdx);
-		} break;
+			}
+			break;
+		}
 		case ACTION_UNKNOWN_6:
-			animPos = readByte(data);
+			animPos = stream.readByte();
 			if (animPos == actor->animPosition) {
-				int32 var_8, var_C, dx, var_24, temp;
-
 				//The folowing fetches 7 bytes, but the else block skips only 6 bytes.
 				// Please check if that's correct.
-				var_8 = readWord(data);
-				var_C = readByte(data);
-				dx = readByte(data);
-				var_24 = readWord(data);
-				temp = readByte(data);
+				int32 var_8 = stream.readSint16LE();
+				int32 var_C = stream.readByte();
+				int32 dx = stream.readByte();
+				int32 var_24 = stream.readSint16LE();
+				int32 temp = stream.readByte();
 
 				_engine->_extra->addExtraAiming(actorIdx, actor->x, actor->y + var_8, actor->z, var_C, dx, var_24, temp);
 			} else {
-				skipBytes(data, 6);
+				stream.skip(6);
 			}
 			break;
 		case ACTION_UNKNOWN_7: {
-			int32 yHeight, var_C, var_24, var_14, cx, dx, var;
-
-			animPos = readByte(data);
-			yHeight = readWord(data);
-			var_C = readByte(data);
-			dx = readWord(data);
-			cx = actor->angle + readWord(data);
-			var_24 = readWord(data);
-			var_14 = readByte(data);
-			var = readByte(data);
-
-			if (animPos == actor->animPosition)
+			animPos = stream.readByte();
+			int32 yHeight = stream.readSint16LE();
+			int32 var_C = stream.readByte();
+			int32 dx = stream.readSint16LE();
+			int32 cx = actor->angle + stream.readSint16LE();
+			int32 var_24 = stream.readSint16LE();
+			int32 var_14 = stream.readByte();
+			int32 var = stream.readByte();
+
+			if (animPos == actor->animPosition) {
 				_engine->_extra->addExtraThrow(actorIdx, actor->x, actor->y + yHeight, actor->z, var_C, dx, cx, var_24, var_14, var);
-		} break;
+			}
+			break;
+		}
 		case ACTION_SAMPLE_STOP: {
-			int32 sampleIdx;
-
-			animPos = readByte(data);
-			sampleIdx = readByte(data); //why is it reading a byte but saving it in a 32bit variable?
-			skipBytes(data, 1);         //what is the meaning of this extra byte?
+			animPos = stream.readByte();
+			int32 sampleIdx = stream.readByte(); //why is it reading a byte but saving it in a 32bit variable?
+			stream.skip(1);               //what is the meaning of this extra byte?
 
 			if (animPos == actor->animPosition) {
 				_engine->_sound->stopSample(sampleIdx);
 			}
-		} break;
+			break;
+		}
 		case ACTION_SAMPLE_BRICK_1:
-			animPos = readByte(data);
+			animPos = stream.readByte();
 			if (animPos == actor->animPosition && (actor->brickSound & 0x0F0) != 0x0F0) {
 				int16 sampleIdx = (actor->brickSound & 0x0F) + 126;
 				_engine->_sound->playSample(sampleIdx, _engine->getRandomNumber(1000) + 3596, 1, actor->x, actor->y, actor->z, actorIdx);
 			}
 			break;
 		case ACTION_SAMPLE_BRICK_2:
-			animPos = readByte(data);
+			animPos = stream.readByte();
 			if (animPos == actor->animPosition && (actor->brickSound & 0x0F0) != 0x0F0) {
 				int16 sampleIdx = (actor->brickSound & 0x0F) + 126;
 				_engine->_sound->playSample(sampleIdx, _engine->getRandomNumber(1000) + 3596, 1, actor->x, actor->y, actor->z, actorIdx);
 			}
 			break;
 		case ACTION_HERO_HITTING:
-			animPos = readByte(data) - 1;
+			animPos = stream.readByte() - 1;
 			if (animPos == actor->animPosition) {
 				actor->strengthOfHit = magicLevelStrengthOfHit[_engine->_gameState->magicLevelIdx];
 				actor->dynamicFlags.bIsHitting = 1;
 			}
 			break;
 		case ACTION_UNKNOWN_13: {
-			int32 throwX, throwY, throwZ;
-			int32 distanceX, distanceY, distanceZ;
-			int32 spriteIdx, strength;
-			int32 param1, param2, param3, param4;
-
-			animPos = readByte(data);
-			distanceX = readWord(data);
-			distanceY = readWord(data);
-			distanceZ = readWord(data);
+			animPos = stream.readByte();
+			int32 distanceX = stream.readSint16LE();
+			int32 distanceY = stream.readSint16LE();
+			int32 distanceZ = stream.readSint16LE();
 
-			spriteIdx = readByte(data);
+			int32 spriteIdx = stream.readByte();
 
-			param1 = readWord(data);
-			param2 = readWord(data);
-			param3 = readWord(data);
-			param4 = readByte(data);
+			int32 param1 = stream.readSint16LE();
+			int32 param2 = stream.readSint16LE();
+			int32 param3 = stream.readSint16LE();
+			int32 param4 = stream.readByte();
 
-			strength = readByte(data);
+			int32 strength = stream.readByte();
 
 			if (animPos == actor->animPosition) {
 				_engine->_movements->rotateActor(distanceX, distanceZ, actor->angle);
 
-				throwX = _engine->_renderer->destX + actor->x;
-				throwY = distanceY + actor->y;
-				throwZ = _engine->_renderer->destZ + actor->z;
+				int32 throwX = _engine->_renderer->destX + actor->x;
+				int32 throwY = distanceY + actor->y;
+				int32 throwZ = _engine->_renderer->destZ + actor->z;
 
 				_engine->_extra->addExtraThrow(actorIdx, throwX, throwY, throwZ, spriteIdx,
 				                               param1, param2 + actor->angle, param3, param4, strength);
 			}
-		} break;
+			break;
+		}
 		case ACTION_UNKNOWN_14: {
-			int32 newAngle, throwX, throwY, throwZ;
-			int32 distanceX, distanceY, distanceZ;
-			int32 spriteIdx, strength;
-			int32 param1, param2, param3, param4;
-
-			animPos = readByte(data);
-			distanceX = readWord(data);
-			distanceY = readWord(data);
-			distanceZ = readWord(data);
+			animPos = stream.readByte();
+			int32 distanceX = stream.readSint16LE();
+			int32 distanceY = stream.readSint16LE();
+			int32 distanceZ = stream.readSint16LE();
 
-			spriteIdx = readByte(data);
+			int32 spriteIdx = stream.readByte();
 
-			param1 = readWord(data);
-			param2 = readWord(data);
-			param3 = readWord(data);
-			param4 = readByte(data);
+			int32 param1 = stream.readSint16LE();
+			int32 param2 = stream.readSint16LE();
+			int32 param3 = stream.readSint16LE();
+			int32 param4 = stream.readByte();
 
-			strength = readByte(data);
+			int32 strength = stream.readByte();
 
 			if (animPos == actor->animPosition) {
-				newAngle = _engine->_movements->getAngleAndSetTargetActorDistance(actor->y, 0, _engine->_scene->sceneHero->y, _engine->_movements->getDistance2D(actor->x, actor->z, _engine->_scene->sceneHero->x, _engine->_scene->sceneHero->z));
+				int32 newAngle = _engine->_movements->getAngleAndSetTargetActorDistance(actor->y, 0, _engine->_scene->sceneHero->y, _engine->_movements->getDistance2D(actor->x, actor->z, _engine->_scene->sceneHero->x, _engine->_scene->sceneHero->z));
 
 				_engine->_movements->rotateActor(distanceX, distanceZ, actor->angle);
 
-				throwX = _engine->_renderer->destX + actor->x;
-				throwY = distanceY + actor->y;
-				throwZ = _engine->_renderer->destZ + actor->z;
+				int32 throwX = _engine->_renderer->destX + actor->x;
+				int32 throwY = distanceY + actor->y;
+				int32 throwZ = _engine->_renderer->destZ + actor->z;
 
 				_engine->_extra->addExtraThrow(actorIdx, throwX, throwY, throwZ, spriteIdx,
 				                               param1 + newAngle, param2 + actor->angle, param3, param4, strength);
 			}
-		} break;
+			break;
+		}
 		case ACTION_UNKNOWN_15: {
-			int32 distanceX, distanceY, distanceZ;
-			int32 spriteIdx, targetActor, param3, param4;
-
-			animPos = readByte(data);
-			distanceX = readWord(data);
-			distanceY = readWord(data);
-			distanceZ = readWord(data);
-			spriteIdx = readByte(data);
-			targetActor = readByte(data);
-			param3 = readWord(data);
-			param4 = readByte(data);
+			animPos = stream.readByte();
+			int32 distanceX = stream.readSint16LE();
+			int32 distanceY = stream.readSint16LE();
+			int32 distanceZ = stream.readSint16LE();
+			int32 spriteIdx = stream.readByte();
+			int32 targetActor = stream.readByte();
+			int32 param3 = stream.readSint16LE();
+			int32 param4 = stream.readByte();
 
 			if (animPos == actor->animPosition) {
 				_engine->_movements->rotateActor(distanceX, distanceZ, actor->angle);
 				_engine->_extra->addExtraAiming(actorIdx, actor->x + _engine->_renderer->destX, actor->y + distanceY, actor->z + distanceZ, spriteIdx,
 				                                targetActor, param3, param4);
 			}
-		} break;
+			break;
+		}
 		case ACTION_UNKNOWN_9:
 			break;
 		default:
 			break;
 		}
 	}
-	free(data);
 }
 
 int32 Animations::initAnim(AnimationTypes newAnim, int16 animType, uint8 animExtra, int32 actorIdx) {


Commit: 78eb7e6d290eeac45d21a1a65ca6117da719f8b1
    https://github.com/scummvm/scummvm/commit/78eb7e6d290eeac45d21a1a65ca6117da719f8b1
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2020-10-27T17:14:05+01:00

Commit Message:
TWINE: const

Changed paths:
    engines/twine/animations.cpp


diff --git a/engines/twine/animations.cpp b/engines/twine/animations.cpp
index af6fd9596c..55555637b0 100644
--- a/engines/twine/animations.cpp
+++ b/engines/twine/animations.cpp
@@ -471,8 +471,6 @@ int32 Animations::verifyAnimAtKeyframe(int32 animIdx, uint8 *animPtr, uint8 *bod
 }
 
 void Animations::processAnimActions(int32 actorIdx) {
-	int32 index = 0, endAnimEntityIdx, actionType, animPos;
-
 	ActorStruct *actor = _engine->_scene->getActor(actorIdx);
 	if (!actor->animExtraPtr) {
 		return; // avoid null pointers
@@ -480,17 +478,19 @@ void Animations::processAnimActions(int32 actorIdx) {
 
 	Common::MemoryReadStream stream(actor->animExtraPtr, 1000000);
 
-	endAnimEntityIdx = stream.readByte();
+	int32 index = 0;
+	const int32 endAnimEntityIdx = stream.readByte();
 	while (index++ < endAnimEntityIdx) {
-		actionType = stream.readByte() - 5;
+		int32 actionType = stream.readByte() - 5;
 		if (actionType >= ACTION_LAST) {
 			return;
 		}
 
+		int32 animPos;
 		switch (actionType) {
 		case ACTION_HITTING: {
 			animPos = stream.readByte() - 1;
-			int8 strength = stream.readByte();
+			const int8 strength = stream.readByte();
 
 			if (animPos == actor->animPosition) {
 				actor->strengthOfHit = strength;
@@ -500,7 +500,7 @@ void Animations::processAnimActions(int32 actorIdx) {
 		}
 		case ACTION_SAMPLE: {
 			animPos = stream.readByte();
-			int16 sampleIdx = stream.readSint16LE();
+			const int16 sampleIdx = stream.readSint16LE();
 
 			if (animPos == actor->animPosition) {
 				_engine->_sound->playSample(sampleIdx, 0x1000, 1, actor->x, actor->y, actor->z, actorIdx);
@@ -509,7 +509,7 @@ void Animations::processAnimActions(int32 actorIdx) {
 		}
 		case ACTION_SAMPLE_FREQ: {
 			animPos = stream.readByte();
-			int16 sampleIdx = stream.readSint16LE();
+			const int16 sampleIdx = stream.readSint16LE();
 			int16 frequency = stream.readSint16LE();
 
 			if (animPos == actor->animPosition) {
@@ -520,13 +520,13 @@ void Animations::processAnimActions(int32 actorIdx) {
 		}
 		case ACTION_THROW_EXTRA_BONUS: {
 			animPos = stream.readByte();
-			int32 yHeight = stream.readSint16LE();
-			int32 var_C = stream.readByte();
-			int32 cx = stream.readSint16LE();
-			int32 dx = actor->angle + stream.readSint16LE();
-			int32 var_24 = stream.readSint16LE();
-			int32 var_14 = stream.readByte();
-			int32 var = stream.readByte();
+			const int32 yHeight = stream.readSint16LE();
+			const int32 var_C = stream.readByte();
+			const int32 cx = stream.readSint16LE();
+			const int32 dx = actor->angle + stream.readSint16LE();
+			const int32 var_24 = stream.readSint16LE();
+			const int32 var_14 = stream.readByte();
+			const int32 var = stream.readByte();
 
 			if (animPos == actor->animPosition) {
 				_engine->_extra->addExtraThrow(actorIdx, actor->x, actor->y + yHeight, actor->z, var_C, cx, dx, var_24, var_14, var);
@@ -535,10 +535,10 @@ void Animations::processAnimActions(int32 actorIdx) {
 		}
 		case ACTION_THROW_MAGIC_BALL: {
 			animPos = stream.readByte();
-			int32 var_8 = stream.readSint16LE();
-			int32 dx = stream.readSint16LE();
-			int32 var_24 = stream.readSint16LE();
-			int32 var_14 = stream.readByte();
+			const int32 var_8 = stream.readSint16LE();
+			const int32 dx = stream.readSint16LE();
+			const int32 var_24 = stream.readSint16LE();
+			const int32 var_14 = stream.readByte();
 
 			if (_engine->_gameState->magicBallIdx == -1 && animPos == actor->animPosition) {
 				_engine->_extra->addExtraThrowMagicball(actor->x, actor->y + var_8, actor->z, dx, actor->angle, var_24, var_14);
@@ -547,8 +547,8 @@ void Animations::processAnimActions(int32 actorIdx) {
 		}
 		case ACTION_SAMPLE_REPEAT: {
 			animPos = stream.readByte();
-			int16 sampleIdx = stream.readSint16LE();
-			int16 repeat = stream.readSint16LE();
+			const int16 sampleIdx = stream.readSint16LE();
+			const int16 repeat = stream.readSint16LE();
 
 			if (animPos == actor->animPosition) {
 				_engine->_sound->playSample(sampleIdx, 0x1000, repeat, actor->x, actor->y, actor->z, actorIdx);
@@ -560,11 +560,11 @@ void Animations::processAnimActions(int32 actorIdx) {
 			if (animPos == actor->animPosition) {
 				//The folowing fetches 7 bytes, but the else block skips only 6 bytes.
 				// Please check if that's correct.
-				int32 var_8 = stream.readSint16LE();
-				int32 var_C = stream.readByte();
-				int32 dx = stream.readByte();
-				int32 var_24 = stream.readSint16LE();
-				int32 temp = stream.readByte();
+				const int32 var_8 = stream.readSint16LE();
+				const int32 var_C = stream.readByte();
+				const int32 dx = stream.readByte();
+				const int32 var_24 = stream.readSint16LE();
+				const int32 temp = stream.readByte();
 
 				_engine->_extra->addExtraAiming(actorIdx, actor->x, actor->y + var_8, actor->z, var_C, dx, var_24, temp);
 			} else {
@@ -573,13 +573,13 @@ void Animations::processAnimActions(int32 actorIdx) {
 			break;
 		case ACTION_UNKNOWN_7: {
 			animPos = stream.readByte();
-			int32 yHeight = stream.readSint16LE();
-			int32 var_C = stream.readByte();
-			int32 dx = stream.readSint16LE();
-			int32 cx = actor->angle + stream.readSint16LE();
-			int32 var_24 = stream.readSint16LE();
-			int32 var_14 = stream.readByte();
-			int32 var = stream.readByte();
+			const int32 yHeight = stream.readSint16LE();
+			const int32 var_C = stream.readByte();
+			const int32 dx = stream.readSint16LE();
+			const int32 cx = actor->angle + stream.readSint16LE();
+			const int32 var_24 = stream.readSint16LE();
+			const int32 var_14 = stream.readByte();
+			const int32 var = stream.readByte();
 
 			if (animPos == actor->animPosition) {
 				_engine->_extra->addExtraThrow(actorIdx, actor->x, actor->y + yHeight, actor->z, var_C, dx, cx, var_24, var_14, var);
@@ -588,7 +588,7 @@ void Animations::processAnimActions(int32 actorIdx) {
 		}
 		case ACTION_SAMPLE_STOP: {
 			animPos = stream.readByte();
-			int32 sampleIdx = stream.readByte(); //why is it reading a byte but saving it in a 32bit variable?
+			const int32 sampleIdx = stream.readByte(); //why is it reading a byte but saving it in a 32bit variable?
 			stream.skip(1);               //what is the meaning of this extra byte?
 
 			if (animPos == actor->animPosition) {
@@ -599,14 +599,14 @@ void Animations::processAnimActions(int32 actorIdx) {
 		case ACTION_SAMPLE_BRICK_1:
 			animPos = stream.readByte();
 			if (animPos == actor->animPosition && (actor->brickSound & 0x0F0) != 0x0F0) {
-				int16 sampleIdx = (actor->brickSound & 0x0F) + 126;
+				const int16 sampleIdx = (actor->brickSound & 0x0F) + 126;
 				_engine->_sound->playSample(sampleIdx, _engine->getRandomNumber(1000) + 3596, 1, actor->x, actor->y, actor->z, actorIdx);
 			}
 			break;
 		case ACTION_SAMPLE_BRICK_2:
 			animPos = stream.readByte();
 			if (animPos == actor->animPosition && (actor->brickSound & 0x0F0) != 0x0F0) {
-				int16 sampleIdx = (actor->brickSound & 0x0F) + 126;
+				const int16 sampleIdx = (actor->brickSound & 0x0F) + 126;
 				_engine->_sound->playSample(sampleIdx, _engine->getRandomNumber(1000) + 3596, 1, actor->x, actor->y, actor->z, actorIdx);
 			}
 			break;
@@ -619,25 +619,22 @@ void Animations::processAnimActions(int32 actorIdx) {
 			break;
 		case ACTION_UNKNOWN_13: {
 			animPos = stream.readByte();
-			int32 distanceX = stream.readSint16LE();
-			int32 distanceY = stream.readSint16LE();
-			int32 distanceZ = stream.readSint16LE();
-
-			int32 spriteIdx = stream.readByte();
-
-			int32 param1 = stream.readSint16LE();
-			int32 param2 = stream.readSint16LE();
-			int32 param3 = stream.readSint16LE();
-			int32 param4 = stream.readByte();
-
-			int32 strength = stream.readByte();
+			const int32 distanceX = stream.readSint16LE();
+			const int32 distanceY = stream.readSint16LE();
+			const int32 distanceZ = stream.readSint16LE();
+			const int32 spriteIdx = stream.readByte();
+			const int32 param1 = stream.readSint16LE();
+			const int32 param2 = stream.readSint16LE();
+			const int32 param3 = stream.readSint16LE();
+			const int32 param4 = stream.readByte();
+			const int32 strength = stream.readByte();
 
 			if (animPos == actor->animPosition) {
 				_engine->_movements->rotateActor(distanceX, distanceZ, actor->angle);
 
-				int32 throwX = _engine->_renderer->destX + actor->x;
-				int32 throwY = distanceY + actor->y;
-				int32 throwZ = _engine->_renderer->destZ + actor->z;
+				const int32 throwX = _engine->_renderer->destX + actor->x;
+				const int32 throwY = distanceY + actor->y;
+				const int32 throwZ = _engine->_renderer->destZ + actor->z;
 
 				_engine->_extra->addExtraThrow(actorIdx, throwX, throwY, throwZ, spriteIdx,
 				                               param1, param2 + actor->angle, param3, param4, strength);
@@ -646,27 +643,24 @@ void Animations::processAnimActions(int32 actorIdx) {
 		}
 		case ACTION_UNKNOWN_14: {
 			animPos = stream.readByte();
-			int32 distanceX = stream.readSint16LE();
-			int32 distanceY = stream.readSint16LE();
-			int32 distanceZ = stream.readSint16LE();
-
-			int32 spriteIdx = stream.readByte();
-
-			int32 param1 = stream.readSint16LE();
-			int32 param2 = stream.readSint16LE();
-			int32 param3 = stream.readSint16LE();
-			int32 param4 = stream.readByte();
-
-			int32 strength = stream.readByte();
+			const int32 distanceX = stream.readSint16LE();
+			const int32 distanceY = stream.readSint16LE();
+			const int32 distanceZ = stream.readSint16LE();
+			const int32 spriteIdx = stream.readByte();
+			const int32 param1 = stream.readSint16LE();
+			const int32 param2 = stream.readSint16LE();
+			const int32 param3 = stream.readSint16LE();
+			const int32 param4 = stream.readByte();
+			const int32 strength = stream.readByte();
 
 			if (animPos == actor->animPosition) {
-				int32 newAngle = _engine->_movements->getAngleAndSetTargetActorDistance(actor->y, 0, _engine->_scene->sceneHero->y, _engine->_movements->getDistance2D(actor->x, actor->z, _engine->_scene->sceneHero->x, _engine->_scene->sceneHero->z));
+				const int32 newAngle = _engine->_movements->getAngleAndSetTargetActorDistance(actor->y, 0, _engine->_scene->sceneHero->y, _engine->_movements->getDistance2D(actor->x, actor->z, _engine->_scene->sceneHero->x, _engine->_scene->sceneHero->z));
 
 				_engine->_movements->rotateActor(distanceX, distanceZ, actor->angle);
 
-				int32 throwX = _engine->_renderer->destX + actor->x;
-				int32 throwY = distanceY + actor->y;
-				int32 throwZ = _engine->_renderer->destZ + actor->z;
+				const int32 throwX = _engine->_renderer->destX + actor->x;
+				const int32 throwY = distanceY + actor->y;
+				const int32 throwZ = _engine->_renderer->destZ + actor->z;
 
 				_engine->_extra->addExtraThrow(actorIdx, throwX, throwY, throwZ, spriteIdx,
 				                               param1 + newAngle, param2 + actor->angle, param3, param4, strength);
@@ -675,13 +669,13 @@ void Animations::processAnimActions(int32 actorIdx) {
 		}
 		case ACTION_UNKNOWN_15: {
 			animPos = stream.readByte();
-			int32 distanceX = stream.readSint16LE();
-			int32 distanceY = stream.readSint16LE();
-			int32 distanceZ = stream.readSint16LE();
-			int32 spriteIdx = stream.readByte();
-			int32 targetActor = stream.readByte();
-			int32 param3 = stream.readSint16LE();
-			int32 param4 = stream.readByte();
+			const int32 distanceX = stream.readSint16LE();
+			const int32 distanceY = stream.readSint16LE();
+			const int32 distanceZ = stream.readSint16LE();
+			const int32 spriteIdx = stream.readByte();
+			const int32 targetActor = stream.readByte();
+			const int32 param3 = stream.readSint16LE();
+			const int32 param4 = stream.readByte();
 
 			if (animPos == actor->animPosition) {
 				_engine->_movements->rotateActor(distanceX, distanceZ, actor->angle);


Commit: 40b049ca5967720379d787fd86fd3d08d24cdbf1
    https://github.com/scummvm/scummvm/commit/40b049ca5967720379d787fd86fd3d08d24cdbf1
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2020-10-27T17:14:05+01:00

Commit Message:
TWINE: reduced visibility

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


diff --git a/engines/twine/grid.cpp b/engines/twine/grid.cpp
index 1fc1cb3c0a..fe50f3b1f0 100644
--- a/engines/twine/grid.cpp
+++ b/engines/twine/grid.cpp
@@ -36,6 +36,8 @@ namespace TwinE {
 
 Grid::Grid(TwinEEngine *engine) : _engine(engine) {}
 
+Grid::~Grid() {}
+
 void Grid::copyGridMask(int32 index, int32 x, int32 y, uint8 *buffer) {
 	uint8 *ptr = brickMaskTable[index];
 
diff --git a/engines/twine/grid.h b/engines/twine/grid.h
index 4abfc58b59..381801b174 100644
--- a/engines/twine/grid.h
+++ b/engines/twine/grid.h
@@ -149,9 +149,6 @@ private:
 	 */
 	void copyGridMask(int32 index, int32 x, int32 y, uint8 *buffer);
 
-public:
-	Grid(TwinEEngine *engine);
-
 	/** Table with all loaded bricks */
 	uint8 *brickTable[NUM_BRICKS]{nullptr};
 	/** Table with all loaded bricks masks */
@@ -168,9 +165,6 @@ public:
 	/** Number of block libraries */
 	int32 numberOfBll = 0;
 
-	/** Grid block entry types */
-	typedef struct BlockEntry blockMap[GRID_SIZE_X][GRID_SIZE_Z][GRID_SIZE_Y];
-
 	/** Brick data buffer */
 	BrickEntry bricksDataBuffer[28][150];
 	/** Brick info buffer */
@@ -181,6 +175,13 @@ public:
 	/** Current brick pixel Y position */
 	int32 brickPixelPosY = 0;
 
+public:
+	Grid(TwinEEngine *engine);
+	~Grid();
+
+	/** Grid block entry types */
+	typedef struct BlockEntry blockMap[GRID_SIZE_X][GRID_SIZE_Z][GRID_SIZE_Y];
+
 	/** New grid camera X coordinates */
 	int32 newCameraX = 0;
 	/** New grid camera Y coordinates */


Commit: 716313db75ea842995ac8b25fa158b5dda53ccc1
    https://github.com/scummvm/scummvm/commit/716313db75ea842995ac8b25fa158b5dda53ccc1
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2020-10-27T17:14:05+01:00

Commit Message:
TWINE: hide the blockBuffer member and fixed a memory leak

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


diff --git a/engines/twine/actor.h b/engines/twine/actor.h
index 378e1d0ac1..c58f9966c6 100644
--- a/engines/twine/actor.h
+++ b/engines/twine/actor.h
@@ -252,7 +252,7 @@ public:
 	int32 shadowY = 0;
 	/** Actor shadow Z coordinate */
 	int32 shadowZ = 0;
-	/** Actor shadow collition type */
+	/** Actor shadow collition type - brick shape */
 	int8 shadowCollisionType = 0; // shadowVar
 
 	HeroBehaviourType heroBehaviour = kNormal;
diff --git a/engines/twine/grid.cpp b/engines/twine/grid.cpp
index fe50f3b1f0..3232557876 100644
--- a/engines/twine/grid.cpp
+++ b/engines/twine/grid.cpp
@@ -34,9 +34,13 @@
 
 namespace TwinE {
 
-Grid::Grid(TwinEEngine *engine) : _engine(engine) {}
+Grid::Grid(TwinEEngine *engine) : _engine(engine) {
+	blockBuffer = (uint8 *)malloc(GRID_SIZE_X * GRID_SIZE_Z * GRID_SIZE_Y * 2 * sizeof(uint8));
+}
 
-Grid::~Grid() {}
+Grid::~Grid() {
+	free(blockBuffer);
+}
 
 void Grid::copyGridMask(int32 index, int32 x, int32 y, uint8 *buffer) {
 	uint8 *ptr = brickMaskTable[index];
@@ -512,6 +516,35 @@ void Grid::drawBrickSprite(int32 index, int32 posX, int32 posY, uint8 *ptr, bool
 	}
 }
 
+uint8* Grid::getBlockBuffer(int32 x, int32 y, int32 z) {
+	int32 tempX = (x + 0x100) >> 9;
+	int32 tempY = y >> 8;
+	int32 tempZ = (z + 0x100) >> 9;
+	return blockBuffer + tempY * 2 + tempX * GRID_SIZE_Y * 2 + (tempZ << 6) * GRID_SIZE_Y * 2;
+}
+
+const uint8* Grid::getBlockBufferGround(int32 x, int32 y, int32 z, int16 &ground) const {
+	_engine->_grid->updateCollisionCoordinates(x, y, z);
+	const int32 tempX = _engine->_collision->collisionX;
+	int32 tempY = _engine->_collision->collisionY;
+	const int32 tempZ = _engine->_collision->collisionZ;
+	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
+			break;
+		}
+		tempY--;
+		ptr -= 2;
+	}
+
+	_engine->_collision->collisionY = tempY;
+	ground = (int16)((tempY + 1) << 8);
+
+	return ptr;
+}
+
+
 uint8 *Grid::getBlockLibrary(int32 index) {
 	int32 offset = *((uint32 *)(currentBll + 4 * index));
 	return (uint8 *)(currentBll + offset);
@@ -602,9 +635,7 @@ void Grid::redrawGrid() {
 }
 
 int32 Grid::getBrickShape(int32 x, int32 y, int32 z) {
-	_engine->_collision->collisionX = (x + 0x100) >> 9;
-	_engine->_collision->collisionY = y >> 8;
-	_engine->_collision->collisionZ = (z + 0x100) >> 9;
+	updateCollisionCoordinates(x, y, z);
 
 	if (_engine->_collision->collisionX < 0 || _engine->_collision->collisionX >= GRID_SIZE_X) {
 		return 0;
@@ -619,7 +650,7 @@ int32 Grid::getBrickShape(int32 x, int32 y, int32 z) {
 	}
 
 	uint8 *blockBufferPtr = blockBuffer;
-	blockBufferPtr += _engine->_collision->collisionX * 50;
+	blockBufferPtr += _engine->_collision->collisionX * GRID_SIZE_Y * 2;
 	blockBufferPtr += _engine->_collision->collisionY * 2;
 	blockBufferPtr += (_engine->_collision->collisionZ << 7) * GRID_SIZE_Y;
 
@@ -639,10 +670,14 @@ int32 Grid::getBrickShape(int32 x, int32 y, int32 z) {
 	return *(blockBufferPtr + 1);
 }
 
-int32 Grid::getBrickShapeFull(int32 x, int32 y, int32 z, int32 y2) {
+void Grid::updateCollisionCoordinates(int32 x, int32 y, int32 z) {
 	_engine->_collision->collisionX = (x + 0x100) >> 9;
 	_engine->_collision->collisionY = y >> 8;
 	_engine->_collision->collisionZ = (z + 0x100) >> 9;
+}
+
+int32 Grid::getBrickShapeFull(int32 x, int32 y, int32 z, int32 y2) {
+	updateCollisionCoordinates(x, y, z);
 
 	if (_engine->_collision->collisionX < 0 || _engine->_collision->collisionX >= GRID_SIZE_X) {
 		return 0;
@@ -657,7 +692,7 @@ int32 Grid::getBrickShapeFull(int32 x, int32 y, int32 z, int32 y2) {
 	}
 
 	uint8 *blockBufferPtr = blockBuffer;
-	blockBufferPtr += _engine->_collision->collisionX * 50;
+	blockBufferPtr += _engine->_collision->collisionX * GRID_SIZE_Y * 2;
 	blockBufferPtr += _engine->_collision->collisionY * 2;
 	blockBufferPtr += (_engine->_collision->collisionZ << 7) * GRID_SIZE_Y;
 
@@ -714,9 +749,7 @@ int32 Grid::getBrickShapeFull(int32 x, int32 y, int32 z, int32 y2) {
 }
 
 int32 Grid::getBrickSoundType(int32 x, int32 y, int32 z) { // getPos2
-	_engine->_collision->collisionX = (x + 0x100) >> 9;
-	_engine->_collision->collisionY = y >> 8;
-	_engine->_collision->collisionZ = (z + 0x100) >> 9;
+	updateCollisionCoordinates(x, y, z);
 
 	if (_engine->_collision->collisionX < 0 || _engine->_collision->collisionX >= GRID_SIZE_X) {
 		return 0;
@@ -731,7 +764,7 @@ int32 Grid::getBrickSoundType(int32 x, int32 y, int32 z) { // getPos2
 	}
 
 	uint8 *blockBufferPtr = blockBuffer;
-	blockBufferPtr += _engine->_collision->collisionX * 50;
+	blockBufferPtr += _engine->_collision->collisionX * GRID_SIZE_Y * 2;
 	blockBufferPtr += _engine->_collision->collisionY * 2;
 	blockBufferPtr += (_engine->_collision->collisionZ << 7) * GRID_SIZE_Y;
 
diff --git a/engines/twine/grid.h b/engines/twine/grid.h
index 381801b174..b59200daef 100644
--- a/engines/twine/grid.h
+++ b/engines/twine/grid.h
@@ -175,6 +175,9 @@ private:
 	/** Current brick pixel Y position */
 	int32 brickPixelPosY = 0;
 
+	/** Celling grid brick block buffer */
+	uint8 *blockBuffer = nullptr;
+
 public:
 	Grid(TwinEEngine *engine);
 	~Grid();
@@ -182,6 +185,14 @@ public:
 	/** Grid block entry types */
 	typedef struct BlockEntry blockMap[GRID_SIZE_X][GRID_SIZE_Z][GRID_SIZE_Y];
 
+	uint8* getBlockBuffer(int32 x, int32 y, int32 z);
+	/**
+	 * search down until either ground is found or lower border of the cube is reached
+	 */
+	const uint8* getBlockBufferGround(int32 x, int32 y, int32 z, int16 &ground) const;
+
+	void updateCollisionCoordinates(int32 x, int32 y, int32 z);
+
 	/** New grid camera X coordinates */
 	int32 newCameraX = 0;
 	/** New grid camera Y coordinates */
@@ -196,9 +207,6 @@ public:
 	/** Current grid camera Z coordinates */
 	int32 cameraZ = 0;
 
-	/** Celling grid brick block buffer */
-	uint8 *blockBuffer = nullptr;
-
 	/** Flag to know if the engine is using celling grids */
 	int16 useCellingGrid = 0; // useAnotherGrm
 	/** Current celling grid index */
diff --git a/engines/twine/movements.cpp b/engines/twine/movements.cpp
index 83cf307c46..36f71d6207 100644
--- a/engines/twine/movements.cpp
+++ b/engines/twine/movements.cpp
@@ -36,46 +36,19 @@ namespace TwinE {
 
 Movements::Movements(TwinEEngine *engine) : _engine(engine) {}
 
-void Movements::getShadowPosition(int32 X, int32 Y, int32 Z) {
-	int32 tempX;
-	int32 tempY;
-	int32 tempZ;
-	uint8 *ptr;
-
-	tempX = (X + 0x100) >> 9;
-	tempY = Y >> 8;
-	tempZ = (Z + 0x100) >> 9;
-
-	ptr = _engine->_grid->blockBuffer + tempY * 2 + tempX * 25 * 2 + (tempZ << 6) * 25 * 2;
-
-	while (tempY) {        // search down until either ground is found or lower border of the cube is reached
-		if (*(int16 *)ptr) // found the ground
-			break;
-
-		tempY--;
-		ptr -= 2;
-	}
-
-	_engine->_actor->shadowCollisionType = 0;
-
-	_engine->_collision->collisionX = tempX;
-	_engine->_collision->collisionY = tempY;
-	_engine->_collision->collisionZ = tempZ;
-
-	processActorX = X;
-	processActorY = (tempY + 1) << 8;
-	processActorZ = Z;
-
-	if (*ptr) { //*((uint8 *)(blockPtr))
-		uint8 *blockPtr;
-		uint8 brickShape;
-
-		blockPtr = _engine->_grid->getBlockLibrary(*(ptr)-1) + 3 + *(ptr + 1) * 4;
-		brickShape = *((uint8 *)(blockPtr));
-
+void Movements::getShadowPosition(int32 x, int32 y, int32 z) {
+	const uint8 *ptr = _engine->_grid->getBlockBufferGround(x, y, z, processActorY);
+	processActorX = x;
+	processActorZ = z;
+
+	if (*ptr) {
+		uint8 *blockPtr = _engine->_grid->getBlockLibrary(*ptr - 1) + 3 + *(ptr + 1) * 4;
+		uint8 brickShape = *((uint8 *)(blockPtr));
 		_engine->_actor->shadowCollisionType = brickShape;
-		_engine->_collision->reajustActorPosition(_engine->_actor->shadowCollisionType);
+	} else {
+		_engine->_actor->shadowCollisionType = 0;
 	}
+	_engine->_collision->reajustActorPosition(_engine->_actor->shadowCollisionType);
 
 	_engine->_actor->shadowX = processActorX;
 	_engine->_actor->shadowY = processActorY;
@@ -168,18 +141,15 @@ int32 Movements::getAngleAndSetTargetActorDistance(int32 x1, int32 z1, int32 x2,
 }
 
 int32 Movements::getRealAngle(ActorMoveStruct *movePtr) {
-	int32 timePassed;
-	int32 remainingAngle;
-
 	if (movePtr->numOfStep) {
-		timePassed = _engine->lbaTime - movePtr->timeOfChange;
+		int32 timePassed = _engine->lbaTime - movePtr->timeOfChange;
 
 		if (timePassed >= movePtr->numOfStep) { // rotation is finished
 			movePtr->numOfStep = 0;
 			return movePtr->to;
 		}
 
-		remainingAngle = movePtr->to - movePtr->from;
+		int32 remainingAngle = movePtr->to - movePtr->from;
 
 		if (remainingAngle < -0x200) {
 			remainingAngle += 0x400;
@@ -198,8 +168,6 @@ int32 Movements::getRealAngle(ActorMoveStruct *movePtr) {
 }
 
 int32 Movements::getRealValue(ActorMoveStruct *movePtr) {
-	int32 tempStep;
-
 	if (!movePtr->numOfStep) {
 		return movePtr->to;
 	}
@@ -209,7 +177,7 @@ int32 Movements::getRealValue(ActorMoveStruct *movePtr) {
 		return movePtr->to;
 	}
 
-	tempStep = movePtr->to - movePtr->from;
+	int32 tempStep = movePtr->to - movePtr->from;
 	tempStep *= _engine->lbaTime - movePtr->timeOfChange;
 	tempStep /= movePtr->numOfStep;
 
diff --git a/engines/twine/twine.cpp b/engines/twine/twine.cpp
index 56a160f7e6..04715a23c3 100644
--- a/engines/twine/twine.cpp
+++ b/engines/twine/twine.cpp
@@ -323,7 +323,6 @@ void TwinEEngine::initSVGA() {
 }
 
 void TwinEEngine::initAll() {
-	_grid->blockBuffer = (uint8 *)malloc(GRID_SIZE_X * GRID_SIZE_Z * GRID_SIZE_Y * 2 * sizeof(uint8));
 	_animations->animBuffer1 = _animations->animBuffer2 = (uint8 *)malloc(5000 * sizeof(uint8));
 	memset(_menu->itemAngle, 0, sizeof(_menu->itemAngle)); // reset inventory items angles
 


Commit: 11fda12409fae389f24b091219cbf6a8feec8cd2
    https://github.com/scummvm/scummvm/commit/11fda12409fae389f24b091219cbf6a8feec8cd2
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2020-10-27T17:14:05+01:00

Commit Message:
TWINE: plug a memory leak and reduced visiblity

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


diff --git a/engines/twine/animations.cpp b/engines/twine/animations.cpp
index 55555637b0..1d2758bd6c 100644
--- a/engines/twine/animations.cpp
+++ b/engines/twine/animations.cpp
@@ -69,6 +69,11 @@ enum ActionType {
 };
 
 Animations::Animations(TwinEEngine *engine) : _engine(engine) {
+	animBuffer1 = animBuffer2 = (uint8 *)malloc(5000 * sizeof(uint8));
+}
+
+Animations::~Animations() {
+	free(animBuffer1);
 }
 
 int32 Animations::setAnimAtKeyframe(int32 keyframeIdx, uint8 *animPtr, uint8 *bodyPtr, AnimTimerDataStruct *animTimerDataPtr) {
@@ -382,7 +387,8 @@ int32 Animations::getBodyAnimIndex(AnimationTypes animIdx, int32 actorIdx) {
 	return 0;
 }
 
-int32 Animations::stockAnimation(uint8 *animPtr, uint8 *bodyPtr, AnimTimerDataStruct *animTimerDataPtr) {
+int32 Animations::stockAnimation(uint8 *bodyPtr, AnimTimerDataStruct *animTimerDataPtr) {
+	uint8 *animPtr = animBuffer2;
 	int32 playAnim = *(int16 *)(bodyPtr);
 
 	if (!(playAnim & 2)) {
@@ -415,6 +421,12 @@ int32 Animations::stockAnimation(uint8 *animPtr, uint8 *bodyPtr, AnimTimerDataSt
 		esi = (int32 *)(((int8 *)esi) + 30);
 	} while (counter--);
 
+	animBuffer2 += var2;
+
+	if (animBuffer1 + 4488 < animBuffer2) {
+		animBuffer2 = animBuffer1;
+	}
+
 	return var2;
 }
 
@@ -738,7 +750,7 @@ int32 Animations::initAnim(AnimationTypes newAnim, int16 animType, uint8 animExt
 	if (actor->previousAnimIdx == -1) { // if no previous animation
 		setAnimAtKeyframe(0, animTable[animIndex], _engine->_actor->bodyTable[actor->entity], &actor->animTimerData);
 	} else { // interpolation between animations
-		animBuffer2 += stockAnimation(animBuffer2, _engine->_actor->bodyTable[actor->entity], &actor->animTimerData);
+		animBuffer2 += stockAnimation(_engine->_actor->bodyTable[actor->entity], &actor->animTimerData);
 		if (animBuffer1 + 4488 < animBuffer2) {
 			animBuffer2 = animBuffer1;
 		}
diff --git a/engines/twine/animations.h b/engines/twine/animations.h
index 73819238ef..8a356be654 100644
--- a/engines/twine/animations.h
+++ b/engines/twine/animations.h
@@ -41,19 +41,13 @@ private:
 	int32 getAnimMode(uint8 **ptr);
 	void applyAnimStep(uint8 **ptr, int32 bp, int32 bx);
 
-public:
-	Animations(TwinEEngine *engine);
-	/** Table with all loaded animations */
-	uint8 *animTable[NUM_ANIMS]{nullptr};
-	/** Table with all loaded animations sizes */
-	uint32 animSizeTable[NUM_ANIMS]{0};
+	uint8 *animBuffer1 = nullptr;
+	uint8 *animBuffer2 = nullptr;
 
 	/** Rotation by anim and not by engine */
 	int16 processRotationByAnim = 0; // processActorVar5
 	/** Last rotation angle */
 	int16 processLastRotationAngle = 0; // processActorVar6
-	/** Current process actor index */
-	int16 currentlyProcessedActorIdx = 0;
 
 	/** Current step X coornidate */
 	int16 currentStepX = 0;
@@ -61,16 +55,23 @@ public:
 	int16 currentStepY = 0;
 	/** Current step Z coornidate */
 	int16 currentStepZ = 0;
-	/** Current actor anim extra pointer */
-	uint8 *currentActorAnimExtraPtr = nullptr;
 
 	/** Pointer to current animation keyframe */
 	uint8 *keyFramePtr = nullptr;
 	/** Pointer to last animation keyframe */
 	uint8 *lastKeyFramePtr = nullptr;
 
-	uint8 *animBuffer1 = nullptr;
-	uint8 *animBuffer2 = nullptr;
+public:
+	Animations(TwinEEngine *engine);
+	~Animations();
+	/** Table with all loaded animations */
+	uint8 *animTable[NUM_ANIMS]{nullptr};
+	/** Table with all loaded animations sizes */
+	uint32 animSizeTable[NUM_ANIMS]{0};
+	/** Current process actor index */
+	int16 currentlyProcessedActorIdx = 0;
+	/** Current actor anim extra pointer */
+	uint8 *currentActorAnimExtraPtr = nullptr;
 
 	/**
 	 * Set animation keyframe
@@ -111,11 +112,10 @@ public:
 
 	/**
 	 * Stock animation - copy the next keyFrame from a different buffer
-	 * @param animPtr Animation pointer
 	 * @param bodyPtr Body model poitner
 	 * @param animTimerDataPtr Animation time data
 	 */
-	int32 stockAnimation(uint8 *animPtr, uint8 *bodyPtr, AnimTimerDataStruct *animTimerDataPtr);
+	int32 stockAnimation(uint8 *bodyPtr, AnimTimerDataStruct *animTimerDataPtr);
 
 	/**
 	 * Verify animation at keyframe
diff --git a/engines/twine/gamestate.cpp b/engines/twine/gamestate.cpp
index 1790842fbf..1b25f0a965 100644
--- a/engines/twine/gamestate.cpp
+++ b/engines/twine/gamestate.cpp
@@ -332,10 +332,7 @@ void GameState::processFoundItem(int32 item) {
 
 	AnimTimerDataStruct tmpAnimTimer = _engine->_scene->sceneHero->animTimerData;
 
-	_engine->_animations->animBuffer2 += _engine->_animations->stockAnimation(_engine->_animations->animBuffer2, _engine->_actor->bodyTable[_engine->_scene->sceneHero->entity], &_engine->_scene->sceneHero->animTimerData);
-	if (_engine->_animations->animBuffer1 + 4488 < _engine->_animations->animBuffer2) {
-		_engine->_animations->animBuffer2 = _engine->_animations->animBuffer1;
-	}
+	_engine->_animations->stockAnimation(_engine->_actor->bodyTable[_engine->_scene->sceneHero->entity], &_engine->_scene->sceneHero->animTimerData);
 
 	int32 currentAnimState = 0;
 
@@ -444,7 +441,7 @@ void GameState::processGameChoices(int32 choiceIdx) {
 	}
 }
 
-void GameState::processGameoverAnimation() { // makeGameOver
+void GameState::processGameoverAnimation() {
 	int32 tmpLbaTime = _engine->lbaTime;
 
 	// workaround to fix hero redraw after drowning
diff --git a/engines/twine/grid.cpp b/engines/twine/grid.cpp
index 3232557876..4bf8759a83 100644
--- a/engines/twine/grid.cpp
+++ b/engines/twine/grid.cpp
@@ -40,6 +40,9 @@ Grid::Grid(TwinEEngine *engine) : _engine(engine) {
 
 Grid::~Grid() {
 	free(blockBuffer);
+	for (int32 b = 0; b < NUM_BRICKS; b++) {
+		free(brickMaskTable[b]);
+	}
 }
 
 void Grid::copyGridMask(int32 index, int32 x, int32 y, uint8 *buffer) {
diff --git a/engines/twine/twine.cpp b/engines/twine/twine.cpp
index 04715a23c3..037e2ba768 100644
--- a/engines/twine/twine.cpp
+++ b/engines/twine/twine.cpp
@@ -323,7 +323,6 @@ void TwinEEngine::initSVGA() {
 }
 
 void TwinEEngine::initAll() {
-	_animations->animBuffer1 = _animations->animBuffer2 = (uint8 *)malloc(5000 * sizeof(uint8));
 	memset(_menu->itemAngle, 0, sizeof(_menu->itemAngle)); // reset inventory items angles
 
 	_redraw->bubbleSpriteIndex = SPRITEHQR_DIAG_BUBBLE_LEFT;


Commit: e5fe47d542c10db2949268fc76d4945cec3b7f78
    https://github.com/scummvm/scummvm/commit/e5fe47d542c10db2949268fc76d4945cec3b7f78
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2020-10-27T17:14:05+01:00

Commit Message:
TWINE: plug memory leaks

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


diff --git a/engines/twine/actor.cpp b/engines/twine/actor.cpp
index 0d64e5feec..808b9ccf3b 100644
--- a/engines/twine/actor.cpp
+++ b/engines/twine/actor.cpp
@@ -41,6 +41,14 @@ namespace TwinE {
 Actor::Actor(TwinEEngine *engine) : _engine(engine) {
 }
 
+Actor::~Actor() {
+	free(heroEntityNORMAL);
+	free(heroEntityATHLETIC);
+	free(heroEntityAGGRESSIVE);
+	free(heroEntityDISCRETE);
+	free(heroEntityPROTOPACK);
+}
+
 void Actor::restartHeroScene() {
 	_engine->_scene->sceneHero->controlMode = ControlMode::kManual;
 	memset(&_engine->_scene->sceneHero->dynamicFlags, 0, sizeof(_engine->_scene->sceneHero->dynamicFlags));
diff --git a/engines/twine/actor.h b/engines/twine/actor.h
index c58f9966c6..5e49dd6bc2 100644
--- a/engines/twine/actor.h
+++ b/engines/twine/actor.h
@@ -239,6 +239,8 @@ private:
 	void initSpriteActor(int32 actorIdx);
 public:
 	Actor(TwinEEngine* engine);
+	~Actor();
+
 	/** Table with all loaded sprites */
 	uint8 *spriteTable[NUM_SPRITES] {nullptr};
 	/** Table with all loaded sprite sizes */


Commit: a3927197d1e8c78b718a83df3cfb78b39c46666f
    https://github.com/scummvm/scummvm/commit/a3927197d1e8c78b718a83df3cfb78b39c46666f
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2020-10-27T17:14:05+01:00

Commit Message:
TWINE: const

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


diff --git a/engines/twine/grid.cpp b/engines/twine/grid.cpp
index 4bf8759a83..28ce2a8b0d 100644
--- a/engines/twine/grid.cpp
+++ b/engines/twine/grid.cpp
@@ -450,14 +450,14 @@ void Grid::drawBrick(int32 index, int32 posX, int32 posY) {
 	drawBrickSprite(index, posX, posY, brickTable[index], false);
 }
 
-void Grid::drawSprite(int32 index, int32 posX, int32 posY, uint8 *ptr) {
+void Grid::drawSprite(int32 index, int32 posX, int32 posY, const uint8 *ptr) {
 	drawBrickSprite(index, posX, posY, ptr, true);
 }
 
 // WARNING: Rewrite this function to have better performance
-void Grid::drawBrickSprite(int32 index, int32 posX, int32 posY, uint8 *ptr, bool isSprite) {
+void Grid::drawBrickSprite(int32 index, int32 posX, int32 posY, const uint8 *ptr, bool isSprite) {
 	if (isSprite) {
-		ptr = ptr + *((uint32 *)(ptr + index * 4));
+		ptr = ptr + *((const uint32 *)(ptr + index * 4));
 	}
 
 	int32 left = posX + *(ptr + 2);
diff --git a/engines/twine/grid.h b/engines/twine/grid.h
index b59200daef..f3a15841a5 100644
--- a/engines/twine/grid.h
+++ b/engines/twine/grid.h
@@ -252,7 +252,7 @@ public:
 	 * @param posY sprite Y position to draw
 	 * @param ptr sprite buffer pointer to draw
 	 */
-	void drawSprite(int32 index, int32 posX, int32 posY, uint8 *spritePtr);
+	void drawSprite(int32 index, int32 posX, int32 posY, const uint8 *spritePtr);
 
 	/**
 	 * Draw sprite or bricks in the screen according with the type
@@ -262,7 +262,7 @@ public:
 	 * @param ptr sprite buffer pointer to draw
 	 * @param isSprite allows to identify if the sprite to display is brick or a single sprite
 	 */
-	void drawBrickSprite(int32 index, int32 posX, int32 posY, uint8 *spritePtr, bool isSprite);
+	void drawBrickSprite(int32 index, int32 posX, int32 posY, const uint8 *spritePtr, bool isSprite);
 
 	/**
 	 * Get block library


Commit: 156d6ca14da1ba0c35bb73dbe191c550ca4a25ed
    https://github.com/scummvm/scummvm/commit/156d6ca14da1ba0c35bb73dbe191c550ca4a25ed
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2020-10-27T17:14:05+01:00

Commit Message:
TWINE: moved spriteTable into Resources class

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


diff --git a/engines/twine/actor.h b/engines/twine/actor.h
index 5e49dd6bc2..e95760aa87 100644
--- a/engines/twine/actor.h
+++ b/engines/twine/actor.h
@@ -241,11 +241,6 @@ public:
 	Actor(TwinEEngine* engine);
 	~Actor();
 
-	/** Table with all loaded sprites */
-	uint8 *spriteTable[NUM_SPRITES] {nullptr};
-	/** Table with all loaded sprite sizes */
-	uint32 spriteSizeTable[NUM_SPRITES] {0};
-
 	ActorStruct *processActorPtr = nullptr; // processActorVar1
 
 	/** Actor shadow X coordinate */
diff --git a/engines/twine/menu.cpp b/engines/twine/menu.cpp
index fa0f86fed4..718c31dc36 100644
--- a/engines/twine/menu.cpp
+++ b/engines/twine/menu.cpp
@@ -752,7 +752,7 @@ void Menu::drawInfoMenu(int16 left, int16 top) {
 
 	newBoxLeft2 = left + 9;
 
-	_engine->_grid->drawSprite(0, newBoxLeft2, top + 13, _engine->_actor->spriteTable[SPRITEHQR_LIFEPOINTS]);
+	_engine->_grid->drawSprite(0, newBoxLeft2, top + 13, _engine->_resources->spriteTable[SPRITEHQR_LIFEPOINTS]);
 
 	boxRight = left + 325;
 	newBoxLeft = left + 25;
@@ -764,7 +764,7 @@ void Menu::drawInfoMenu(int16 left, int16 top) {
 	drawBox(left + 25, top + 10, left + 324, top + 10 + 14);
 
 	if (!_engine->_gameState->gameFlags[GAMEFLAG_INVENTORY_DISABLED] && _engine->_gameState->gameFlags[InventoryItems::kiTunic]) {
-		_engine->_grid->drawSprite(0, newBoxLeft2, top + 36, _engine->_actor->spriteTable[SPRITEHQR_MAGICPOINTS]);
+		_engine->_grid->drawSprite(0, newBoxLeft2, top + 36, _engine->_resources->spriteTable[SPRITEHQR_MAGICPOINTS]);
 		if (_engine->_gameState->magicLevelIdx > 0) {
 			_engine->_interface->drawSplittedBox(newBoxLeft, top + 35, _engine->_screens->crossDot(newBoxLeft, boxRight, 80, _engine->_gameState->inventoryMagicPoints), top + 50, 75);
 		}
@@ -774,13 +774,13 @@ void Menu::drawInfoMenu(int16 left, int16 top) {
 	boxLeft = left + 340;
 
 	/** draw coin sprite */
-	_engine->_grid->drawSprite(0, boxLeft, top + 15, _engine->_actor->spriteTable[SPRITEHQR_KASHES]);
+	_engine->_grid->drawSprite(0, boxLeft, top + 15, _engine->_resources->spriteTable[SPRITEHQR_KASHES]);
 	_engine->_text->setFontColor(155);
 	Common::String inventoryNumKashes = Common::String::format("%d", _engine->_gameState->inventoryNumKashes);
 	_engine->_text->drawText(left + 370, top + 5, inventoryNumKashes.c_str());
 
 	/** draw key sprite */
-	_engine->_grid->drawSprite(0, boxLeft, top + 55, _engine->_actor->spriteTable[SPRITEHQR_KEY]);
+	_engine->_grid->drawSprite(0, boxLeft, top + 55, _engine->_resources->spriteTable[SPRITEHQR_KEY]);
 	_engine->_text->setFontColor(155);
 	Common::String inventoryNumKeys = Common::String::format("%d", _engine->_gameState->inventoryNumKeys);
 	_engine->_text->drawText(left + 370, top + 40, inventoryNumKeys.c_str());
@@ -792,12 +792,12 @@ void Menu::drawInfoMenu(int16 left, int16 top) {
 
 	// Clover leaf boxes
 	for (i = 0; i < _engine->_gameState->inventoryNumLeafsBox; i++) {
-		_engine->_grid->drawSprite(0, _engine->_screens->crossDot(left + 25, left + 325, 10, i), top + 58, _engine->_actor->spriteTable[SPRITEHQR_CLOVERLEAFBOX]);
+		_engine->_grid->drawSprite(0, _engine->_screens->crossDot(left + 25, left + 325, 10, i), top + 58, _engine->_resources->spriteTable[SPRITEHQR_CLOVERLEAFBOX]);
 	}
 
 	// Clover leafs
 	for (i = 0; i < _engine->_gameState->inventoryNumLeafs; i++) {
-		_engine->_grid->drawSprite(0, _engine->_screens->crossDot(left + 25, left + 325, 10, i) + 2, top + 60, _engine->_actor->spriteTable[SPRITEHQR_CLOVERLEAF]);
+		_engine->_grid->drawSprite(0, _engine->_screens->crossDot(left + 25, left + 325, 10, i) + 2, top + 60, _engine->_resources->spriteTable[SPRITEHQR_CLOVERLEAF]);
 	}
 
 	_engine->copyBlockPhys(left, top, left + 450, top + 135);
diff --git a/engines/twine/redraw.cpp b/engines/twine/redraw.cpp
index e08869166a..965d1f0261 100644
--- a/engines/twine/redraw.cpp
+++ b/engines/twine/redraw.cpp
@@ -440,7 +440,7 @@ void Redraw::redrawEngineActions(int32 bgRedraw) { // fullRedraw
 			// Drawing sprite actors
 			else if (flags == 0x1000) {
 				int32 spriteWidth, spriteHeight;
-				uint8 *spritePtr = _engine->_actor->spriteTable[actor2->entity];
+				uint8 *spritePtr = _engine->_resources->spriteTable[actor2->entity];
 
 				// get actor position on screen
 				_engine->_renderer->projectPositionOnScreen(actor2->x - _engine->_grid->cameraX, actor2->y - _engine->_grid->cameraY, actor2->z - _engine->_grid->cameraZ);
@@ -497,15 +497,15 @@ void Redraw::redrawEngineActions(int32 bgRedraw) { // fullRedraw
 					_engine->_extra->drawExtraSpecial(actorIdx, _engine->_renderer->projPosX, _engine->_renderer->projPosY);
 				} else {
 					int32 spriteWidth, spriteHeight;
-					_engine->_grid->getSpriteSize(0, &spriteWidth, &spriteHeight, _engine->_actor->spriteTable[extra->info0]);
+					_engine->_grid->getSpriteSize(0, &spriteWidth, &spriteHeight, _engine->_resources->spriteTable[extra->info0]);
 
 					// calculate sprite position on screen
-					renderLeft = _engine->_renderer->projPosX + *(int16 *)(_engine->_scene->spriteBoundingBoxPtr + extra->info0 * 16);
-					renderTop = _engine->_renderer->projPosY + *(int16 *)(_engine->_scene->spriteBoundingBoxPtr + extra->info0 * 16 + 2);
+					renderLeft = _engine->_renderer->projPosX + *(const int16 *)(_engine->_scene->spriteBoundingBoxPtr + extra->info0 * 16);
+					renderTop = _engine->_renderer->projPosY + *(const int16 *)(_engine->_scene->spriteBoundingBoxPtr + extra->info0 * 16 + 2);
 					renderRight = renderLeft + spriteWidth;
 					renderBottom = renderTop + spriteHeight;
 
-					_engine->_grid->drawSprite(0, renderLeft, renderTop, _engine->_actor->spriteTable[extra->info0]);
+					_engine->_grid->drawSprite(0, renderLeft, renderTop, _engine->_resources->spriteTable[extra->info0]);
 				}
 
 				_engine->_interface->setClip(renderLeft, renderTop, renderRight, renderBottom);
@@ -564,12 +564,12 @@ void Redraw::redrawEngineActions(int32 bgRedraw) { // fullRedraw
 			case koSprite: {
 				int16 offsetX, offsetY;
 				int32 spriteWidth, spriteHeight;
-				uint8 *spritePtr = _engine->_actor->spriteTable[overlay->info0];
+				uint8 *spritePtr = _engine->_resources->spriteTable[overlay->info0];
 
 				_engine->_grid->getSpriteSize(0, &spriteWidth, &spriteHeight, spritePtr);
 
-				offsetX = *((int16 *)(_engine->_scene->spriteBoundingBoxPtr + (overlay->info0 * 16)));
-				offsetY = *((int16 *)(_engine->_scene->spriteBoundingBoxPtr + (overlay->info0 * 16) + 2));
+				offsetX = *((const int16 *)(_engine->_scene->spriteBoundingBoxPtr + (overlay->info0 * 16)));
+				offsetY = *((const int16 *)(_engine->_scene->spriteBoundingBoxPtr + (overlay->info0 * 16) + 2));
 
 				renderLeft = offsetX + overlay->x;
 				renderTop = offsetY + overlay->y;
@@ -740,7 +740,7 @@ void Redraw::drawBubble(int32 actorIdx) {
 		bubbleActor = actorIdx;
 	}
 
-	spritePtr = _engine->_actor->spriteTable[bubbleSpriteIndex];
+	spritePtr = _engine->_resources->spriteTable[bubbleSpriteIndex];
 	_engine->_grid->getSpriteSize(0, &spriteWidth, &spriteHeight, spritePtr);
 
 	// calculate sprite position on screen
diff --git a/engines/twine/resources.cpp b/engines/twine/resources.cpp
index 1a0d90235c..5314bb3491 100644
--- a/engines/twine/resources.cpp
+++ b/engines/twine/resources.cpp
@@ -50,7 +50,7 @@ void Resources::preloadSprites() {
 	}
 	debug("preload %i sprites", numEntries);
 	for (int32 i = 0; i < numEntries; i++) {
-		_engine->_actor->spriteSizeTable[i] = _engine->_hqrdepack->hqrGetallocEntry(&_engine->_actor->spriteTable[i], Resources::HQR_SPRITES_FILE, i);
+		spriteSizeTable[i] = _engine->_hqrdepack->hqrGetallocEntry(&spriteTable[i], Resources::HQR_SPRITES_FILE, i);
 	}
 }
 
diff --git a/engines/twine/resources.h b/engines/twine/resources.h
index 29026ee21d..c4325cade5 100644
--- a/engines/twine/resources.h
+++ b/engines/twine/resources.h
@@ -116,6 +116,11 @@ public:
 	/** Table with all loaded samples sizes */
 	uint32 inventorySizeTable[NUM_INVENTORY_ITEMS] {0};
 
+	/** Table with all loaded sprites */
+	uint8 *spriteTable[NUM_SPRITES] {nullptr};
+	/** Table with all loaded sprite sizes */
+	uint32 spriteSizeTable[NUM_SPRITES] {0};
+
 	/** Initialize resource pointers */
 	void initResources();
 


Commit: 0e9bc030f1a2c59b6418c38f7630316cd774b2c1
    https://github.com/scummvm/scummvm/commit/0e9bc030f1a2c59b6418c38f7630316cd774b2c1
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2020-10-27T17:14:05+01:00

Commit Message:
TWINE: moved animTable into Resources class

Changed paths:
    engines/twine/animations.cpp
    engines/twine/animations.h
    engines/twine/gamestate.cpp
    engines/twine/menu.cpp
    engines/twine/redraw.cpp
    engines/twine/resources.cpp
    engines/twine/resources.h


diff --git a/engines/twine/animations.cpp b/engines/twine/animations.cpp
index 1d2758bd6c..8a0a1a420d 100644
--- a/engines/twine/animations.cpp
+++ b/engines/twine/animations.cpp
@@ -748,7 +748,7 @@ int32 Animations::initAnim(AnimationTypes newAnim, int16 animType, uint8 animExt
 	}
 
 	if (actor->previousAnimIdx == -1) { // if no previous animation
-		setAnimAtKeyframe(0, animTable[animIndex], _engine->_actor->bodyTable[actor->entity], &actor->animTimerData);
+		setAnimAtKeyframe(0, _engine->_resources->animTable[animIndex], _engine->_actor->bodyTable[actor->entity], &actor->animTimerData);
 	} else { // interpolation between animations
 		animBuffer2 += stockAnimation(_engine->_actor->bodyTable[actor->entity], &actor->animTimerData);
 		if (animBuffer1 + 4488 < animBuffer2) {
@@ -890,7 +890,7 @@ void Animations::processActorAnimations(int32 actorIdx) { // DoAnim
 	} else { // 3D actor
 		if (actor->previousAnimIdx != -1) {
 			int32 keyFramePassed;
-			uint8 *animPtr = animTable[actor->previousAnimIdx];
+			uint8 *animPtr = _engine->_resources->animTable[actor->previousAnimIdx];
 
 			keyFramePassed = verifyAnimAtKeyframe(actor->animPosition, animPtr, _engine->_actor->bodyTable[actor->entity], &actor->animTimerData);
 
diff --git a/engines/twine/animations.h b/engines/twine/animations.h
index 8a356be654..3a86c08c92 100644
--- a/engines/twine/animations.h
+++ b/engines/twine/animations.h
@@ -29,9 +29,6 @@
 
 namespace TwinE {
 
-/** Total number of animations allowed in the game */
-#define NUM_ANIMS 600
-
 class TwinEEngine;
 
 class Animations {
@@ -64,10 +61,7 @@ private:
 public:
 	Animations(TwinEEngine *engine);
 	~Animations();
-	/** Table with all loaded animations */
-	uint8 *animTable[NUM_ANIMS]{nullptr};
-	/** Table with all loaded animations sizes */
-	uint32 animSizeTable[NUM_ANIMS]{0};
+
 	/** Current process actor index */
 	int16 currentlyProcessedActorIdx = 0;
 	/** Current actor anim extra pointer */
diff --git a/engines/twine/gamestate.cpp b/engines/twine/gamestate.cpp
index 1b25f0a965..cd3de71eb8 100644
--- a/engines/twine/gamestate.cpp
+++ b/engines/twine/gamestate.cpp
@@ -328,7 +328,7 @@ void GameState::processFoundItem(int32 item) {
 	_engine->_text->initVoxToPlay(item);
 
 	const int32 bodyAnimIdx = _engine->_animations->getBodyAnimIndex(AnimationTypes::kFoundItem);
-	uint8 *currentAnim = _engine->_animations->animTable[bodyAnimIdx];
+	uint8 *currentAnim = _engine->_resources->animTable[bodyAnimIdx];
 
 	AnimTimerDataStruct tmpAnimTimer = _engine->_scene->sceneHero->animTimerData;
 
diff --git a/engines/twine/menu.cpp b/engines/twine/menu.cpp
index 718c31dc36..f5ed258b16 100644
--- a/engines/twine/menu.cpp
+++ b/engines/twine/menu.cpp
@@ -810,7 +810,7 @@ void Menu::drawBehaviour(HeroBehaviourType behaviour, int32 angle, int16 cantDra
 	int32 boxTop = 110;
 	int32 boxBottom = 229;
 
-	uint8 *currentAnim = _engine->_animations->animTable[_engine->_actor->heroAnimIdx[behaviour]];
+	uint8 *currentAnim = _engine->_resources->animTable[_engine->_actor->heroAnimIdx[behaviour]];
 	int32 currentAnimState = behaviourAnimState[behaviour];
 
 	if (_engine->_animations->setModelAnimation(currentAnimState, currentAnim, behaviourEntity, &behaviourAnimData[behaviour])) {
@@ -861,16 +861,16 @@ void Menu::drawBehaviourMenu(int32 angle) {
 	drawBox(100, 100, 550, 290);
 	_engine->_interface->drawTransparentBox(101, 101, 549, 289, 2);
 
-	_engine->_animations->setAnimAtKeyframe(behaviourAnimState[kNormal], _engine->_animations->animTable[_engine->_actor->heroAnimIdx[kNormal]], behaviourEntity, &behaviourAnimData[kNormal]);
+	_engine->_animations->setAnimAtKeyframe(behaviourAnimState[kNormal], _engine->_resources->animTable[_engine->_actor->heroAnimIdx[kNormal]], behaviourEntity, &behaviourAnimData[kNormal]);
 	drawBehaviour(kNormal, angle, 0);
 
-	_engine->_animations->setAnimAtKeyframe(behaviourAnimState[kAthletic], _engine->_animations->animTable[_engine->_actor->heroAnimIdx[kAthletic]], behaviourEntity, &behaviourAnimData[kAthletic]);
+	_engine->_animations->setAnimAtKeyframe(behaviourAnimState[kAthletic], _engine->_resources->animTable[_engine->_actor->heroAnimIdx[kAthletic]], behaviourEntity, &behaviourAnimData[kAthletic]);
 	drawBehaviour(kAthletic, angle, 0);
 
-	_engine->_animations->setAnimAtKeyframe(behaviourAnimState[kAggressive], _engine->_animations->animTable[_engine->_actor->heroAnimIdx[kAggressive]], behaviourEntity, &behaviourAnimData[kAggressive]);
+	_engine->_animations->setAnimAtKeyframe(behaviourAnimState[kAggressive], _engine->_resources->animTable[_engine->_actor->heroAnimIdx[kAggressive]], behaviourEntity, &behaviourAnimData[kAggressive]);
 	drawBehaviour(kAggressive, angle, 0);
 
-	_engine->_animations->setAnimAtKeyframe(behaviourAnimState[kDiscrete], _engine->_animations->animTable[_engine->_actor->heroAnimIdx[kDiscrete]], behaviourEntity, &behaviourAnimData[kDiscrete]);
+	_engine->_animations->setAnimAtKeyframe(behaviourAnimState[kDiscrete], _engine->_resources->animTable[_engine->_actor->heroAnimIdx[kDiscrete]], behaviourEntity, &behaviourAnimData[kDiscrete]);
 	drawBehaviour(kDiscrete, angle, 0);
 
 	drawInfoMenu(100, 300);
@@ -904,7 +904,7 @@ void Menu::processBehaviourMenu() {
 
 	HeroBehaviourType tmpHeroBehaviour = _engine->_actor->heroBehaviour;
 
-	_engine->_animations->setAnimAtKeyframe(behaviourAnimState[_engine->_actor->heroBehaviour], _engine->_animations->animTable[_engine->_actor->heroAnimIdx[_engine->_actor->heroBehaviour]], behaviourEntity, &behaviourAnimData[_engine->_actor->heroBehaviour]);
+	_engine->_animations->setAnimAtKeyframe(behaviourAnimState[_engine->_actor->heroBehaviour], _engine->_resources->animTable[_engine->_actor->heroAnimIdx[_engine->_actor->heroBehaviour]], behaviourEntity, &behaviourAnimData[_engine->_actor->heroBehaviour]);
 
 	int32 tmpTime = _engine->lbaTime;
 
@@ -930,7 +930,7 @@ void Menu::processBehaviourMenu() {
 			drawBehaviour(tmpHeroBehaviour, _engine->_scene->sceneHero->angle, 1);
 			tmpHeroBehaviour = _engine->_actor->heroBehaviour;
 			_engine->_movements->setActorAngleSafe(_engine->_scene->sceneHero->angle, _engine->_scene->sceneHero->angle - 256, 50, &moveMenu);
-			_engine->_animations->setAnimAtKeyframe(behaviourAnimState[_engine->_actor->heroBehaviour], _engine->_animations->animTable[_engine->_actor->heroAnimIdx[_engine->_actor->heroBehaviour]], behaviourEntity, &behaviourAnimData[_engine->_actor->heroBehaviour]);
+			_engine->_animations->setAnimAtKeyframe(behaviourAnimState[_engine->_actor->heroBehaviour], _engine->_resources->animTable[_engine->_actor->heroAnimIdx[_engine->_actor->heroBehaviour]], behaviourEntity, &behaviourAnimData[_engine->_actor->heroBehaviour]);
 		}
 
 		drawBehaviour(_engine->_actor->heroBehaviour, -1, 1);
diff --git a/engines/twine/redraw.cpp b/engines/twine/redraw.cpp
index 965d1f0261..638afdb5ee 100644
--- a/engines/twine/redraw.cpp
+++ b/engines/twine/redraw.cpp
@@ -353,7 +353,7 @@ void Redraw::redrawEngineActions(int32 bgRedraw) { // fullRedraw
 			// Drawing actors
 			if (flags < 0xC00) {
 				if (!flags) {
-					_engine->_animations->setModelAnimation(actor2->animPosition, _engine->_animations->animTable[actor2->previousAnimIdx], _engine->_actor->bodyTable[actor2->entity], &actor2->animTimerData);
+					_engine->_animations->setModelAnimation(actor2->animPosition, _engine->_resources->animTable[actor2->previousAnimIdx], _engine->_actor->bodyTable[actor2->entity], &actor2->animTimerData);
 
 					if (!_engine->_renderer->renderIsoModel(actor2->x - _engine->_grid->cameraX, actor2->y - _engine->_grid->cameraY, actor2->z - _engine->_grid->cameraZ, 0, actor2->angle, 0, _engine->_actor->bodyTable[actor2->entity])) {
 						if (renderLeft < 0) {
diff --git a/engines/twine/resources.cpp b/engines/twine/resources.cpp
index 5314bb3491..de4ac83cab 100644
--- a/engines/twine/resources.cpp
+++ b/engines/twine/resources.cpp
@@ -61,7 +61,7 @@ void Resources::preloadAnimations() {
 	}
 	debug("preload %i animations", numEntries);
 	for (int32 i = 0; i < numEntries; i++) {
-		_engine->_animations->animSizeTable[i] = _engine->_hqrdepack->hqrGetallocEntry(&_engine->_animations->animTable[i], Resources::HQR_ANIM_FILE, i);
+		animSizeTable[i] = _engine->_hqrdepack->hqrGetallocEntry(&animTable[i], Resources::HQR_ANIM_FILE, i);
 	}
 }
 
diff --git a/engines/twine/resources.h b/engines/twine/resources.h
index c4325cade5..6e849c90d1 100644
--- a/engines/twine/resources.h
+++ b/engines/twine/resources.h
@@ -95,6 +95,9 @@ namespace TwinE {
 #define SPRITEHQR_DIAG_BUBBLE_RIGHT 90
 #define SPRITEHQR_DIAG_BUBBLE_LEFT 91
 
+/** Total number of animations allowed in the game */
+#define NUM_ANIMS 600
+
 class TwinEEngine;
 class Resources {
 private:
@@ -121,6 +124,11 @@ public:
 	/** Table with all loaded sprite sizes */
 	uint32 spriteSizeTable[NUM_SPRITES] {0};
 
+	/** Table with all loaded animations */
+	uint8 *animTable[NUM_ANIMS]{nullptr};
+	/** Table with all loaded animations sizes */
+	uint32 animSizeTable[NUM_ANIMS]{0};
+
 	/** Initialize resource pointers */
 	void initResources();
 


Commit: 7d2991aa0b1ac8a46f611ac05f2438e31258c145
    https://github.com/scummvm/scummvm/commit/7d2991aa0b1ac8a46f611ac05f2438e31258c145
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2020-10-27T17:14:05+01:00

Commit Message:
TWINE: moved more cached resources into the Resources class

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


diff --git a/engines/twine/resources.cpp b/engines/twine/resources.cpp
index de4ac83cab..649072718f 100644
--- a/engines/twine/resources.cpp
+++ b/engines/twine/resources.cpp
@@ -72,7 +72,7 @@ void Resources::preloadSamples() {
 	}
 	debug("preload %i samples", numEntries);
 	for (int32 i = 0; i < numEntries; i++) {
-		_engine->_sound->samplesSizeTable[i] = _engine->_hqrdepack->hqrGetallocEntry(&_engine->_sound->samplesTable[i], Resources::HQR_SAMPLES_FILE, i);
+		samplesSizeTable[i] = _engine->_hqrdepack->hqrGetallocEntry(&samplesTable[i], Resources::HQR_SAMPLES_FILE, i);
 	}
 }
 
@@ -91,7 +91,7 @@ void Resources::initResources() {
 	// Menu and in-game palette
 	initPalettes();
 
-	if (_engine->_hqrdepack->hqrGetallocEntry(&_engine->_text->fontPtr, Resources::HQR_RESS_FILE, RESSHQR_LBAFONT) == 0) {
+	if (_engine->_hqrdepack->hqrGetallocEntry(&fontPtr, Resources::HQR_RESS_FILE, RESSHQR_LBAFONT) == 0) {
 		error("Failed to load font");
 	}
 
diff --git a/engines/twine/resources.h b/engines/twine/resources.h
index 6e849c90d1..2f6136d040 100644
--- a/engines/twine/resources.h
+++ b/engines/twine/resources.h
@@ -98,6 +98,9 @@ namespace TwinE {
 /** Total number of animations allowed in the game */
 #define NUM_ANIMS 600
 
+/** Total number of samples allowed in the game */
+#define NUM_SAMPLES 243
+
 class TwinEEngine;
 class Resources {
 private:
@@ -129,6 +132,14 @@ public:
 	/** Table with all loaded animations sizes */
 	uint32 animSizeTable[NUM_ANIMS]{0};
 
+	/** Table with all loaded samples */
+	uint8 *samplesTable[NUM_SAMPLES]{nullptr};
+	/** Table with all loaded samples sizes */
+	uint32 samplesSizeTable[NUM_SAMPLES]{0};
+
+	/** Font buffer pointer */
+	uint8 *fontPtr = nullptr;
+
 	/** Initialize resource pointers */
 	void initResources();
 
diff --git a/engines/twine/sound.cpp b/engines/twine/sound.cpp
index d5bffbd96f..6865297106 100644
--- a/engines/twine/sound.cpp
+++ b/engines/twine/sound.cpp
@@ -94,6 +94,8 @@ void Sound::playSample(int32 index, int32 frequency, int32 repeat, int32 x, int3
 	if (channelIdx == -1) {
 		return;
 	}
+
+	// TODO: use Resources class
 	uint8 *sampPtr;
 	int32 sampSize = _engine->_hqrdepack->hqrGetallocEntry(&sampPtr, Resources::HQR_SAMPLES_FILE, index);
 	if (actorIdx != -1) {
diff --git a/engines/twine/sound.h b/engines/twine/sound.h
index 687d5f4e70..e0fcdeb983 100644
--- a/engines/twine/sound.h
+++ b/engines/twine/sound.h
@@ -28,8 +28,6 @@
 
 namespace TwinE {
 
-/** Total number of samples allowed in the game */
-#define NUM_SAMPLES 243
 #define NUM_CHANNELS 32
 
 class TwinEEngine;
@@ -52,10 +50,6 @@ public:
 	Sound(TwinEEngine *engine);
 
 	bool isChannelPlaying(int32 channel);
-	/** Table with all loaded samples */
-	uint8 *samplesTable[NUM_SAMPLES]{nullptr};
-	/** Table with all loaded samples sizes */
-	uint32 samplesSizeTable[NUM_SAMPLES]{0};
 
 	/**
 	 * Sample volume
diff --git a/engines/twine/text.cpp b/engines/twine/text.cpp
index 9a78c3f8ae..78d1471266 100644
--- a/engines/twine/text.cpp
+++ b/engines/twine/text.cpp
@@ -68,7 +68,7 @@ void Text::initVoxBank(int32 bankIdx) {
 bool Text::initVoxToPlay(int32 index) { // setVoxFileAtDigit
 	int32 currIdx = 0;
 
-	int16 *localOrderBuf = (int16 *)dialOrderPtr;
+	const int16 *localOrderBuf = (const int16 *)dialOrderPtr;
 
 	voxHiddenIndex = 0;
 	hasHiddenVox = false;
@@ -166,7 +166,7 @@ void Text::drawCharacter(int32 x, int32 y, uint8 character) { // drawCharacter
 	int32 tempX;
 	int32 tempY;
 
-	data = fontPtr + *((int16 *)(fontPtr + character * 4));
+	data = _engine->_resources->fontPtr + *((const int16 *)(_engine->_resources->fontPtr + character * 4));
 
 	dialTextSize = sizeX = *(data++);
 	sizeY = *(data++);
@@ -251,8 +251,10 @@ void Text::drawCharacterShadow(int32 x, int32 y, uint8 character, int32 color) {
 }
 
 void Text::drawText(int32 x, int32 y, const char *dialogue) { // Font
-	if (fontPtr == 0)                                         // if the font is not defined
+	                                                          // if the font is not defined
+	if (_engine->_resources->fontPtr == nullptr) {
 		return;
+	}
 
 	do {
 		const uint8 currChar = (uint8) * (dialogue++); // read the next char from the string
@@ -264,7 +266,7 @@ void Text::drawText(int32 x, int32 y, const char *dialogue) { // Font
 		if (currChar == ' ') {
 			x += dialCharSpace;
 		} else {
-			dialTextSize = *(fontPtr + (*((int16 *)(fontPtr + currChar * 4)))); // get the length of the character
+			dialTextSize = getCharWidth(currChar);
 			drawCharacter(x, y, currChar);                                      // draw the character on screen
 			// add the length of the space between 2 characters
 			x += dialSpaceBetween;
@@ -286,7 +288,7 @@ int32 Text::getTextSize(const char *dialogue) { // SizeFont
 			dialTextSize += dialCharSpace;
 		} else {
 			dialTextSize += dialSpaceBetween;
-			dialTextSize += *(fontPtr + *((int16 *)(fontPtr + currChar * 4)));
+			dialTextSize += getCharWidth(currChar);
 		}
 	} while (1);
 
@@ -508,10 +510,8 @@ void Text::printText10Sub2() {
 	};
 }
 
-void Text::TEXT_GetLetterSize(uint8 character, int32 *pLetterWidth, int32 *pLetterHeight, uint8 *pFont) { // TEXT_GetLetterSize
-	uint8 *temp = (uint8 *)(pFont + *((int16 *)(pFont + character * 4)));
-	*pLetterWidth = *(temp);
-	*pLetterHeight = *(temp + 1);
+int32 Text::getCharWidth(uint8 chr) const {
+	return *(_engine->_resources->fontPtr + *((const int16 *)(_engine->_resources->fontPtr + chr * 4)));
 }
 
 // TODO: refactor this code
@@ -551,9 +551,7 @@ int Text::printText10() {
 
 	printText8Sub4(TEXT_CurrentLetterX, TEXT_CurrentLetterY, *printText8Ptr2);
 	printText10Sub2();
-	int32 charWidth;
-	int32 charHeight;
-	TEXT_GetLetterSize(*printText8Ptr2, &charWidth, &charHeight, (uint8 *)fontPtr);
+	int8 charWidth = getCharWidth(*printText8Ptr2);
 
 	if (*printText8Ptr2 != ' ') {
 		TEXT_CurrentLetterX += charWidth + 2;
@@ -568,8 +566,9 @@ int Text::printText10() {
 	// next character
 	printText8Ptr2++;
 
-	if (*printText8Ptr2 != '\0')
+	if (*printText8Ptr2 != '\0') {
 		return 1;
+	}
 
 	TEXT_CurrentLetterY += 38;
 	TEXT_CurrentLetterX = dialTextBoxLeft + 8;
@@ -664,12 +663,6 @@ void Text::drawTextFullscreen(int32 index) { // printTextFullScreen
 	_engine->_interface->loadClip();
 }
 
-void Text::setFont(uint8 *font, int32 spaceBetween, int32 charSpace) {
-	fontPtr = font;
-	dialCharSpace = charSpace;
-	dialSpaceBetween = spaceBetween;
-}
-
 void Text::setFontParameters(int32 spaceBetween, int32 charSpace) {
 	dialSpaceBetween = spaceBetween;
 	dialCharSpace = charSpace;
@@ -697,8 +690,8 @@ bool Text::getText(int32 index) { // findString
 	int32 currIdx = 0;
 	int32 orderIdx = 0;
 
-	int16 *localTextBuf = (int16 *)dialTextPtr;
-	int16 *localOrderBuf = (int16 *)dialOrderPtr;
+	const int16 *localTextBuf = (const int16 *)dialTextPtr;
+	const int16 *localOrderBuf = (const int16 *)dialOrderPtr;
 
 	int32 numEntries = numDialTextEntries;
 
@@ -729,8 +722,7 @@ bool Text::getText(int32 index) { // findString
 }
 
 void Text::copyText(const char *src, char *dst, int32 size) { // copyStringToString
-	int32 i;
-	for (i = 0; i < size; i++) {
+	for (int32 i = 0; i < size; i++) {
 		*(dst++) = *(src++);
 	}
 }
diff --git a/engines/twine/text.h b/engines/twine/text.h
index eac358c0a6..c0c2541557 100644
--- a/engines/twine/text.h
+++ b/engines/twine/text.h
@@ -59,7 +59,7 @@ private:
 	// draw next page arrow polygon
 	void printText10Sub();
 	void printText10Sub2();
-	void TEXT_GetLetterSize(uint8 character, int32 *pLetterWidth, int32 *pLetterHeight, uint8 *pFont);
+	int32 getCharWidth(uint8 chr) const;
 	/**
 	 * Copy dialogue text
 	 * @param src source text buffer
@@ -109,9 +109,6 @@ public:
 	/** Current dialogue text pointer */
 	char *currDialTextPtr = nullptr;
 
-	/** Font buffer pointer */
-	uint8 *fontPtr = nullptr;
-
 	/** Dialogue text size */
 	int32 dialTextSize = 0;
 	/** Pixel size between dialogue text */
@@ -180,8 +177,6 @@ public:
 	void initText(int32 index);
 	int printText10();
 
-	void setFont(uint8 *font, int32 spaceBetween, int32 charSpace);
-
 	/**
 	 * Set font type parameters
 	 * @param spaceBetween number in pixels of space between characters


Commit: c34239c7fc10814e364616bf068261e1d93cbca4
    https://github.com/scummvm/scummvm/commit/c34239c7fc10814e364616bf068261e1d93cbca4
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2020-10-27T17:14:05+01:00

Commit Message:
TWINE: moved latest cache entries into Resources class

Changed paths:
    engines/twine/actor.cpp
    engines/twine/collision.cpp
    engines/twine/extra.cpp
    engines/twine/redraw.cpp
    engines/twine/resources.cpp
    engines/twine/resources.h
    engines/twine/scene.h


diff --git a/engines/twine/actor.cpp b/engines/twine/actor.cpp
index 808b9ccf3b..9bf763df40 100644
--- a/engines/twine/actor.cpp
+++ b/engines/twine/actor.cpp
@@ -159,7 +159,7 @@ 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->_scene->spriteBoundingBoxPtr + localActor->sprite * 16 + 4);
+		const int16 *ptr = (const int16 *)(_engine->_resources->spriteBoundingBoxPtr + localActor->sprite * 16 + 4);
 
 		localActor->entity = localActor->sprite;
 		localActor->boudingBox.x.bottomLeft = *(ptr++);
diff --git a/engines/twine/collision.cpp b/engines/twine/collision.cpp
index 55ad89e850..60e33cb121 100644
--- a/engines/twine/collision.cpp
+++ b/engines/twine/collision.cpp
@@ -29,6 +29,7 @@
 #include "twine/grid.h"
 #include "twine/movements.h"
 #include "twine/renderer.h"
+#include "twine/resources.h"
 #include "twine/scene.h"
 #include "twine/twine.h"
 
@@ -477,7 +478,7 @@ void Collision::stopFalling() { // ReceptionObj()
 }
 
 int32 Collision::checkExtraCollisionWithActors(ExtraListStruct *extra, int32 actorIdx) {
-	int16 *spriteBounding = (int16 *)(_engine->_scene->spriteBoundingBoxPtr + extra->info0 * 16 + 4);
+	int16 *spriteBounding = (int16 *)(_engine->_resources->spriteBoundingBoxPtr + extra->info0 * 16 + 4);
 
 	int32 xLeft = *(spriteBounding++) + extra->x;
 	int32 xRight = *(spriteBounding++) + extra->x;
@@ -539,7 +540,7 @@ int32 Collision::checkExtraCollisionWithBricks(int32 X, int32 Y, int32 Z, int32
 }
 
 int32 Collision::checkExtraCollisionWithExtra(ExtraListStruct *extra, int32 extraIdx) {
-	int16 *spriteBounding = (int16 *)(_engine->_scene->spriteBoundingBoxPtr + extra->info0 * 16 + 4);
+	int16 *spriteBounding = (int16 *)(_engine->_resources->spriteBoundingBoxPtr + extra->info0 * 16 + 4);
 
 	int32 xLeft = *(spriteBounding++) + extra->x;
 	int32 xRight = *(spriteBounding++) + extra->x;
@@ -554,7 +555,7 @@ int32 Collision::checkExtraCollisionWithExtra(ExtraListStruct *extra, int32 extr
 		ExtraListStruct *extraTest = &_engine->_extra->extraList[i];
 		if (i != extraIdx && extraTest->info0 != -1) {
 			//            int16 * spriteBoundingTest;
-			//	        spriteBoundingTest = (int16*)(_engine->_scene->spriteBoundingBoxPtr + extraTest->info0 * 16 + 4);
+			//	        spriteBoundingTest = (int16*)(_engine->_resources->spriteBoundingBoxPtr + extraTest->info0 * 16 + 4);
 
 			int32 xLeftTest = *(spriteBounding++) + extraTest->x;
 			int32 xRightTest = *(spriteBounding++) + extraTest->x;
diff --git a/engines/twine/extra.cpp b/engines/twine/extra.cpp
index f1320936ab..44433020ac 100644
--- a/engines/twine/extra.cpp
+++ b/engines/twine/extra.cpp
@@ -842,9 +842,7 @@ void Extra::processExtras() {
 				}
 
 				if (process) {
-					int16 *spriteBounds;
-
-					spriteBounds = (int16 *)(_engine->_scene->spriteBoundingBoxPtr + extra->info0 * 16 + 8);
+					const int16 *spriteBounds = (const int16 *)(_engine->_resources->spriteBoundingBoxPtr + extra->info0 * 16 + 8);
 					extra->y = (_engine->_collision->collisionY << 8) + 0x100 - *(spriteBounds);
 					extra->type &= 0xFFED;
 					continue;
diff --git a/engines/twine/redraw.cpp b/engines/twine/redraw.cpp
index 638afdb5ee..4536778ff5 100644
--- a/engines/twine/redraw.cpp
+++ b/engines/twine/redraw.cpp
@@ -408,7 +408,7 @@ void Redraw::redrawEngineActions(int32 bgRedraw) { // fullRedraw
 				_engine->_renderer->projectPositionOnScreen(shadow.x - _engine->_grid->cameraX, shadow.y - _engine->_grid->cameraY, shadow.z - _engine->_grid->cameraZ);
 
 				int32 spriteWidth, spriteHeight;
-				_engine->_grid->getSpriteSize(shadow.field_A, &spriteWidth, &spriteHeight, _engine->_scene->spriteShadowPtr);
+				_engine->_grid->getSpriteSize(shadow.field_A, &spriteWidth, &spriteHeight, _engine->_resources->spriteShadowPtr);
 
 				// calculate sprite size and position on screen
 				renderLeft = _engine->_renderer->projPosX - (spriteWidth / 2);
@@ -419,7 +419,7 @@ void Redraw::redrawEngineActions(int32 bgRedraw) { // fullRedraw
 				_engine->_interface->setClip(renderLeft, renderTop, renderRight, renderBottom);
 
 				if (_engine->_interface->textWindowLeft <= _engine->_interface->textWindowRight && _engine->_interface->textWindowTop <= _engine->_interface->textWindowBottom) {
-					_engine->_grid->drawSprite(shadow.field_A, renderLeft, renderTop, _engine->_scene->spriteShadowPtr);
+					_engine->_grid->drawSprite(shadow.field_A, renderLeft, renderTop, _engine->_resources->spriteShadowPtr);
 				}
 
 				const int32 tmpX = (shadow.x + 0x100) >> 9;
@@ -448,8 +448,8 @@ void Redraw::redrawEngineActions(int32 bgRedraw) { // fullRedraw
 				_engine->_grid->getSpriteSize(0, &spriteWidth, &spriteHeight, spritePtr);
 
 				// calculate sprite position on screen
-				renderLeft = _engine->_renderer->projPosX + *((int16 *)(_engine->_scene->spriteBoundingBoxPtr + (actor2->entity * 16)));
-				renderTop = _engine->_renderer->projPosY + *((int16 *)(_engine->_scene->spriteBoundingBoxPtr + (actor2->entity * 16) + 2));
+				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));
 				renderRight = renderLeft + spriteWidth;
 				renderBottom = renderTop + spriteHeight;
 
@@ -500,8 +500,8 @@ 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->_scene->spriteBoundingBoxPtr + extra->info0 * 16);
-					renderTop = _engine->_renderer->projPosY + *(const int16 *)(_engine->_scene->spriteBoundingBoxPtr + extra->info0 * 16 + 2);
+					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);
 					renderRight = renderLeft + spriteWidth;
 					renderBottom = renderTop + spriteHeight;
 
@@ -562,14 +562,13 @@ void Redraw::redrawEngineActions(int32 bgRedraw) { // fullRedraw
 			// process overlay type
 			switch (overlay->type) {
 			case koSprite: {
-				int16 offsetX, offsetY;
 				int32 spriteWidth, spriteHeight;
 				uint8 *spritePtr = _engine->_resources->spriteTable[overlay->info0];
 
 				_engine->_grid->getSpriteSize(0, &spriteWidth, &spriteHeight, spritePtr);
 
-				offsetX = *((const int16 *)(_engine->_scene->spriteBoundingBoxPtr + (overlay->info0 * 16)));
-				offsetY = *((const int16 *)(_engine->_scene->spriteBoundingBoxPtr + (overlay->info0 * 16) + 2));
+				const int16 offsetX = *((const int16 *)(_engine->_resources->spriteBoundingBoxPtr + (overlay->info0 * 16)));
+				const int16 offsetY = *((const int16 *)(_engine->_resources->spriteBoundingBoxPtr + (overlay->info0 * 16) + 2));
 
 				renderLeft = offsetX + overlay->x;
 				renderTop = offsetY + overlay->y;
diff --git a/engines/twine/resources.cpp b/engines/twine/resources.cpp
index 649072718f..1a24d5aeda 100644
--- a/engines/twine/resources.cpp
+++ b/engines/twine/resources.cpp
@@ -99,11 +99,11 @@ void Resources::initResources() {
 	_engine->_text->setFontColor(14);
 	_engine->_text->setTextCrossColor(136, 143, 2);
 
-	if (_engine->_hqrdepack->hqrGetallocEntry(&_engine->_scene->spriteShadowPtr, Resources::HQR_RESS_FILE, RESSHQR_SPRITESHADOW) == 0) {
+	if (_engine->_hqrdepack->hqrGetallocEntry(&spriteShadowPtr, Resources::HQR_RESS_FILE, RESSHQR_SPRITESHADOW) == 0) {
 		error("Failed to load sprite shadow");
 	}
 
-	if (_engine->_hqrdepack->hqrGetallocEntry(&_engine->_scene->spriteBoundingBoxPtr, Resources::HQR_RESS_FILE, RESSHQR_SPRITEBOXDATA) == 0) {
+	if (_engine->_hqrdepack->hqrGetallocEntry(&spriteBoundingBoxPtr, Resources::HQR_RESS_FILE, RESSHQR_SPRITEBOXDATA) == 0) {
 		error("Failed to load actors bounding box data");
 	}
 
diff --git a/engines/twine/resources.h b/engines/twine/resources.h
index 2f6136d040..36d60e8e4f 100644
--- a/engines/twine/resources.h
+++ b/engines/twine/resources.h
@@ -140,6 +140,9 @@ public:
 	/** Font buffer pointer */
 	uint8 *fontPtr = nullptr;
 
+	uint8 *spriteShadowPtr = nullptr;
+	uint8 *spriteBoundingBoxPtr = nullptr;
+
 	/** Initialize resource pointers */
 	void initResources();
 
diff --git a/engines/twine/scene.h b/engines/twine/scene.h
index 383cad00ca..87c940dd9b 100644
--- a/engines/twine/scene.h
+++ b/engines/twine/scene.h
@@ -251,9 +251,6 @@ public:
 	int32 currentSceneIdx = LBA1SceneId::Citadel_Island_Prison;
 	int32 previousSceneIdx = LBA1SceneId::Citadel_Island_Prison;
 
-	uint8 *spriteShadowPtr = nullptr;
-	uint8 *spriteBoundingBoxPtr = nullptr;
-
 	int32 currentGameOverScene = 0;
 	int32 alphaLight = 0;
 	int32 betaLight = 0;


Commit: 1b143bca5cb3544df3614499e5710a3a815ec969
    https://github.com/scummvm/scummvm/commit/1b143bca5cb3544df3614499e5710a3a815ec969
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2020-10-27T17:14:05+01:00

Commit Message:
TWINE: missing mean breaks

Changed paths:
    engines/twine/menu.cpp


diff --git a/engines/twine/menu.cpp b/engines/twine/menu.cpp
index f5ed258b16..4044002007 100644
--- a/engines/twine/menu.cpp
+++ b/engines/twine/menu.cpp
@@ -563,6 +563,9 @@ int32 Menu::processMenu(int16 *menuSettings) {
 
 		// draw plasma effect for the current selected button
 		drawButton(menuSettings, true);
+		if (_engine->shouldQuit()) {
+			break;
+		}
 		// TODO: update volume settings
 		_engine->_system->delayMillis(10);
 	} while (!_engine->_input->toggleActionIfActive(TwinEActionType::UIEnter));
@@ -668,6 +671,9 @@ int32 Menu::optionsMenu() {
 		default:
 			break;
 		}
+		if (_engine->shouldQuit()) {
+			break;
+		}
 	} while (ret != 1);
 
 	return 0;


Commit: 8626b873ce9db7a82deec73d3a12858f74989f7d
    https://github.com/scummvm/scummvm/commit/8626b873ce9db7a82deec73d3a12858f74989f7d
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2020-10-27T17:14:05+01:00

Commit Message:
TWINE: use the cached sound samples

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


diff --git a/engines/twine/resources.cpp b/engines/twine/resources.cpp
index 1a24d5aeda..6d021db680 100644
--- a/engines/twine/resources.cpp
+++ b/engines/twine/resources.cpp
@@ -73,6 +73,15 @@ void Resources::preloadSamples() {
 	debug("preload %i samples", numEntries);
 	for (int32 i = 0; i < numEntries; i++) {
 		samplesSizeTable[i] = _engine->_hqrdepack->hqrGetallocEntry(&samplesTable[i], Resources::HQR_SAMPLES_FILE, i);
+		if (samplesSizeTable[i] == 0) {
+			warning("Failed to load sample %i", i);
+			continue;
+		}
+		// Fix incorrect sample files first byte
+		if (*samplesTable[i] != 'C') {
+			debug(0, "Sample %i has incorrect magic id", i);
+			*samplesTable[i] = 'C';
+		}
 	}
 }
 
diff --git a/engines/twine/sound.cpp b/engines/twine/sound.cpp
index 6865297106..a8217a6619 100644
--- a/engines/twine/sound.cpp
+++ b/engines/twine/sound.cpp
@@ -95,16 +95,16 @@ void Sound::playSample(int32 index, int32 frequency, int32 repeat, int32 x, int3
 		return;
 	}
 
-	// TODO: use Resources class
-	uint8 *sampPtr;
-	int32 sampSize = _engine->_hqrdepack->hqrGetallocEntry(&sampPtr, Resources::HQR_SAMPLES_FILE, index);
+
 	if (actorIdx != -1) {
 		setSamplePosition(channelIdx, x, y, z);
 		// save the actor index for the channel so we can check the position
 		samplesPlayingActors[channelIdx] = actorIdx;
 	}
 
-	playSample(channelIdx, index, sampPtr, sampSize, repeat, Resources::HQR_SAMPLES_FILE);
+	uint8 *sampPtr = _engine->_resources->samplesTable[index];
+	int32 sampSize = _engine->_resources->samplesSizeTable[index];
+	playSample(channelIdx, index, sampPtr, sampSize, repeat, Resources::HQR_SAMPLES_FILE, DisposeAfterUse::NO);
 }
 
 void Sound::playVoxSample(int32 index) {
@@ -129,15 +129,11 @@ void Sound::playVoxSample(int32 index) {
 	playSample(channelIdx, index, sampPtr, sampSize, 1, _engine->_text->currentVoxBankFile.c_str());
 }
 
-bool Sound::playSample(int channelIdx, int index, uint8 *sampPtr, int32 sampSize, int32 loop, const char *name) {
-	// Fix incorrect sample files first byte
-	if (*sampPtr != 'C') {
-		*sampPtr = 'C';
-	}
-	Common::MemoryReadStream *stream = new Common::MemoryReadStream(sampPtr, sampSize, DisposeAfterUse::YES);
+bool Sound::playSample(int channelIdx, int index, uint8 *sampPtr, int32 sampSize, int32 loop, const char *name, DisposeAfterUse::Flag disposeFlag) {
+	Common::MemoryReadStream *stream = new Common::MemoryReadStream(sampPtr, sampSize, disposeFlag);
 	Audio::SeekableAudioStream *audioStream = Audio::makeVOCStream(stream, DisposeAfterUse::YES);
 	if (audioStream == nullptr) {
-		warning("Failed to create voc audio stream for %s", name);
+		warning("Failed to create audio stream for %s", name);
 		return false;
 	}
 	_engine->_system->getMixer()->playStream(Audio::Mixer::kPlainSoundType, &samplesPlaying[channelIdx], audioStream, index);
diff --git a/engines/twine/sound.h b/engines/twine/sound.h
index e0fcdeb983..699a071110 100644
--- a/engines/twine/sound.h
+++ b/engines/twine/sound.h
@@ -25,6 +25,7 @@
 
 #include "audio/mixer.h"
 #include "common/scummsys.h"
+#include "common/types.h"
 
 namespace TwinE {
 
@@ -44,7 +45,7 @@ private:
 	/** Samples playing at a actors position */
 	int32 samplesPlayingActors[NUM_CHANNELS]{0};
 
-	bool playSample(int channelIdx, int index, uint8 *sampPtr, int32 sampSize, int32 loop, const char *name);
+	bool playSample(int channelIdx, int index, uint8 *sampPtr, int32 sampSize, int32 loop, const char *name, DisposeAfterUse::Flag disposeFlag = DisposeAfterUse::YES);
 
 public:
 	Sound(TwinEEngine *engine);


Commit: 3b0b130a0ad3246bb2e366bae1b9656ed5afed90
    https://github.com/scummvm/scummvm/commit/3b0b130a0ad3246bb2e366bae1b9656ed5afed90
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2020-10-27T17:14:05+01:00

Commit Message:
TWINE: plug memory leaks

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


diff --git a/engines/twine/resources.cpp b/engines/twine/resources.cpp
index 6d021db680..253e753ccc 100644
--- a/engines/twine/resources.cpp
+++ b/engines/twine/resources.cpp
@@ -21,6 +21,7 @@
  */
 
 #include "twine/resources.h"
+#include "common/util.h"
 #include "twine/animations.h"
 #include "twine/scene.h"
 #include "twine/screens.h"
@@ -29,6 +30,24 @@
 
 namespace TwinE {
 
+Resources::~Resources() {
+	for (size_t i = 0; i < ARRAYSIZE(inventoryTable); ++i) {
+		free(inventoryTable[i]);
+	}
+	for (size_t i = 0; i < ARRAYSIZE(spriteTable); ++i) {
+		free(spriteTable[i]);
+	}
+	for (size_t i = 0; i < ARRAYSIZE(animTable); ++i) {
+		free(animTable[i]);
+	}
+	for (size_t i = 0; i < ARRAYSIZE(samplesTable); ++i) {
+		free(samplesTable[i]);
+	}
+	free(fontPtr);
+	free(spriteShadowPtr);
+	free(spriteBoundingBoxPtr);
+}
+
 void Resources::initPalettes() {
 	// Init standard palette
 	_engine->_hqrdepack->hqrGetallocEntry(&_engine->_screens->mainPalette, Resources::HQR_RESS_FILE, RESSHQR_MAINPAL);
diff --git a/engines/twine/resources.h b/engines/twine/resources.h
index 36d60e8e4f..752e10000a 100644
--- a/engines/twine/resources.h
+++ b/engines/twine/resources.h
@@ -117,6 +117,8 @@ private:
 
 public:
 	Resources(TwinEEngine *engine) : _engine(engine) {}
+	~Resources();
+
 	/** Table with all loaded samples */
 	uint8 *inventoryTable[NUM_INVENTORY_ITEMS] {nullptr};
 	/** Table with all loaded samples sizes */


Commit: 26c6a63ac1860f00542c5a426b416c2789a9df19
    https://github.com/scummvm/scummvm/commit/26c6a63ac1860f00542c5a426b416c2789a9df19
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2020-10-27T17:14:05+01:00

Commit Message:
TWINE: plug memory leaks

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


diff --git a/engines/twine/grid.cpp b/engines/twine/grid.cpp
index 28ce2a8b0d..fe0a2773f6 100644
--- a/engines/twine/grid.cpp
+++ b/engines/twine/grid.cpp
@@ -40,8 +40,11 @@ Grid::Grid(TwinEEngine *engine) : _engine(engine) {
 
 Grid::~Grid() {
 	free(blockBuffer);
-	for (int32 b = 0; b < NUM_BRICKS; b++) {
-		free(brickMaskTable[b]);
+	for (int32 i = 0; i < ARRAYSIZE(brickMaskTable); i++) {
+		free(brickMaskTable[i]);
+	}
+	for (int32 i = 0; i < ARRAYSIZE(brickTable); i++) {
+		free(brickTable[i]);
 	}
 }
 
@@ -307,6 +310,9 @@ int32 Grid::loadGridBricks(int32 gridSize) {
 		if (!brickUsageTable[i]) {
 			continue;
 		}
+		if (brickTable[i]) {
+			free(brickTable[i]);
+		}
 		brickSizeTable[i] = _engine->_hqrdepack->hqrGetallocEntry(&brickTable[i], Resources::HQR_LBA_BRK_FILE, i);
 		if (brickSizeTable[i] == 0) {
 			warning("Failed to load isometric brick index %i", i);
diff --git a/engines/twine/twine.cpp b/engines/twine/twine.cpp
index 037e2ba768..b3327c8e9b 100644
--- a/engines/twine/twine.cpp
+++ b/engines/twine/twine.cpp
@@ -161,6 +161,7 @@ Common::Error TwinEEngine::run() {
 	while (!shouldQuit()) {
 		_menu->run();
 	}
+	_sound->stopSamples();
 	_music->stopTrackMusic();
 	_music->stopMidiMusic();
 	return Common::kNoError;


Commit: 1d3fa8e9507e4eab0f3b5c56c7f0e371398b5700
    https://github.com/scummvm/scummvm/commit/1d3fa8e9507e4eab0f3b5c56c7f0e371398b5700
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2020-10-27T17:14:05+01:00

Commit Message:
TWINE: fixed segfault and plug mem leak

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


diff --git a/engines/twine/actor.cpp b/engines/twine/actor.cpp
index 9bf763df40..65fd68711e 100644
--- a/engines/twine/actor.cpp
+++ b/engines/twine/actor.cpp
@@ -47,6 +47,10 @@ Actor::~Actor() {
 	free(heroEntityAGGRESSIVE);
 	free(heroEntityDISCRETE);
 	free(heroEntityPROTOPACK);
+
+	for (size_t i = 0; i < ARRAYSIZE(bodyTable); ++i) {
+		free(bodyTable[i]);
+	}
 }
 
 void Actor::restartHeroScene() {
@@ -193,6 +197,9 @@ int32 Actor::initBody(int32 bodyIdx, int32 actorIdx) {
 				int16 flag = *((uint16 *)bodyPtr3);
 
 				if (!(flag & 0x8000)) {
+					if (bodyTable[currentPositionInBodyPtrTab]) {
+						free(bodyTable[currentPositionInBodyPtrTab]);
+					}
 					_engine->_hqrdepack->hqrGetallocEntry(&bodyTable[currentPositionInBodyPtrTab], Resources::HQR_BODY_FILE, flag & 0xFFFF);
 
 					if (!bodyTable[currentPositionInBodyPtrTab]) {
diff --git a/engines/twine/actor.h b/engines/twine/actor.h
index e95760aa87..88988f9935 100644
--- a/engines/twine/actor.h
+++ b/engines/twine/actor.h
@@ -236,6 +236,35 @@ class Actor {
 private:
 	TwinEEngine* _engine;
 
+	/** Hero 3D entity for normal behaviour */
+	uint8 *heroEntityNORMAL = nullptr; // file3D0
+	int32 heroEntityNORMALSize = 0;
+	/** Hero 3D entity for athletic behaviour */
+	uint8 *heroEntityATHLETIC = nullptr; // file3D1
+	int32 heroEntityATHLETICSize = 0;
+	/** Hero 3D entity for aggressive behaviour */
+	uint8 *heroEntityAGGRESSIVE = nullptr; // file3D2
+	int32 heroEntityAGGRESSIVESize = 0;
+	/** Hero 3D entity for discrete behaviour */
+	uint8 *heroEntityDISCRETE = nullptr; // file3D3
+	int32 heroEntityDISCRETESize = 0;
+	/** Hero 3D entity for protopack behaviour */
+	uint8 *heroEntityPROTOPACK = nullptr; // file3D4
+	int32 heroEntityPROTOPACKSize = 0;
+
+	/** Actor bounding box bottom left X coordinate */
+	int16 bottomLeftX; // loadCostumeVar
+	/** Actor bounding box bottom left Y coordinate */
+	int16 bottomLeftY; // loadCostumeVar2
+	/** Actor bounding box bottom left Z coordinate */
+	int16 bottomLeftZ; // loadCostumeVar3
+	/** Actor bounding box top left X coordinate */
+	int16 topRightX; // loadCostumeVar4
+	/** Actor bounding box top left Y coordinate */
+	int16 topRightY; // loadCostumeVar5
+	/** Actor bounding box top left Z coordinate */
+	int16 topRightZ; // loadCostumeVar6
+
 	void initSpriteActor(int32 actorIdx);
 public:
 	Actor(TwinEEngine* engine);
@@ -262,22 +291,6 @@ public:
 
 	int16 cropBottomScreen = 0;
 
-	/** Hero 3D entity for normal behaviour */
-	uint8 *heroEntityNORMAL = nullptr; // file3D0
-	int32 heroEntityNORMALSize = 0;
-	/** Hero 3D entity for athletic behaviour */
-	uint8 *heroEntityATHLETIC = nullptr; // file3D1
-	int32 heroEntityATHLETICSize = 0;
-	/** Hero 3D entity for aggressive behaviour */
-	uint8 *heroEntityAGGRESSIVE = nullptr; // file3D2
-	int32 heroEntityAGGRESSIVESize = 0;
-	/** Hero 3D entity for discrete behaviour */
-	uint8 *heroEntityDISCRETE = nullptr; // file3D3
-	int32 heroEntityDISCRETESize = 0;
-	/** Hero 3D entity for protopack behaviour */
-	uint8 *heroEntityPROTOPACK = nullptr; // file3D4
-	int32 heroEntityPROTOPACKSize = 0;
-
 	/** Hero current anim for normal behaviour */
 	int16 heroAnimIdxNORMAL = 0; // TCos0Init
 	/** Hero current anim for athletic behaviour */
@@ -293,24 +306,11 @@ public:
 	int16 heroAnimIdx[4]; // TCOS
 
 	/** Actors 3D body table - size of NUM_BODIES */
-	uint8 *bodyTable[NUM_BODIES];
+	uint8 *bodyTable[NUM_BODIES]{nullptr};
 
 	/** Current position in body table */
 	int32 currentPositionInBodyPtrTab;
 
-	/** Actor bounding box bottom left X coordinate */
-	int16 bottomLeftX; // loadCostumeVar
-	/** Actor bounding box bottom left Y coordinate */
-	int16 bottomLeftY; // loadCostumeVar2
-	/** Actor bounding box bottom left Z coordinate */
-	int16 bottomLeftZ; // loadCostumeVar3
-	/** Actor bounding box top left X coordinate */
-	int16 topRightX; // loadCostumeVar4
-	/** Actor bounding box top left Y coordinate */
-	int16 topRightY; // loadCostumeVar5
-	/** Actor bounding box top left Z coordinate */
-	int16 topRightZ; // loadCostumeVar6
-
 	/** Restart hero variables while opening new scenes */
 	void restartHeroScene();
 


Commit: f9bcdaae4635c4b51dad692b9677e18968c467eb
    https://github.com/scummvm/scummvm/commit/f9bcdaae4635c4b51dad692b9677e18968c467eb
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2020-10-27T17:14:05+01:00

Commit Message:
TWINE: allow to quit from menus

Changed paths:
    engines/twine/menu.cpp


diff --git a/engines/twine/menu.cpp b/engines/twine/menu.cpp
index 4044002007..5d96bcfde1 100644
--- a/engines/twine/menu.cpp
+++ b/engines/twine/menu.cpp
@@ -100,6 +100,8 @@ enum AdvOptionsMenuType {
 	kSceneryZoom = 8
 };
 
+#define kQuitEngine -1
+
 namespace _priv {
 /** Main Menu Settings
 
@@ -367,7 +369,7 @@ void Menu::drawButtonGfx(int32 width, int32 topheight, int32 buttonId, int32 tex
 				newWidth = _engine->_screens->crossDot(left, right, Audio::Mixer::kMaxMixerVolume, volume);
 				break;
 			}
-			};
+			}
 
 			processPlasmaEffect(left, top, 80);
 			if (!(_engine->getRandomNumber() % 5)) {
@@ -394,8 +396,6 @@ void Menu::drawButtonGfx(int32 width, int32 topheight, int32 buttonId, int32 tex
 	const int32 textSize = _engine->_text->getTextSize(dialText);
 	_engine->_text->drawText(width - (textSize / 2), topheight - 18, dialText);
 
-	// TODO: make volume buttons
-
 	_engine->copyBlockPhys(left, top, right, bottom);
 }
 
@@ -422,7 +422,6 @@ void Menu::drawButton(const int16 *menuSettings, bool hover) {
 		// get menu item settings
 		uint8 menuItemId = (uint8)*localData;
 		localData += 1;
-		// applicable for sound menus, to save the volume/sound bar
 		uint16 textId = *localData;
 		localData += 1;
 		if (hover) {
@@ -564,7 +563,7 @@ int32 Menu::processMenu(int16 *menuSettings) {
 		// draw plasma effect for the current selected button
 		drawButton(menuSettings, true);
 		if (_engine->shouldQuit()) {
-			break;
+			return kQuitEngine;
 		}
 		// TODO: update volume settings
 		_engine->_system->delayMillis(10);
@@ -589,6 +588,8 @@ int32 Menu::advoptionsMenu() {
 			ret = 1; // quit option menu
 			break;
 		}
+		case kQuitEngine:
+			return kQuitEngine;
 		//TODO: add other options
 		default:
 			break;
@@ -610,6 +611,8 @@ int32 Menu::savemanageMenu() {
 			ret = 1; // quit option menu
 			break;
 		}
+		case kQuitEngine:
+			return kQuitEngine;
 		//TODO: add other options
 		default:
 			break;
@@ -631,6 +634,8 @@ int32 Menu::volumeMenu() {
 			ret = 1; // quit option menu
 			break;
 		}
+		case kQuitEngine:
+			return kQuitEngine;
 		//TODO: add other options
 		default:
 			break;
@@ -651,6 +656,8 @@ int32 Menu::optionsMenu() {
 
 	do {
 		switch (processMenu(OptionsMenuState)) {
+		case kQuitEngine:
+			return kQuitEngine;
 		case kReturnGame:
 		case kReturnMenu: {
 			ret = 1; // quit option menu
@@ -671,9 +678,6 @@ int32 Menu::optionsMenu() {
 		default:
 			break;
 		}
-		if (_engine->shouldQuit()) {
-			break;
-		}
 	} while (ret != 1);
 
 	return 0;
@@ -716,6 +720,8 @@ void Menu::run() {
 		_engine->_screens->loadMenuImage();
 		break;
 	}
+	case kQuitEngine:
+		return;
 	}
 	_engine->_system->delayMillis(1000 / _engine->cfgfile.Fps);
 }
@@ -735,6 +741,9 @@ int32 Menu::giveupMenu() {
 	do {
 		_engine->_text->initTextBank(0);
 		menuId = processMenu(localMenu);
+		if (menuId == kQuitEngine) {
+			return kQuitEngine;
+		}
 		_engine->_text->initTextBank(_engine->_text->currentTextBank + 3);
 		_engine->_system->delayMillis(1000 / _engine->cfgfile.Fps);
 	} while (menuId != kGiveUp && menuId != kContinue);


Commit: 9671ab083a16ea5b21ba516807a2e866d9116cdb
    https://github.com/scummvm/scummvm/commit/9671ab083a16ea5b21ba516807a2e866d9116cdb
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2020-10-27T17:14:05+01:00

Commit Message:
TWINE: implemented options

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


diff --git a/engines/twine/menu.cpp b/engines/twine/menu.cpp
index 5d96bcfde1..259c8ed89a 100644
--- a/engines/twine/menu.cpp
+++ b/engines/twine/menu.cpp
@@ -467,16 +467,36 @@ int32 Menu::processMenu(int16 *menuSettings) {
 			buttonsNeedRedraw = true;
 		}
 
-		const int16 id = *(&menuSettings[MenuSettings_FirstButtonState] + currentButton * 2); // get button parameters from settings array
+		int16 *menuStatePtr = &menuSettings[MenuSettings_FirstButtonState] + currentButton * 2;
+		const int16 id = *menuStatePtr; // get button parameters from settings array
+		int16 *textId = menuStatePtr + 1; // to store the changed values
 		if (menuSettings == AdvOptionsMenuState) {
 			switch (id) {
 			case kAgressiveMode:
 				if (_engine->_input->toggleActionIfActive(TwinEActionType::UILeft) || _engine->_input->toggleActionIfActive(TwinEActionType::UIRight)) {
-					_engine->_actor->autoAgressive = !_engine->_actor->autoAgressive;
+					if (_engine->_actor->autoAgressive) {
+						_engine->_actor->autoAgressive = false;
+						*textId = 2;
+					} else {
+						_engine->_actor->autoAgressive = true;
+						*textId = 4;
+					}
 				}
 				break;
 			case kPolygonDetails:
-				// TODO:
+				if (_engine->_input->toggleActionIfActive(TwinEActionType::UILeft)) {
+					_engine->cfgfile.PolygonDetails--;
+				} else if (_engine->_input->toggleActionIfActive(TwinEActionType::UIRight)) {
+					_engine->cfgfile.PolygonDetails++;
+				}
+				_engine->cfgfile.PolygonDetails %= 3;
+				if (_engine->cfgfile.PolygonDetails == 0) {
+					*textId = 231;
+				} else if (_engine->cfgfile.PolygonDetails == 1) {
+					*textId = 131;
+				} else {
+					*textId = 31;
+				}
 				break;
 			case kShadowSettings:
 				if (_engine->_input->toggleActionIfActive(TwinEActionType::UILeft)) {
@@ -485,10 +505,23 @@ int32 Menu::processMenu(int16 *menuSettings) {
 					_engine->cfgfile.ShadowMode++;
 				}
 				_engine->cfgfile.ShadowMode %= 3;
+				if (_engine->cfgfile.ShadowMode == 0) {
+					*textId = 232;
+				} else if (_engine->cfgfile.ShadowMode == 1) {
+					*textId = 132;
+				} else {
+					*textId = 32;
+				}
 				break;
 			case kSceneryZoom:
 				if (_engine->_input->toggleActionIfActive(TwinEActionType::UILeft) || _engine->_input->toggleActionIfActive(TwinEActionType::UIRight)) {
-					_engine->cfgfile.SceZoom = !_engine->cfgfile.SceZoom;
+					if (_engine->cfgfile.SceZoom) {
+						_engine->cfgfile.SceZoom = false;
+						*textId = 233;
+					} else {
+						_engine->cfgfile.SceZoom = true;
+						*textId = 133;
+					}
 				}
 				break;
 			default:
diff --git a/engines/twine/twine.h b/engines/twine/twine.h
index 4bf1265c36..18877e5973 100644
--- a/engines/twine/twine.h
+++ b/engines/twine/twine.h
@@ -119,6 +119,7 @@ struct ConfigFile {
 	int32 UseAutoSaving = 0;
 	/** Shadow mode type, value: all, character only, none */
 	int32 ShadowMode = 0;
+	int32 PolygonDetails = 2;
 	/** SceZoom mode type */
 	bool SceZoom = false;
 	/** Flag to toggle Wall Collision */


Commit: b7aa5624841c4d2ff989afd660c987d2dea29b55
    https://github.com/scummvm/scummvm/commit/b7aa5624841c4d2ff989afd660c987d2dea29b55
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2020-10-27T17:14:05+01:00

Commit Message:
TWINE: replaced magic numbers with text ids

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


diff --git a/engines/twine/menu.cpp b/engines/twine/menu.cpp
index 259c8ed89a..eb5353ca52 100644
--- a/engines/twine/menu.cpp
+++ b/engines/twine/menu.cpp
@@ -60,47 +60,21 @@ static const uint16 kMainMenuButtonWidth = 320;
 /** Used to calculate the spanning between button and screen */
 static const uint16 kMainMenuButtonSpan = 550;
 
-/** Main menu types */
-enum MainMenuType {
-	kNewGame = 20,
-	kContinueGame = 21,
-	kOptions = 23,
-	kQuit = 22,
-	kBackground = 9999
-};
-
-/** Give up menu types */
-enum GiveUpMenuType {
-	kContinue = 28,
-	kGiveUp = 27 // quit
-};
-
-/** Options menu types */
-enum OptionsMenuType {
-	kReturnGame = 15,
-	kReturnMenu = 26,
-	kVolume = 30,
-	kSaveManage = 46,
-	kAdvanced = 47
-};
-
-/** Volume menu types */
-enum VolumeMenuType {
+namespace MenuButtonTypes {
+enum _MenuButtonTypes {
 	kMusicVolume = 1,
 	kSoundVolume = 2,
 	kCDVolume = 3,
 	kLineVolume = 4,
-	kMasterVolume = 5
-};
-
-enum AdvOptionsMenuType {
-	kAgressiveMode = 0,
-	kPolygonDetails = 6,
-	kShadowSettings = 7,
-	kSceneryZoom = 8
+	kMasterVolume = 5,
+	kAgressiveMode = 6,
+	kPolygonDetails = 7,
+	kShadowSettings = 8,
+	kSceneryZoom = 9
 };
+}
 
-#define kQuitEngine -1
+#define kBackground 9999
 
 namespace _priv {
 /** Main Menu Settings
@@ -112,13 +86,13 @@ static const int16 MainMenuSettings[] = {
     200, // Buttons box height ( is used to calc the height where the first button will appear )
     0,   // unused
     0,
-    kNewGame, // new game
+    TextId::kNewGame, // new game
     0,
-    kContinueGame, // continue game
+    TextId::kContinueGame, // continue game
     0,
-    kOptions, // options
+    TextId::kOptions, // options
     0,
-    kQuit, // quit
+    TextId::kQuit, // quit
 };
 
 /** Give Up Menu Settings
@@ -130,9 +104,9 @@ static const int16 GiveUpMenuSettings[] = {
     240, // Buttons box height ( is used to calc the height where the first button will appear )
     0,   // unused
     0,
-    28, // continue game
+    TextId::kContinue, // continue game
     0,
-    27, // quit game
+    TextId::kGiveUp, // quit game
 };
 
 /** Give Up Menu Settings
@@ -144,11 +118,11 @@ static const int16 GiveUpMenuWithSaveSettings[] = {
     240, // Buttons box height ( is used to calc the height where the first button will appear )
     0,   // unused
     0,
-    28, // continue game
+    TextId::kContinue, // continue game
     0,
-    16, // save game
+    TextId::kCreateSaveGame, // save game
     0,
-    27, // quit game
+    TextId::kGiveUp, // quit game
 };
 
 /** Options Menu Settings
@@ -160,13 +134,13 @@ static const int16 OptionsMenuSettings[] = {
     0, // Buttons box height ( is used to calc the height where the first button will appear )
     0, // unused
     0,
-    24, // return to previous menu
+    TextId::kReturnMenu, // return to previous menu
     0,
-    kVolume, // volume settings
+    TextId::kVolumeSettings, // volume settings
     0,
-    kSaveManage, // save game management
+    TextId::kSaveManage, // save game management
     0,
-    kAdvanced, // advanced options
+    TextId::kAdvanced, // advanced options
 };
 
 /** Advanced Options Menu Settings
@@ -178,15 +152,15 @@ static const int16 AdvOptionsMenuSettings[] = {
     0, // Buttons box height ( is used to calc the height where the first button will appear )
     0, // unused
     0,
-    26, // return to main menu
-    kAgressiveMode,
-    4, // aggressive mode (manual|auto)
-    kPolygonDetails,
-    31, // Polygon detail (full|medium|low)
-    kShadowSettings,
-    32, // Shadows (all|character|no)
-    kSceneryZoom,
-    33, // scenary zoon (on|off)
+    TextId::kReturnMenu, // return to main menu
+    MenuButtonTypes::kAgressiveMode,
+    TextId::kBehaviourAgressiveManual, // aggressive mode (manual|auto)
+    MenuButtonTypes::kPolygonDetails,
+    TextId::kDetailsPolygonsHigh, // Polygon detail (full|medium|low)
+    MenuButtonTypes::kShadowSettings,
+    TextId::kDetailsShadowHigh, // Shadows (all|character|no)
+    MenuButtonTypes::kSceneryZoom,
+    TextId::kScenaryZoomOn, // scenary zoon (on|off)
 };
 
 /** Save Game Management Menu Settings
@@ -198,11 +172,11 @@ static const int16 SaveManageMenuSettings[] = {
     0, // Buttons box height ( is used to calc the height where the first button will appear )
     0, // unused
     0,
-    26, // return to main menu
+    TextId::kReturnMenu, // return to main menu
     0,
-    41, // copy saved game
+    TextId::kCreateSaveGame, // copy saved game
     0,
-    45, // delete saved game
+    TextId::kDeleteSaveGame, // delete saved game
 };
 
 /** Volume Menu Settings
@@ -214,19 +188,19 @@ static const int16 VolumeMenuSettings[] = {
     0, // Buttons box height ( is used to calc the height where the first button will appear )
     0, // unused
     0,
-    26, // return to main menu
-    kMusicVolume,
-    10, // music volume
-    kSoundVolume,
-    11, // sfx volume
-    kCDVolume,
-    12, // cd volume
-    kLineVolume,
-    13, // line-in volume
-    kMasterVolume,
-    14, // master volume
+    TextId::kReturnMenu, // return to main menu
+    MenuButtonTypes::kMusicVolume,
+    TextId::kMusicVolume, // music volume
+    MenuButtonTypes::kSoundVolume,
+    TextId::kSoundVolume, // sfx volume
+    MenuButtonTypes::kCDVolume,
+    TextId::kCDVolume, // cd volume
+    MenuButtonTypes::kLineVolume,
+    TextId::kLineInVolume, // line-in volume
+    MenuButtonTypes::kMasterVolume,
+    TextId::kMasterVolume, // master volume
     0,
-    16, // save parameters
+    TextId::kSaveSettings, // save parameters
 };
 } // namespace _priv
 
@@ -341,30 +315,30 @@ void Menu::drawButtonGfx(int32 width, int32 topheight, int32 buttonId, int32 tex
 	const int32 bottom = topheight + 25;
 
 	if (hover) {
-		if (buttonId <= kMasterVolume && buttonId >= kMusicVolume) {
+		if (buttonId <= MenuButtonTypes::kMasterVolume && buttonId >= MenuButtonTypes::kMusicVolume) {
 			int32 newWidth = 0;
 			switch (buttonId) {
-			case kMusicVolume: {
+			case MenuButtonTypes::kMusicVolume: {
 				const int volume = _engine->_system->getMixer()->getVolumeForSoundType(Audio::Mixer::kMusicSoundType);
 				newWidth = _engine->_screens->crossDot(left, right, Audio::Mixer::kMaxMixerVolume, volume);
 				break;
 			}
-			case kSoundVolume: {
+			case MenuButtonTypes::kSoundVolume: {
 				const int volume = _engine->_system->getMixer()->getVolumeForSoundType(Audio::Mixer::kSFXSoundType);
 				newWidth = _engine->_screens->crossDot(left, right, Audio::Mixer::kMaxMixerVolume, volume);
 				break;
 			}
-			case kCDVolume: {
+			case MenuButtonTypes::kCDVolume: {
 				const AudioCDManager::Status status = _engine->_system->getAudioCDManager()->getStatus();
 				newWidth = _engine->_screens->crossDot(left, right, Audio::Mixer::kMaxMixerVolume, status.volume);
 				break;
 			}
-			case kLineVolume: {
+			case MenuButtonTypes::kLineVolume: {
 				const int volume = _engine->_system->getMixer()->getVolumeForSoundType(Audio::Mixer::kSpeechSoundType);
 				newWidth = _engine->_screens->crossDot(left, right, Audio::Mixer::kMaxMixerVolume, volume);
 				break;
 			}
-			case kMasterVolume: {
+			case MenuButtonTypes::kMasterVolume: {
 				const int volume = _engine->_system->getMixer()->getVolumeForSoundType(Audio::Mixer::kPlainSoundType);
 				newWidth = _engine->_screens->crossDot(left, right, Audio::Mixer::kMaxMixerVolume, volume);
 				break;
@@ -472,18 +446,18 @@ int32 Menu::processMenu(int16 *menuSettings) {
 		int16 *textId = menuStatePtr + 1; // to store the changed values
 		if (menuSettings == AdvOptionsMenuState) {
 			switch (id) {
-			case kAgressiveMode:
+			case MenuButtonTypes::kAgressiveMode:
 				if (_engine->_input->toggleActionIfActive(TwinEActionType::UILeft) || _engine->_input->toggleActionIfActive(TwinEActionType::UIRight)) {
 					if (_engine->_actor->autoAgressive) {
 						_engine->_actor->autoAgressive = false;
-						*textId = 2;
+						*textId = TextId::kBehaviourAgressiveManual;
 					} else {
 						_engine->_actor->autoAgressive = true;
-						*textId = 4;
+						*textId = TextId::kBehaviourAgressiveAuto;
 					}
 				}
 				break;
-			case kPolygonDetails:
+			case MenuButtonTypes::kPolygonDetails:
 				if (_engine->_input->toggleActionIfActive(TwinEActionType::UILeft)) {
 					_engine->cfgfile.PolygonDetails--;
 				} else if (_engine->_input->toggleActionIfActive(TwinEActionType::UIRight)) {
@@ -491,14 +465,14 @@ int32 Menu::processMenu(int16 *menuSettings) {
 				}
 				_engine->cfgfile.PolygonDetails %= 3;
 				if (_engine->cfgfile.PolygonDetails == 0) {
-					*textId = 231;
+					*textId = TextId::kDetailsPolygonsLow;
 				} else if (_engine->cfgfile.PolygonDetails == 1) {
-					*textId = 131;
+					*textId = TextId::kDetailsPolygonsMiddle;
 				} else {
-					*textId = 31;
+					*textId = TextId::kDetailsPolygonsHigh;
 				}
 				break;
-			case kShadowSettings:
+			case MenuButtonTypes::kShadowSettings:
 				if (_engine->_input->toggleActionIfActive(TwinEActionType::UILeft)) {
 					_engine->cfgfile.ShadowMode--;
 				} else if (_engine->_input->toggleActionIfActive(TwinEActionType::UIRight)) {
@@ -506,21 +480,21 @@ int32 Menu::processMenu(int16 *menuSettings) {
 				}
 				_engine->cfgfile.ShadowMode %= 3;
 				if (_engine->cfgfile.ShadowMode == 0) {
-					*textId = 232;
+					*textId = TextId::kShadowsDisabled;
 				} else if (_engine->cfgfile.ShadowMode == 1) {
-					*textId = 132;
+					*textId = TextId::kShadowsFigures;
 				} else {
-					*textId = 32;
+					*textId = TextId::kDetailsShadowHigh;
 				}
 				break;
-			case kSceneryZoom:
+			case MenuButtonTypes::kSceneryZoom:
 				if (_engine->_input->toggleActionIfActive(TwinEActionType::UILeft) || _engine->_input->toggleActionIfActive(TwinEActionType::UIRight)) {
 					if (_engine->cfgfile.SceZoom) {
 						_engine->cfgfile.SceZoom = false;
-						*textId = 233;
+						*textId = TextId::kNoScenaryZoom;
 					} else {
 						_engine->cfgfile.SceZoom = true;
-						*textId = 133;
+						*textId = TextId::kScenaryZoomOn;
 					}
 				}
 				break;
@@ -530,7 +504,7 @@ int32 Menu::processMenu(int16 *menuSettings) {
 		} else if (menuSettings == VolumeMenuState) {
 			Audio::Mixer *mixer = _engine->_system->getMixer();
 			switch (id) {
-			case kMusicVolume: {
+			case MenuButtonTypes::kMusicVolume: {
 				int volume = mixer->getVolumeForSoundType(Audio::Mixer::SoundType::kMusicSoundType);
 				if (_engine->_input->isActionActive(TwinEActionType::UILeft)) {
 					volume -= 4;
@@ -540,7 +514,7 @@ int32 Menu::processMenu(int16 *menuSettings) {
 				_engine->_music->musicVolume(volume);
 				break;
 			}
-			case kSoundVolume: {
+			case MenuButtonTypes::kSoundVolume: {
 				int volume = mixer->getVolumeForSoundType(Audio::Mixer::kSFXSoundType);
 				if (_engine->_input->isActionActive(TwinEActionType::UILeft)) {
 					volume -= 4;
@@ -550,7 +524,7 @@ int32 Menu::processMenu(int16 *menuSettings) {
 				mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, volume);
 				break;
 			}
-			case kCDVolume: {
+			case MenuButtonTypes::kCDVolume: {
 				AudioCDManager::Status status = _engine->_system->getAudioCDManager()->getStatus();
 				if (_engine->_input->isActionActive(TwinEActionType::UILeft)) {
 					status.volume -= 4;
@@ -560,7 +534,7 @@ int32 Menu::processMenu(int16 *menuSettings) {
 				_engine->_system->getAudioCDManager()->setVolume(status.volume);
 				break;
 			}
-			case kLineVolume: {
+			case MenuButtonTypes::kLineVolume: {
 				int volume = mixer->getVolumeForSoundType(Audio::Mixer::kSpeechSoundType);
 				if (_engine->_input->isActionActive(TwinEActionType::UILeft)) {
 					volume -= 4;
@@ -570,7 +544,7 @@ int32 Menu::processMenu(int16 *menuSettings) {
 				mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, volume);
 				break;
 			}
-			case kMasterVolume: {
+			case MenuButtonTypes::kMasterVolume: {
 				int volume = mixer->getVolumeForSoundType(Audio::Mixer::kPlainSoundType);
 				if (_engine->_input->isActionActive(TwinEActionType::UILeft)) {
 					volume -= 4;
@@ -602,116 +576,117 @@ int32 Menu::processMenu(int16 *menuSettings) {
 		_engine->_system->delayMillis(10);
 	} while (!_engine->_input->toggleActionIfActive(TwinEActionType::UIEnter));
 
-	currentButton = *(menuSettings + MenuSettings_FirstButton + currentButton * 2); // get current browsed button
-
-	_engine->readKeys();
-
-	return currentButton;
+	const int buttonTextId = *(menuSettings + MenuSettings_FirstButton + currentButton * 2); // get current browsed button
+	return buttonTextId;
 }
 
 int32 Menu::advoptionsMenu() {
-	int32 ret = 0;
-
 	_engine->_screens->copyScreen(_engine->workVideoBuffer, _engine->frontVideoBuffer);
 	_engine->flip();
 
-	do {
+	for (;;) {
 		switch (processMenu(AdvOptionsMenuState)) {
-		case kReturnMenu: {
-			ret = 1; // quit option menu
-			break;
+		case TextId::kReturnMenu: {
+			return 0;
 		}
 		case kQuitEngine:
 			return kQuitEngine;
-		//TODO: add other options
+		case TextId::kBehaviourAgressiveManual:
+		case TextId::kDetailsPolygonsHigh:
+		case TextId::kDetailsShadowHigh:
+		case TextId::kScenaryZoomOn:
 		default:
+			warning("Unknown menu button handled");
 			break;
 		}
-	} while (ret != 1);
+	}
 
 	return 0;
 }
 
 int32 Menu::savemanageMenu() {
-	int32 ret = 0;
-
 	_engine->_screens->copyScreen(_engine->workVideoBuffer, _engine->frontVideoBuffer);
 	_engine->flip();
 
-	do {
+	for (;;) {
 		switch (processMenu(SaveManageMenuState)) {
-		case kReturnMenu: {
-			ret = 1; // quit option menu
+		case TextId::kReturnMenu:
+			return 0;
+		case TextId::kCreateSaveGame:
+			// TODO: implement save game handling and slot rendering
+			break;
+		case TextId::kDeleteSaveGame:
+			// TODO: implement save game deletion and slot rendering
 			break;
-		}
 		case kQuitEngine:
 			return kQuitEngine;
-		//TODO: add other options
 		default:
+			warning("Unknown menu button handled");
 			break;
 		}
-	} while (ret != 1);
+	}
 
 	return 0;
 }
 
 int32 Menu::volumeMenu() {
-	int32 ret = 0;
-
 	_engine->_screens->copyScreen(_engine->workVideoBuffer, _engine->frontVideoBuffer);
 	_engine->flip();
 
-	do {
+	for (;;) {
 		switch (processMenu(VolumeMenuState)) {
-		case kReturnMenu: {
-			ret = 1; // quit option menu
+		case TextId::kReturnMenu:
+			return 0;
+		case TextId::kSaveSettings:
+			// TODO: implement setting persisting
 			break;
-		}
 		case kQuitEngine:
 			return kQuitEngine;
-		//TODO: add other options
+		case TextId::kMusicVolume:
+		case TextId::kSoundVolume:
+		case TextId::kCDVolume:
+		case TextId::kLineInVolume:
+		case TextId::kMasterVolume:
 		default:
+			warning("Unknown menu button handled");
 			break;
 		}
-	} while (ret != 1);
+	}
 
 	return 0;
 }
 
 int32 Menu::optionsMenu() {
-	int32 ret = 0;
-
 	_engine->_screens->copyScreen(_engine->workVideoBuffer, _engine->frontVideoBuffer);
 	_engine->flip();
 
 	_engine->_sound->stopSamples();
 	//_engine->_music->playCDtrack(9);
 
-	do {
+	for (;;) {
 		switch (processMenu(OptionsMenuState)) {
-		case kQuitEngine:
-			return kQuitEngine;
-		case kReturnGame:
-		case kReturnMenu: {
-			ret = 1; // quit option menu
-			break;
+		case TextId::kReturnGame:
+		case TextId::kReturnMenu: {
+			return 0;
 		}
-		case kVolume: {
+		case TextId::kVolumeSettings: {
 			volumeMenu();
 			break;
 		}
-		case kSaveManage: {
+		case TextId::kSaveManage: {
 			savemanageMenu();
 			break;
 		}
-		case kAdvanced: {
+		case TextId::kAdvanced: {
 			advoptionsMenu();
 			break;
 		}
+		case kQuitEngine:
+			return kQuitEngine;
 		default:
 			break;
 		}
-	} while (ret != 1);
+	}
 
 	return 0;
 }
@@ -730,20 +705,19 @@ void Menu::run() {
 	_engine->_sound->stopSamples();
 
 	switch (processMenu(MainMenuState)) {
-	case kNewGame: {
+	case TextId::kNewGame: {
 		_engine->_menuOptions->newGameMenu();
 		break;
 	}
-	case kContinueGame: {
+	case TextId::kContinueGame: {
 		_engine->_menuOptions->continueGameMenu();
 		break;
 	}
-	case kOptions: {
-		OptionsMenuState[MenuSettings_FirstButton] = kReturnMenu;
+	case TextId::kOptions: {
 		optionsMenu();
 		break;
 	}
-	case kQuit: {
+	case TextId::kQuit: {
 		Common::Event event;
 		event.type = Common::EVENT_QUIT;
 		_engine->_system->getEventManager()->pushEvent(event);
@@ -774,19 +748,25 @@ int32 Menu::giveupMenu() {
 	do {
 		_engine->_text->initTextBank(0);
 		menuId = processMenu(localMenu);
-		if (menuId == kQuitEngine) {
+		switch (menuId) {
+		case TextId::kContinue:
+			_engine->_sound->resumeSamples();
+			break;
+		case TextId::kGiveUp:
+			_engine->_sound->stopSamples();
+			return 1;
+		case TextId::kCreateSaveGame:
+			// TODO: handle save game creation
+			break;
+		case kQuitEngine:
 			return kQuitEngine;
+		default:
+			warning("Unknown menu button handled: %i", menuId);
 		}
 		_engine->_text->initTextBank(_engine->_text->currentTextBank + 3);
 		_engine->_system->delayMillis(1000 / _engine->cfgfile.Fps);
-	} while (menuId != kGiveUp && menuId != kContinue);
-
-	if (menuId == kGiveUp) {
-		_engine->_sound->stopSamples();
-		return 1;
-	}
+	} while (menuId != TextId::kGiveUp && menuId != TextId::kContinue);
 
-	_engine->_sound->resumeSamples();
 	return 0;
 }
 
diff --git a/engines/twine/menu.h b/engines/twine/menu.h
index ed9fa98e75..f39e353a09 100644
--- a/engines/twine/menu.h
+++ b/engines/twine/menu.h
@@ -38,8 +38,58 @@ enum MenuSettingsType {
 	MenuSettings_FirstButton = 5
 };
 
+/** menu text ids */
+namespace TextId {
+enum _TextId {
+	kBehaviourNormal = 0,
+	kBehaviourSporty = 1,
+	kBehaviourAgressiveManual = 2,
+	kBehaviourHiding = 3,
+	kBehaviourAgressiveAuto = 4,
+	kUseProtopack = 5,
+	kMusicVolume = 10,
+	kSoundVolume = 11,
+	kCDVolume = 12,
+	kLineInVolume = 13,
+	kMasterVolume = 14,
+	kReturnGame = 15,
+	kSaveSettings = 16,
+	kNewGame = 20,
+	kContinueGame = 21,
+	kQuit = 22,
+	kOptions = 23,
+	kDelete = 24,
+	kReturnMenu = 26,
+	kGiveUp = 27,
+	kContinue = 28,
+	kVolumeSettings = 30,
+	kDetailsPolygonsHigh = 31,
+	kDetailsShadowHigh = 32,
+	//kScenaryZoomOn = 33, // duplicate with 133 - TODO check if this is the same in all languages
+	kCreateNewPlayer = 40,
+	kCreateSaveGame = 41,
+	kEnterYourName = 42,
+	kPlayerAlreadyExists = 43,
+	kEnterYourNewName = 44,
+	kDeleteSaveGame = 45,
+	kSaveManage = 46,
+	kAdvanced = 47,
+	kDelete2 = 48, // difference between 24 and 48?
+	kTransferVoices = 49,
+	kPleaseWaitWhileVoicesAreSaved = 50,
+	kRemoveProtoPack = 105,
+	kDetailsPolygonsMiddle = 131,
+	kShadowsFigures = 132,
+	kScenaryZoomOn = 133,
+	kDetailsPolygonsLow = 231,
+	kShadowsDisabled = 232,
+	kNoScenaryZoom = 233
+};
+}
+
 #define PLASMA_WIDTH 320
 #define PLASMA_HEIGHT 50
+#define kQuitEngine 9998
 
 class Menu {
 private:
diff --git a/engines/twine/text.cpp b/engines/twine/text.cpp
index 78d1471266..e5b30aff58 100644
--- a/engines/twine/text.cpp
+++ b/engines/twine/text.cpp
@@ -721,23 +721,23 @@ bool Text::getText(int32 index) { // findString
 	return true;
 }
 
-void Text::copyText(const char *src, char *dst, int32 size) { // copyStringToString
+void Text::copyText(const char *src, char *dst, int32 size) {
 	for (int32 i = 0; i < size; i++) {
 		*(dst++) = *(src++);
 	}
 }
 
-void Text::getMenuText(int32 index, char *text, uint32 textSize) { // GetMultiText
+bool Text::getMenuText(int32 index, char *text, uint32 textSize) {
 	if (index == _engine->_menu->currMenuTextIndex) {
 		if (_engine->_menu->currMenuTextBank == currentTextBank) {
 			Common::strlcpy(text, _engine->_menu->currMenuTextBuffer, textSize);
-			return;
+			return true;
 		}
 	}
 	if (!getText(index)) {
 		// if doesn't have text
 		text[0] = '\0';
-		return;
+		return false;
 	}
 
 	if ((currDialTextSize - 1) > 0xFF) {
@@ -750,6 +750,7 @@ void Text::getMenuText(int32 index, char *text, uint32 textSize) { // GetMultiTe
 
 	_engine->_menu->currMenuTextIndex = index;
 	_engine->_menu->currMenuTextBank = currentTextBank;
+	return true;
 }
 
 void Text::textClipFull() { // newGame2
diff --git a/engines/twine/text.h b/engines/twine/text.h
index c0c2541557..3e4e0acd9c 100644
--- a/engines/twine/text.h
+++ b/engines/twine/text.h
@@ -216,7 +216,7 @@ public:
 	 * @param text dialogue text buffer to display
 	 * @param textSize The size of the text buffer
 	 */
-	void getMenuText(int32 index, char *text, uint32 textSize);
+	bool getMenuText(int32 index, char *text, uint32 textSize);
 
 	void textClipFull();
 	void textClipSmall();
diff --git a/engines/twine/twine.cpp b/engines/twine/twine.cpp
index b3327c8e9b..9296bc104d 100644
--- a/engines/twine/twine.cpp
+++ b/engines/twine/twine.cpp
@@ -388,7 +388,11 @@ int32 TwinEEngine::runGameEngine() { // mainLoopInteration
 		// Process give up menu - Press ESC
 		if (_input->toggleAbortAction() && _scene->sceneHero->life > 0 && _scene->sceneHero->entity != -1 && !_scene->sceneHero->staticFlags.bIsHidden) {
 			freezeTime();
-			if (_menu->giveupMenu()) {
+			const int giveUp = _menu->giveupMenu();
+			if (giveUp == kQuitEngine) {
+				return 0;
+			}
+			if (giveUp == 1) {
 				unfreezeTime();
 				_redraw->redrawEngineActions(1);
 				freezeTime();
@@ -404,10 +408,11 @@ int32 TwinEEngine::runGameEngine() { // mainLoopInteration
 		if (_input->toggleActionIfActive(TwinEActionType::OptionsMenu)) {
 			freezeTime();
 			_sound->pauseSamples();
-			_menu->OptionsMenuState[MenuSettings_FirstButton] = 15; // TODO: why? - where is the reset? kReturnGame
+			_menu->OptionsMenuState[MenuSettings_FirstButton] = TextId::kReturnGame;
 			_text->initTextBank(0);
 			_menu->optionsMenu();
 			_text->initTextBank(_text->currentTextBank + 3);
+			_menu->OptionsMenuState[MenuSettings_FirstButton] = TextId::kReturnMenu;
 			// TODO: play music
 			_sound->resumeSamples();
 			unfreezeTime();


Commit: f5273eef64df9c1f24bcb3c382d4ae839a509ef1
    https://github.com/scummvm/scummvm/commit/f5273eef64df9c1f24bcb3c382d4ae839a509ef1
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2020-10-27T17:14:05+01:00

Commit Message:
TWINE: debug command to list menu texts

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


diff --git a/engines/twine/console.cpp b/engines/twine/console.cpp
index af02f38db9..e14799ac53 100644
--- a/engines/twine/console.cpp
+++ b/engines/twine/console.cpp
@@ -24,17 +24,29 @@
 #include "twine/twine.h"
 #include "twine/gamestate.h"
 #include "twine/scene.h"
+#include "twine/text.h"
 
 namespace TwinE {
 
 TwinEConsole::TwinEConsole(TwinEEngine *engine) : _engine(engine), GUI::Debugger() {
 	registerCmd("give_allitems", WRAP_METHOD(TwinEConsole, doGiveAllItems));
 	registerCmd("change_scene", WRAP_METHOD(TwinEConsole, doChangeScene));
+	registerCmd("list_menutext", WRAP_METHOD(TwinEConsole, doListMenuText));
 }
 
 TwinEConsole::~TwinEConsole() {
 }
 
+bool TwinEConsole::doListMenuText(int argc, const char **argv) {
+	for (int32 i = 0; i < 1000; ++i) {
+		char buf[256];
+		if (_engine->_text->getMenuText(i, buf, sizeof(buf))) {
+			debug("%4i: %s", i, buf);
+		}
+	}
+	return true;
+}
+
 bool TwinEConsole::doChangeScene(int argc, const char **argv) {
 	if (argc <= 1) {
 		warning("Expected to get a scene index as first parameter");
diff --git a/engines/twine/console.h b/engines/twine/console.h
index 30515c505a..c1f2c68fd9 100644
--- a/engines/twine/console.h
+++ b/engines/twine/console.h
@@ -35,6 +35,7 @@ private:
 
 	bool doGiveAllItems(int argc, const char **argv);
 	bool doChangeScene(int argc, const char **argv);
+	bool doListMenuText(int argc, const char **argv);
 public:
 	TwinEConsole(TwinEEngine *engine);
 	~TwinEConsole() override;


Commit: 10571de5aa84f8984029d5a038306cb049746ece
    https://github.com/scummvm/scummvm/commit/10571de5aa84f8984029d5a038306cb049746ece
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2020-10-27T17:14:05+01:00

Commit Message:
TWINE: reduced visibility and return value checks

Changed paths:
    engines/twine/menu.cpp
    engines/twine/menuoptions.cpp
    engines/twine/text.cpp
    engines/twine/text.h


diff --git a/engines/twine/menu.cpp b/engines/twine/menu.cpp
index eb5353ca52..557bb4182d 100644
--- a/engines/twine/menu.cpp
+++ b/engines/twine/menu.cpp
@@ -74,6 +74,7 @@ enum _MenuButtonTypes {
 };
 }
 
+#define checkMenuQuit(callMenu) if ((callMenu) == kQuitEngine) { return kQuitEngine; }
 #define kBackground 9999
 
 namespace _priv {
@@ -670,15 +671,15 @@ int32 Menu::optionsMenu() {
 			return 0;
 		}
 		case TextId::kVolumeSettings: {
-			volumeMenu();
+			checkMenuQuit(volumeMenu())
 			break;
 		}
 		case TextId::kSaveManage: {
-			savemanageMenu();
+			checkMenuQuit(savemanageMenu())
 			break;
 		}
 		case TextId::kAdvanced: {
-			advoptionsMenu();
+			checkMenuQuit(advoptionsMenu())
 			break;
 		}
 		case kQuitEngine:
diff --git a/engines/twine/menuoptions.cpp b/engines/twine/menuoptions.cpp
index 4b5a5ea4f8..220f9f9ced 100644
--- a/engines/twine/menuoptions.cpp
+++ b/engines/twine/menuoptions.cpp
@@ -38,11 +38,6 @@
 
 namespace TwinE {
 
-/** Main menu continue game option key */
-#define MAINMENU_CONTINUEGAME 21
-/** Main menu enter players name */
-#define MAINMENU_ENTERPLAYERNAME 42
-
 #define ONSCREENKEYBOARD_WIDTH 14
 #define ONSCREENKEYBOARD_HEIGHT 5
 
@@ -283,7 +278,7 @@ bool MenuOptions::enterPlayerName(int32 textIdx) {
 }
 
 void MenuOptions::newGameMenu() {
-	if (enterPlayerName(MAINMENU_ENTERPLAYERNAME)) {
+	if (enterPlayerName(TextId::kEnterYourName)) {
 		_engine->_gameState->initEngineVars();
 		newGame();
 
@@ -320,7 +315,7 @@ int MenuOptions::chooseSave(int textIdx) {
 }
 
 void MenuOptions::continueGameMenu() {
-	const int slot = chooseSave(MAINMENU_CONTINUEGAME);
+	const int slot = chooseSave(TextId::kContinueGame);
 	if (slot >= 0) {
 		_engine->_gameState->initEngineVars();
 		_engine->loadSaveSlot(slot);
diff --git a/engines/twine/text.cpp b/engines/twine/text.cpp
index e5b30aff58..5871fbd6a3 100644
--- a/engines/twine/text.cpp
+++ b/engines/twine/text.cpp
@@ -594,7 +594,7 @@ int Text::printText10() {
 }
 
 // TODO: refactor this code
-void Text::drawTextFullscreen(int32 index) { // printTextFullScreen
+void Text::drawTextFullscreen(int32 index) {
 	ScopedKeyMap scopedKeyMap(_engine, cutsceneKeyMapId);
 
 	_engine->_interface->saveClip();
@@ -668,7 +668,7 @@ void Text::setFontParameters(int32 spaceBetween, int32 charSpace) {
 	dialCharSpace = charSpace;
 }
 
-void Text::setFontCrossColor(int32 color) { // TestCoulDial
+void Text::setFontCrossColor(int32 color) {
 	dialTextStepSize = -1;
 	dialTextBufferSize = 14;
 	dialTextStartColor = color << 4;
@@ -686,7 +686,7 @@ void Text::setTextCrossColor(int32 stopColor, int32 startColor, int32 stepSize)
 	dialTextBufferSize = ((startColor - stopColor) + 1) / stepSize;
 }
 
-bool Text::getText(int32 index) { // findString
+bool Text::getText(int32 index) {
 	int32 currIdx = 0;
 	int32 orderIdx = 0;
 
diff --git a/engines/twine/text.h b/engines/twine/text.h
index 3e4e0acd9c..a90d7de0b3 100644
--- a/engines/twine/text.h
+++ b/engines/twine/text.h
@@ -99,15 +99,16 @@ private:
 	int16 pt8s4[96] {0};
 	int32 printText8PrepareBufferVar2 = 0;
 	// ---
+
+	/** Current dialogue text pointer */
+	char *currDialTextPtr = nullptr;
+	/** Current dialogue text size */
+	int32 currDialTextSize = 0;
 public:
 	Text(TwinEEngine *engine) : _engine(engine) {}
 
 	/** Current text bank */
 	int32 currentTextBank = -1;
-	/** Current dialogue text size */
-	int32 currDialTextSize = 0;
-	/** Current dialogue text pointer */
-	char *currDialTextPtr = nullptr;
 
 	/** Dialogue text size */
 	int32 dialTextSize = 0;


Commit: 444dfc18ee0bc3324dd612b4255cce1e6ab868b6
    https://github.com/scummvm/scummvm/commit/444dfc18ee0bc3324dd612b4255cce1e6ab868b6
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2020-10-27T17:14:05+01:00

Commit Message:
TWINE: doesn't make sense to use delaySkip for 1ms

Changed paths:
    engines/twine/gamestate.cpp


diff --git a/engines/twine/gamestate.cpp b/engines/twine/gamestate.cpp
index cd3de71eb8..38f757d2c1 100644
--- a/engines/twine/gamestate.cpp
+++ b/engines/twine/gamestate.cpp
@@ -398,7 +398,7 @@ void GameState::processFoundItem(int32 item) {
 		if (_engine->shouldQuit() || _engine->_input->toggleAbortAction()) {
 			break;
 		}
-		_engine->delaySkip(1);
+		_engine->_system->delayMillis(1);
 	}
 
 	initEngineProjections();


Commit: 191eed29c3593b445902de64cd36855fc82ca02d
    https://github.com/scummvm/scummvm/commit/191eed29c3593b445902de64cd36855fc82ca02d
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2020-10-27T17:14:05+01:00

Commit Message:
TWINE: debug command to toggle the debug mode of the game

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


diff --git a/engines/twine/console.cpp b/engines/twine/console.cpp
index e14799ac53..788ed8d17e 100644
--- a/engines/twine/console.cpp
+++ b/engines/twine/console.cpp
@@ -32,11 +32,23 @@ TwinEConsole::TwinEConsole(TwinEEngine *engine) : _engine(engine), GUI::Debugger
 	registerCmd("give_allitems", WRAP_METHOD(TwinEConsole, doGiveAllItems));
 	registerCmd("change_scene", WRAP_METHOD(TwinEConsole, doChangeScene));
 	registerCmd("list_menutext", WRAP_METHOD(TwinEConsole, doListMenuText));
+	registerCmd("toggle_debug", WRAP_METHOD(TwinEConsole, doToggleDebug));
 }
 
 TwinEConsole::~TwinEConsole() {
 }
 
+bool TwinEConsole::doToggleDebug(int argc, const char **argv) {
+	if (_engine->cfgfile.Debug) {
+		debug("Disabling debug mode");
+		_engine->cfgfile.Debug = false;
+	} else {
+		debug("Enabling debug mode");
+		_engine->cfgfile.Debug = true;
+	}
+	return true;
+}
+
 bool TwinEConsole::doListMenuText(int argc, const char **argv) {
 	for (int32 i = 0; i < 1000; ++i) {
 		char buf[256];
diff --git a/engines/twine/console.h b/engines/twine/console.h
index c1f2c68fd9..cf8518bc4a 100644
--- a/engines/twine/console.h
+++ b/engines/twine/console.h
@@ -36,6 +36,7 @@ private:
 	bool doGiveAllItems(int argc, const char **argv);
 	bool doChangeScene(int argc, const char **argv);
 	bool doListMenuText(int argc, const char **argv);
+	bool doToggleDebug(int argc, const char **argv);
 public:
 	TwinEConsole(TwinEEngine *engine);
 	~TwinEConsole() override;
diff --git a/engines/twine/gamestate.cpp b/engines/twine/gamestate.cpp
index 38f757d2c1..e1b602b414 100644
--- a/engines/twine/gamestate.cpp
+++ b/engines/twine/gamestate.cpp
@@ -31,8 +31,8 @@
 #include "twine/collision.h"
 #include "twine/extra.h"
 #include "twine/grid.h"
-#include "twine/interface.h"
 #include "twine/input.h"
+#include "twine/interface.h"
 #include "twine/menu.h"
 #include "twine/menuoptions.h"
 #include "twine/music.h"
@@ -56,7 +56,6 @@ GameState::GameState(TwinEEngine *engine) : _engine(engine) {
 	playerName[0] = 0;
 	Common::fill(&gameChoices[0], &gameChoices[10], 0);
 	Common::fill(&gameChoicesSettings[0], &gameChoicesSettings[18], 0);
-
 }
 
 void GameState::initEngineProjections() {
@@ -169,7 +168,7 @@ void GameState::initEngineVars() {
 	_engine->_actor->previousHeroBehaviour = kNormal;
 }
 
-bool GameState::loadGame(Common::InSaveFile* file) {
+bool GameState::loadGame(Common::InSaveFile *file) {
 	if (file == nullptr) {
 		return false;
 	}
@@ -237,7 +236,7 @@ bool GameState::loadGame(Common::InSaveFile* file) {
 	return true;
 }
 
-bool GameState::saveGame(Common::OutSaveFile* file) {
+bool GameState::saveGame(Common::OutSaveFile *file) {
 	// TODO: the player name must be handled properly
 	Common::strlcpy(playerName, "TwinEngineSave", sizeof(playerName));
 
@@ -452,55 +451,55 @@ void GameState::processGameoverAnimation() {
 	// TODO: drawInGameTransBox
 	_engine->setPalette(_engine->_screens->paletteRGBA);
 	_engine->_screens->copyScreen(_engine->frontVideoBuffer, _engine->workVideoBuffer);
-	uint8 *gameOverPtr = (uint8 *)malloc(_engine->_hqrdepack->hqrEntrySize(Resources::HQR_RESS_FILE, RESSHQR_GAMEOVERMDL));
-	_engine->_hqrdepack->hqrGetEntry(gameOverPtr, Resources::HQR_RESS_FILE, RESSHQR_GAMEOVERMDL);
-
-	if (gameOverPtr) {
-		const int32 left = 120;
-		const int32 top = 120;
-		const int32 right = 519;
-		const int32 bottom = 359;
-		_engine->_renderer->prepareIsoModel(gameOverPtr);
-		_engine->_sound->stopSamples();
-		_engine->_music->stopMidiMusic(); // stop fade music
-		_engine->_renderer->setCameraPosition(320, 240, 128, 200, 200);
-		int32 startLbaTime = _engine->lbaTime;
-		_engine->_interface->setClip(left, top, right, bottom);
-
-		while (!_engine->_input->toggleAbortAction() && (_engine->lbaTime - startLbaTime) <= 500) {
-			_engine->readKeys();
-			if (_engine->shouldQuit()) {
-				return;
-			}
-
-			const int32 avg = _engine->_collision->getAverageValue(40000, 3200, 500, _engine->lbaTime - startLbaTime);
-			const int32 cdot = _engine->_screens->crossDot(1, 1024, 100, (_engine->lbaTime - startLbaTime) % 0x64);
-
-			_engine->_interface->blitBox(left, top, right, bottom, (int8 *)_engine->workVideoBuffer.getPixels(), 120, 120, (int8 *)_engine->frontVideoBuffer.getPixels());
-			_engine->_renderer->setCameraAngle(0, 0, 0, 0, -cdot, 0, avg);
-			_engine->_renderer->renderIsoModel(0, 0, 0, 0, 0, 0, gameOverPtr);
-			_engine->copyBlockPhys(left, top, right, bottom);
+	uint8 *gameOverPtr = nullptr;
+	if (_engine->_hqrdepack->hqrGetallocEntry(&gameOverPtr, Resources::HQR_RESS_FILE, RESSHQR_GAMEOVERMDL) == 0) {
+		return;
+	}
 
-			_engine->lbaTime++;
-			_engine->_system->delayMillis(15);
+	const int32 left = 120;
+	const int32 top = 120;
+	const int32 right = 519;
+	const int32 bottom = 359;
+	_engine->_renderer->prepareIsoModel(gameOverPtr);
+	_engine->_sound->stopSamples();
+	_engine->_music->stopMidiMusic(); // stop fade music
+	_engine->_renderer->setCameraPosition(320, 240, 128, 200, 200);
+	int32 startLbaTime = _engine->lbaTime;
+	_engine->_interface->setClip(left, top, right, bottom);
+
+	while (!_engine->_input->toggleAbortAction() && (_engine->lbaTime - startLbaTime) <= 500) {
+		_engine->readKeys();
+		if (_engine->shouldQuit()) {
+			return;
 		}
 
-		_engine->_sound->playSample(37, _engine->getRandomNumber(2000) + 3096);
+		const int32 avg = _engine->_collision->getAverageValue(40000, 3200, 500, _engine->lbaTime - startLbaTime);
+		const int32 cdot = _engine->_screens->crossDot(1, 1024, 100, (_engine->lbaTime - startLbaTime) % 0x64);
+
 		_engine->_interface->blitBox(left, top, right, bottom, (int8 *)_engine->workVideoBuffer.getPixels(), 120, 120, (int8 *)_engine->frontVideoBuffer.getPixels());
-		_engine->_renderer->setCameraAngle(0, 0, 0, 0, 0, 0, 3200);
+		_engine->_renderer->setCameraAngle(0, 0, 0, 0, -cdot, 0, avg);
 		_engine->_renderer->renderIsoModel(0, 0, 0, 0, 0, 0, gameOverPtr);
 		_engine->copyBlockPhys(left, top, right, bottom);
 
-		_engine->delaySkip(2000);
+		_engine->lbaTime++;
+		_engine->_system->delayMillis(15);
+	}
 
-		_engine->_interface->resetClip();
-		free(gameOverPtr);
-		_engine->_screens->copyScreen(_engine->workVideoBuffer, _engine->frontVideoBuffer);
-		_engine->flip();
-		initEngineProjections();
+	_engine->_sound->playSample(37, _engine->getRandomNumber(2000) + 3096);
+	_engine->_interface->blitBox(left, top, right, bottom, (int8 *)_engine->workVideoBuffer.getPixels(), 120, 120, (int8 *)_engine->frontVideoBuffer.getPixels());
+	_engine->_renderer->setCameraAngle(0, 0, 0, 0, 0, 0, 3200);
+	_engine->_renderer->renderIsoModel(0, 0, 0, 0, 0, 0, gameOverPtr);
+	_engine->copyBlockPhys(left, top, right, bottom);
 
-		_engine->lbaTime = tmpLbaTime;
-	}
+	_engine->delaySkip(2000);
+
+	_engine->_interface->resetClip();
+	free(gameOverPtr);
+	_engine->_screens->copyScreen(_engine->workVideoBuffer, _engine->frontVideoBuffer);
+	_engine->flip();
+	initEngineProjections();
+
+	_engine->lbaTime = tmpLbaTime;
 }
 
 } // namespace TwinE


Commit: 5f7c967481be552ea56b2e7fdf494aa32907d02d
    https://github.com/scummvm/scummvm/commit/5f7c967481be552ea56b2e7fdf494aa32907d02d
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2020-10-27T17:14:05+01:00

Commit Message:
TWINE: fixed toggleAbortAction to reset all states

otherwise the next call to this function might still succeed due another action still being active

Changed paths:
    engines/twine/input.cpp


diff --git a/engines/twine/input.cpp b/engines/twine/input.cpp
index 3096e6be83..aa946ef70f 100644
--- a/engines/twine/input.cpp
+++ b/engines/twine/input.cpp
@@ -103,7 +103,11 @@ bool Input::toggleActionIfActive(TwinEActionType actionType) {
 }
 
 bool Input::toggleAbortAction() {
-	return toggleActionIfActive(TwinEActionType::CutsceneAbort) || toggleActionIfActive(TwinEActionType::UIAbort) || toggleActionIfActive(TwinEActionType::Escape);
+	bool abortState = false;
+	abortState |= toggleActionIfActive(TwinEActionType::CutsceneAbort);
+	abortState |= toggleActionIfActive(TwinEActionType::UIAbort);
+	abortState |= toggleActionIfActive(TwinEActionType::Escape);
+	return abortState;
 }
 
 bool Input::isQuickBehaviourActionActive() const {


Commit: 0bef6c419da6c3c88f17dc808847a0660f2f5f08
    https://github.com/scummvm/scummvm/commit/0bef6c419da6c3c88f17dc808847a0660f2f5f08
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2020-10-27T17:14:05+01:00

Commit Message:
TWINE: according to the manual you don't have to hold down shift

... for the inventory menu

Changed paths:
    engines/twine/menu.cpp


diff --git a/engines/twine/menu.cpp b/engines/twine/menu.cpp
index 557bb4182d..8dec40dbb7 100644
--- a/engines/twine/menu.cpp
+++ b/engines/twine/menu.cpp
@@ -1051,11 +1051,11 @@ void Menu::processInventoryMenu() {
 	Common::Keymapper *keymapper = g_system->getEventManager()->getKeymapper();
 	keymapper->getKeymap(uiKeyMapId)->setEnabled(true);
 
-	while (_engine->_input->isActionActive(TwinEActionType::InventoryMenu)) {
+	for (;;) {
 		_engine->readKeys();
 		int32 prevSelectedItem = inventorySelectedItem;
 
-		if (_engine->_input->toggleAbortAction()) {
+		if (_engine->_input->toggleAbortAction() || _engine->shouldQuit()) {
 			break;
 		}
 
@@ -1135,6 +1135,8 @@ void Menu::processInventoryMenu() {
 			drawItem(inventorySelectedItem);
 			break;
 		}
+
+		_engine->_system->delayMillis(1);
 	}
 
 	keymapper->getKeymap(uiKeyMapId)->setEnabled(false);


Commit: 68c0eff29a473106fd9a0ee494e0ae0002b9f7a5
    https://github.com/scummvm/scummvm/commit/68c0eff29a473106fd9a0ee494e0ae0002b9f7a5
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2020-10-27T17:14:05+01:00

Commit Message:
TWINE: persist some ui-changable settings via ConfMan

Changed paths:
    engines/twine/twine.cpp


diff --git a/engines/twine/twine.cpp b/engines/twine/twine.cpp
index 9296bc104d..5112d58dd2 100644
--- a/engines/twine/twine.cpp
+++ b/engines/twine/twine.cpp
@@ -161,6 +161,12 @@ Common::Error TwinEEngine::run() {
 	while (!shouldQuit()) {
 		_menu->run();
 	}
+
+	ConfMan.setInt("CombatAuto", _actor->autoAgressive ? 1 : 0);
+	ConfMan.setInt("Shadow", cfgfile.ShadowMode);
+	ConfMan.setInt("SceZoom", cfgfile.SceZoom ? 1 : 0);
+	ConfMan.setInt("PolygonDetails", cfgfile.PolygonDetails);
+
 	_sound->stopSamples();
 	_music->stopTrackMusic();
 	_music->stopMidiMusic();


Commit: 0e16c3f09e25a64313418a6d3f92ae1c5fab871a
    https://github.com/scummvm/scummvm/commit/0e16c3f09e25a64313418a6d3f92ae1c5fab871a
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2020-10-27T17:14:05+01:00

Commit Message:
TWINE: small comment about the language index

Changed paths:
    engines/twine/twine.cpp


diff --git a/engines/twine/twine.cpp b/engines/twine/twine.cpp
index 5112d58dd2..1f6e6f2ba8 100644
--- a/engines/twine/twine.cpp
+++ b/engines/twine/twine.cpp
@@ -240,6 +240,7 @@ static int getLanguageTypeIndex(const char *languageName) {
 	}
 
 	debug("Failed to detect language %s - falling back to english", languageName);
+	// select english for the fan translations
 	return 0; // English
 }
 


Commit: 3b73ba9c37762c6352d54b294d0fb3a620e04eb4
    https://github.com/scummvm/scummvm/commit/3b73ba9c37762c6352d54b294d0fb3a620e04eb4
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2020-10-27T17:14:06+01:00

Commit Message:
TWINE: comments and grouping of members in ConfigFile struct

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


diff --git a/engines/twine/twine.cpp b/engines/twine/twine.cpp
index 1f6e6f2ba8..88036a3a6c 100644
--- a/engines/twine/twine.cpp
+++ b/engines/twine/twine.cpp
@@ -274,14 +274,17 @@ void TwinEEngine::initConfigurations() {
 	cfgfile.UseCD = ConfGetIntOrDefault("UseCD", 0);
 	cfgfile.Sound = ConfGetIntOrDefault("Sound", 1);
 	cfgfile.Movie = ConfGetIntOrDefault("Movie", CONF_MOVIE_FLA);
-	cfgfile.CrossFade = ConfGetIntOrDefault("CrossFade", 0);
 	cfgfile.Fps = ConfGetIntOrDefault("Fps", DEFAULT_FRAMES_PER_SECOND);
 	cfgfile.Debug = ConfGetIntOrDefault("Debug", 0) == 1;
+
 	cfgfile.UseAutoSaving = ConfGetIntOrDefault("UseAutoSaving", 0);
+	cfgfile.CrossFade = ConfGetIntOrDefault("CrossFade", 0);
+	cfgfile.WallCollision = ConfGetIntOrDefault("WallCollision", 0);
+
 	_actor->autoAgressive = ConfGetIntOrDefault("CombatAuto", 1) == 1;
 	cfgfile.ShadowMode = ConfGetIntOrDefault("Shadow", 2);
 	cfgfile.SceZoom = ConfGetIntOrDefault("SceZoom", 0) == 0;
-	cfgfile.WallCollision = ConfGetIntOrDefault("WallCollision", 0);
+	cfgfile.PolygonDetails = ConfGetIntOrDefault("PolygonDetails", 2);
 }
 
 void TwinEEngine::initEngine() {
diff --git a/engines/twine/twine.h b/engines/twine/twine.h
index 18877e5973..ec1f35ee8b 100644
--- a/engines/twine/twine.h
+++ b/engines/twine/twine.h
@@ -87,9 +87,7 @@ enum MovieType {
 	CONF_MOVIE_FLAPCX = 3
 };
 
-// TODO: persist on shutdown
 /** Configuration file structure
-
 	Used in the engine to load/use certain parts of code according with
 	this settings. Check \a lba.cfg file for valid values for each settings.\n
 	All the settings with (*) means they are new and only exist in this engine. */
@@ -109,21 +107,26 @@ struct ConfigFile {
 	int32 Sound = 0;
 	/** Allow various movie types */
 	int32 Movie = CONF_MOVIE_FLA;
-	/** Use cross fade effect while changing images, or be as the original */
-	int32 CrossFade = 0;
 	/** Flag used to keep the game frames per second */
 	int32 Fps = 0;
 	/** Flag to display game debug */
 	bool Debug = false;
+
+	// these settings are not available in the original version
+	/** Use cross fade effect while changing images, or be as the original */
+	int32 CrossFade = 0;
+	/** Flag to toggle Wall Collision */
+	int32 WallCollision = 0;
 	/** Use original autosaving system or save when you want */
 	int32 UseAutoSaving = 0;
+
+	// these settings can be changed in-game - and must be persisted
 	/** Shadow mode type, value: all, character only, none */
 	int32 ShadowMode = 0;
+	// TODO: currently unused
 	int32 PolygonDetails = 2;
-	/** SceZoom mode type */
+	/** Scenery Zoom */
 	bool SceZoom = false;
-	/** Flag to toggle Wall Collision */
-	int32 WallCollision = 0;
 };
 
 class Actor;


Commit: 31b6aecaba32a9036bc7c7c6a9ed303f8beabeeb
    https://github.com/scummvm/scummvm/commit/31b6aecaba32a9036bc7c7c6a9ed303f8beabeeb
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2020-10-27T17:14:06+01:00

Commit Message:
TWINE: copy vox comments

... taken from http://lbafileinfo.kazekr.net/index.php\?title\=LBA_1_files

Changed paths:
    engines/twine/text.cpp


diff --git a/engines/twine/text.cpp b/engines/twine/text.cpp
index 5871fbd6a3..2f8042fd60 100644
--- a/engines/twine/text.cpp
+++ b/engines/twine/text.cpp
@@ -39,28 +39,33 @@ namespace TwinE {
 /** FLA movie extension */
 #define VOX_EXT ".vox"
 
+#define INDEXOFFSET 0
+#define DIALOGSOFFSET 1
+
 void Text::initVoxBank(int32 bankIdx) {
 	static const char *LanguageSufixTypes[] = {
 	    "sys",
 	    "cre",
-	    "gam",
-	    "000",
-	    "001",
-	    "002",
-	    "003",
-	    "004",
-	    "005",
-	    "006",
-	    "007",
-	    "008",
-	    "009",
-	    "010",
-	    "011"};
+	    "gam", // global game voices (e.g. inventory descriptions)
+	    "000", // Citadel Island voices
+	    "001", // Principal Island voices
+	    "002", // White Leaf Desert voices
+	    "003", // Proxima Island voices
+	    "004", // Rebellion Island voices
+	    "005", // Hamalayi Mountains - sourthern range voices
+	    "006", // Hamalayi Mountains - northern range voices
+	    "007", // Tippett Island voices
+	    "008", // Brundle Island voices
+	    "009", // Fortress Island voices
+	    "010", // Polar Island voices
+	    "011"  //
+	};
 	if (bankIdx < 0 || bankIdx >= ARRAYSIZE(LanguageSufixTypes)) {
 		error("bankIdx is out of bounds: %i", bankIdx);
 	}
 	// get the correct vox hqr file
 	currentVoxBankFile = Common::String::format("%s%s" VOX_EXT, LanguageTypes[_engine->cfgfile.LanguageId].id, LanguageSufixTypes[bankIdx]);
+	// TODO: loop through other languages and take the scummvm settings regarding voices into account...
 
 	// TODO check the rest to reverse
 }
@@ -117,7 +122,7 @@ bool Text::stopVox(int32 index) {
 	return true;
 }
 
-void Text::initTextBank(int32 bankIdx) { // InitDial
+void Text::initTextBank(int32 bankIdx) {
 	// don't load if we already have the dialogue text bank loaded
 	if (bankIdx == currentBankIdx) {
 		return;
@@ -129,7 +134,7 @@ void Text::initTextBank(int32 bankIdx) { // InitDial
 	// get index according with language
 	const int32 size = 28; // lba2 is 30
 	const int32 languageIndex = _engine->cfgfile.LanguageId * size + bankIdx * 2;
-	const int32 hqrSize = _engine->_hqrdepack->hqrGetallocEntry((uint8 **)&dialOrderPtr, Resources::HQR_TEXT_FILE, languageIndex);
+	const int32 hqrSize = _engine->_hqrdepack->hqrGetallocEntry((uint8 **)&dialOrderPtr, Resources::HQR_TEXT_FILE, languageIndex + INDEXOFFSET);
 	if (hqrSize == 0) {
 		warning("Failed to initialize text bank %i from file %s", languageIndex, Resources::HQR_TEXT_FILE);
 		return;
@@ -137,7 +142,7 @@ void Text::initTextBank(int32 bankIdx) { // InitDial
 
 	numDialTextEntries = hqrSize / 2;
 
-	if (_engine->_hqrdepack->hqrGetallocEntry((uint8 **)&dialTextPtr, Resources::HQR_TEXT_FILE, languageIndex + 1) == 0) {
+	if (_engine->_hqrdepack->hqrGetallocEntry((uint8 **)&dialTextPtr, Resources::HQR_TEXT_FILE, languageIndex + DIALOGSOFFSET) == 0) {
 		warning("Failed to initialize additional text bank %i from file %s", languageIndex + 1, Resources::HQR_TEXT_FILE);
 		return;
 	}


Commit: 117cf827ee97294ed6c157ddd93b19117e63d074
    https://github.com/scummvm/scummvm/commit/117cf827ee97294ed6c157ddd93b19117e63d074
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2020-10-27T17:14:06+01:00

Commit Message:
TWINE: reduced scope and cleanup in text rendering

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


diff --git a/engines/twine/text.cpp b/engines/twine/text.cpp
index 2f8042fd60..bbb51d0aaa 100644
--- a/engines/twine/text.cpp
+++ b/engines/twine/text.cpp
@@ -150,51 +150,26 @@ void Text::initTextBank(int32 bankIdx) {
 }
 
 void Text::drawCharacter(int32 x, int32 y, uint8 character) { // drawCharacter
-	uint8 sizeX;
-	uint8 sizeY;
-	uint8 param1;
-	uint8 param2;
-	uint8 *data;
-	uint8 *screen2;
+	const uint8 sizeX = getCharWidth(character);
+	uint8 sizeY = getCharHeight(character);
+	uint8 *data = _engine->_resources->fontPtr + *((const int16 *)(_engine->_resources->fontPtr + character * 4));
+	data += 2;
+	x += *(data++);
+	y += *(data++);
 
-	// int temp=0;
-	int32 toNextLine;
-	uint8 index;
+	const uint8 usedColor = dialTextColor;
 
-	// char color;
-	uint8 usedColor;
-	uint8 number;
-	uint8 jump;
+	uint8 *screen2 = (uint8 *)_engine->frontVideoBuffer.getPixels() + _engine->screenLookupTable[y] + x;
 
-	int32 i;
+	int32 tempX = x;
+	int32 tempY = y;
 
-	int32 tempX;
-	int32 tempY;
-
-	data = _engine->_resources->fontPtr + *((const int16 *)(_engine->_resources->fontPtr + character * 4));
-
-	dialTextSize = sizeX = *(data++);
-	sizeY = *(data++);
-
-	param1 = *(data++);
-	param2 = *(data++);
-
-	x += param1;
-	y += param2;
-
-	usedColor = dialTextColor;
-
-	screen2 = (uint8 *)_engine->frontVideoBuffer.getPixels() + _engine->screenLookupTable[y] + x;
-
-	tempX = x;
-	tempY = y;
-
-	toNextLine = SCREEN_WIDTH - sizeX;
+	const int32 toNextLine = SCREEN_WIDTH - sizeX;
 
 	do {
-		index = *(data++);
+		uint8 index = *(data++);
 		do {
-			jump = *(data++);
+			const uint8 jump = *(data++);
 			screen2 += jump;
 			tempX += jump;
 			if (--index == 0) {
@@ -206,28 +181,27 @@ void Text::drawCharacter(int32 x, int32 y, uint8 character) { // drawCharacter
 					return;
 				}
 				break;
-			} else {
-				number = *(data++);
-				for (i = 0; i < number; i++) {
-					if (tempX >= SCREEN_TEXTLIMIT_LEFT && tempX < SCREEN_TEXTLIMIT_RIGHT && tempY >= SCREEN_TEXTLIMIT_TOP && tempY < SCREEN_TEXTLIMIT_BOTTOM) {
-						*((uint8 *)_engine->frontVideoBuffer.getBasePtr(tempX, tempY)) = usedColor;
-					}
-
-					screen2++;
-					tempX++;
+			}
+			uint8 number = *(data++);
+			for (uint8 i = 0; i < number; i++) {
+				if (tempX >= SCREEN_TEXTLIMIT_LEFT && tempX < SCREEN_TEXTLIMIT_RIGHT && tempY >= SCREEN_TEXTLIMIT_TOP && tempY < SCREEN_TEXTLIMIT_BOTTOM) {
+					*((uint8 *)_engine->frontVideoBuffer.getBasePtr(tempX, tempY)) = usedColor;
 				}
 
-				if (--index == 0) {
-					screen2 += toNextLine;
-					tempY++;
-					tempX = x;
+				screen2++;
+				tempX++;
+			}
 
-					sizeY--;
-					if (sizeY <= 0) {
-						return;
-					}
-					break;
+			if (--index == 0) {
+				screen2 += toNextLine;
+				tempY++;
+				tempX = x;
+
+				sizeY--;
+				if (sizeY <= 0) {
+					return;
 				}
+				break;
 			}
 		} while (1);
 	} while (1);
@@ -272,7 +246,7 @@ void Text::drawText(int32 x, int32 y, const char *dialogue) { // Font
 			x += dialCharSpace;
 		} else {
 			dialTextSize = getCharWidth(currChar);
-			drawCharacter(x, y, currChar);                                      // draw the character on screen
+			drawCharacter(x, y, currChar); // draw the character on screen
 			// add the length of the space between 2 characters
 			x += dialSpaceBetween;
 			// add the length of the current character
@@ -519,6 +493,10 @@ int32 Text::getCharWidth(uint8 chr) const {
 	return *(_engine->_resources->fontPtr + *((const int16 *)(_engine->_resources->fontPtr + chr * 4)));
 }
 
+int32 Text::getCharHeight(uint8 chr) const {
+	return *(_engine->_resources->fontPtr + 1 + *((const int16 *)(_engine->_resources->fontPtr + chr * 4)));
+}
+
 // TODO: refactor this code
 int Text::printText10() {
 	if (printTextVar13 == 0) {
diff --git a/engines/twine/text.h b/engines/twine/text.h
index a90d7de0b3..c29963ee60 100644
--- a/engines/twine/text.h
+++ b/engines/twine/text.h
@@ -60,6 +60,7 @@ private:
 	void printText10Sub();
 	void printText10Sub2();
 	int32 getCharWidth(uint8 chr) const;
+	int32 getCharHeight(uint8 chr) const;
 	/**
 	 * Copy dialogue text
 	 * @param src source text buffer


Commit: e14950077daa6333c3190b49545c9816413dfdd8
    https://github.com/scummvm/scummvm/commit/e14950077daa6333c3190b49545c9816413dfdd8
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2020-10-27T17:20:07+01:00

Commit Message:
TWINE: missing inventory item constants

Changed paths:
    engines/twine/gamestate.h


diff --git a/engines/twine/gamestate.h b/engines/twine/gamestate.h
index 6b4ffa33a6..94496cc5dc 100644
--- a/engines/twine/gamestate.h
+++ b/engines/twine/gamestate.h
@@ -38,11 +38,29 @@ enum InventoryItems {
 	kiHolomap = 0,
 	kiMagicBall = 1,
 	kiUseSabre = 2,
+	kiGawleysHorn = 3,
 	kiTunic = 4,
 	kiBookOfBu = 5,
+	kSendellsMedallion = 6,
+	kFlaskOfClearWater = 7,
+	kRedCard = 8,
+	kBlueCard = 9,
+	kIDCard = 10,
+	kMrMiesPass = 11,
 	kiProtoPack = 12,
+	kSnowboard = 13,
 	kiPinguin = 14,
 	kGasItem = 15,
+	kPirateFlag = 16,
+	kMagicFlute = 17,
+	kSpaceGuitar = 18,
+	kHairDryer = 19,
+	kAncesteralKey = 20,
+	kBottleOfSyrup = 21,
+	kEmptyBottle = 22,
+	kFerryTicket = 23,
+	kKeypad = 24,
+	kCoffeeCan  = 25,
 	kiBonusList = 26,
 	kiCloverLeaf = 27
 };
@@ -108,9 +126,9 @@ public:
 	char playerName[30];
 
 	int32 gameChoices[10];         // inGameMenuData
-	int32 numChoices = 0;             // numOfOptionsInChoice
+	int32 numChoices = 0;          // numOfOptionsInChoice
 	int16 gameChoicesSettings[18]; // choiceTab -  same structure as menu settings
-	int32 choiceAnswer = 0;           // inGameMenuAnswer
+	int32 choiceAnswer = 0;        // inGameMenuAnswer
 
 	/** Initialize all engine variables */
 	void initEngineVars();
@@ -120,8 +138,8 @@ public:
 
 	void processFoundItem(int32 item);
 
-	bool loadGame(Common::InSaveFile* file);
-	bool saveGame(Common::OutSaveFile* file);
+	bool loadGame(Common::InSaveFile *file);
+	bool saveGame(Common::OutSaveFile *file);
 
 	void processGameChoices(int32 choiceIdx);
 


Commit: caeb854b0a46179e856c609ae2787590636f8f28
    https://github.com/scummvm/scummvm/commit/caeb854b0a46179e856c609ae2787590636f8f28
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2020-10-27T17:30:15+01:00

Commit Message:
TWINE: reduced scope and visibility

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


diff --git a/engines/twine/renderer.cpp b/engines/twine/renderer.cpp
index e26a709a66..1ad806afaa 100644
--- a/engines/twine/renderer.cpp
+++ b/engines/twine/renderer.cpp
@@ -406,21 +406,15 @@ FORCEINLINE int16 clamp(int16 x, int16 a, int16 b) {
 }
 
 int32 Renderer::computePolygons() {
-	int16 *outPtr;
-	int32 i, nVertex;
-	int8 direction, up;
-	int64 slope;
-	vertexData *vertices;
-
 	pRenderV1 = vertexCoordinates;
 	pRenderV2 = pRenderV3;
 
-	vertices = (vertexData *)vertexCoordinates;
+	vertexData *vertices = (vertexData *)vertexCoordinates;
 
 	vleft = vtop = 32767;
 	vright = vbottom = -32768;
 
-	for (i = 0; i < numOfVertex; i++) {
+	for (int32 i = 0; i < numOfVertex; i++) {
 		vertices[i].x = clamp(vertices[i].x, 0, SCREEN_WIDTH - 1);
 		int16 vertexX = vertices[i].x;
 
@@ -441,7 +435,7 @@ int32 Renderer::computePolygons() {
 	int16 currentVertexX = vertices[numOfVertex - 1].x;
 	int16 currentVertexY = vertices[numOfVertex - 1].y;
 
-	for (nVertex = 0; nVertex < numOfVertex; nVertex++) {
+	for (int32 nVertex = 0; nVertex < numOfVertex; nVertex++) {
 		int16 oldVertexY = currentVertexY;
 		int16 oldVertexX = currentVertexX;
 		oldVertexParam = vertexParam1;
@@ -452,11 +446,12 @@ int32 Renderer::computePolygons() {
 
 		// drawLine(oldVertexX,oldVertexY,currentVertexX,currentVertexY,255);
 
-		if (currentVertexY == oldVertexY)
+		if (currentVertexY == oldVertexY) {
 			continue;
+		}
 
-		up = currentVertexY < oldVertexY;
-		direction = up ? -1 : 1;
+		int8 up = currentVertexY < oldVertexY;
+		int8 direction = up ? -1 : 1;
 
 		int16 vsize = ABS(currentVertexY - oldVertexY);
 		int16 hsize = ABS(currentVertexX - oldVertexX);
@@ -477,15 +472,17 @@ int32 Renderer::computePolygons() {
 			cvalue = (oldVertexParam << 8) + ((vertexParam2 - oldVertexParam) << 8) % vsize;
 			cdelta = ((vertexParam2 - oldVertexParam) << 8) / vsize;
 		}
-		outPtr = &polyTab[ypos + (up ? 480 : 0)]; // outPtr is the output ptr in the renderTab
+		int16 *outPtr = &polyTab[ypos + (up ? 480 : 0)]; // outPtr is the output ptr in the renderTab
 
-		slope = (int64)hsize / (int64)vsize;
+		int64 slope = (int64)hsize / (int64)vsize;
 		slope = up ? -slope : slope;
 
-		for (i = 0; i < vsize + 2; i++) {
-			if ((outPtr - polyTab) < 960)
-				if ((outPtr - polyTab) > 0)
-					*(outPtr) = xpos;
+		for (int32  i = 0; i < vsize + 2; i++) {
+			if (outPtr - polyTab < 960) {
+				if (outPtr - polyTab > 0) {
+					*outPtr = xpos;
+				}
+			}
 			outPtr += direction;
 			xpos += slope;
 		}
@@ -493,35 +490,35 @@ int32 Renderer::computePolygons() {
 		if (polyRenderType >= 7) { // we must compute the color progression
 			int16 *outPtr2 = &polyTab2[ypos + (up ? 480 : 0)];
 
-			for (i = 0; i < vsize + 2; i++) {
-				if ((outPtr2 - polyTab2) < 960)
-					if ((outPtr2 - polyTab2) > 0)
-						*(outPtr2) = cvalue;
+			for (int32 i = 0; i < vsize + 2; i++) {
+				if (outPtr2 - polyTab2 < 960) {
+					if (outPtr2 - polyTab2 > 0) {
+						*outPtr2 = cvalue;
+					}
+				}
 				outPtr2 += direction;
 				cvalue += cdelta;
 			}
 		}
 	}
 
-	return (1);
+	return 1;
 }
 
 void Renderer::renderPolygons(int32 renderType, int32 color) {
-	uint8 *out, *out2;
-	int16 *ptr1;
-	int16 *ptr2;
-	int32 vsize, hsize;
+	uint8 *out2;
+	int32 hsize;
 	int32 j;
 	int32 currentLine;
 
 	int16 start, stop;
 
-	out = (uint8*)_engine->frontVideoBuffer.getPixels() + 640 * vtop;
+	uint8 *out = (uint8*)_engine->frontVideoBuffer.getPixels() + 640 * vtop;
 
-	ptr1 = &polyTab[vtop];
-	ptr2 = &polyTab2[vtop];
+	int16 *ptr1 = &polyTab[vtop];
+	int16 *ptr2 = &polyTab2[vtop];
 
-	vsize = vbottom - vtop;
+	int32 vsize = vbottom - vtop;
 	vsize++;
 
 	switch (renderType) {
@@ -637,7 +634,7 @@ void Renderer::renderPolygons(int32 renderType, int32 color) {
 					break;
 
 				out2 = start + out;
-				*(out2) = ((unsigned short)(bx >> 0x18)) & 0x0F;
+				*out2 = ((unsigned short)(bx >> 0x18)) & 0x0F;
 
 				color = *(out2 + 1);
 
@@ -682,8 +679,9 @@ void Renderer::renderPolygons(int32 renderType, int32 color) {
 					ax += dx;
 
 					--j;
-					if (!j)
+					if (!j) {
 						break;
+					}
 
 					*(out2++) = ax & 0x0F;
 					ax += dx;
diff --git a/engines/twine/renderer.h b/engines/twine/renderer.h
index f72c47781b..e9dc7032de 100644
--- a/engines/twine/renderer.h
+++ b/engines/twine/renderer.h
@@ -214,11 +214,11 @@ private:
 	int32 renderLoop = 0;
 	// end render polygon vars
 
+	int32 isUsingOrhoProjection = 0;
+
 public:
 	Renderer(TwinEEngine *engine) : _engine(engine) {}
 
-	int32 isUsingOrhoProjection = 0;
-
 	int16 projPosXScreen = 0; // fullRedrawVar1
 	int16 projPosYScreen = 0; // fullRedrawVar2
 	int16 projPosZScreen = 0; // fullRedrawVar3


Commit: 83610de2eb0cc2590b0fd28c38f915a376aef52b
    https://github.com/scummvm/scummvm/commit/83610de2eb0cc2590b0fd28c38f915a376aef52b
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2020-10-27T17:33:09+01:00

Commit Message:
TWINE: convert comment into code

Changed paths:
    engines/twine/text.cpp


diff --git a/engines/twine/text.cpp b/engines/twine/text.cpp
index bbb51d0aaa..8771c28455 100644
--- a/engines/twine/text.cpp
+++ b/engines/twine/text.cpp
@@ -132,7 +132,7 @@ void Text::initTextBank(int32 bankIdx) {
 	textVar2[0] = '\0';
 
 	// get index according with language
-	const int32 size = 28; // lba2 is 30
+	const int32 size = _engine->isLBA1() ? 28 : 30;
 	const int32 languageIndex = _engine->cfgfile.LanguageId * size + bankIdx * 2;
 	const int32 hqrSize = _engine->_hqrdepack->hqrGetallocEntry((uint8 **)&dialOrderPtr, Resources::HQR_TEXT_FILE, languageIndex + INDEXOFFSET);
 	if (hqrSize == 0) {


Commit: 31ed2761be50e99765583ccf3b162e488581e585
    https://github.com/scummvm/scummvm/commit/31ed2761be50e99765583ccf3b162e488581e585
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2020-10-27T17:58:29+01:00

Commit Message:
TWINE: fixed button states on menu initialization

Changed paths:
    engines/twine/menu.cpp


diff --git a/engines/twine/menu.cpp b/engines/twine/menu.cpp
index 8dec40dbb7..996c0b24f3 100644
--- a/engines/twine/menu.cpp
+++ b/engines/twine/menu.cpp
@@ -449,22 +449,22 @@ int32 Menu::processMenu(int16 *menuSettings) {
 			switch (id) {
 			case MenuButtonTypes::kAgressiveMode:
 				if (_engine->_input->toggleActionIfActive(TwinEActionType::UILeft) || _engine->_input->toggleActionIfActive(TwinEActionType::UIRight)) {
-					if (_engine->_actor->autoAgressive) {
-						_engine->_actor->autoAgressive = false;
-						*textId = TextId::kBehaviourAgressiveManual;
-					} else {
-						_engine->_actor->autoAgressive = true;
-						*textId = TextId::kBehaviourAgressiveAuto;
-					}
+					_engine->_actor->autoAgressive = !_engine->_actor->autoAgressive;
+				}
+				if (_engine->_actor->autoAgressive) {
+					*textId = TextId::kBehaviourAgressiveManual;
+				} else {
+					*textId = TextId::kBehaviourAgressiveAuto;
 				}
 				break;
 			case MenuButtonTypes::kPolygonDetails:
 				if (_engine->_input->toggleActionIfActive(TwinEActionType::UILeft)) {
 					_engine->cfgfile.PolygonDetails--;
+					_engine->cfgfile.PolygonDetails %= 3;
 				} else if (_engine->_input->toggleActionIfActive(TwinEActionType::UIRight)) {
 					_engine->cfgfile.PolygonDetails++;
+					_engine->cfgfile.PolygonDetails %= 3;
 				}
-				_engine->cfgfile.PolygonDetails %= 3;
 				if (_engine->cfgfile.PolygonDetails == 0) {
 					*textId = TextId::kDetailsPolygonsLow;
 				} else if (_engine->cfgfile.PolygonDetails == 1) {
@@ -476,10 +476,11 @@ int32 Menu::processMenu(int16 *menuSettings) {
 			case MenuButtonTypes::kShadowSettings:
 				if (_engine->_input->toggleActionIfActive(TwinEActionType::UILeft)) {
 					_engine->cfgfile.ShadowMode--;
+					_engine->cfgfile.ShadowMode %= 3;
 				} else if (_engine->_input->toggleActionIfActive(TwinEActionType::UIRight)) {
 					_engine->cfgfile.ShadowMode++;
+					_engine->cfgfile.ShadowMode %= 3;
 				}
-				_engine->cfgfile.ShadowMode %= 3;
 				if (_engine->cfgfile.ShadowMode == 0) {
 					*textId = TextId::kShadowsDisabled;
 				} else if (_engine->cfgfile.ShadowMode == 1) {
@@ -490,13 +491,12 @@ int32 Menu::processMenu(int16 *menuSettings) {
 				break;
 			case MenuButtonTypes::kSceneryZoom:
 				if (_engine->_input->toggleActionIfActive(TwinEActionType::UILeft) || _engine->_input->toggleActionIfActive(TwinEActionType::UIRight)) {
-					if (_engine->cfgfile.SceZoom) {
-						_engine->cfgfile.SceZoom = false;
-						*textId = TextId::kNoScenaryZoom;
-					} else {
-						_engine->cfgfile.SceZoom = true;
-						*textId = TextId::kScenaryZoomOn;
-					}
+					_engine->cfgfile.SceZoom = !_engine->cfgfile.SceZoom;
+				}
+				if (_engine->cfgfile.SceZoom) {
+					*textId = TextId::kNoScenaryZoom;
+				} else {
+					*textId = TextId::kScenaryZoomOn;
 				}
 				break;
 			default:




More information about the Scummvm-git-logs mailing list