[Scummvm-git-logs] scummvm master -> b15064e6d98df88cd5d0c1079e3f595a49cfcc13

mgerhardy martin.gerhardy at gmail.com
Mon Oct 26 17:14:51 UTC 2020


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

Summary:
f8210aac82 TWINE: added game variant detection by gameId
f64dfffc48 TWINE: removed manually searching the directories - SearchMan has vox and fla registered
6622d32274 TWINE: renamed variables
567cee4e6f TWINE: reduced code duplication
ec9d67d0b0 TWINE: add debug commands to switch the scene and give all items
be4725fe58 TWINE: let the debug command give all items
3283e420e2 TWINE: replaced magic numbers
3dd13e456b TWINE: fixed typo
40564c4b00 TWINE: nextpage action to read multi page ui text
05bc119526 TWINE: tweaked inventory menu (not yet working 100%)
7f8c588af9 TWINE: replaced magic numbers
74896d1846 TWINE: reduced scope + cleanup
4f638d30b5 TWINE: enable the ui bindings for the inventory menu
dd2e97ebd6 TWINE: close the inventory menu if i is no longer pressed
67568dd0e8 TWINE: 'fixed' a div0 error
483723cd4f TWINE: comments from http://lbafileinfo.kazekr.net
b951291d5e TWINE: removed internalKeyCode from Input class
a2ec51e46c TWINE: store script sizes
9d53e69b79 TWINE: converted scene loading to stream
662aceb922 TWINE: reduced scope
94d0bc8b21 TWINE: reduced scope
8df39f3eeb TWINE: fixed copyBlockPhys
0a56ddc670 TWINE: script warnings if not implemented or invalid opcode
e845ab153b TWINE: fixed warning while initializing itemAngle array
64ce952c74 TWINE: reset global text vars if compiling without intros
71921f241c TWINE: started to implement saving and loading as well as player name entering
934a250cfd TWINE: fixed assert in drawPlayerName
b307011170 TWINE: cleanup input code and replaced magic numbers
632b794e2b TWINE: converted to boolean
4712894133 TWINE: make more or less private
b90797e00d TWINE: moved pressed key states into movements class
b2463be755 TWINE: replaced magic number
2cf3832bed TWINE: reduced scope
a8ca9e017b TWINE: make cursorKeys obsolet
afdee7237f TWINE: moved actor pointer into actor class
1eb3acf27a TWINE: small helper method for the Input class
69b06478b3 TWINE: restore old variable use - we're not yet there
ea850b8c50 TWINE: fixed previousLoopCursorKeys handling for attack animations
2ad34e17f1 TWINE: script cleanup - input cleanup
927e6cc2d1 TWINE: cleanup in move script
bb76f5ed99 TWINE: don't use the global var
b15064e6d9 TWINE: cleanup move script


Commit: f8210aac8201f4297a107c19fc270a90e81b9471
    https://github.com/scummvm/scummvm/commit/f8210aac8201f4297a107c19fc270a90e81b9471
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2020-10-26T18:11:14+01:00

Commit Message:
TWINE: added game variant detection by gameId

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


diff --git a/engines/twine/detection.h b/engines/twine/detection.h
index 5fb93b1ac3..abeb637e9f 100644
--- a/engines/twine/detection.h
+++ b/engines/twine/detection.h
@@ -26,8 +26,8 @@
 namespace TwinE {
 
 enum TwineGameType {
-	GType_LBA = (1 << 1),
-	GType_LBA2 = (1 << 2)
+	GType_LBA = 1,
+	GType_LBA2 = 2
 };
 
 } // End of namespace TwinE
diff --git a/engines/twine/metaengine.cpp b/engines/twine/metaengine.cpp
index 41dfb91418..b3e45c4010 100644
--- a/engines/twine/metaengine.cpp
+++ b/engines/twine/metaengine.cpp
@@ -47,7 +47,14 @@ public:
 
 	bool createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const override {
 		if (desc) {
-			*engine = new TwinE::TwinEEngine(syst, desc->language, desc->flags);
+			TwineGameType gameType = TwineGameType::GType_LBA;
+			const Common::String gameId = desc->gameId;
+			if (gameId == "lba") {
+				gameType = TwineGameType::GType_LBA;
+			} else if (gameId == "lba2") {
+				gameType = TwineGameType::GType_LBA2;
+			}
+			*engine = new TwinE::TwinEEngine(syst, desc->language, desc->flags, gameType);
 		}
 		return desc != nullptr;
 	}
diff --git a/engines/twine/twine.cpp b/engines/twine/twine.cpp
index fee71112a7..cdf789c4ac 100644
--- a/engines/twine/twine.cpp
+++ b/engines/twine/twine.cpp
@@ -66,8 +66,8 @@
 
 namespace TwinE {
 
-TwinEEngine::TwinEEngine(OSystem *system, Common::Language language, uint32 flags)
-    : Engine(system), _gameLang(language), _gameFlags(flags), _rnd("twine") {
+TwinEEngine::TwinEEngine(OSystem *system, Common::Language language, uint32 flags, TwineGameType gameType)
+    : Engine(system), _gameType(gameType), _gameLang(language), _gameFlags(flags), _rnd("twine") {
 	// Add default file directories
 	const Common::FSNode gameDataDir(ConfMan.get("path"));
 	SearchMan.addSubDirectoryMatching(gameDataDir, "fla");
diff --git a/engines/twine/twine.h b/engines/twine/twine.h
index 4d29479a34..9d965c38dd 100644
--- a/engines/twine/twine.h
+++ b/engines/twine/twine.h
@@ -158,16 +158,17 @@ private:
 	int32 saveFreezedTime = 0;
 	ActorMoveStruct loopMovePtr; // mainLoopVar1
 	PauseToken _pauseToken;
+	TwineGameType _gameType;
 
 public:
-	TwinEEngine(OSystem *system, Common::Language language, uint32 flags);
+	TwinEEngine(OSystem *system, Common::Language language, uint32 flagsTwineGameType, TwineGameType gameType);
 	~TwinEEngine() override;
 
 	Common::Error run() override;
 	bool hasFeature(EngineFeature f) const override;
 
-	bool isLBA1() const { return _gameFlags & TwineGameType::GType_LBA;};
-	bool isLBA2() const { return _gameFlags & TwineGameType::GType_LBA2;};
+	bool isLBA1() const { return _gameType == TwineGameType::GType_LBA; };
+	bool isLBA2() const { return _gameType == TwineGameType::GType_LBA2; };
 
 	Actor *_actor;
 	Animations *_animations;


Commit: f64dfffc48b1b53aebc53db17cac4f60e3dfb520
    https://github.com/scummvm/scummvm/commit/f64dfffc48b1b53aebc53db17cac4f60e3dfb520
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2020-10-26T18:11:14+01:00

Commit Message:
TWINE: removed manually searching the directories - SearchMan has vox and fla registered

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


diff --git a/engines/twine/flamovies.cpp b/engines/twine/flamovies.cpp
index 19f550cd1d..703c0067dc 100644
--- a/engines/twine/flamovies.cpp
+++ b/engines/twine/flamovies.cpp
@@ -249,11 +249,9 @@ void FlaMovies::playFlaMovie(const char *flaName) {
 	fadeOutFrames = 0;
 
 	file.close();
-	if (!file.open(FLA_DIR + fileNamePath)) {
-		if (!file.open(fileNamePath)) {
-			warning("Failed to open fla movie '%s'", fileNamePath.c_str());
-			return;
-		}
+	if (!file.open(fileNamePath)) {
+		warning("Failed to open fla movie '%s'", fileNamePath.c_str());
+		return;
 	}
 
 	file.read(&flaHeaderData.version, 6);
diff --git a/engines/twine/flamovies.h b/engines/twine/flamovies.h
index e877430e4c..3cc00b30ab 100644
--- a/engines/twine/flamovies.h
+++ b/engines/twine/flamovies.h
@@ -28,8 +28,6 @@
 
 namespace TwinE {
 
-/** FLA movie directory */
-#define FLA_DIR "fla/"
 /** Original FLA screen width */
 #define FLASCREEN_WIDTH 320
 /** Original FLA screen height */
diff --git a/engines/twine/sound.cpp b/engines/twine/sound.cpp
index 4a1025ba59..d5bffbd96f 100644
--- a/engines/twine/sound.cpp
+++ b/engines/twine/sound.cpp
@@ -76,18 +76,13 @@ void Sound::playFlaSample(int32 index, int32 frequency, int32 repeat, int32 x, i
 	}
 
 	uint8 *sampPtr;
-	int32 sampSize;
-	Common::String sampfile = Common::String::format("%s", Resources::HQR_FLASAMP_FILE);
-	sampSize = _engine->_hqrdepack->hqrGetallocEntry(&sampPtr, sampfile.c_str(), index);
+	const int32 sampSize = _engine->_hqrdepack->hqrGetallocEntry(&sampPtr, Resources::HQR_FLASAMP_FILE, index);
 	if (sampSize == 0) {
-		sampfile = Common::String::format(FLA_DIR "%s", Resources::HQR_FLASAMP_FILE);
-		sampSize = _engine->_hqrdepack->hqrGetallocEntry(&sampPtr, sampfile.c_str(), index);
-		if (sampSize == 0) {
-			return;
-		}
+		warning("Failed to load %s", Resources::HQR_FLASAMP_FILE);
+		return;
 	}
 
-	playSample(channelIdx, index, sampPtr, sampSize, repeat, sampfile.c_str());
+	playSample(channelIdx, index, sampPtr, sampSize, repeat, Resources::HQR_FLASAMP_FILE);
 }
 
 void Sound::playSample(int32 index, int32 frequency, int32 repeat, int32 x, int32 y, int32 z, int32 actorIdx) {
diff --git a/engines/twine/text.cpp b/engines/twine/text.cpp
index 3c2ba0ac9a..9547355693 100644
--- a/engines/twine/text.cpp
+++ b/engines/twine/text.cpp
@@ -38,8 +38,6 @@ namespace TwinE {
 
 /** FLA movie extension */
 #define VOX_EXT ".vox"
-/** Common movie directory */
-#define VOX_DIR "vox/"
 
 void Text::initVoxBank(int32 bankIdx) {
 	static const char *LanguageSufixTypes[] = {
@@ -62,7 +60,7 @@ void Text::initVoxBank(int32 bankIdx) {
 		error("bankIdx is out of bounds: %i", bankIdx);
 	}
 	// get the correct vox hqr file
-	currentVoxBankFile = Common::String::format(VOX_DIR "%s%s" VOX_EXT, LanguageTypes[_engine->cfgfile.LanguageId].id, LanguageSufixTypes[bankIdx]);
+	currentVoxBankFile = Common::String::format("%s%s" VOX_EXT, LanguageTypes[_engine->cfgfile.LanguageId].id, LanguageSufixTypes[bankIdx]);
 
 	// TODO check the rest to reverse
 }


Commit: 6622d32274697112bc84e5f1b34b98d969d13d5a
    https://github.com/scummvm/scummvm/commit/6622d32274697112bc84e5f1b34b98d969d13d5a
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2020-10-26T18:11:15+01:00

Commit Message:
TWINE: renamed variables

Changed paths:
    engines/twine/screens.cpp


diff --git a/engines/twine/screens.cpp b/engines/twine/screens.cpp
index c2aad58265..83d211fed0 100644
--- a/engines/twine/screens.cpp
+++ b/engines/twine/screens.cpp
@@ -61,12 +61,12 @@ void Screens::loadCustomPalette(int32 index) {
 }
 
 void Screens::convertPalToRGBA(const uint8* in, uint32* out) {
-	uint8* palDest = (uint8*)out;
+	uint8* paletteOut = (uint8*)out;
 	for (int i = 0; i < NUMOFCOLORS; i++) {
-		palDest[0] = in[0];
-		palDest[1] = in[1];
-		palDest[2] = in[2];
-		palDest += 4;
+		paletteOut[0] = in[0];
+		paletteOut[1] = in[1];
+		paletteOut[2] = in[2];
+		paletteOut += 4;
 		in += 3;
 	}
 }
@@ -122,21 +122,21 @@ int32 Screens::crossDot(int32 modifier, int32 color, int32 param, int32 intensit
 }
 
 void Screens::adjustPalette(uint8 R, uint8 G, uint8 B, const uint32 *rgbaPal, int32 intensity) {
-	uint32 pal2[NUMOFCOLORS];
+	uint32 pal[NUMOFCOLORS];
 
 	int32 counter = 0;
 
-	const uint8 *pal = (const uint8*)rgbaPal;
-	uint8 *localPalette = (uint8*)pal2;
-	uint8 *newR = &localPalette[0];
-	uint8 *newG = &localPalette[1];
-	uint8 *newB = &localPalette[2];
-	uint8 *newA = &localPalette[3];
+	const uint8 *paletteIn = (const uint8*)rgbaPal;
+	uint8 *paletteOut = (uint8*)pal;
+	uint8 *newR = &paletteOut[0];
+	uint8 *newG = &paletteOut[1];
+	uint8 *newB = &paletteOut[2];
+	uint8 *newA = &paletteOut[3];
 
 	for (int32 i = 0; i < NUMOFCOLORS; i++) {
-		*newR = crossDot(R, pal[counter], 100, intensity);
-		*newG = crossDot(G, pal[counter + 1], 100, intensity);
-		*newB = crossDot(B, pal[counter + 2], 100, intensity);
+		*newR = crossDot(R, paletteIn[counter], 100, intensity);
+		*newG = crossDot(G, paletteIn[counter + 1], 100, intensity);
+		*newB = crossDot(B, paletteIn[counter + 2], 100, intensity);
 		*newA = 0;
 
 		newR += 4;
@@ -147,29 +147,28 @@ void Screens::adjustPalette(uint8 R, uint8 G, uint8 B, const uint32 *rgbaPal, in
 		counter += 4;
 	}
 
-	_engine->setPalette(pal2);
+	_engine->setPalette(pal);
 }
 
 void Screens::adjustCrossPalette(const uint32 *pal1, const uint32 *pal2) {
 	uint32 pal[NUMOFCOLORS];
 
-	int32 i;
 	int32 counter = 0;
 	int32 intensity = 0;
 
 	const uint8 *pal1p = (const uint8*)pal1;
 	const uint8 *pal2p = (const uint8*)pal2;
-	uint8 *localPalette = (uint8*)pal;
+	uint8 *paletteOut = (uint8*)pal;
 	do {
 		counter = 0;
 
-		uint8 *newR = &localPalette[counter];
-		uint8 *newG = &localPalette[counter + 1];
-		uint8 *newB = &localPalette[counter + 2];
-		uint8 *newA = &localPalette[counter + 3];
+		uint8 *newR = &paletteOut[counter];
+		uint8 *newG = &paletteOut[counter + 1];
+		uint8 *newB = &paletteOut[counter + 2];
+		uint8 *newA = &paletteOut[counter + 3];
 
-		for (i = 0; i < NUMOFCOLORS; i++) {
-			*newR = crossDot(pal1p[counter], pal2p[counter], 100, intensity);
+		for (int32 i = 0; i < NUMOFCOLORS; i++) {
+			*newR = crossDot(pal1p[counter + 0], pal2p[counter + 0], 100, intensity);
 			*newG = crossDot(pal1p[counter + 1], pal2p[counter + 1], 100, intensity);
 			*newB = crossDot(pal1p[counter + 2], pal2p[counter + 2], 100, intensity);
 			*newA = 0;


Commit: 567cee4e6fc027a40ef1503ac4036223f01d5d19
    https://github.com/scummvm/scummvm/commit/567cee4e6fc027a40ef1503ac4036223f01d5d19
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2020-10-26T18:11:15+01:00

Commit Message:
TWINE: reduced code duplication

Changed paths:
    engines/twine/script_life.cpp
    engines/twine/script_move.cpp


diff --git a/engines/twine/script_life.cpp b/engines/twine/script_life.cpp
index 2dbb8d1301..888c4c5f48 100644
--- a/engines/twine/script_life.cpp
+++ b/engines/twine/script_life.cpp
@@ -956,13 +956,14 @@ static int32 lZOOM(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
 static int32 lPOS_POINT(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
 	int32 trackIdx = *(scriptPtr++);
 
-	engine->_renderer->destX = engine->_scene->sceneTracks[trackIdx].x;
-	engine->_renderer->destY = engine->_scene->sceneTracks[trackIdx].y;
-	engine->_renderer->destZ = engine->_scene->sceneTracks[trackIdx].z;
-
-	actor->x = engine->_renderer->destX;
-	actor->y = engine->_renderer->destY;
-	actor->z = engine->_renderer->destZ;
+	const ScenePoint& sp = engine->_scene->sceneTracks[trackIdx];
+	engine->_renderer->destX = sp.x;
+	engine->_renderer->destY = sp.y;
+	engine->_renderer->destZ = sp.z;
+
+	actor->x = sp.x;
+	actor->y = sp.y;
+	actor->z = sp.z;
 
 	return 0;
 }
diff --git a/engines/twine/script_move.cpp b/engines/twine/script_move.cpp
index 14ba9a7ece..97b2c273da 100644
--- a/engines/twine/script_move.cpp
+++ b/engines/twine/script_move.cpp
@@ -89,11 +89,12 @@ static int32 mGOTO_POINT(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor
 	actor->positionInMoveScript++;
 	engine->_scene->currentScriptValue = *(scriptPtr);
 
-	engine->_renderer->destX = engine->_scene->sceneTracks[engine->_scene->currentScriptValue].x;
-	engine->_renderer->destY = engine->_scene->sceneTracks[engine->_scene->currentScriptValue].y;
-	engine->_renderer->destZ = engine->_scene->sceneTracks[engine->_scene->currentScriptValue].z;
+	const ScenePoint& sp = engine->_scene->sceneTracks[engine->_scene->currentScriptValue];
+	engine->_renderer->destX = sp.x;
+	engine->_renderer->destY = sp.y;
+	engine->_renderer->destZ = sp.z;
 
-	newAngle = engine->_movements->getAngleAndSetTargetActorDistance(actor->x, actor->z, engine->_renderer->destX, engine->_renderer->destZ);
+	newAngle = engine->_movements->getAngleAndSetTargetActorDistance(actor->x, actor->z, sp.x, sp.z);
 
 	if (actor->staticFlags.bIsSpriteActor) {
 		actor->angle = newAngle;
@@ -150,17 +151,18 @@ static int32 mPOS_POINT(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor)
 	actor->positionInMoveScript++;
 	engine->_scene->currentScriptValue = *(scriptPtr);
 
-	engine->_renderer->destX = engine->_scene->sceneTracks[engine->_scene->currentScriptValue].x;
-	engine->_renderer->destY = engine->_scene->sceneTracks[engine->_scene->currentScriptValue].y;
-	engine->_renderer->destZ = engine->_scene->sceneTracks[engine->_scene->currentScriptValue].z;
+	const ScenePoint& sp = engine->_scene->sceneTracks[engine->_scene->currentScriptValue];
+	engine->_renderer->destX = sp.x;
+	engine->_renderer->destY = sp.y;
+	engine->_renderer->destZ = sp.z;
 
 	if (actor->staticFlags.bIsSpriteActor) {
 		actor->speed = 0;
 	}
 
-	actor->x = engine->_renderer->destX;
-	actor->y = engine->_renderer->destY;
-	actor->z = engine->_renderer->destZ;
+	actor->x = sp.x;
+	actor->y = sp.y;
+	actor->z = sp.z;
 
 	return 0;
 }
@@ -188,16 +190,15 @@ static int32 mSTOP(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
 
 /*0x0C*/
 static int32 mGOTO_SYM_POINT(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
-	int32 newAngle;
-
 	actor->positionInMoveScript++;
 	engine->_scene->currentScriptValue = *(scriptPtr);
 
-	engine->_renderer->destX = engine->_scene->sceneTracks[engine->_scene->currentScriptValue].x;
-	engine->_renderer->destY = engine->_scene->sceneTracks[engine->_scene->currentScriptValue].y;
-	engine->_renderer->destZ = engine->_scene->sceneTracks[engine->_scene->currentScriptValue].z;
+	const ScenePoint& sp = engine->_scene->sceneTracks[engine->_scene->currentScriptValue];
+	engine->_renderer->destX = sp.x;
+	engine->_renderer->destY = sp.y;
+	engine->_renderer->destZ = sp.z;
 
-	newAngle = 0x200 + engine->_movements->getAngleAndSetTargetActorDistance(actor->x, actor->z, engine->_renderer->destX, engine->_renderer->destZ);
+	const int32 newAngle = 0x200 + engine->_movements->getAngleAndSetTargetActorDistance(actor->x, actor->z, sp.x, sp.z);
 
 	if (actor->staticFlags.bIsSpriteActor) {
 		actor->angle = newAngle;
@@ -255,24 +256,27 @@ static int32 mSAMPLE(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
 static int32 mGOTO_POINT_3D(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
 	actor->positionInMoveScript++;
 
-	if (actor->staticFlags.bIsSpriteActor) {
-		engine->_scene->currentScriptValue = *(scriptPtr);
+	if (!actor->staticFlags.bIsSpriteActor) {
+		return 0;
+	}
 
-		engine->_renderer->destX = engine->_scene->sceneTracks[engine->_scene->currentScriptValue].x;
-		engine->_renderer->destY = engine->_scene->sceneTracks[engine->_scene->currentScriptValue].y;
-		engine->_renderer->destZ = engine->_scene->sceneTracks[engine->_scene->currentScriptValue].z;
+	engine->_scene->currentScriptValue = *(scriptPtr);
 
-		actor->angle = engine->_movements->getAngleAndSetTargetActorDistance(actor->x, actor->z, engine->_renderer->destX, engine->_renderer->destZ);
-		actor->animType = engine->_movements->getAngleAndSetTargetActorDistance(actor->y, 0, engine->_renderer->destY, engine->_movements->targetActorDistance);
+	const ScenePoint& sp = engine->_scene->sceneTracks[engine->_scene->currentScriptValue];
+	engine->_renderer->destX = sp.x;
+	engine->_renderer->destY = sp.y;
+	engine->_renderer->destZ = sp.z;
 
-		if (engine->_movements->targetActorDistance > 100) {
-			continueMove = 0;
-			actor->positionInMoveScript -= 2;
-		} else {
-			actor->x = engine->_renderer->destX;
-			actor->y = engine->_renderer->destY;
-			actor->z = engine->_renderer->destZ;
-		}
+	actor->angle = engine->_movements->getAngleAndSetTargetActorDistance(actor->x, actor->z, sp.x, sp.z);
+	actor->animType = engine->_movements->getAngleAndSetTargetActorDistance(actor->y, 0, sp.y, engine->_movements->targetActorDistance);
+
+	if (engine->_movements->targetActorDistance > 100) {
+		continueMove = 0;
+		actor->positionInMoveScript -= 2;
+	} else {
+		actor->x = sp.x;
+		actor->y = sp.y;
+		actor->z = sp.z;
 	}
 
 	return 0;
@@ -294,7 +298,7 @@ static int32 mSPEED(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
 static int32 mBACKGROUND(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
 	actor->positionInMoveScript++;
 
-	if (*(scriptPtr) != 0) {
+	if (*scriptPtr != 0) {
 		if (!actor->staticFlags.bIsBackgrounded) {
 			actor->staticFlags.bIsBackgrounded = 1;
 			if (actor->dynamicFlags.bIsVisible) {
@@ -315,11 +319,10 @@ static int32 mBACKGROUND(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor
 
 /*0x12*/
 static int32 mWAIT_NUM_SECOND(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
-	int32 numSeconds, currentTime;
 	actor->positionInMoveScript += 5;
 
-	numSeconds = *(scriptPtr++);
-	currentTime = *((int32 *)scriptPtr);
+	int32 numSeconds = *(scriptPtr++);
+	int32 currentTime = *((int32 *)scriptPtr);
 
 	if (currentTime == 0) {
 		currentTime = engine->lbaTime + numSeconds * 50;
@@ -344,9 +347,7 @@ static int32 mNO_BODY(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
 
 /*0x14*/
 static int32 mBETA(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
-	int16 beta;
-
-	beta = *((int16 *)scriptPtr);
+	const int16 beta = *((int16 *)scriptPtr);
 	actor->positionInMoveScript += 2;
 
 	actor->angle = beta;


Commit: ec9d67d0b07517ae76c9d44d8982681d3913f270
    https://github.com/scummvm/scummvm/commit/ec9d67d0b07517ae76c9d44d8982681d3913f270
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2020-10-26T18:11:15+01:00

Commit Message:
TWINE: add debug commands to switch the scene and give all items

Changed paths:
  A engines/twine/console.cpp
  A engines/twine/console.h
    engines/twine/animations.cpp
    engines/twine/debug_grid.cpp
    engines/twine/gamestate.h
    engines/twine/menu.cpp
    engines/twine/module.mk
    engines/twine/scene.cpp
    engines/twine/scene.h
    engines/twine/twine.cpp


diff --git a/engines/twine/animations.cpp b/engines/twine/animations.cpp
index 7d68bf570d..2750291480 100644
--- a/engines/twine/animations.cpp
+++ b/engines/twine/animations.cpp
@@ -38,12 +38,13 @@
 namespace TwinE {
 
 static const int32 magicLevelStrengthOfHit[] = {
-    kNoBallStrenght,
-    kYellowBallStrenght,
-    kGreenBallStrenght,
-    kRedBallStrenght,
-    kFireBallStrength,
-    0};
+	kNoBallStrength,
+	kYellowBallStrength,
+	kGreenBallStrength,
+	kRedBallStrength,
+	kFireBallStrength,
+	0
+};
 
 enum ActionType {
 	ACTION_HITTING = 0,
diff --git a/engines/twine/console.cpp b/engines/twine/console.cpp
new file mode 100644
index 0000000000..3b7f110e83
--- /dev/null
+++ b/engines/twine/console.cpp
@@ -0,0 +1,76 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "twine/console.h"
+#include "twine/twine.h"
+#include "twine/gamestate.h"
+#include "twine/scene.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));
+}
+
+TwinEConsole::~TwinEConsole() {
+}
+
+bool TwinEConsole::doChangeScene(int argc, const char **argv) {
+	if (argc <= 1) {
+		warning("Expected to get a scene index as first parameter");
+		return false;
+	}
+	byte newSceneIndex = atoi(argv[1]);
+	if (newSceneIndex >= LBA1SceneId::SceneIdMax) {
+		warning("Scene index out of bounds");
+		return false;
+	}
+	_engine->_scene->needChangeScene = atoi(argv[1]);
+	_engine->_scene->changeScene();
+	return true;
+}
+
+bool TwinEConsole::doGiveAllItems(int argc, const char **argv) {
+	_engine->_gameState->gameFlags[InventoryItems::kiHolomap] = 1;
+	_engine->_gameState->gameFlags[InventoryItems::kiMagicBall] = 1;
+	_engine->_gameState->gameFlags[InventoryItems::kiUseSabre] = 1;
+	_engine->_gameState->gameFlags[InventoryItems::kiTunic] = 1;
+	_engine->_gameState->gameFlags[InventoryItems::kiBookOfBu] = 1;
+	_engine->_gameState->gameFlags[InventoryItems::kiProtoPack ] = 1;
+	_engine->_gameState->gameFlags[InventoryItems::kiPinguin ] = 1;
+	_engine->_gameState->gameFlags[InventoryItems::kiBonusList ] = 1;
+	_engine->_gameState->gameFlags[InventoryItems::kiCloverLeaf] = 1;
+	int amount = 10;
+	if (argc > 1) {
+		amount = atoi(argv[1]);
+	}
+	_engine->_gameState->inventoryNumKeys += amount;
+	_engine->_gameState->inventoryNumKashes += amount;
+	_engine->_gameState->inventoryNumLeafsBox += amount;
+	_engine->_gameState->inventoryNumLeafs += amount;
+	_engine->_gameState->inventoryMagicPoints += amount;
+	_engine->_gameState->inventoryNumGas += amount;
+	return true;
+}
+
+} // End of namespace TwinE
diff --git a/engines/twine/console.h b/engines/twine/console.h
new file mode 100644
index 0000000000..30515c505a
--- /dev/null
+++ b/engines/twine/console.h
@@ -0,0 +1,46 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef TWINE_CONSOLE_H
+#define TWINE_CONSOLE_H
+
+#include "gui/debugger.h"
+
+namespace TwinE {
+
+class TwinEEngine;
+
+class TwinEConsole : public GUI::Debugger {
+private:
+	TwinEEngine *_engine;
+
+	bool doGiveAllItems(int argc, const char **argv);
+	bool doChangeScene(int argc, const char **argv);
+public:
+	TwinEConsole(TwinEEngine *engine);
+	~TwinEConsole() override;
+
+};
+
+} // End of namespace TwinE
+
+#endif // TWINE_CONSOLE_H
diff --git a/engines/twine/debug_grid.cpp b/engines/twine/debug_grid.cpp
index 53e3a1e84a..bf10e6f9fa 100644
--- a/engines/twine/debug_grid.cpp
+++ b/engines/twine/debug_grid.cpp
@@ -70,8 +70,9 @@ void DebugGrid::changeGrid() {
 	// Press up - more X positions
 	if (_engine->_input->toggleActionIfActive(TwinEActionType::NextRoom)) {
 		_engine->_scene->currentSceneIdx++;
-		if (_engine->_scene->currentSceneIdx > NUM_SCENES)
+		if (_engine->_scene->currentSceneIdx >= LBA1SceneId::SceneIdMax) {
 			_engine->_scene->currentSceneIdx = 0;
+		}
 		_engine->_scene->needChangeScene = _engine->_scene->currentSceneIdx;
 		_engine->_redraw->reqBgRedraw = true;
 	}
@@ -79,8 +80,9 @@ void DebugGrid::changeGrid() {
 	// Press down - less X positions
 	if (_engine->_input->toggleActionIfActive(TwinEActionType::PreviousRoom)) {
 		_engine->_scene->currentSceneIdx--;
-		if (_engine->_scene->currentSceneIdx < 0)
-			_engine->_scene->currentSceneIdx = NUM_SCENES;
+		if (_engine->_scene->currentSceneIdx < 0) {
+			_engine->_scene->currentSceneIdx = LBA1SceneId::SceneIdMax - 1;
+		}
 		_engine->_scene->needChangeScene = _engine->_scene->currentSceneIdx;
 		_engine->_redraw->reqBgRedraw = true;
 	}
diff --git a/engines/twine/gamestate.h b/engines/twine/gamestate.h
index 649baa05a5..a8d6549701 100644
--- a/engines/twine/gamestate.h
+++ b/engines/twine/gamestate.h
@@ -47,10 +47,10 @@ enum InventoryItems {
 
 /** Magicball strength*/
 enum MagicballStrengthType {
-	kNoBallStrenght = 2,
-	kYellowBallStrenght = 3,
-	kGreenBallStrenght = 4,
-	kRedBallStrenght = 6,
+	kNoBallStrength = 2,
+	kYellowBallStrength = 3,
+	kGreenBallStrength = 4,
+	kRedBallStrength = 6,
 	kFireBallStrength = 8
 };
 
diff --git a/engines/twine/menu.cpp b/engines/twine/menu.cpp
index 2b9ecac731..7447d37b1f 100644
--- a/engines/twine/menu.cpp
+++ b/engines/twine/menu.cpp
@@ -1000,7 +1000,6 @@ void Menu::drawInventoryItems() {
 }
 
 void Menu::processInventoryMenu() {
-
 	int32 tmpAlphaLight = _engine->_scene->alphaLight;
 	int32 tmpBetaLight = _engine->_scene->betaLight;
 
@@ -1012,6 +1011,8 @@ void Menu::processInventoryMenu() {
 
 	if (_engine->_gameState->inventoryNumLeafs > 0) {
 		_engine->_gameState->gameFlags[InventoryItems::kiCloverLeaf] = 1;
+	// TODO: shouldn't this get reset? } else {
+	//	_engine->_gameState->gameFlags[InventoryItems::kiCloverLeaf] = 0;
 	}
 
 	drawInventoryItems();
diff --git a/engines/twine/module.mk b/engines/twine/module.mk
index d5dfe8ebe1..2716de5512 100644
--- a/engines/twine/module.mk
+++ b/engines/twine/module.mk
@@ -4,6 +4,7 @@ MODULE_OBJS := \
 	actor.o \
 	animations.o \
 	collision.o \
+	console.o \
 	debug.o \
 	debug_grid.o \
 	debug_scene.o \
diff --git a/engines/twine/scene.cpp b/engines/twine/scene.cpp
index b6f71400c1..fe29adbe20 100644
--- a/engines/twine/scene.cpp
+++ b/engines/twine/scene.cpp
@@ -307,8 +307,9 @@ void Scene::changeScene() {
 	int32 a;
 
 	// change twinsen house destroyed hard-coded
-	if (needChangeScene == 4 && _engine->_gameState->gameFlags[30] != 0)
+	if (needChangeScene == 4 && _engine->_gameState->gameFlags[30] != 0) {
 		needChangeScene = 118;
+	}
 
 	// local backup previous scene
 	previousSceneIdx = currentSceneIdx;
diff --git a/engines/twine/scene.h b/engines/twine/scene.h
index 8b59daceb7..cda0b66c12 100644
--- a/engines/twine/scene.h
+++ b/engines/twine/scene.h
@@ -24,15 +24,13 @@
 #define TWINE_SCENE_H
 
 #include "common/scummsys.h"
+#include "common/util.h"
 #include "twine/actor.h"
 
 namespace TwinE {
 
 #define NUM_SCENES_FLAGS 80
 
-#define NUM_SCENES_ENTRIES 120
-#define NUM_SCENES NUM_SCENES_ENTRIES - 1
-
 #define NUM_MAX_ACTORS 100
 #define NUM_MAX_ZONES 100
 #define NUM_MAX_TRACKS 200
@@ -99,6 +97,131 @@ enum ZoneType {
 	kLadder = 6    // Hero can climb on it
 };
 
+enum LBA1SceneId {
+	Citadel_Island_Prison = 0,
+	Citadel_Island_outside_the_citadel = 1,
+	Citadel_Island_near_the_tavern = 2,
+	Citadel_Island_near_the_pharmacy = 3,
+	Citadel_Island_near_twinsens_house = 4,
+	Citadel_Island_inside_Twinsens_house = 5,
+	Citadel_Island_Harbor = 6,
+	Citadel_Island_Pharmacy = 7,
+	White_Leaf_Desert_Temple_of_Bu_1st_scene = 8,
+	Hamalayi_Mountains_landing_place = 9,
+	Principal_Island_Library = 10,
+	Principal_Island_Harbor = 11,
+	Principal_Island_outside_the_fortress = 12,
+	Principal_Island_Old_Burg = 13,
+	Citadel_Island_Tavern = 14,
+	Hamalayi_Mountains_Rabbibunny_village = 15,
+	Citadel_Island_inside_a_Rabbibunny_house = 16,
+	Principal_Island_Ruins = 17,
+	Principal_Island_outside_the_library = 18,
+	Principal_Island_Militairy_camp = 19,
+	Citadel_Island_Architects_house = 20,
+	Citadel_Island_secret_chamber_in_the_house = 21,
+	Principal_Island_Ticket_office = 22,
+	Principal_Island_Prison = 23,
+	Principal_Island_Port_Belooga = 24,
+	Principal_Island_Peg_Leg_Street = 25,
+	Principal_Island_Shop = 26,
+	Principal_Island_Locksmith = 27,
+	Principal_Island_inside_a_Rabbibunny_house = 28,
+	Principal_Island_Astronimers_House = 29,
+	Principal_Island_Tavern = 30,
+	Principal_Island_Basement_of_the_Astronomer = 31,
+	Principal_Island_Stables = 32,
+	Citadel_Island_Cellar_of_the_Tavern = 33,
+	Citadel_Island_Sewer_of_the_1st_scene = 34,
+	Citadel_Island_Warehouse = 35,
+	White_Leaf_Desert_outside_the_Temple_of_Bu = 36,
+	Principal_Island_outside_the_water_tower = 37,
+	Principal_Island_inside_the_water_tower = 38,
+	White_Leaf_Desert_Militairy_camp = 39,
+	White_Leaf_Desert_Temple_of_Bu_2nd_scene = 40,
+	White_Leaf_Desert_Temple_of_Bu_3rd_scene = 41,
+	Proxima_Island_Proxim_City = 42,
+	Proxima_Island_Museum = 43,
+	Proxima_Island_near_the_Inventors_house = 44,
+	Proxima_Island_upper_rune_stone = 45,
+	Proxima_Island_lower_rune_stone = 46,
+	Proxima_Island_befor_the_upper_rune_stone = 47,
+	Proxima_Island_Forgers_house = 48,
+	Proxima_Island_Prison = 49,
+	Proxima_Island_Shop = 50,
+	Proxima_Island_Sewer = 51,
+	Principal_Island_house_at_Peg_Leg_Street = 52,
+	Proxima_Island_Grobo_house = 53,
+	Proxima_Island_Inventors_house = 54,
+	Citadel_Island_Sewer_secret = 55,
+	Principal_Island_Sewer_secret = 56,
+	White_Leaf_Desert_Maze = 57,
+	Principal_Island_House_with_the_TV = 58,
+	Rebelion_Island_Harbor = 59,
+	Rebelion_Island_Rebel_camp = 60,
+	Some_room_cut_out = 61,
+	Hamalayi_Mountains_1st_fighting_scene = 62,
+	Hamalayi_Mountains_2nd_fighting_scene = 63,
+	Hamalayi_Mountains_Prison = 64,
+	Hamalayi_Mountains_outside_the_transporter = 65,
+	Hamalayi_Mountains_inside_the_transporter = 66,
+	Hamalayi_Mountains_Mutation_centre_1st_scene = 67,
+	Hamalayi_Mountains_Mutation_centre_2nd_scene = 68,
+	Hamalayi_Mountains_3rd_fighting_scene = 69,
+	Hamalayi_Mountains_Entrance_to_the_prison = 70,
+	Hamalayi_Mountains_outside_the_prison = 71,
+	Hamalayi_Mountains_Catamaran_dock = 72,
+	Hamalayi_Mountains_Bunker_near_clear_water = 73,
+	Tippet_Island_Village = 74,
+	Tippet_Island_Secret_passage_scene_2 = 75,
+	Tippet_Island_near_the_bar = 76,
+	Tippet_Island_Secret_passage_scene_1 = 77,
+	Tippet_Island_near_the_Dino_Fly = 78,
+	Tippet_Island_Secret_passage_scene_3 = 79,
+	Tippet_Island_Twinsun_Cafe = 80,
+	Hamalayi_Mountains_Sacret_Carrot = 81,
+	Hamalayi_Mountains_Backdoor_of_the_prison = 82,
+	Fortress_Island_inside_the_fortress = 83,
+	Fortress_Island_outside_the_forstress = 84,
+	Fortress_Island_Secret_passage_scene_1 = 85,
+	Fortress_Island_Secret_in_the_fortress = 86,
+	Fortress_Island_near_Zoes_cell = 87,
+	Fortress_Island_Swimming_pool = 88,
+	Fortress_Island_Cloning_centre = 89,
+	Fortress_Island_Rune_stone = 90,
+	Hamalayi_Mountains_Behind_the_sacret_carrot = 91,
+	Hamalayi_Mountains_Clear_water_lake = 92,
+	Fortress_Island_outside_fortress_destroyed = 93,
+	Brundle_Island_outside_the_teleportation = 94,
+	Brundle_Island_inside_the_teleportation = 95,
+	Hamalayi_Mountains_Ski_resort = 96,
+	Brundle_Island_Docks = 97,
+	Brundle_Island_Secret_room = 98,
+	Brundle_Island_near_the_telepods = 99,
+	Fortress_Island_Docks = 100,
+	Tippet_Island_Shop = 101,
+	Principal_Island_house_in_port_Belooga = 102,
+	Brundle_Island_Painters_house = 103,
+	Citadel_Island_Ticket_Office = 104,
+	Principal_Island_inside_the_fortress = 105,
+	Polar_Island_2nd_scene = 106,
+	Polar_Island_3rd_scene = 107,
+	Polar_Island_Before_the_rocky_peak = 108,
+	Polar_Island_4th_scene = 109,
+	Polar_Island_The_rocky_peak = 110,
+	Polar_Island_on_the_rocky_peak = 111,
+	Polar_Island_Before_the_end_room = 112,
+	Polar_Island_Final_Battle = 113,
+	Polar_Island_end_scene = 114,
+	Polar_Island_1st_scene = 115,
+	Citadel_Island_end_sequence_1 = 116,
+	Citadel_Island_end_sequence_2 = 117,
+	Citadel_Island_Twinsens_house_destroyed = 118,
+	Credits_List_Sequence = 119,
+
+	SceneIdMax = 120
+};
+
 #define OWN_ACTOR_SCENE_INDEX 0
 
 class TwinEEngine;
@@ -191,7 +314,7 @@ public:
 	int16 changeRoomVar10 = 0;
 	int16 changeRoomVar11 = 0;
 
-	uint8 sceneFlags[80] {0}; // cubeFlags
+	uint8 sceneFlags[NUM_SCENES_FLAGS] {0}; // cubeFlags
 
 	int32 sceneNumZones = 0;
 	ZoneStruct sceneZones[NUM_MAX_ZONES];
diff --git a/engines/twine/twine.cpp b/engines/twine/twine.cpp
index cdf789c4ac..bb3021a568 100644
--- a/engines/twine/twine.cpp
+++ b/engines/twine/twine.cpp
@@ -39,6 +39,7 @@
 #include "twine/actor.h"
 #include "twine/animations.h"
 #include "twine/collision.h"
+#include "twine/console.h"
 #include "twine/debug.h"
 #include "twine/debug_grid.h"
 #include "twine/debug_scene.h"
@@ -73,7 +74,7 @@ TwinEEngine::TwinEEngine(OSystem *system, Common::Language language, uint32 flag
 	SearchMan.addSubDirectoryMatching(gameDataDir, "fla");
 	SearchMan.addSubDirectoryMatching(gameDataDir, "vox");
 
-	setDebugger(new GUI::Debugger());
+	setDebugger(new TwinEConsole(this));
 	_actor = new Actor(this);
 	_animations = new Animations(this);
 	_collision = new Collision(this);
@@ -465,7 +466,8 @@ int32 TwinEEngine::runGameEngine() { // mainLoopInteration
 					_gameState->gameFlags[InventoryItems::kiPinguin] = 0; // byte_50D89 = 0;
 					pinguin->info0 = lbaTime + 1500;
 				}
-			} break;
+				break;
+			}
 			case kiBonusList: {
 				unfreezeTime();
 				_redraw->redrawEngineActions(1);
@@ -476,7 +478,8 @@ int32 TwinEEngine::runGameEngine() { // mainLoopInteration
 				_text->drawTextFullscreen(162);
 				_text->textClipSmall();
 				_text->initTextBank(_text->currentTextBank + 3);
-			} break;
+				break;
+			}
 			case kiCloverLeaf:
 				if (_scene->sceneHero->life < 50) {
 					if (_gameState->inventoryNumLeafs > 0) {


Commit: be4725fe580f7e530d731510bf73090dcfe7018f
    https://github.com/scummvm/scummvm/commit/be4725fe580f7e530d731510bf73090dcfe7018f
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2020-10-26T18:11:15+01:00

Commit Message:
TWINE: let the debug command give all items

Changed paths:
    engines/twine/console.cpp


diff --git a/engines/twine/console.cpp b/engines/twine/console.cpp
index 3b7f110e83..3bbcf74afc 100644
--- a/engines/twine/console.cpp
+++ b/engines/twine/console.cpp
@@ -51,15 +51,9 @@ bool TwinEConsole::doChangeScene(int argc, const char **argv) {
 }
 
 bool TwinEConsole::doGiveAllItems(int argc, const char **argv) {
-	_engine->_gameState->gameFlags[InventoryItems::kiHolomap] = 1;
-	_engine->_gameState->gameFlags[InventoryItems::kiMagicBall] = 1;
-	_engine->_gameState->gameFlags[InventoryItems::kiUseSabre] = 1;
-	_engine->_gameState->gameFlags[InventoryItems::kiTunic] = 1;
-	_engine->_gameState->gameFlags[InventoryItems::kiBookOfBu] = 1;
-	_engine->_gameState->gameFlags[InventoryItems::kiProtoPack ] = 1;
-	_engine->_gameState->gameFlags[InventoryItems::kiPinguin ] = 1;
-	_engine->_gameState->gameFlags[InventoryItems::kiBonusList ] = 1;
-	_engine->_gameState->gameFlags[InventoryItems::kiCloverLeaf] = 1;
+	for (int32 i = 0; i < NUM_INVENTORY_ITEMS; ++i) {
+		_engine->_gameState->gameFlags[i] = 1;
+	}
 	int amount = 10;
 	if (argc > 1) {
 		amount = atoi(argv[1]);


Commit: 3283e420e247fdaa04e4016acaeedf182807e1ed
    https://github.com/scummvm/scummvm/commit/3283e420e247fdaa04e4016acaeedf182807e1ed
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2020-10-26T18:11:15+01:00

Commit Message:
TWINE: replaced magic numbers

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


diff --git a/engines/twine/gamestate.cpp b/engines/twine/gamestate.cpp
index 662e3bcc35..323244a412 100644
--- a/engines/twine/gamestate.cpp
+++ b/engines/twine/gamestate.cpp
@@ -143,7 +143,7 @@ void GameState::initEngineVars() {
 	_engine->_scene->newHeroZ = 0x2000;
 
 	_engine->_scene->currentSceneIdx = -1;
-	_engine->_scene->needChangeScene = 0;
+	_engine->_scene->needChangeScene = LBA1SceneId::Citadel_Island_Prison;
 	_engine->quitGame = -1;
 	_engine->_scene->mecaPinguinIdx = -1;
 	_engine->_menuOptions->canShowCredits = false;
diff --git a/engines/twine/gamestate.h b/engines/twine/gamestate.h
index a8d6549701..152b19b4de 100644
--- a/engines/twine/gamestate.h
+++ b/engines/twine/gamestate.h
@@ -41,6 +41,7 @@ enum InventoryItems {
 	kiBookOfBu = 5,
 	kiProtoPack = 12,
 	kiPinguin = 14,
+	kGasItem = 15,
 	kiBonusList = 26,
 	kiCloverLeaf = 27
 };
diff --git a/engines/twine/menu.cpp b/engines/twine/menu.cpp
index 7447d37b1f..7f350b01df 100644
--- a/engines/twine/menu.cpp
+++ b/engines/twine/menu.cpp
@@ -961,13 +961,13 @@ void Menu::drawMagicItemsBox(int32 left, int32 top, int32 right, int32 bottom, i
 }
 
 void Menu::drawItem(int32 item) {
-	int32 itemX = (item / 4) * 85 + 64;
-	int32 itemY = (item & 3) * 75 + 52;
+	const int32 itemX = (item / 4) * 85 + 64;
+	const int32 itemY = (item & 3) * 75 + 52;
 
-	int32 left = itemX - 37;
-	int32 right = itemX + 37;
-	int32 top = itemY - 32;
-	int32 bottom = itemY + 32;
+	const int32 left = itemX - 37;
+	const int32 right = itemX + 37;
+	const int32 top = itemY - 32;
+	const int32 bottom = itemY + 32;
 
 	_engine->_interface->drawSplittedBox(left, top, right, bottom,
 	                                     inventorySelectedItem == item ? inventorySelectedColor : 0);
@@ -977,7 +977,7 @@ void Menu::drawItem(int32 item) {
 		itemAngle[item] += 8;
 		_engine->_renderer->renderInventoryItem(itemX, itemY, _engine->_resources->inventoryTable[item], itemAngle[item], 15000);
 
-		if (item == 15) { // has GAS
+		if (item == InventoryItems::kGasItem) { // has GAS
 			_engine->_text->setFontColor(15);
 			Common::String inventoryNumGas = Common::String::format("%d", _engine->_gameState->inventoryNumGas);
 			_engine->_text->drawText(left + 3, top + 32, inventoryNumGas.c_str());


Commit: 3dd13e456ba1da38581821c629d8df1ef2d4831a
    https://github.com/scummvm/scummvm/commit/3dd13e456ba1da38581821c629d8df1ef2d4831a
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2020-10-26T18:11:15+01:00

Commit Message:
TWINE: fixed typo

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


diff --git a/engines/twine/input.cpp b/engines/twine/input.cpp
index 333b0210b3..9ced81a913 100644
--- a/engines/twine/input.cpp
+++ b/engines/twine/input.cpp
@@ -83,11 +83,11 @@ ScopedKeyMapperDisable::~ScopedKeyMapperDisable() {
 
 ScopedKeyMap::ScopedKeyMap(TwinEEngine* engine, const char *id) : _engine(engine) {
 	_prevKeyMap = _engine->_input->currentKeyMap();
-	_engine->_input->enabledKeyMap(cutsceneKeyMapId);
+	_engine->_input->enableKeyMap(cutsceneKeyMapId);
 }
 
 ScopedKeyMap::~ScopedKeyMap() {
-	_engine->_input->enabledKeyMap(_prevKeyMap.c_str());
+	_engine->_input->enableKeyMap(_prevKeyMap.c_str());
 }
 
 Input::Input(TwinEEngine *engine) : _engine(engine) {}
@@ -122,7 +122,7 @@ bool Input::isQuickBehaviourActionActive() const {
 	return isActionActive(TwinEActionType::QuickBehaviourNormal) || isActionActive(TwinEActionType::QuickBehaviourAthletic) || isActionActive(TwinEActionType::QuickBehaviourAggressive) || isActionActive(TwinEActionType::QuickBehaviourDiscreet);
 }
 
-void Input::enabledKeyMap(const char *id) {
+void Input::enableKeyMap(const char *id) {
 	if (_currentKeyMap == id) {
 		return;
 	}
diff --git a/engines/twine/input.h b/engines/twine/input.h
index 685dc22ba8..4a818a0a23 100644
--- a/engines/twine/input.h
+++ b/engines/twine/input.h
@@ -174,7 +174,7 @@ public:
 	 * @brief Dependent on the context we are currently in the game, we might want to disable certain keymaps.
 	 * Like disabling ui keymaps when we are in-game - or vice versa.
 	 */
-	void enabledKeyMap(const char *id);
+	void enableKeyMap(const char *id);
 
 	const Common::String currentKeyMap() const;
 
diff --git a/engines/twine/menu.cpp b/engines/twine/menu.cpp
index 7f350b01df..a3ee36c389 100644
--- a/engines/twine/menu.cpp
+++ b/engines/twine/menu.cpp
@@ -454,7 +454,7 @@ int32 Menu::processMenu(int16 *menuSettings) {
 	const int32 numEntry = menuSettings[MenuSettings_NumberOfButtons];
 	int32 maxButton = numEntry - 1;
 
-	_engine->_input->enabledKeyMap(uiKeyMapId);
+	_engine->_input->enableKeyMap(uiKeyMapId);
 
 	_engine->_screens->loadMenuImage(false);
 	do {
diff --git a/engines/twine/twine.cpp b/engines/twine/twine.cpp
index bb3021a568..52263486c3 100644
--- a/engines/twine/twine.cpp
+++ b/engines/twine/twine.cpp
@@ -253,7 +253,7 @@ void TwinEEngine::initEngine() {
 	_music->initCdrom();
 
 #if TWINE_PLAY_INTROS
-	_input->enabledKeyMap(cutsceneKeyMapId);
+	_input->enableKeyMap(cutsceneKeyMapId);
 	// Display company logo
 	_screens->adelineLogo();
 
@@ -275,7 +275,7 @@ void TwinEEngine::initEngine() {
 
 	_flaMovies->playFlaMovie(FLA_DRAGON3);
 #else
-	_input->enabledKeyMap(uiKeyMapId);
+	_input->enableKeyMap(uiKeyMapId);
 #endif
 
 	_screens->loadMenuImage();
@@ -335,7 +335,7 @@ void TwinEEngine::processActorSamplePosition(int32 actorIdx) {
 }
 
 int32 TwinEEngine::runGameEngine() { // mainLoopInteration
-	_input->enabledKeyMap(mainKeyMapId);
+	_input->enableKeyMap(mainKeyMapId);
 
 	readKeys();
 


Commit: 40564c4b0043f434cb16cec54cce85736814eb64
    https://github.com/scummvm/scummvm/commit/40564c4b0043f434cb16cec54cce85736814eb64
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2020-10-26T18:11:15+01:00

Commit Message:
TWINE: nextpage action to read multi page ui text

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


diff --git a/engines/twine/input.h b/engines/twine/input.h
index 4a818a0a23..444b48a331 100644
--- a/engines/twine/input.h
+++ b/engines/twine/input.h
@@ -73,6 +73,7 @@ enum TwinEActionType {
 	UIRight,
 	UIUp,
 	UIDown,
+	UINextPage,
 
 	CutsceneAbort,
 
@@ -120,6 +121,7 @@ static constexpr const struct ActionMapping {
     {UIRight, 0x00},
     {UIUp, 0x00},
     {UIDown, 0x00},
+    {UINextPage, 0x00},
     {CutsceneAbort, 0x00}};
 
 static_assert(ARRAYSIZE(twineactions) == TwinEActionType::Max, "Unexpected action mapping array size");
diff --git a/engines/twine/metaengine.cpp b/engines/twine/metaengine.cpp
index b3e45c4010..a5ef1c8caf 100644
--- a/engines/twine/metaengine.cpp
+++ b/engines/twine/metaengine.cpp
@@ -271,6 +271,12 @@ Common::KeymapArray TwinEMetaEngine::initKeymaps(const char *target) const {
 		act->addDefaultInputMapping("KP4");
 		uiKeyMap->addAction(act);
 
+		act = new Action("NEXTPAGE", _("Next Page"));
+		act->setCustomEngineActionEvent(TwinEActionType::UINextPage);
+		act->addDefaultInputMapping("SPACE");
+		act->addDefaultInputMapping("PAGEDOWN");
+		uiKeyMap->addAction(act);
+
 		array[1] = uiKeyMap;
 	}
 


Commit: 05bc1195269d92a0e4dd4ef83461e41011e31ff8
    https://github.com/scummvm/scummvm/commit/05bc1195269d92a0e4dd4ef83461e41011e31ff8
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2020-10-26T18:11:15+01:00

Commit Message:
TWINE: tweaked inventory menu (not yet working 100%)

Changed paths:
    engines/twine/menu.cpp


diff --git a/engines/twine/menu.cpp b/engines/twine/menu.cpp
index a3ee36c389..130275a785 100644
--- a/engines/twine/menu.cpp
+++ b/engines/twine/menu.cpp
@@ -1028,20 +1028,22 @@ void Menu::processInventoryMenu() {
 		_engine->readKeys();
 		int32 prevSelectedItem = inventorySelectedItem;
 
-		if (_engine->_input->toggleAbortAction() || _engine->_input->isActionActive(TwinEActionType::ExecuteBehaviourAction)) {
+		if (_engine->_input->toggleAbortAction()) {
 			break;
 		}
 
-		if (_engine->_input->toggleActionIfActive(TwinEActionType::UIDown)) {
+		const bool cursorDown = _engine->_input->toggleActionIfActive(TwinEActionType::UIDown);
+		const bool cursorUp = _engine->_input->toggleActionIfActive(TwinEActionType::UIUp);
+		const bool cursorLeft = _engine->_input->toggleActionIfActive(TwinEActionType::UILeft);
+		const bool cursorRight = _engine->_input->toggleActionIfActive(TwinEActionType::UIRight);
+		if (cursorDown) {
 			inventorySelectedItem++;
 			if (inventorySelectedItem >= NUM_INVENTORY_ITEMS) {
 				inventorySelectedItem = 0;
 			}
 			drawItem(prevSelectedItem);
 			bx = 3;
-		}
-
-		if (_engine->_input->toggleActionIfActive(TwinEActionType::UIUp)) {
+		} else if (cursorUp) {
 			inventorySelectedItem--;
 			if (inventorySelectedItem < 0) {
 				inventorySelectedItem = NUM_INVENTORY_ITEMS - 1;
@@ -1050,16 +1052,14 @@ void Menu::processInventoryMenu() {
 			bx = 3;
 		}
 
-		if (_engine->_input->toggleActionIfActive(TwinEActionType::UILeft)) {
+		if (cursorLeft) {
 			inventorySelectedItem -= 4;
 			if (inventorySelectedItem < 0) {
 				inventorySelectedItem += NUM_INVENTORY_ITEMS;
 			}
 			drawItem(prevSelectedItem);
 			bx = 3;
-		}
-
-		if (_engine->_input->toggleActionIfActive(TwinEActionType::UIRight)) {
+		} else if (cursorRight) {
 			inventorySelectedItem += 4;
 			if (inventorySelectedItem >= NUM_INVENTORY_ITEMS) {
 				inventorySelectedItem -= NUM_INVENTORY_ITEMS;
@@ -1088,7 +1088,7 @@ void Menu::processInventoryMenu() {
 			_engine->_system->delayMillis(15);
 		}
 
-		if (_engine->_input->toggleActionIfActive(TwinEActionType::UIUp)) {
+		if (_engine->_input->toggleActionIfActive(TwinEActionType::UINextPage)) {
 			if (bx == 2) {
 				_engine->_text->initInventoryDialogueBox();
 				bx = 0;
@@ -1102,7 +1102,7 @@ void Menu::processInventoryMenu() {
 
 		drawItem(inventorySelectedItem);
 
-		if (_engine->_input->toggleActionIfActive(TwinEActionType::UIDown) && _engine->_gameState->gameFlags[inventorySelectedItem] == 1 && !_engine->_gameState->gameFlags[GAMEFLAG_INVENTORY_DISABLED] && inventorySelectedItem < NUM_INVENTORY_ITEMS) {
+		if (_engine->_input->toggleActionIfActive(TwinEActionType::UIEnter) && _engine->_gameState->gameFlags[inventorySelectedItem] == 1 && !_engine->_gameState->gameFlags[GAMEFLAG_INVENTORY_DISABLED] && inventorySelectedItem < NUM_INVENTORY_ITEMS) {
 			_engine->loopInventoryItem = inventorySelectedItem;
 			inventorySelectedColor = 91;
 			drawItem(inventorySelectedItem);


Commit: 7f8c588af9eb1ad7d82ec8b8054868d36185d296
    https://github.com/scummvm/scummvm/commit/7f8c588af9eb1ad7d82ec8b8054868d36185d296
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2020-10-26T18:11:15+01:00

Commit Message:
TWINE: replaced magic numbers

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


diff --git a/engines/twine/menuoptions.cpp b/engines/twine/menuoptions.cpp
index fed6aca658..21296aa2f3 100644
--- a/engines/twine/menuoptions.cpp
+++ b/engines/twine/menuoptions.cpp
@@ -97,8 +97,8 @@ void MenuOptions::showCredits() {
 	int32 tmpShadowMode = _engine->cfgfile.ShadowMode;
 	_engine->cfgfile.ShadowMode = 0;
 	_engine->_gameState->initEngineVars();
-	_engine->_scene->currentSceneIdx = 119;
-	_engine->_scene->needChangeScene = 119;
+	_engine->_scene->currentSceneIdx = LBA1SceneId::Credits_List_Sequence;
+	_engine->_scene->needChangeScene = LBA1SceneId::Credits_List_Sequence;
 
 	_engine->gameEngineLoop();
 
diff --git a/engines/twine/scene.cpp b/engines/twine/scene.cpp
index fe29adbe20..c52deabad9 100644
--- a/engines/twine/scene.cpp
+++ b/engines/twine/scene.cpp
@@ -183,7 +183,7 @@ void Scene::loadScene() {
 		}
 
 		sceneActors[i].body = *(localScene++);
-		sceneActors[i].anim = (AnimationTypes)*(localScene++);
+		sceneActors[i].anim = (AnimationTypes) * (localScene++);
 		sceneActors[i].sprite = *((uint16 *)localScene);
 		localScene += 2;
 		sceneActors[i].x = *((uint16 *)localScene);
@@ -307,8 +307,8 @@ void Scene::changeScene() {
 	int32 a;
 
 	// change twinsen house destroyed hard-coded
-	if (needChangeScene == 4 && _engine->_gameState->gameFlags[30] != 0) {
-		needChangeScene = 118;
+	if (needChangeScene == LBA1SceneId::Citadel_Island_near_twinsens_house && _engine->_gameState->gameFlags[30] != 0) {
+		needChangeScene = LBA1SceneId::Citadel_Island_Twinsens_house_destroyed;
 	}
 
 	// local backup previous scene
@@ -330,7 +330,7 @@ void Scene::changeScene() {
 
 	// TODO: treat holomap trajectories
 
-	if (needChangeScene == 116 || needChangeScene == 117) {
+	if (needChangeScene == LBA1SceneId::Citadel_Island_end_sequence_1 || needChangeScene == LBA1SceneId::Citadel_Island_end_sequence_2) {
 		_engine->_text->currentTextBank = 10;
 	}
 
@@ -394,7 +394,7 @@ void Scene::changeScene() {
 	}
 }
 
-ActorStruct* Scene::getActor(int32 actorIdx) {
+ActorStruct *Scene::getActor(int32 actorIdx) {
 	assert(actorIdx >= 0);
 	assert(actorIdx < NUM_MAX_ACTORS);
 	return &sceneActors[actorIdx];
diff --git a/engines/twine/scene.h b/engines/twine/scene.h
index cda0b66c12..7045d86041 100644
--- a/engines/twine/scene.h
+++ b/engines/twine/scene.h
@@ -246,7 +246,7 @@ public:
 
 	uint8 *currentScene = nullptr;
 
-	int32 needChangeScene = 0;
+	int32 needChangeScene = LBA1SceneId::Citadel_Island_Prison;
 	int32 currentSceneIdx = 0;
 	int32 previousSceneIdx = 0;
 


Commit: 74896d184682c7d778bf3fc96357e74805e861e6
    https://github.com/scummvm/scummvm/commit/74896d184682c7d778bf3fc96357e74805e861e6
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2020-10-26T18:11:15+01:00

Commit Message:
TWINE: reduced scope + cleanup

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


diff --git a/engines/twine/menuoptions.cpp b/engines/twine/menuoptions.cpp
index 21296aa2f3..74f684e96c 100644
--- a/engines/twine/menuoptions.cpp
+++ b/engines/twine/menuoptions.cpp
@@ -116,34 +116,31 @@ void MenuOptions::showCredits() {
 }
 
 void MenuOptions::drawSelectableCharacter(int32 x, int32 y, int32 arg) {
-	char buffer[256];
-	int32 centerX, left, top, centerY, bottom, right, right2;
+	char buffer[2];
 
 	buffer[0] = allowedCharIndex[y + x * 14];
+	buffer[1] = '\0';
 
-	centerX = y * 45 + 25;
-	left = centerX - 20;
-	right = centerX + 20;
-	top = x * 56 + 200 - 25;
-	buffer[1] = 0;
-	centerY = x * 56 + 200;
-	bottom = x * 56 + 200 + 25;
+	const int32 centerX = y * 45 + 25;
+	const int32 left = centerX - 20;
+	const int32 right = centerX + 20;
+	const int32 top = x * 56 + 200 - 25;
+	const int32 centerY = x * 56 + 200;
+	const int32 bottom = x * 56 + 200 + 25;
 
 	if (arg != 0) {
 		_engine->_interface->drawSplittedBox(left, top, right, bottom, 91);
 	} else {
 		_engine->_interface->blitBox(left, top, right, bottom, (const int8 *)_engine->workVideoBuffer.getPixels(), left, top, (int8 *)_engine->frontVideoBuffer.getPixels());
-		right2 = right;
-		_engine->_interface->drawTransparentBox(left, top, right2, bottom, 4);
+		_engine->_interface->drawTransparentBox(left, top, right, bottom, 4);
 	}
 
 	_engine->_menu->drawBox(left, top, right, bottom);
-	right2 = right;
 
 	_engine->_text->setFontColor(15);
 	_engine->_text->drawText(centerX - _engine->_text->getTextSize(buffer) / 2, centerY - 18, buffer);
 
-	_engine->copyBlockPhys(left, top, right2, bottom);
+	_engine->copyBlockPhys(left, top, right, bottom);
 }
 
 void MenuOptions::drawSelectableCharacters() {
diff --git a/engines/twine/scene.cpp b/engines/twine/scene.cpp
index c52deabad9..4218b63b3e 100644
--- a/engines/twine/scene.cpp
+++ b/engines/twine/scene.cpp
@@ -20,6 +20,7 @@
  *
  */
 
+#include "twine/scene.h"
 #include "common/util.h"
 #include "twine/actor.h"
 #include "twine/animations.h"
@@ -31,7 +32,6 @@
 #include "twine/redraw.h"
 #include "twine/renderer.h"
 #include "twine/resources.h"
-#include "twine/scene.h"
 #include "twine/screens.h"
 #include "twine/sound.h"
 #include "twine/text.h"
@@ -435,57 +435,52 @@ void Scene::processEnvironmentSound() {
 }
 
 void Scene::processZoneExtraBonus(ZoneStruct *zone) {
-	int32 a, numBonus;
-	int8 bonusTable[8], currentBonus;
-
-	numBonus = 0;
-
 	// bonus not used yet
-	if (!zone->infoData.generic.info3) {
-		for (a = 0; a < 5; a++) {
-			if (zone->infoData.generic.info1 & (1 << (a + 4))) {
-				bonusTable[numBonus++] = a;
-			}
+	if (zone->infoData.generic.info3) {
+		return;
+	}
+	int8 bonusTable[8];
+	int32 numBonus = 0;
+	for (int32 a = 0; a < 5; a++) {
+		if (zone->infoData.generic.info1 & (1 << (a + 4))) {
+			bonusTable[numBonus++] = a;
 		}
+	}
 
-		if (numBonus) {
-			int32 angle, index;
-			currentBonus = bonusTable[_engine->getRandomNumber(numBonus)];
+	if (numBonus) {
+		int32 angle, index;
+		int8 currentBonus = bonusTable[_engine->getRandomNumber(numBonus)];
 
-			// if bonus is magic an no magic level yet, then give life points
-			if (!_engine->_gameState->magicLevelIdx && currentBonus == 2) {
-				currentBonus = 1;
-			}
+		// if bonus is magic an no magic level yet, then give life points
+		if (!_engine->_gameState->magicLevelIdx && currentBonus == 2) {
+			currentBonus = 1;
+		}
 
-			angle = _engine->_movements->getAngleAndSetTargetActorDistance(ABS(zone->topRight.x + zone->bottomLeft.x) / 2, ABS(zone->topRight.z + zone->bottomLeft.z) / 2, sceneHero->x, sceneHero->z);
-			index = _engine->_extra->addExtraBonus(ABS(zone->topRight.x + zone->bottomLeft.x) / 2, zone->topRight.y, ABS(zone->topRight.z + zone->bottomLeft.z) / 2, 180, angle, currentBonus + 3, zone->infoData.generic.info2);
+		angle = _engine->_movements->getAngleAndSetTargetActorDistance(ABS(zone->topRight.x + zone->bottomLeft.x) / 2, ABS(zone->topRight.z + zone->bottomLeft.z) / 2, sceneHero->x, sceneHero->z);
+		index = _engine->_extra->addExtraBonus(ABS(zone->topRight.x + zone->bottomLeft.x) / 2, zone->topRight.y, ABS(zone->topRight.z + zone->bottomLeft.z) / 2, 180, angle, currentBonus + 3, zone->infoData.generic.info2);
 
-			if (index != -1) {
-				_engine->_extra->extraList[index].type |= 0x400;
-				zone->infoData.generic.info3 = 1; // set as used
-			}
+		if (index != -1) {
+			_engine->_extra->extraList[index].type |= 0x400;
+			zone->infoData.generic.info3 = 1; // set as used
 		}
 	}
 }
 
 void Scene::processActorZones(int32 actorIdx) {
-	int32 currentX, currentY, currentZ, z, tmpCellingGrid;
-	ActorStruct *actor;
-
-	actor = &sceneActors[actorIdx];
+	ActorStruct *actor = &sceneActors[actorIdx];
 
-	currentX = actor->x;
-	currentY = actor->y;
-	currentZ = actor->z;
+	int32 currentX = actor->x;
+	int32 currentY = actor->y;
+	int32 currentZ = actor->z;
 
 	actor->zone = -1;
-	tmpCellingGrid = 0;
+	int32 tmpCellingGrid = 0;
 
 	if (!actorIdx) {
 		currentActorInZone = actorIdx;
 	}
 
-	for (z = 0; z < sceneNumZones; z++) {
+	for (int32 z = 0; z < sceneNumZones; z++) {
 		ZoneStruct *zone = &sceneZones[z];
 
 		// check if actor is in zone


Commit: 4f638d30b522130d5057a683bead622b19dff4ea
    https://github.com/scummvm/scummvm/commit/4f638d30b522130d5057a683bead622b19dff4ea
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2020-10-26T18:11:15+01:00

Commit Message:
TWINE: enable the ui bindings for the inventory menu

Changed paths:
    engines/twine/menu.cpp


diff --git a/engines/twine/menu.cpp b/engines/twine/menu.cpp
index 130275a785..07c25e0f4f 100644
--- a/engines/twine/menu.cpp
+++ b/engines/twine/menu.cpp
@@ -23,6 +23,7 @@
 #include "twine/menu.h"
 #include "audio/mixer.h"
 #include "backends/audiocd/audiocd.h"
+#include "backends/keymapper/keymapper.h"
 #include "common/config-manager.h"
 #include "common/events.h"
 #include "common/keyboard.h"
@@ -1024,6 +1025,9 @@ void Menu::processInventoryMenu() {
 	_engine->_text->setFontCrossColor(4);
 	_engine->_text->initDialogueBox();
 
+	Common::Keymapper *keymapper = g_system->getEventManager()->getKeymapper();
+	keymapper->getKeymap(uiKeyMapId)->setEnabled(true);
+
 	while (_engine->_input->isActionActive(TwinEActionType::InventoryMenu)) {
 		_engine->readKeys();
 		int32 prevSelectedItem = inventorySelectedItem;
@@ -1110,6 +1114,8 @@ void Menu::processInventoryMenu() {
 		}
 	}
 
+	keymapper->getKeymap(uiKeyMapId)->setEnabled(false);
+
 	_engine->_text->printTextVar13 = 0;
 
 	_engine->_scene->alphaLight = tmpAlphaLight;


Commit: dd2e97ebd68501f947197889b6fc4c8aa46ac1e6
    https://github.com/scummvm/scummvm/commit/dd2e97ebd68501f947197889b6fc4c8aa46ac1e6
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2020-10-26T18:11:15+01:00

Commit Message:
TWINE: close the inventory menu if i is no longer pressed

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


diff --git a/engines/twine/menu.cpp b/engines/twine/menu.cpp
index 07c25e0f4f..c48baeb60d 100644
--- a/engines/twine/menu.cpp
+++ b/engines/twine/menu.cpp
@@ -1124,12 +1124,6 @@ void Menu::processInventoryMenu() {
 	_engine->_gameState->initEngineProjections();
 
 	_engine->_text->initTextBank(_engine->_text->currentTextBank + 3);
-
-	while (!_engine->_input->toggleAbortAction()) {
-		_engine->readKeys();
-		_engine->_system->delayMillis(1);
-		_engine->flip(); // TODO: needed?
-	}
 }
 
 } // namespace TwinE
diff --git a/engines/twine/text.cpp b/engines/twine/text.cpp
index 9547355693..67d91790d0 100644
--- a/engines/twine/text.cpp
+++ b/engines/twine/text.cpp
@@ -450,8 +450,9 @@ void Text::processTextLine() {
 		break;
 	}
 
-	if (printText8PrepareBufferVar2 != 0)
+	if (printText8PrepareBufferVar2 != 0) {
 		printText8PrepareBufferVar2--;
+	}
 
 	if (*printText8Var8 != '\0' && var4 == 1) {
 		dialCharSpace += (dialTextBoxParam2 - addLineBreakX) / printText8PrepareBufferVar2;


Commit: 67568dd0e8373ee55cd7f094294099cf408e171f
    https://github.com/scummvm/scummvm/commit/67568dd0e8373ee55cd7f094294099cf408e171f
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2020-10-26T18:11:15+01:00

Commit Message:
TWINE: 'fixed' a div0 error

right now the inventory text is not visible - this must be related

Changed paths:
    engines/twine/text.cpp


diff --git a/engines/twine/text.cpp b/engines/twine/text.cpp
index 67d91790d0..9a78c3f8ae 100644
--- a/engines/twine/text.cpp
+++ b/engines/twine/text.cpp
@@ -455,6 +455,9 @@ void Text::processTextLine() {
 	}
 
 	if (*printText8Var8 != '\0' && var4 == 1) {
+		if (printText8PrepareBufferVar2 == 0) {
+			printText8PrepareBufferVar2 = 1;
+		}
 		dialCharSpace += (dialTextBoxParam2 - addLineBreakX) / printText8PrepareBufferVar2;
 		printText10Var1 = dialTextBoxParam2 - addLineBreakX - dialTextBoxParam2 - addLineBreakX; // stupid... recheck
 	}


Commit: 483723cd4f20ab95ef2a84313278876b1af67743
    https://github.com/scummvm/scummvm/commit/483723cd4f20ab95ef2a84313278876b1af67743
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2020-10-26T18:11:15+01:00

Commit Message:
TWINE: comments from http://lbafileinfo.kazekr.net

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


diff --git a/engines/twine/hqrdepack.h b/engines/twine/hqrdepack.h
index 63c0839d02..0ee512b097 100644
--- a/engines/twine/hqrdepack.h
+++ b/engines/twine/hqrdepack.h
@@ -29,6 +29,11 @@ namespace TwinE {
 
 class TwinEEngine;
 
+/**
+ * High Quality Resource
+ *
+ * http://lbafileinfo.kazekr.net/index.php?title=High_quality_resource
+ */
 class HQRDepack {
 private:
 	TwinEEngine *_engine;
diff --git a/engines/twine/resources.h b/engines/twine/resources.h
index 949bf980af..29026ee21d 100644
--- a/engines/twine/resources.h
+++ b/engines/twine/resources.h
@@ -125,17 +125,28 @@ public:
 	static constexpr const char *HQR_TEXT_FILE = "text.hqr";
 	// samples
 	static constexpr const char *HQR_SAMPLES_FILE = "samples.hqr";
-	// isometric grids
+	/**
+	 * This file contains isometric grids that are used to display area backgrounds and define 3D shape of the surface.
+	 * Each of the entries is associated with the entry of lba_bll.hqr with the same index. lba_bll entries define block
+	 * sets for use with the grids. Each grid may use only one set of blocks (one entry of lba_bll.hqr).
+	 */
 	static constexpr const char *HQR_LBA_GRI_FILE = "lba_gri.hqr";
-	// isometric libraries
+	// isometric libraries for use in grids.
 	static constexpr const char *HQR_LBA_BLL_FILE = "lba_bll.hqr";
-	// isometric bricks
+	/**
+	 * isometric bricks, which are some kind of tiles, that are used for building the terrains in LBA 1 isometric scenes.
+	 * One brick is the tiniest piece of a grid, which has 64 x 64 x 25 cells. Bricks cannot be used directly on a grid,
+	 * but instead they are grouped into blocks by block libraries, which are then referenced by grids
+	 */
 	static constexpr const char *HQR_LBA_BRK_FILE = "lba_brk.hqr";
-	// scenes
+	// scenes (active area content (actors, scripts, etc.))
 	static constexpr const char *HQR_SCENE_FILE = "scene.hqr";
 	// sprites
 	static constexpr const char *HQR_SPRITES_FILE = "sprites.hqr";
-	// model/animation entities
+	/**
+	 * model/animation entities
+	 * contains data associating 3D models (Body.hqr) with animations (Anim.hqr) for the game characters.
+	 */
 	static constexpr const char *HQR_FILE3D_FILE = "file3d.hqr";
 	// 3d model data
 	static constexpr const char *HQR_BODY_FILE = "body.hqr";


Commit: b951291d5ee05400a8036470a1ddc05ff0984074
    https://github.com/scummvm/scummvm/commit/b951291d5ee05400a8036470a1ddc05ff0984074
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2020-10-26T18:11:15+01:00

Commit Message:
TWINE: removed internalKeyCode from Input class

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


diff --git a/engines/twine/gamestate.cpp b/engines/twine/gamestate.cpp
index 323244a412..fc9fa727cd 100644
--- a/engines/twine/gamestate.cpp
+++ b/engines/twine/gamestate.cpp
@@ -422,15 +422,6 @@ void GameState::processFoundItem(int32 item) {
 
 	initEngineProjections();
 	_engine->_text->initTextBank(_engine->_text->currentTextBank + 3);
-
-	/*do {
-		_engine->readKeys();
-		if (_engine->shouldQuit()) {
-			break;
-		}
-		delaySkip(1);
-	} while (!_engine->_input->internalKeyCode);*/
-
 	_engine->_text->stopVox(_engine->_text->currDialTextEntry);
 
 	_engine->_scene->sceneHero->animTimerData = tmpAnimTimer;
diff --git a/engines/twine/input.cpp b/engines/twine/input.cpp
index 9ced81a913..81e75d1812 100644
--- a/engines/twine/input.cpp
+++ b/engines/twine/input.cpp
@@ -144,7 +144,6 @@ void Input::enableKeyMap(const char *id) {
 
 void Input::readKeys() {
 	skippedKey = 0;
-	internalKeyCode = 0;
 
 	Common::Event event;
 	while (g_system->getEventManager()->pollEvent(event)) {
@@ -207,7 +206,6 @@ void Input::readKeys() {
 				break;
 			}
 		}
-		internalKeyCode = localKey;
 	}
 }
 
diff --git a/engines/twine/input.h b/engines/twine/input.h
index 444b48a331..47681fce7b 100644
--- a/engines/twine/input.h
+++ b/engines/twine/input.h
@@ -161,7 +161,6 @@ private:
 	Common::String _currentKeyMap;
 
 	uint8 actionStates[TwinEActionType::Max]{false};
-	int16 internalKeyCode = 0;
 	int16 currentKey = 0;
 public:
 	Input(TwinEEngine *engine);


Commit: a2ec51e46c5ec18b73c3ed73935d661b949db5ff
    https://github.com/scummvm/scummvm/commit/a2ec51e46c5ec18b73c3ed73935d661b949db5ff
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2020-10-26T18:11:15+01:00

Commit Message:
TWINE: store script sizes

Changed paths:
    engines/twine/actor.h
    engines/twine/scene.cpp
    engines/twine/scene.h
    engines/twine/script_life.cpp
    engines/twine/script_move.cpp


diff --git a/engines/twine/actor.h b/engines/twine/actor.h
index 40fb392453..52fcf06e29 100644
--- a/engines/twine/actor.h
+++ b/engines/twine/actor.h
@@ -186,9 +186,11 @@ struct ActorStruct {
 
 	int32 positionInMoveScript = 0;
 	uint8 *moveScript = nullptr;
+	int32 moveScriptSize = 0;
 
 	int32 positionInLifeScript = 0;
 	uint8 *lifeScript = nullptr;
+	int32 lifeScriptSize = 0;
 
 	int32 labelIdx = 0;        // script label index
 	int32 currentLabelPtr = 0; // pointer to LABEL offset
diff --git a/engines/twine/scene.cpp b/engines/twine/scene.cpp
index 4218b63b3e..d41653cfaa 100644
--- a/engines/twine/scene.cpp
+++ b/engines/twine/scene.cpp
@@ -91,9 +91,7 @@ void Scene::setActorStaticFlags(int32 actorIdx, uint16 staticFlags) {
 	}
 }
 
-void Scene::loadScene() {
-	int32 i;
-	int32 scriptSize = 0;
+void Scene::loadSceneLBA1() {
 	uint8 *localScene = currentScene;
 
 	// load scene ambience properties
@@ -153,20 +151,20 @@ void Scene::loadScene() {
 	sceneHeroZ = *((uint16 *)localScene);
 	localScene += 2;
 
-	scriptSize = *((uint16 *)localScene);
+	sceneHero->moveScriptSize = *((uint16 *)localScene);
 	localScene += 2;
 	sceneHero->moveScript = localScene;
-	localScene += scriptSize;
+	localScene += sceneHero->moveScriptSize;
 
-	scriptSize = *((uint16 *)localScene);
+	sceneHero->lifeScriptSize = *((uint16 *)localScene);
 	localScene += 2;
 	sceneHero->lifeScript = localScene;
-	localScene += scriptSize;
+	localScene += sceneHero->lifeScriptSize;
 
 	sceneNumActors = *((uint16 *)localScene);
 	localScene += 2;
 
-	for (i = 1; i < sceneNumActors; i++) {
+	for (int32 i = 1; i < sceneNumActors; i++) {
 		uint16 staticFlags;
 
 		_engine->_actor->resetActor(i);
@@ -219,21 +217,21 @@ void Scene::loadScene() {
 		sceneActors[i].armor = *(localScene++);
 		sceneActors[i].life = *(localScene++);
 
-		scriptSize = *((uint16 *)localScene);
+		sceneActors[i].moveScriptSize = *((uint16 *)localScene);
 		localScene += 2;
 		sceneActors[i].moveScript = localScene;
-		localScene += scriptSize;
+		localScene += sceneActors[i].moveScriptSize;
 
-		scriptSize = *((uint16 *)localScene);
+		sceneActors[i].lifeScriptSize = *((uint16 *)localScene);
 		localScene += 2;
 		sceneActors[i].lifeScript = localScene;
-		localScene += scriptSize;
+		localScene += sceneActors[i].lifeScriptSize;
 	}
 
 	sceneNumZones = *((uint16 *)localScene);
 	localScene += 2;
 
-	for (i = 0; i < sceneNumZones; i++) {
+	for (int32 i = 0; i < sceneNumZones; i++) {
 		sceneZones[i].bottomLeft.x = *((uint16 *)localScene);
 		localScene += 2;
 		sceneZones[i].bottomLeft.y = *((uint16 *)localScene);
@@ -267,7 +265,7 @@ void Scene::loadScene() {
 	sceneNumTracks = *((uint16 *)localScene);
 	localScene += 2;
 
-	for (i = 0; i < sceneNumTracks; i++) {
+	for (int32 i = 0; i < sceneNumTracks; i++) {
 		sceneTracks[i].x = *((uint16 *)localScene);
 		localScene += 2;
 		sceneTracks[i].y = *((uint16 *)localScene);
@@ -281,7 +279,9 @@ int32 Scene::initScene(int32 index) {
 	// load scene from file
 	_engine->_hqrdepack->hqrGetallocEntry(&currentScene, Resources::HQR_SCENE_FILE, index);
 
-	loadScene();
+	if (_engine->isLBA1()) {
+		loadSceneLBA1();
+	}
 
 	return 1;
 }
diff --git a/engines/twine/scene.h b/engines/twine/scene.h
index 7045d86041..9b556e4d03 100644
--- a/engines/twine/scene.h
+++ b/engines/twine/scene.h
@@ -232,7 +232,7 @@ private:
 /** Process zone extra bonus */
 	void processZoneExtraBonus(ZoneStruct *zone);
 	void setActorStaticFlags(int32 actorIdx, uint16 staticFlags);
-	void loadScene();
+	void loadSceneLBA1();
 	/** Initialize new scene */
 	int32 initScene(int32 index);
 	/** Reset scene */
diff --git a/engines/twine/script_life.cpp b/engines/twine/script_life.cpp
index 888c4c5f48..a602b2a25d 100644
--- a/engines/twine/script_life.cpp
+++ b/engines/twine/script_life.cpp
@@ -20,6 +20,7 @@
  *
  */
 
+#include "common/stream.h"
 #include "twine/actor.h"
 #include "twine/animations.h"
 #include "twine/collision.h"
@@ -1599,6 +1600,7 @@ ScriptLife::ScriptLife(TwinEEngine *engine) : _engine(engine) {
 
 void ScriptLife::processLifeScript(int32 actorIdx) {
 	ActorStruct *actor = _engine->_scene->getActor(actorIdx);
+	// TODO: use Common::MemoryReadStream for the script parsing
 	scriptPtr = actor->lifeScript + actor->positionInLifeScript;
 
 	int32 end = -2;
diff --git a/engines/twine/script_move.cpp b/engines/twine/script_move.cpp
index 97b2c273da..d0cdc23c5e 100644
--- a/engines/twine/script_move.cpp
+++ b/engines/twine/script_move.cpp
@@ -590,6 +590,7 @@ void ScriptMove::processMoveScript(int32 actorIdx) {
 
 	do {
 		scriptPosition = actor->positionInMoveScript;
+		// TODO: use Common::MemoryReadStream for the script parsing
 		scriptPtr = actor->moveScript + scriptPosition;
 		int32 scriptOpcode = *(scriptPtr++);
 


Commit: 9d53e69b7900482fd987631fcc26db88e4564c26
    https://github.com/scummvm/scummvm/commit/9d53e69b7900482fd987631fcc26db88e4564c26
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2020-10-26T18:11:15+01:00

Commit Message:
TWINE: converted scene loading to stream

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


diff --git a/engines/twine/actor.cpp b/engines/twine/actor.cpp
index 1424519583..cd843f5021 100644
--- a/engines/twine/actor.cpp
+++ b/engines/twine/actor.cpp
@@ -66,34 +66,40 @@ void Actor::restartHeroScene() {
 }
 
 void Actor::loadHeroEntities() {
-	if (_engine->_hqrdepack->hqrGetallocEntry(&heroEntityATHLETIC, Resources::HQR_FILE3D_FILE, FILE3DHQR_HEROATHLETIC) == 0) {
+	heroEntityATHLETICSize = _engine->_hqrdepack->hqrGetallocEntry(&heroEntityATHLETIC, Resources::HQR_FILE3D_FILE, FILE3DHQR_HEROATHLETIC);
+	if (heroEntityATHLETICSize == 0) {
 		error("Failed to load actor athletic 3d data");
 	}
 	_engine->_scene->sceneHero->entityDataPtr = heroEntityATHLETIC;
 	heroAnimIdxATHLETIC = _engine->_animations->getBodyAnimIndex(0, 0);
 
-	if (_engine->_hqrdepack->hqrGetallocEntry(&heroEntityAGGRESSIVE, Resources::HQR_FILE3D_FILE, FILE3DHQR_HEROAGGRESSIVE) == 0) {
+	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);
 
-	if (_engine->_hqrdepack->hqrGetallocEntry(&heroEntityDISCRETE, Resources::HQR_FILE3D_FILE, FILE3DHQR_HERODISCRETE) == 0) {
+	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);
 
-	if (_engine->_hqrdepack->hqrGetallocEntry(&heroEntityPROTOPACK, Resources::HQR_FILE3D_FILE, FILE3DHQR_HEROPROTOPACK) == 0) {
+	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);
 
-	if (_engine->_hqrdepack->hqrGetallocEntry(&heroEntityNORMAL, Resources::HQR_FILE3D_FILE, FILE3DHQR_HERONORMAL) == 0) {
+	heroEntityNORMALSize = _engine->_hqrdepack->hqrGetallocEntry(&heroEntityNORMAL, Resources::HQR_FILE3D_FILE, FILE3DHQR_HERONORMAL);
+	if (heroEntityNORMALSize == 0) {
 		error("Failed to load actor normal 3d data");
 	}
 	_engine->_scene->sceneHero->entityDataPtr = heroEntityNORMAL;
+	_engine->_scene->sceneHero->entityDataSize = heroEntityNORMALSize;
 	heroAnimIdxNORMAL = _engine->_animations->getBodyAnimIndex(0, 0);
 
 	_engine->_scene->sceneHero->animExtraPtr = _engine->_animations->currentActorAnimExtraPtr;
@@ -104,22 +110,27 @@ void Actor::setBehaviour(int32 behaviour) {
 	case kNormal:
 		heroBehaviour = kNormal;
 		_engine->_scene->sceneHero->entityDataPtr = heroEntityNORMAL;
+		_engine->_scene->sceneHero->entityDataSize = heroEntityNORMALSize;
 		break;
 	case kAthletic:
 		heroBehaviour = kAthletic;
 		_engine->_scene->sceneHero->entityDataPtr = heroEntityATHLETIC;
+		_engine->_scene->sceneHero->entityDataSize = heroEntityATHLETICSize;
 		break;
 	case kAggressive:
 		heroBehaviour = kAggressive;
 		_engine->_scene->sceneHero->entityDataPtr = heroEntityAGGRESSIVE;
+		_engine->_scene->sceneHero->entityDataSize = heroEntityAGGRESSIVESize;
 		break;
 	case kDiscrete:
 		heroBehaviour = kDiscrete;
 		_engine->_scene->sceneHero->entityDataPtr = heroEntityDISCRETE;
+		_engine->_scene->sceneHero->entityDataSize = heroEntityDISCRETESize;
 		break;
 	case kProtoPack:
 		heroBehaviour = kProtoPack;
 		_engine->_scene->sceneHero->entityDataPtr = heroEntityPROTOPACK;
+		_engine->_scene->sceneHero->entityDataSize = heroEntityPROTOPACKSize;
 		break;
 	};
 
diff --git a/engines/twine/actor.h b/engines/twine/actor.h
index 52fcf06e29..5289fb10a9 100644
--- a/engines/twine/actor.h
+++ b/engines/twine/actor.h
@@ -160,6 +160,7 @@ struct ActorStruct {
 	uint8 *animExtraPtr = nullptr;
 	int32 sprite = 0; // field_8
 	uint8 *entityDataPtr = nullptr;
+	int32 entityDataSize = 0;
 
 	int32 x = 0;
 	int32 y = 0;
@@ -252,14 +253,19 @@ public:
 
 	/** 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
diff --git a/engines/twine/scene.cpp b/engines/twine/scene.cpp
index d41653cfaa..ef7859944e 100644
--- a/engines/twine/scene.cpp
+++ b/engines/twine/scene.cpp
@@ -21,6 +21,8 @@
  */
 
 #include "twine/scene.h"
+#include "common/memstream.h"
+#include "common/stream.h"
 #include "common/util.h"
 #include "twine/actor.h"
 #include "twine/animations.h"
@@ -41,249 +43,197 @@ namespace TwinE {
 
 void Scene::setActorStaticFlags(int32 actorIdx, uint16 staticFlags) {
 	if (staticFlags & 0x1) {
-		sceneActors[actorIdx].staticFlags.bComputeCollisionWithObj = 1;
+		_sceneActors[actorIdx].staticFlags.bComputeCollisionWithObj = 1;
 	}
 	if (staticFlags & 0x2) {
-		sceneActors[actorIdx].staticFlags.bComputeCollisionWithBricks = 1;
+		_sceneActors[actorIdx].staticFlags.bComputeCollisionWithBricks = 1;
 	}
 	if (staticFlags & 0x4) {
-		sceneActors[actorIdx].staticFlags.bIsZonable = 1;
+		_sceneActors[actorIdx].staticFlags.bIsZonable = 1;
 	}
 	if (staticFlags & 0x8) {
-		sceneActors[actorIdx].staticFlags.bUsesClipping = 1;
+		_sceneActors[actorIdx].staticFlags.bUsesClipping = 1;
 	}
 	if (staticFlags & 0x10) {
-		sceneActors[actorIdx].staticFlags.bCanBePushed = 1;
+		_sceneActors[actorIdx].staticFlags.bCanBePushed = 1;
 	}
 	if (staticFlags & 0x20) {
-		sceneActors[actorIdx].staticFlags.bComputeLowCollision = 1;
+		_sceneActors[actorIdx].staticFlags.bComputeLowCollision = 1;
 	}
 	if (staticFlags & 0x40) {
-		sceneActors[actorIdx].staticFlags.bCanDrown = 1;
+		_sceneActors[actorIdx].staticFlags.bCanDrown = 1;
 	}
 	if (staticFlags & 0x80) {
-		sceneActors[actorIdx].staticFlags.bUnk80 = 1;
+		_sceneActors[actorIdx].staticFlags.bUnk80 = 1;
 	}
 
 	if (staticFlags & 0x100) {
-		sceneActors[actorIdx].staticFlags.bUnk0100 = 1;
+		_sceneActors[actorIdx].staticFlags.bUnk0100 = 1;
 	}
 	if (staticFlags & 0x200) {
-		sceneActors[actorIdx].staticFlags.bIsHidden = 1;
+		_sceneActors[actorIdx].staticFlags.bIsHidden = 1;
 	}
 	if (staticFlags & 0x400) {
-		sceneActors[actorIdx].staticFlags.bIsSpriteActor = 1;
+		_sceneActors[actorIdx].staticFlags.bIsSpriteActor = 1;
 	}
 	if (staticFlags & 0x800) {
-		sceneActors[actorIdx].staticFlags.bCanFall = 1;
+		_sceneActors[actorIdx].staticFlags.bCanFall = 1;
 	}
 	if (staticFlags & 0x1000) {
-		sceneActors[actorIdx].staticFlags.bDoesntCastShadow = 1;
+		_sceneActors[actorIdx].staticFlags.bDoesntCastShadow = 1;
 	}
 	if (staticFlags & 0x2000) {
 		//sceneActors[actorIdx].staticFlags.bIsBackgrounded = 1;
 	}
 	if (staticFlags & 0x4000) {
-		sceneActors[actorIdx].staticFlags.bIsCarrierActor = 1;
+		_sceneActors[actorIdx].staticFlags.bIsCarrierActor = 1;
 	}
 	if (staticFlags & 0x8000) {
-		sceneActors[actorIdx].staticFlags.bUseMiniZv = 1;
+		_sceneActors[actorIdx].staticFlags.bUseMiniZv = 1;
 	}
 }
 
-void Scene::loadSceneLBA1() {
-	uint8 *localScene = currentScene;
+bool Scene::loadSceneLBA1() {
+	Common::MemoryReadStream stream(currentScene, _currentSceneSize);
 
 	// load scene ambience properties
-	_engine->_text->currentTextBank = *(localScene++);
-	currentGameOverScene = *(localScene++);
-	localScene += 4;
+	_engine->_text->currentTextBank = stream.readByte();
+	currentGameOverScene = stream.readByte();
+	stream.skip(4);
 
-	alphaLight = *((uint16 *)localScene);
-	localScene += 2;
-	betaLight = *((uint16 *)localScene);
-	localScene += 2;
+	alphaLight = stream.readUint16LE();
+	betaLight = stream.readUint16LE();
 
 	// FIXME: Workaround to fix lighting issue - not using proper dark light
 	alphaLight = 896;
 	betaLight = 950;
 
-	sampleAmbiance[0] = *((uint16 *)localScene);
-	localScene += 2;
-	sampleRepeat[0] = *((uint16 *)localScene);
-	localScene += 2;
-	sampleRound[0] = *((uint16 *)localScene);
-	localScene += 2;
-
-	sampleAmbiance[1] = *((uint16 *)localScene);
-	localScene += 2;
-	sampleRepeat[1] = *((uint16 *)localScene);
-	localScene += 2;
-	sampleRound[1] = *((uint16 *)localScene);
-	localScene += 2;
-
-	sampleAmbiance[2] = *((uint16 *)localScene);
-	localScene += 2;
-	sampleRepeat[2] = *((uint16 *)localScene);
-	localScene += 2;
-	sampleRound[2] = *((uint16 *)localScene);
-	localScene += 2;
-
-	sampleAmbiance[3] = *((uint16 *)localScene);
-	localScene += 2;
-	sampleRepeat[3] = *((uint16 *)localScene);
-	localScene += 2;
-	sampleRound[3] = *((uint16 *)localScene);
-	localScene += 2;
-
-	sampleMinDelay = *((uint16 *)localScene);
-	localScene += 2;
-	sampleMinDelayRnd = *((uint16 *)localScene);
-	localScene += 2;
-
-	sceneMusic = *(localScene++);
+	sampleAmbiance[0] = stream.readUint16LE();
+	sampleRepeat[0] = stream.readUint16LE();
+	sampleRound[0] = stream.readUint16LE();
+
+	sampleAmbiance[1] = stream.readUint16LE();
+	sampleRepeat[1] = stream.readUint16LE();
+	sampleRound[1] = stream.readUint16LE();
+
+	sampleAmbiance[2] = stream.readUint16LE();
+	sampleRepeat[2] = stream.readUint16LE();
+	sampleRound[2] = stream.readUint16LE();
+
+	sampleAmbiance[3] = stream.readUint16LE();
+	sampleRepeat[3] = stream.readUint16LE();
+	sampleRound[3] = stream.readUint16LE();
+
+	sampleMinDelay = stream.readUint16LE();
+	sampleMinDelayRnd = stream.readUint16LE();
+
+	sceneMusic = stream.readByte();
 
 	// load hero properties
-	sceneHeroX = *((uint16 *)localScene);
-	localScene += 2;
-	sceneHeroY = *((uint16 *)localScene);
-	localScene += 2;
-	sceneHeroZ = *((uint16 *)localScene);
-	localScene += 2;
-
-	sceneHero->moveScriptSize = *((uint16 *)localScene);
-	localScene += 2;
-	sceneHero->moveScript = localScene;
-	localScene += sceneHero->moveScriptSize;
-
-	sceneHero->lifeScriptSize = *((uint16 *)localScene);
-	localScene += 2;
-	sceneHero->lifeScript = localScene;
-	localScene += sceneHero->lifeScriptSize;
-
-	sceneNumActors = *((uint16 *)localScene);
-	localScene += 2;
+	sceneHeroX = stream.readUint16LE();
+	sceneHeroY = stream.readUint16LE();
+	sceneHeroZ = stream.readUint16LE();
 
-	for (int32 i = 1; i < sceneNumActors; i++) {
-		uint16 staticFlags;
+	sceneHero->moveScriptSize = stream.readUint16LE();
+	sceneHero->moveScript = currentScene + stream.pos();
+	stream.skip(sceneHero->moveScriptSize);
 
+	sceneHero->lifeScriptSize = stream.readUint16LE();
+	sceneHero->lifeScript = currentScene + stream.pos();
+	stream.skip(sceneHero->lifeScriptSize);
+
+	sceneNumActors = stream.readUint16LE();
+	for (int32 i = 1; i < sceneNumActors; i++) {
 		_engine->_actor->resetActor(i);
 
-		staticFlags = *((uint16 *)localScene);
-		localScene += 2;
+		const uint16 staticFlags = stream.readUint16LE();
 		setActorStaticFlags(i, staticFlags);
 
-		sceneActors[i].entity = *((uint16 *)localScene);
-		localScene += 2;
+		ActorStruct* act = &_sceneActors[i];
+		act->entity = stream.readUint16LE();
 
-		if (!sceneActors[i].staticFlags.bIsSpriteActor) {
-			_engine->_hqrdepack->hqrGetallocEntry(&sceneActors[i].entityDataPtr, Resources::HQR_FILE3D_FILE, sceneActors[i].entity);
+		if (!act->staticFlags.bIsSpriteActor) {
+			act->entityDataSize = _engine->_hqrdepack->hqrGetallocEntry(&act->entityDataPtr, Resources::HQR_FILE3D_FILE, act->entity);
 		}
 
-		sceneActors[i].body = *(localScene++);
-		sceneActors[i].anim = (AnimationTypes) * (localScene++);
-		sceneActors[i].sprite = *((uint16 *)localScene);
-		localScene += 2;
-		sceneActors[i].x = *((uint16 *)localScene);
-		sceneActors[i].collisionX = sceneActors[i].x;
-		localScene += 2;
-		sceneActors[i].y = *((uint16 *)localScene);
-		sceneActors[i].collisionY = sceneActors[i].y;
-		localScene += 2;
-		sceneActors[i].z = *((uint16 *)localScene);
-		sceneActors[i].collisionZ = sceneActors[i].z;
-		localScene += 2;
-		sceneActors[i].strengthOfHit = *(localScene++);
-		sceneActors[i].bonusParameter = *((uint16 *)localScene);
-		localScene += 2;
-		sceneActors[i].bonusParameter &= 0xFE;
-		sceneActors[i].angle = *((uint16 *)localScene);
-		localScene += 2;
-		sceneActors[i].speed = *((uint16 *)localScene);
-		localScene += 2;
-		sceneActors[i].controlMode = *((uint16 *)localScene);
-		localScene += 2;
-		sceneActors[i].info0 = *((int16 *)localScene);
-		localScene += 2;
-		sceneActors[i].info1 = *((int16 *)localScene);
-		localScene += 2;
-		sceneActors[i].info2 = *((int16 *)localScene);
-		localScene += 2;
-		sceneActors[i].info3 = *((int16 *)localScene);
-		localScene += 2;
-		sceneActors[i].followedActor = sceneActors[i].info3;
-		sceneActors[i].bonusAmount = *(localScene++);
-		sceneActors[i].talkColor = *(localScene++);
-		sceneActors[i].armor = *(localScene++);
-		sceneActors[i].life = *(localScene++);
-
-		sceneActors[i].moveScriptSize = *((uint16 *)localScene);
-		localScene += 2;
-		sceneActors[i].moveScript = localScene;
-		localScene += sceneActors[i].moveScriptSize;
-
-		sceneActors[i].lifeScriptSize = *((uint16 *)localScene);
-		localScene += 2;
-		sceneActors[i].lifeScript = localScene;
-		localScene += sceneActors[i].lifeScriptSize;
-	}
-
-	sceneNumZones = *((uint16 *)localScene);
-	localScene += 2;
-
+		act->body = stream.readByte();
+		act->anim = (AnimationTypes) stream.readByte();
+		act->sprite = stream.readUint16LE();
+		act->x = stream.readUint16LE();
+		act->collisionX = act->x;
+		act->y = stream.readUint16LE();
+		act->collisionY = act->y;
+		act->z = stream.readUint16LE();
+		act->collisionZ = act->z;
+		act->strengthOfHit = stream.readByte();
+		act->bonusParameter = stream.readUint16LE();
+		act->bonusParameter &= 0xFE;
+		act->angle = stream.readUint16LE();
+		act->speed = stream.readUint16LE();
+		act->controlMode = stream.readUint16LE();
+		act->info0 = stream.readUint16LE();
+		act->info1 = stream.readUint16LE();
+		act->info2 = stream.readUint16LE();
+		act->info3 = stream.readUint16LE();
+		act->followedActor = act->info3;
+		act->bonusAmount = stream.readByte();
+		act->talkColor = stream.readByte();
+		act->armor = stream.readByte();
+		act->life = stream.readByte();
+
+		act->moveScriptSize = stream.readUint16LE();
+		act->moveScript = currentScene + stream.pos();
+		stream.skip(act->moveScriptSize);
+
+		act->lifeScriptSize = stream.readUint16LE();
+		act->lifeScript = currentScene + stream.pos();
+		stream.skip(act->lifeScriptSize);
+	}
+
+	sceneNumZones = stream.readUint16LE();
 	for (int32 i = 0; i < sceneNumZones; i++) {
-		sceneZones[i].bottomLeft.x = *((uint16 *)localScene);
-		localScene += 2;
-		sceneZones[i].bottomLeft.y = *((uint16 *)localScene);
-		localScene += 2;
-		sceneZones[i].bottomLeft.z = *((uint16 *)localScene);
-		localScene += 2;
-
-		sceneZones[i].topRight.x = *((uint16 *)localScene);
-		localScene += 2;
-		sceneZones[i].topRight.y = *((uint16 *)localScene);
-		localScene += 2;
-		sceneZones[i].topRight.z = *((uint16 *)localScene);
-		localScene += 2;
-
-		sceneZones[i].type = *((uint16 *)localScene);
-		localScene += 2;
-
-		sceneZones[i].infoData.generic.info0 = *((uint16 *)localScene);
-		localScene += 2;
-		sceneZones[i].infoData.generic.info1 = *((uint16 *)localScene);
-		localScene += 2;
-		sceneZones[i].infoData.generic.info2 = *((uint16 *)localScene);
-		localScene += 2;
-		sceneZones[i].infoData.generic.info3 = *((uint16 *)localScene);
-		localScene += 2;
-
-		sceneZones[i].snap = *((uint16 *)localScene);
-		localScene += 2;
-	}
-
-	sceneNumTracks = *((uint16 *)localScene);
-	localScene += 2;
+		ZoneStruct* zone = &sceneZones[i];
+		zone->bottomLeft.x = stream.readUint16LE();
+		zone->bottomLeft.y = stream.readUint16LE();
+		zone->bottomLeft.z = stream.readUint16LE();
+
+		zone->topRight.x = stream.readUint16LE();
+		zone->topRight.y = stream.readUint16LE();
+		zone->topRight.z = stream.readUint16LE();
+
+		zone->type = stream.readUint16LE();
+
+		zone->infoData.generic.info0 = stream.readUint16LE();
+		zone->infoData.generic.info1 = stream.readUint16LE();
+		zone->infoData.generic.info2 = stream.readUint16LE();
+		zone->infoData.generic.info3 = stream.readUint16LE();
 
+		zone->snap = stream.readUint16LE();
+	}
+
+	sceneNumTracks = stream.readUint16LE();
 	for (int32 i = 0; i < sceneNumTracks; i++) {
-		sceneTracks[i].x = *((uint16 *)localScene);
-		localScene += 2;
-		sceneTracks[i].y = *((uint16 *)localScene);
-		localScene += 2;
-		sceneTracks[i].z = *((uint16 *)localScene);
-		localScene += 2;
+		ScenePoint* point = &sceneTracks[i];
+		point->x = stream.readUint16LE();
+		point->y = stream.readUint16LE();
+		point->z = stream.readUint16LE();
 	}
+
+	return true;
 }
 
-int32 Scene::initScene(int32 index) {
+bool Scene::initScene(int32 index) {
 	// load scene from file
-	_engine->_hqrdepack->hqrGetallocEntry(&currentScene, Resources::HQR_SCENE_FILE, index);
+	_currentSceneSize = _engine->_hqrdepack->hqrGetallocEntry(&currentScene, Resources::HQR_SCENE_FILE, index);
+	if (_currentSceneSize == 0) {
+		return false;
+	}
 
 	if (_engine->isLBA1()) {
-		loadSceneLBA1();
+		return loadSceneLBA1();
 	}
 
-	return 1;
+	return false;
 }
 
 void Scene::resetScene() {
@@ -372,9 +322,9 @@ void Scene::changeScene() {
 	heroPositionType = ScenePositionType::kNoPosition;
 	sampleAmbienceTime = 0;
 
-	_engine->_grid->newCameraX = sceneActors[currentlyFollowedActor].x >> 9;
-	_engine->_grid->newCameraY = sceneActors[currentlyFollowedActor].y >> 8;
-	_engine->_grid->newCameraZ = sceneActors[currentlyFollowedActor].z >> 9;
+	_engine->_grid->newCameraX = _sceneActors[currentlyFollowedActor].x >> 9;
+	_engine->_grid->newCameraY = _sceneActors[currentlyFollowedActor].y >> 8;
+	_engine->_grid->newCameraZ = _sceneActors[currentlyFollowedActor].z >> 9;
 
 	_engine->_gameState->magicBallIdx = -1;
 	_engine->_movements->heroMoved = true;
@@ -397,7 +347,7 @@ void Scene::changeScene() {
 ActorStruct *Scene::getActor(int32 actorIdx) {
 	assert(actorIdx >= 0);
 	assert(actorIdx < NUM_MAX_ACTORS);
-	return &sceneActors[actorIdx];
+	return &_sceneActors[actorIdx];
 }
 
 void Scene::processEnvironmentSound() {
@@ -467,7 +417,7 @@ void Scene::processZoneExtraBonus(ZoneStruct *zone) {
 }
 
 void Scene::processActorZones(int32 actorIdx) {
-	ActorStruct *actor = &sceneActors[actorIdx];
+	ActorStruct *actor = &_sceneActors[actorIdx];
 
 	int32 currentX = actor->x;
 	int32 currentY = actor->y;
diff --git a/engines/twine/scene.h b/engines/twine/scene.h
index 9b556e4d03..5764c2dcf6 100644
--- a/engines/twine/scene.h
+++ b/engines/twine/scene.h
@@ -232,14 +232,15 @@ private:
 /** Process zone extra bonus */
 	void processZoneExtraBonus(ZoneStruct *zone);
 	void setActorStaticFlags(int32 actorIdx, uint16 staticFlags);
-	void loadSceneLBA1();
+	bool loadSceneLBA1();
 	/** Initialize new scene */
-	int32 initScene(int32 index);
+	bool initScene(int32 index);
 	/** Reset scene */
 	void resetScene();
 
 	// the first actor is the own hero
-	ActorStruct sceneActors[NUM_MAX_ACTORS];
+	ActorStruct _sceneActors[NUM_MAX_ACTORS];
+	int32 _currentSceneSize = 0;
 
 public:
 	Scene(TwinEEngine *engine) : _engine(engine) {}


Commit: 662aceb9226d93984fc64cf0e0ac72eb0f4fc7f6
    https://github.com/scummvm/scummvm/commit/662aceb9226d93984fc64cf0e0ac72eb0f4fc7f6
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2020-10-26T18:11:15+01:00

Commit Message:
TWINE: reduced scope

Changed paths:
    engines/twine/scene.cpp
    engines/twine/script_life.cpp
    engines/twine/script_move.cpp


diff --git a/engines/twine/scene.cpp b/engines/twine/scene.cpp
index ef7859944e..162b18911e 100644
--- a/engines/twine/scene.cpp
+++ b/engines/twine/scene.cpp
@@ -237,15 +237,13 @@ bool Scene::initScene(int32 index) {
 }
 
 void Scene::resetScene() {
-	int32 i;
-
 	_engine->_extra->resetExtras();
 
-	for (i = 0; i < ARRAYSIZE(sceneFlags); i++) {
+	for (int32 i = 0; i < ARRAYSIZE(sceneFlags); i++) {
 		sceneFlags[i] = 0;
 	}
 
-	for (i = 0; i < OVERLAY_MAX_ENTRIES; i++) {
+	for (int32 i = 0; i < OVERLAY_MAX_ENTRIES; i++) {
 		_engine->_redraw->overlayList[i].info0 = -1;
 	}
 
@@ -254,8 +252,6 @@ void Scene::resetScene() {
 }
 
 void Scene::changeScene() {
-	int32 a;
-
 	// change twinsen house destroyed hard-coded
 	if (needChangeScene == LBA1SceneId::Citadel_Island_near_twinsens_house && _engine->_gameState->gameFlags[30] != 0) {
 		needChangeScene = LBA1SceneId::Citadel_Island_Twinsens_house_destroyed;
@@ -313,7 +309,7 @@ void Scene::changeScene() {
 
 	_engine->_actor->restartHeroScene();
 
-	for (a = 1; a < sceneNumActors; a++) {
+	for (int32 a = 1; a < sceneNumActors; a++) {
 		_engine->_actor->initActor(a);
 	}
 
diff --git a/engines/twine/script_life.cpp b/engines/twine/script_life.cpp
index a602b2a25d..573bdd33aa 100644
--- a/engines/twine/script_life.cpp
+++ b/engines/twine/script_life.cpp
@@ -1443,7 +1443,6 @@ static int32 lPROJ_3D(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
 
 /*0x67*/
 static int32 lTEXT(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
-	int32 textSize, textBoxRight;
 	int32 textIdx = *((int16 *)scriptPtr);
 	scriptPtr += 2;
 
@@ -1455,7 +1454,8 @@ static int32 lTEXT(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
 		}
 
 		engine->_text->getMenuText(textIdx, textStr, sizeof(textStr));
-		textSize = textBoxRight = engine->_text->getTextSize(textStr);
+		int32 textSize = engine->_text->getTextSize(textStr);
+		int32 textBoxRight = textSize;
 		engine->_text->setFontColor(15);
 		engine->_text->drawText(0, drawVar1, textStr);
 		if (textSize > 639) {
@@ -1612,11 +1612,11 @@ void ScriptLife::processLifeScript(int32 actorIdx) {
 		if (scriptOpcode >= 0 && scriptOpcode < ARRAYSIZE(function_map)) {
 			end = function_map[scriptOpcode].function(_engine, actorIdx, actor);
 		} else {
-			error("Actor %d with wrong offset/opcode - Offset: %d\n", actorIdx, actor->positionInLifeScript);
+			error("Actor %d with wrong offset/opcode - Offset: %d", actorIdx, actor->positionInLifeScript);
 		}
 
 		if (end < 0) { // show error message
-			warning("Actor %d Life script [%s] not implemented\n", actorIdx, function_map[scriptOpcode].name);
+			warning("Actor %d Life script [%s] not implemented", actorIdx, function_map[scriptOpcode].name);
 		}
 
 	} while (end != 1);
diff --git a/engines/twine/script_move.cpp b/engines/twine/script_move.cpp
index d0cdc23c5e..2bd774d590 100644
--- a/engines/twine/script_move.cpp
+++ b/engines/twine/script_move.cpp
@@ -84,8 +84,6 @@ static int32 mANIM(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
 
 /*0x04*/
 static int32 mGOTO_POINT(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
-	int32 newAngle;
-
 	actor->positionInMoveScript++;
 	engine->_scene->currentScriptValue = *(scriptPtr);
 
@@ -94,7 +92,7 @@ static int32 mGOTO_POINT(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor
 	engine->_renderer->destY = sp.y;
 	engine->_renderer->destZ = sp.z;
 
-	newAngle = engine->_movements->getAngleAndSetTargetActorDistance(actor->x, actor->z, sp.x, sp.z);
+	const int32 newAngle = engine->_movements->getAngleAndSetTargetActorDistance(actor->x, actor->z, sp.x, sp.z);
 
 	if (actor->staticFlags.bIsSpriteActor) {
 		actor->angle = newAngle;
@@ -112,11 +110,10 @@ 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) {
-		continueMove = 0;
 		actor->positionInMoveScript--;
 	} else {
-		continueMove = 0;
 		engine->_movements->clearRealAngle(actor);
 	}
 	return 0;
@@ -506,7 +503,6 @@ static int32 mFACE_HERO(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor)
 
 /*0x22*/
 static int32 mANGLE_RND(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
-	int32 newAngle;
 
 	actor->positionInMoveScript += 4;
 	if (!actor->staticFlags.bIsSpriteActor) {
@@ -515,11 +511,11 @@ static int32 mANGLE_RND(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor)
 		if (engine->_scene->currentScriptValue == -1 && actor->move.numOfStep == 0) {
 			if (engine->getRandomNumber() & 1) {
 				engine->_scene->currentScriptValue = *((int16 *)scriptPtr);
-				newAngle = actor->angle + 0x100 + (ABS(engine->_scene->currentScriptValue) >> 1);
+				const int32 newAngle = actor->angle + 0x100 + (ABS(engine->_scene->currentScriptValue) >> 1);
 				engine->_scene->currentScriptValue = (newAngle - engine->getRandomNumber(engine->_scene->currentScriptValue)) & 0x3FF;
 			} else {
 				engine->_scene->currentScriptValue = *((int16 *)scriptPtr);
-				newAngle = actor->angle - 0x100 + (ABS(engine->_scene->currentScriptValue) >> 1);
+				const int32 newAngle = actor->angle - 0x100 + (ABS(engine->_scene->currentScriptValue) >> 1);
 				engine->_scene->currentScriptValue = (newAngle - engine->getRandomNumber(engine->_scene->currentScriptValue)) & 0x3FF;
 			}
 


Commit: 94d0bc8b21e2c7310e3fa7edda798614b19003a7
    https://github.com/scummvm/scummvm/commit/94d0bc8b21e2c7310e3fa7edda798614b19003a7
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2020-10-26T18:11:15+01:00

Commit Message:
TWINE: reduced scope

Changed paths:
    engines/twine/grid.cpp


diff --git a/engines/twine/grid.cpp b/engines/twine/grid.cpp
index 28c081676e..1fc1cb3c0a 100644
--- a/engines/twine/grid.cpp
+++ b/engines/twine/grid.cpp
@@ -600,8 +600,6 @@ void Grid::redrawGrid() {
 }
 
 int32 Grid::getBrickShape(int32 x, int32 y, int32 z) {
-	uint8 *blockBufferPtr = blockBuffer;
-
 	_engine->_collision->collisionX = (x + 0x100) >> 9;
 	_engine->_collision->collisionY = y >> 8;
 	_engine->_collision->collisionZ = (z + 0x100) >> 9;
@@ -618,6 +616,7 @@ int32 Grid::getBrickShape(int32 x, int32 y, int32 z) {
 		return 0;
 	}
 
+	uint8 *blockBufferPtr = blockBuffer;
 	blockBufferPtr += _engine->_collision->collisionX * 50;
 	blockBufferPtr += _engine->_collision->collisionY * 2;
 	blockBufferPtr += (_engine->_collision->collisionZ << 7) * GRID_SIZE_Y;
@@ -625,15 +624,12 @@ int32 Grid::getBrickShape(int32 x, int32 y, int32 z) {
 	uint8 blockIdx = *blockBufferPtr;
 
 	if (blockIdx) {
-		uint8 *blockPtr;
-		uint8 tmpBrickIdx;
-
-		blockPtr = currentBll;
+		uint8 *blockPtr = currentBll;
 
 		blockPtr += *(uint32 *)(blockPtr + blockIdx * 4 - 4);
 		blockPtr += 3;
 
-		tmpBrickIdx = *(blockBufferPtr + 1);
+		const uint8 tmpBrickIdx = *(blockBufferPtr + 1);
 		blockPtr = blockPtr + tmpBrickIdx * 4;
 
 		return *blockPtr;
@@ -642,8 +638,6 @@ int32 Grid::getBrickShape(int32 x, int32 y, int32 z) {
 }
 
 int32 Grid::getBrickShapeFull(int32 x, int32 y, int32 z, int32 y2) {
-	uint8 *blockBufferPtr = blockBuffer;
-
 	_engine->_collision->collisionX = (x + 0x100) >> 9;
 	_engine->_collision->collisionY = y >> 8;
 	_engine->_collision->collisionZ = (z + 0x100) >> 9;
@@ -660,6 +654,7 @@ int32 Grid::getBrickShapeFull(int32 x, int32 y, int32 z, int32 y2) {
 		return 0;
 	}
 
+	uint8 *blockBufferPtr = blockBuffer;
 	blockBufferPtr += _engine->_collision->collisionX * 50;
 	blockBufferPtr += _engine->_collision->collisionY * 2;
 	blockBufferPtr += (_engine->_collision->collisionZ << 7) * GRID_SIZE_Y;
@@ -717,8 +712,6 @@ int32 Grid::getBrickShapeFull(int32 x, int32 y, int32 z, int32 y2) {
 }
 
 int32 Grid::getBrickSoundType(int32 x, int32 y, int32 z) { // getPos2
-	uint8 *blockBufferPtr = blockBuffer;
-
 	_engine->_collision->collisionX = (x + 0x100) >> 9;
 	_engine->_collision->collisionY = y >> 8;
 	_engine->_collision->collisionZ = (z + 0x100) >> 9;
@@ -735,6 +728,7 @@ int32 Grid::getBrickSoundType(int32 x, int32 y, int32 z) { // getPos2
 		return 0;
 	}
 
+	uint8 *blockBufferPtr = blockBuffer;
 	blockBufferPtr += _engine->_collision->collisionX * 50;
 	blockBufferPtr += _engine->_collision->collisionY * 2;
 	blockBufferPtr += (_engine->_collision->collisionZ << 7) * GRID_SIZE_Y;
@@ -742,15 +736,12 @@ int32 Grid::getBrickSoundType(int32 x, int32 y, int32 z) { // getPos2
 	uint8 blockIdx = *blockBufferPtr;
 
 	if (blockIdx) {
-		uint8 *blockPtr;
-		uint8 tmpBrickIdx;
-
-		blockPtr = currentBll;
+		uint8 *blockPtr = currentBll;
 
 		blockPtr += *(uint32 *)(blockPtr + blockIdx * 4 - 4);
 		blockPtr += 3;
 
-		tmpBrickIdx = *(blockBufferPtr + 1);
+		uint8 tmpBrickIdx = *(blockBufferPtr + 1);
 		blockPtr = blockPtr + tmpBrickIdx * 4;
 		blockPtr++;
 


Commit: 8df39f3eebaeae92a247c643a0dd4b65232f9145
    https://github.com/scummvm/scummvm/commit/8df39f3eebaeae92a247c643a0dd4b65232f9145
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2020-10-26T18:11:15+01:00

Commit Message:
TWINE: fixed copyBlockPhys

Changed paths:
    engines/twine/twine.cpp


diff --git a/engines/twine/twine.cpp b/engines/twine/twine.cpp
index 52263486c3..d86152cafc 100644
--- a/engines/twine/twine.cpp
+++ b/engines/twine/twine.cpp
@@ -830,13 +830,10 @@ void TwinEEngine::flip() {
 void TwinEEngine::copyBlockPhys(int32 left, int32 top, int32 right, int32 bottom) {
 	assert(left <= right);
 	assert(top <= bottom);
-#if 0
-	// TODO: fix this - looks like the palette includes a color key at pos 0
-	g_system->copyRectToScreen(frontVideoBuffer.getPixels(), frontVideoBuffer.pitch, left, top, right - left + 1, bottom - top + 1);
+	const int32 width = right - left + 1;
+	const int32 height = bottom - top + 1;
+	g_system->copyRectToScreen(frontVideoBuffer.getBasePtr(left, top), frontVideoBuffer.pitch, left, top, width, height);
 	g_system->updateScreen();
-#else
-	flip();
-#endif
 }
 
 void TwinEEngine::crossFade(const Graphics::ManagedSurface &buffer, const uint32 *palette) {


Commit: 0a56ddc670a4bfde08081bcce9bf47b7e3450dc8
    https://github.com/scummvm/scummvm/commit/0a56ddc670a4bfde08081bcce9bf47b7e3450dc8
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2020-10-26T18:11:15+01:00

Commit Message:
TWINE: script warnings if not implemented or invalid opcode

Changed paths:
    engines/twine/script_life.cpp
    engines/twine/script_move.cpp


diff --git a/engines/twine/script_life.cpp b/engines/twine/script_life.cpp
index 573bdd33aa..098b530b19 100644
--- a/engines/twine/script_life.cpp
+++ b/engines/twine/script_life.cpp
@@ -1612,13 +1612,12 @@ void ScriptLife::processLifeScript(int32 actorIdx) {
 		if (scriptOpcode >= 0 && scriptOpcode < ARRAYSIZE(function_map)) {
 			end = function_map[scriptOpcode].function(_engine, actorIdx, actor);
 		} else {
-			error("Actor %d with wrong offset/opcode - Offset: %d", actorIdx, actor->positionInLifeScript);
+			error("Actor %d with wrong offset/opcode - Offset: %d (opcode: %i)", actorIdx, actor->positionInLifeScript, scriptOpcode);
 		}
 
 		if (end < 0) { // show error message
 			warning("Actor %d Life script [%s] not implemented", actorIdx, function_map[scriptOpcode].name);
 		}
-
 	} while (end != 1);
 }
 
diff --git a/engines/twine/script_move.cpp b/engines/twine/script_move.cpp
index 2bd774d590..d0ff850db0 100644
--- a/engines/twine/script_move.cpp
+++ b/engines/twine/script_move.cpp
@@ -503,7 +503,6 @@ static int32 mFACE_HERO(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor)
 
 /*0x22*/
 static int32 mANGLE_RND(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
-
 	actor->positionInMoveScript += 4;
 	if (!actor->staticFlags.bIsSpriteActor) {
 		engine->_scene->currentScriptValue = *((int16 *)scriptPtr + 2);
@@ -593,9 +592,11 @@ void ScriptMove::processMoveScript(int32 actorIdx) {
 		actor->positionInMoveScript++;
 
 		if (scriptOpcode >= 0 && scriptOpcode < ARRAYSIZE(function_map)) {
-			function_map[scriptOpcode].function(_engine, actorIdx, actor);
+			if (function_map[scriptOpcode].function(_engine, actorIdx, actor) < 0) {
+				warning("Actor %d Move script [%s] not implemented", actorIdx, function_map[scriptOpcode].name);
+			}
 		} else {
-			error("Wrong opcode %i", scriptOpcode);
+			error("Actor %d with wrong offset/opcode - Offset: %d (opcode: %i)", actorIdx, actor->positionInLifeScript, scriptOpcode);
 		}
 	} while (continueMove);
 }


Commit: e845ab153bbb46c7a63dca8734089cc8237a01a3
    https://github.com/scummvm/scummvm/commit/e845ab153bbb46c7a63dca8734089cc8237a01a3
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2020-10-26T18:11:15+01:00

Commit Message:
TWINE: fixed warning while initializing itemAngle array

Changed paths:
    engines/twine/twine.cpp


diff --git a/engines/twine/twine.cpp b/engines/twine/twine.cpp
index d86152cafc..69c94aefe3 100644
--- a/engines/twine/twine.cpp
+++ b/engines/twine/twine.cpp
@@ -292,7 +292,7 @@ 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, 256, sizeof(_menu->itemAngle)); // reset inventory items angles
+	memset(_menu->itemAngle, 0, sizeof(_menu->itemAngle)); // reset inventory items angles
 
 	_redraw->bubbleSpriteIndex = SPRITEHQR_DIAG_BUBBLE_LEFT;
 
@@ -803,7 +803,6 @@ void TwinEEngine::delaySkip(uint32 time) {
 }
 
 void TwinEEngine::setPalette(const uint32 *palette) {
-#if 1
 	uint8 pal[NUMOFCOLORS * 3];
 	uint8 *out = pal;
 	const uint8 *in = (const uint8 *)palette;
@@ -815,10 +814,6 @@ void TwinEEngine::setPalette(const uint32 *palette) {
 		in += 4;
 	}
 	g_system->getPaletteManager()->setPalette(pal, 0, 256);
-#else
-	frontVideoBuffer.setPalette(palette, 0, 256);
-	workVideoBuffer.setPalette(palette, 0, 256);
-#endif
 	flip();
 }
 


Commit: 64ce952c74e0d39e3f5d67d23c8c8eb28c942a2a
    https://github.com/scummvm/scummvm/commit/64ce952c74e0d39e3f5d67d23c8c8eb28c942a2a
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2020-10-26T18:11:15+01:00

Commit Message:
TWINE: reset global text vars if compiling without intros

Changed paths:
    engines/twine/menuoptions.cpp


diff --git a/engines/twine/menuoptions.cpp b/engines/twine/menuoptions.cpp
index 74f684e96c..107d9cacde 100644
--- a/engines/twine/menuoptions.cpp
+++ b/engines/twine/menuoptions.cpp
@@ -44,9 +44,9 @@ namespace TwinE {
 static const char allowedCharIndex[] = " ABCDEFGHIJKLM.NOPQRSTUVWXYZ-abcdefghijklm?nopqrstuvwxyz!0123456789\040\b\r\0";
 
 void MenuOptions::newGame() {
-#if TWINE_PLAY_INTROS
 	_engine->_music->stopMusic();
 
+#if TWINE_PLAY_INTROS
 	int32 tmpFlagDisplayText = _engine->cfgfile.FlagDisplayText;
 	_engine->cfgfile.FlagDisplayText = true;
 
@@ -61,35 +61,33 @@ void MenuOptions::newGame() {
 	_engine->_text->setFontCrossColor(15);
 
 	_engine->_text->drawTextFullscreen(150);
-	_engine->readKeys();
 
 	// intro screen 2
 	_engine->_screens->loadImage(RESSHQR_INTROSCREEN2IMG);
 	_engine->_text->drawTextFullscreen(151);
-	_engine->readKeys();
 
 	_engine->_screens->loadImage(RESSHQR_INTROSCREEN3IMG);
 	_engine->_text->drawTextFullscreen(152);
 
-	_engine->_text->newGameVar5 = 0;
-	_engine->_text->textClipSmall();
-	_engine->_text->newGameVar4 = 1;
+	_engine->cfgfile.FlagDisplayText = tmpFlagDisplayText;
 
 	_engine->_screens->fadeToBlack(_engine->_screens->paletteRGBACustom);
 	_engine->_screens->clearScreen();
 	_engine->flip();
 
-	_engine->_music->playMidiMusic(1);
+	// _engine->_music->playMidiMusic(1);
 	_engine->_flaMovies->playFlaMovie(FLA_INTROD);
+#endif
 
+	_engine->_text->textClipSmall();
 	_engine->_screens->clearScreen();
 	_engine->flip();
 
+	_engine->_text->newGameVar4 = 1;
+	_engine->_text->newGameVar5 = 0;
+
 	// set main palette back
 	_engine->setPalette(_engine->_screens->paletteRGBA);
-
-	_engine->cfgfile.FlagDisplayText = tmpFlagDisplayText;
-#endif
 }
 
 void MenuOptions::showCredits() {


Commit: 71921f241c9853a042acb617effe6f8d2e4f4c98
    https://github.com/scummvm/scummvm/commit/71921f241c9853a042acb617effe6f8d2e4f4c98
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2020-10-26T18:11:15+01:00

Commit Message:
TWINE: started to implement saving and loading as well as player name entering

Changed paths:
    engines/twine/console.cpp
    engines/twine/debug_grid.cpp
    engines/twine/gamestate.cpp
    engines/twine/gamestate.h
    engines/twine/input.cpp
    engines/twine/input.h
    engines/twine/menu.cpp
    engines/twine/menuoptions.cpp
    engines/twine/menuoptions.h
    engines/twine/scene.cpp
    engines/twine/scene.h
    engines/twine/script_life.cpp
    engines/twine/twine.cpp
    engines/twine/twine.h


diff --git a/engines/twine/console.cpp b/engines/twine/console.cpp
index 3bbcf74afc..af02f38db9 100644
--- a/engines/twine/console.cpp
+++ b/engines/twine/console.cpp
@@ -53,6 +53,7 @@ bool TwinEConsole::doChangeScene(int argc, const char **argv) {
 bool TwinEConsole::doGiveAllItems(int argc, const char **argv) {
 	for (int32 i = 0; i < NUM_INVENTORY_ITEMS; ++i) {
 		_engine->_gameState->gameFlags[i] = 1;
+		_engine->_gameState->inventoryFlags[i] = 1;
 	}
 	int amount = 10;
 	if (argc > 1) {
diff --git a/engines/twine/debug_grid.cpp b/engines/twine/debug_grid.cpp
index bf10e6f9fa..7a2400fd79 100644
--- a/engines/twine/debug_grid.cpp
+++ b/engines/twine/debug_grid.cpp
@@ -71,7 +71,7 @@ void DebugGrid::changeGrid() {
 	if (_engine->_input->toggleActionIfActive(TwinEActionType::NextRoom)) {
 		_engine->_scene->currentSceneIdx++;
 		if (_engine->_scene->currentSceneIdx >= LBA1SceneId::SceneIdMax) {
-			_engine->_scene->currentSceneIdx = 0;
+			_engine->_scene->currentSceneIdx = LBA1SceneId::Citadel_Island_Prison;
 		}
 		_engine->_scene->needChangeScene = _engine->_scene->currentSceneIdx;
 		_engine->_redraw->reqBgRedraw = true;
@@ -80,7 +80,7 @@ void DebugGrid::changeGrid() {
 	// Press down - less X positions
 	if (_engine->_input->toggleActionIfActive(TwinEActionType::PreviousRoom)) {
 		_engine->_scene->currentSceneIdx--;
-		if (_engine->_scene->currentSceneIdx < 0) {
+		if (_engine->_scene->currentSceneIdx < LBA1SceneId::Citadel_Island_Prison) {
 			_engine->_scene->currentSceneIdx = LBA1SceneId::SceneIdMax - 1;
 		}
 		_engine->_scene->needChangeScene = _engine->_scene->currentSceneIdx;
diff --git a/engines/twine/gamestate.cpp b/engines/twine/gamestate.cpp
index fc9fa727cd..97a460b015 100644
--- a/engines/twine/gamestate.cpp
+++ b/engines/twine/gamestate.cpp
@@ -169,19 +169,16 @@ void GameState::initEngineVars() {
 	_engine->_actor->previousHeroBehaviour = kNormal;
 }
 
-bool GameState::loadGame() {
-	Common::File file;
-	// TODO: the filename must be handled properly
-	if (!file.open(SAVE_DIR "S9999.LBA")) {
-		warning("Could not load the gamestate");
+bool GameState::loadGame(Common::InSaveFile* file) {
+	if (file == nullptr) {
 		return false;
 	}
 
-	file.skip(1); // skip save game id
+	file->skip(1); // skip save game id
 
 	int playerNameIdx = 0;
 	do {
-		const byte c = file.readByte();
+		const byte c = file->readByte();
 		if (c == '\0') {
 			break;
 		}
@@ -193,94 +190,87 @@ bool GameState::loadGame() {
 	} while (true);
 	playerName[playerNameIdx] = '\0';
 
-	byte numGameFlags = file.readByte();
+	byte numGameFlags = file->readByte();
 	if (numGameFlags != NUM_GAME_FLAGS) {
 		warning("Failed to load gameflags");
 		return false;
 	}
-	file.read(gameFlags, numGameFlags);
-	_engine->_scene->needChangeScene = file.readByte(); // scene index
-	gameChapter = file.readByte();
+	file->read(gameFlags, numGameFlags);
+	_engine->_scene->needChangeScene = file->readByte(); // scene index
+	gameChapter = file->readByte();
 
-	_engine->_actor->heroBehaviour = (HeroBehaviourType)file.readByte();
+	_engine->_actor->heroBehaviour = (HeroBehaviourType)file->readByte();
 	_engine->_actor->previousHeroBehaviour = _engine->_actor->heroBehaviour;
-	_engine->_scene->sceneHero->life = file.readByte();
-	inventoryNumKashes = file.readSint16LE();
-	magicLevelIdx = file.readByte();
-	inventoryMagicPoints = file.readByte();
-	inventoryNumLeafsBox = file.readByte();
-	_engine->_scene->newHeroX = file.readSint16LE();
-	_engine->_scene->newHeroY = file.readSint16LE();
-	_engine->_scene->newHeroZ = file.readSint16LE();
-	_engine->_scene->sceneHero->angle = file.readSint16LE();
+	_engine->_scene->sceneHero->life = file->readByte();
+	inventoryNumKashes = file->readSint16LE();
+	magicLevelIdx = file->readByte();
+	inventoryMagicPoints = file->readByte();
+	inventoryNumLeafsBox = file->readByte();
+	_engine->_scene->newHeroX = file->readSint16LE();
+	_engine->_scene->newHeroY = file->readSint16LE();
+	_engine->_scene->newHeroZ = file->readSint16LE();
+	_engine->_scene->sceneHero->angle = file->readSint16LE();
 	_engine->_actor->previousHeroAngle = _engine->_scene->sceneHero->angle;
-	_engine->_scene->sceneHero->body = file.readByte();
+	_engine->_scene->sceneHero->body = file->readByte();
 
-	const byte numHolemapFlags = file.readByte(); // number of holomap locations, always 150
+	const byte numHolemapFlags = file->readByte(); // number of holomap locations, always 150
 	if (numHolemapFlags != ARRAYSIZE(holomapFlags)) {
 		warning("Failed to load holomapflags");
 		return false;
 	}
-	file.read(holomapFlags, numHolemapFlags);
+	file->read(holomapFlags, numHolemapFlags);
 
-	inventoryNumGas = file.readByte();
+	inventoryNumGas = file->readByte();
 
-	const byte numInventoryFlags = file.readByte(); // number of used inventory items, always 28
+	const byte numInventoryFlags = file->readByte(); // number of used inventory items, always 28
 	if (numInventoryFlags != NUM_INVENTORY_ITEMS) {
 		warning("Failed to load inventoryFlags");
 		return false;
 	}
-	file.read(inventoryFlags, numInventoryFlags);
+	file->read(inventoryFlags, numInventoryFlags);
 
-	inventoryNumLeafs = file.readByte();
-	usingSabre = file.readByte();
+	inventoryNumLeafs = file->readByte();
+	usingSabre = file->readByte();
 
 	_engine->_scene->currentSceneIdx = -1;
 	_engine->_scene->heroPositionType = ScenePositionType::kReborn;
 	return true;
 }
 
-bool GameState::saveGame() {
-	Common::DumpFile file;
-	// TODO: the filename must be handled properly
-	if (!file.open(SAVE_DIR "S9999.LBA")) {
-		warning("Could not save the game");
-		return false;
-	}
-
+bool GameState::saveGame(Common::OutSaveFile* file) {
 	// TODO: the player name must be handled properly
 	Common::strlcpy(playerName, "TwinEngineSave", sizeof(playerName));
 
-	file.writeByte(0x03);
-	file.writeString(playerName);
-	file.writeByte(NUM_GAME_FLAGS);
-	file.write(gameFlags, sizeof(gameFlags));
-	file.writeByte(_engine->_scene->currentSceneIdx);
-	file.writeByte(gameChapter);
-	file.writeByte(_engine->_actor->heroBehaviour);
-	file.writeByte(_engine->_scene->sceneHero->life);
-	file.writeSint16LE(inventoryNumKashes);
-	file.writeByte(magicLevelIdx);
-	file.writeByte(inventoryMagicPoints);
-	file.writeByte(inventoryNumLeafsBox);
-	file.writeSint16LE(_engine->_scene->newHeroX);
-	file.writeSint16LE(_engine->_scene->newHeroY);
-	file.writeSint16LE(_engine->_scene->newHeroZ);
-	file.writeSint16LE(_engine->_scene->sceneHero->angle);
-	file.writeByte(_engine->_scene->sceneHero->body);
+	file->writeByte(0x03);
+	file->writeString(playerName);
+	file->writeByte(NUM_GAME_FLAGS);
+	file->write(gameFlags, sizeof(gameFlags));
+	file->writeByte(_engine->_scene->currentSceneIdx);
+	file->writeByte(gameChapter);
+	file->writeByte(_engine->_actor->heroBehaviour);
+	file->writeByte(_engine->_scene->sceneHero->life);
+	file->writeSint16LE(inventoryNumKashes);
+	file->writeByte(magicLevelIdx);
+	file->writeByte(inventoryMagicPoints);
+	file->writeByte(inventoryNumLeafsBox);
+	file->writeSint16LE(_engine->_scene->newHeroX);
+	file->writeSint16LE(_engine->_scene->newHeroY);
+	file->writeSint16LE(_engine->_scene->newHeroZ);
+	file->writeSint16LE(_engine->_scene->sceneHero->angle);
+	file->writeByte(_engine->_scene->sceneHero->body);
 
 	// number of holomap locations
-	file.writeByte(ARRAYSIZE(holomapFlags));
-	file.write(holomapFlags, sizeof(holomapFlags));
+	file->writeByte(ARRAYSIZE(holomapFlags));
+	file->write(holomapFlags, sizeof(holomapFlags));
 
-	file.writeByte(inventoryNumGas);
+	file->writeByte(inventoryNumGas);
 
 	// number of inventory items
-	file.writeByte(ARRAYSIZE(inventoryFlags));
-	file.write(inventoryFlags, sizeof(inventoryFlags));
+	file->writeByte(ARRAYSIZE(inventoryFlags));
+	file->write(inventoryFlags, sizeof(inventoryFlags));
 
-	file.writeByte(inventoryNumLeafs);
-	file.writeByte(usingSabre);
+	file->writeByte(inventoryNumLeafs);
+	file->writeByte(usingSabre);
 
 	return true;
 }
diff --git a/engines/twine/gamestate.h b/engines/twine/gamestate.h
index 152b19b4de..6b4ffa33a6 100644
--- a/engines/twine/gamestate.h
+++ b/engines/twine/gamestate.h
@@ -23,6 +23,7 @@
 #ifndef TWINE_GAMESTATE_H
 #define TWINE_GAMESTATE_H
 
+#include "common/savefile.h"
 #include "common/scummsys.h"
 #include "twine/actor.h"
 
@@ -119,8 +120,8 @@ public:
 
 	void processFoundItem(int32 item);
 
-	bool loadGame();
-	bool saveGame();
+	bool loadGame(Common::InSaveFile* file);
+	bool saveGame(Common::OutSaveFile* file);
 
 	void processGameChoices(int32 choiceIdx);
 
diff --git a/engines/twine/input.cpp b/engines/twine/input.cpp
index 81e75d1812..04560f3d15 100644
--- a/engines/twine/input.cpp
+++ b/engines/twine/input.cpp
@@ -142,6 +142,31 @@ void Input::enableKeyMap(const char *id) {
 	debug("enable keymap %s", id);
 }
 
+uint8 Input::processCustomEngineEventStart(const Common::Event &event) {
+	if (!_engine->cfgfile.Debug) {
+		switch (event.customType) {
+		case TwinEActionType::NextRoom:
+		case TwinEActionType::PreviousRoom:
+		case TwinEActionType::ApplyCellingGrid:
+		case TwinEActionType::IncreaseCellingGridIndex:
+		case TwinEActionType::DecreaseCellingGridIndex:
+			break;
+		default:
+			actionStates[event.customType] = 1 + event.kbdRepeat;
+			return twineactions[event.customType].localKey;
+		}
+	} else {
+		actionStates[event.customType] = 1 + event.kbdRepeat;
+		return twineactions[event.customType].localKey;
+	}
+	return 0;
+}
+
+uint8 Input::processCustomEngineEventEnd(const Common::Event &event) {
+	actionStates[event.customType] = 0;
+	return twineactions[event.customType].localKey;
+}
+
 void Input::readKeys() {
 	skippedKey = 0;
 
@@ -150,27 +175,10 @@ void Input::readKeys() {
 		uint8 localKey = 0;
 		switch (event.type) {
 		case Common::EVENT_CUSTOM_ENGINE_ACTION_END:
-			actionStates[event.customType] = 0;
-			localKey = twineactions[event.customType].localKey;
+			localKey = processCustomEngineEventEnd(event);
 			break;
 		case Common::EVENT_CUSTOM_ENGINE_ACTION_START:
-			if (!_engine->cfgfile.Debug) {
-				switch (event.customType) {
-				case TwinEActionType::NextRoom:
-				case TwinEActionType::PreviousRoom:
-				case TwinEActionType::ApplyCellingGrid:
-				case TwinEActionType::IncreaseCellingGridIndex:
-				case TwinEActionType::DecreaseCellingGridIndex:
-					break;
-				default:
-					localKey = twineactions[event.customType].localKey;
-					actionStates[event.customType] = 1 + event.kbdRepeat;
-					break;
-				}
-			} else {
-				localKey = twineactions[event.customType].localKey;
-				actionStates[event.customType] = 1 + event.kbdRepeat;
-			}
+			localKey = processCustomEngineEventStart(event);
 			break;
 		case Common::EVENT_LBUTTONDOWN:
 			leftMouse = 1;
diff --git a/engines/twine/input.h b/engines/twine/input.h
index 47681fce7b..20bd08c4df 100644
--- a/engines/twine/input.h
+++ b/engines/twine/input.h
@@ -23,6 +23,7 @@
 #ifndef TWINE_KEYBOARD_H
 #define TWINE_KEYBOARD_H
 
+#include "common/events.h"
 #include "common/keyboard.h"
 #include "common/scummsys.h"
 #include "common/util.h"
@@ -219,6 +220,8 @@ public:
 	void getMousePositions(MouseStatusStruct *mouseData);
 
 	void readKeys();
+	uint8 processCustomEngineEventStart(const Common::Event& event);
+	uint8 processCustomEngineEventEnd(const Common::Event& event);
 };
 
 inline const Common::String Input::currentKeyMap() const {
diff --git a/engines/twine/menu.cpp b/engines/twine/menu.cpp
index c48baeb60d..7a2dfdeef3 100644
--- a/engines/twine/menu.cpp
+++ b/engines/twine/menu.cpp
@@ -443,9 +443,6 @@ void Menu::drawButton(const int16 *menuSettings, bool hover) {
 
 		currentButton++;
 		topHeight += 56; // increase button top height
-
-		// slow down the CPU
-		_engine->_system->delayMillis(1);
 	} while (currentButton < maxButton);
 }
 
@@ -571,6 +568,7 @@ int32 Menu::processMenu(int16 *menuSettings) {
 		// draw plasma effect for the current selected button
 		drawButton(menuSettings, true);
 		// TODO: update volume settings
+		_engine->_system->delayMillis(10);
 	} while (!_engine->_input->toggleActionIfActive(TwinEActionType::UIEnter));
 
 	currentButton = *(menuSettings + MenuSettings_FirstButton + currentButton * 2); // get current browsed button
diff --git a/engines/twine/menuoptions.cpp b/engines/twine/menuoptions.cpp
index 107d9cacde..7f07c894dc 100644
--- a/engines/twine/menuoptions.cpp
+++ b/engines/twine/menuoptions.cpp
@@ -21,7 +21,9 @@
  */
 
 #include "twine/menuoptions.h"
+#include "common/keyboard.h"
 #include "common/system.h"
+#include "common/util.h"
 #include "twine/flamovies.h"
 #include "twine/gamestate.h"
 #include "twine/input.h"
@@ -41,6 +43,9 @@ namespace TwinE {
 /** Main menu enter players name */
 #define MAINMENU_ENTERPLAYERNAME 42
 
+#define ONSCREENKEYBOARD_WIDTH 14
+#define ONSCREENKEYBOARD_HEIGHT 5
+
 static const char allowedCharIndex[] = " ABCDEFGHIJKLM.NOPQRSTUVWXYZ-abcdefghijklm?nopqrstuvwxyz!0123456789\040\b\r\0";
 
 void MenuOptions::newGame() {
@@ -113,10 +118,10 @@ void MenuOptions::showCredits() {
 	_engine->setPalette(_engine->_screens->paletteRGBA);
 }
 
-void MenuOptions::drawSelectableCharacter(int32 x, int32 y, int32 arg) {
+void MenuOptions::drawSelectableCharacter(int32 x, int32 y, bool selected) {
 	char buffer[2];
 
-	buffer[0] = allowedCharIndex[y + x * 14];
+	buffer[0] = allowedCharIndex[y + x * ONSCREENKEYBOARD_WIDTH];
 	buffer[1] = '\0';
 
 	const int32 centerX = y * 45 + 25;
@@ -126,7 +131,7 @@ void MenuOptions::drawSelectableCharacter(int32 x, int32 y, int32 arg) {
 	const int32 centerY = x * 56 + 200;
 	const int32 bottom = x * 56 + 200 + 25;
 
-	if (arg != 0) {
+	if (selected) {
 		_engine->_interface->drawSplittedBox(left, top, right, bottom, 91);
 	} else {
 		_engine->_interface->blitBox(left, top, right, bottom, (const int8 *)_engine->workVideoBuffer.getPixels(), left, top, (int8 *)_engine->frontVideoBuffer.getPixels());
@@ -142,9 +147,9 @@ void MenuOptions::drawSelectableCharacter(int32 x, int32 y, int32 arg) {
 }
 
 void MenuOptions::drawSelectableCharacters() {
-	for (int8 x = 0; x < 5; x++) {
-		for (int8 y = 0; y < 14; y++) {
-			drawSelectableCharacter(x, y, 0);
+	for (int8 x = 0; x < ONSCREENKEYBOARD_HEIGHT; x++) {
+		for (int8 y = 0; y < ONSCREENKEYBOARD_WIDTH; y++) {
+			drawSelectableCharacter(x, y, _onScreenKeyboardY == x && _onScreenKeyboardX == y);
 		}
 	}
 }
@@ -154,7 +159,7 @@ void MenuOptions::drawPlayerName(int32 centerx, int32 top, int32 type) {
 	const int left = _engine->_text->dialTextBoxLeft;
 	const int right = _engine->_text->dialTextBoxRight;
 	if (type == 1) {
-		_engine->_menu->processPlasmaEffect(left, top, right, 1);
+		_engine->_menu->processPlasmaEffect(left, top, right, 32);
 	}
 
 	const int bottom = _engine->_text->dialTextBoxBottom;
@@ -167,54 +172,120 @@ void MenuOptions::drawPlayerName(int32 centerx, int32 top, int32 type) {
 	// TODO: _engine->copyBlockPhys(left, top, right, bottom);
 }
 
-int32 MenuOptions::enterPlayerName(int32 textIdx) {
+bool MenuOptions::enterPlayerName(int32 textIdx) {
 	_engine->_screens->copyScreen(_engine->workVideoBuffer, _engine->frontVideoBuffer);
 	_engine->flip();
 	playerName[0] = '\0'; // TODO: read from settings?
-	while (1) {
-		_engine->_text->initTextBank(0);
-		char buffer[256];
-		_engine->_text->getMenuText(textIdx, buffer, sizeof(buffer));
-		_engine->_text->setFontColor(15);
-		const int halfScreenWidth = (SCREEN_WIDTH / 2);
-		_engine->_text->drawText(halfScreenWidth - (_engine->_text->getTextSize(buffer) / 2), 20, buffer);
-		_engine->copyBlockPhys(0, 0, SCREEN_WIDTH - 1, 99);
-		drawPlayerName(halfScreenWidth, 100, 1);
-		drawSelectableCharacters();
-		_engine->flip();
+	_engine->_text->initTextBank(0);
+	char buffer[256];
+	_engine->_text->getMenuText(textIdx, buffer, sizeof(buffer));
+	_engine->_text->setFontColor(15);
+	const int halfScreenWidth = (SCREEN_WIDTH / 2);
+	_engine->_text->drawText(halfScreenWidth - (_engine->_text->getTextSize(buffer) / 2), 20, buffer);
+	_engine->copyBlockPhys(0, 0, SCREEN_WIDTH - 1, 99);
+	_engine->flip();
 
-		// we don't want custom events here - as we are entering the player name
-		ScopedKeyMapperDisable scopedKeyMapperDisable;
-		for (;;) {
-			Common::Event event;
-			while (g_system->getEventManager()->pollEvent(event)) {
-				if (event.type == Common::EVENT_KEYDOWN) {
-					if (event.kbd.keycode == Common::KEYCODE_KP_ENTER || event.kbd.keycode == Common::KEYCODE_RETURN) {
-						return 1;
+	for (;;) {
+		Common::Event event;
+		while (g_system->getEventManager()->pollEvent(event)) {
+			switch (event.type) {
+			case Common::EVENT_CUSTOM_ENGINE_ACTION_END:
+				_engine->_input->processCustomEngineEventEnd(event);
+				break;
+			case Common::EVENT_CUSTOM_ENGINE_ACTION_START:
+				_engine->_input->processCustomEngineEventStart(event);
+
+				if (_engine->_input->toggleActionIfActive(TwinEActionType::UIEnter)) {
+					if (_onScreenKeyboardLeaveViaOkButton) {
+						if (_onScreenKeyboardX == ONSCREENKEYBOARD_WIDTH - 1 && _onScreenKeyboardY == ONSCREENKEYBOARD_HEIGHT - 1) {
+							return true;
+						}
+						const size_t size = strlen(playerName);
+						if (_onScreenKeyboardX == ONSCREENKEYBOARD_WIDTH - 2 && _onScreenKeyboardY == ONSCREENKEYBOARD_HEIGHT - 1) {
+							if (size >= 1) {
+								playerName[size - 1] = '\0';
+							}
+							continue;
+						}
+						const char chr = allowedCharIndex[_onScreenKeyboardX + _onScreenKeyboardY * ONSCREENKEYBOARD_WIDTH];
+						playerName[size] = chr;
+						playerName[size + 1] = '\0';
+						if (size + 1 >= sizeof(playerName) - 1) {
+							return true;
+						}
+						continue;
+					}
+					return true;
+				}
+				if (_engine->_input->toggleActionIfActive(TwinEActionType::UIAbort)) {
+					return false;
+				}
+				if (_engine->_input->toggleActionIfActive(TwinEActionType::UILeft)) {
+					--_onScreenKeyboardX;
+					if (_onScreenKeyboardX < 0) {
+						_onScreenKeyboardX = ONSCREENKEYBOARD_WIDTH - 1;
+					}
+					_onScreenKeyboardLeaveViaOkButton = true;
+				} else if (_engine->_input->toggleActionIfActive(TwinEActionType::UIRight)) {
+					++_onScreenKeyboardX;
+					if (_onScreenKeyboardX >= ONSCREENKEYBOARD_WIDTH) {
+						_onScreenKeyboardX = 0;
+					}
+					_onScreenKeyboardLeaveViaOkButton = true;
+				}
+				if (_engine->_input->toggleActionIfActive(TwinEActionType::UIUp)) {
+					--_onScreenKeyboardY;
+					if (_onScreenKeyboardY < 0) {
+						_onScreenKeyboardY = ONSCREENKEYBOARD_HEIGHT - 1;
+					}
+					_onScreenKeyboardLeaveViaOkButton = true;
+				} else if (_engine->_input->toggleActionIfActive(TwinEActionType::UIDown)) {
+					++_onScreenKeyboardY;
+					if (_onScreenKeyboardY >= ONSCREENKEYBOARD_HEIGHT) {
+						_onScreenKeyboardY = 0;
 					}
-					const size_t size = strlen(playerName);
-					if (size >= sizeof(playerName) - 1) {
-						return 1;
+					_onScreenKeyboardLeaveViaOkButton = true;
+				}
+
+				break;
+			case Common::EVENT_KEYDOWN: {
+				const size_t size = strlen(playerName);
+				if (!Common::isPrint(event.kbd.ascii)) {
+					if (event.kbd.keycode == Common::KEYCODE_BACKSPACE) {
+						if (size >= 1) {
+							playerName[size - 1] = '\0';
+							_onScreenKeyboardLeaveViaOkButton = false;
+						}
 					}
+					continue;
+				}
+				if (size >= sizeof(playerName) - 1) {
+					return true;
+				}
+				if (strchr(allowedCharIndex, event.kbd.ascii)) {
 					playerName[size] = event.kbd.ascii;
 					playerName[size + 1] = '\0';
-					debug("name: %s", playerName);
-
-					drawPlayerName(halfScreenWidth, 100, 1);
-					_engine->flip();
+					_onScreenKeyboardLeaveViaOkButton = false;
 				}
+
+				_engine->flip();
+				break;
 			}
-			if (_engine->shouldQuit()) {
+			default:
 				break;
 			}
-			_engine->_system->delayMillis(1);
-		};
+		}
+		if (_engine->shouldQuit()) {
+			break;
+		}
+		_engine->_system->delayMillis(10);
+		drawPlayerName(halfScreenWidth, 100, 1);
+		drawSelectableCharacters();
 	}
-	return 1;
+	return false;
 }
 
 void MenuOptions::newGameMenu() {
-	// TODO: process players name
 	if (enterPlayerName(MAINMENU_ENTERPLAYERNAME)) {
 		_engine->_gameState->initEngineVars();
 		newGame();
@@ -225,16 +296,41 @@ void MenuOptions::newGameMenu() {
 	}
 }
 
+int MenuOptions::chooseSave(int textIdx) {
+	if (!_engine->hasSavedSlots()) {
+		return -1;
+	}
+	_engine->_screens->copyScreen(_engine->workVideoBuffer, _engine->frontVideoBuffer);
+	_engine->flip();
+	do {
+		// TODO: assemble menu with save slots and make then loadable.
+		_engine->_text->initTextBank(0);
+		char buffer[256];
+		_engine->_text->getMenuText(textIdx, buffer, sizeof(buffer));
+		_engine->_text->setFontColor(15);
+		const int halfScreenWidth = (SCREEN_WIDTH / 2);
+		_engine->_text->drawText(halfScreenWidth - (_engine->_text->getTextSize(buffer) / 2), 20, buffer);
+		_engine->copyBlockPhys(0, 0, SCREEN_WIDTH - 1, 99);
+		_engine->flip();
+
+		if (_engine->shouldQuit()) {
+			break;
+		}
+		_engine->_system->delayMillis(1);
+	} while (_engine->_input->toggleAbortAction());
+
+	return 0;
+}
+
 void MenuOptions::continueGameMenu() {
-	//TODO: get list of saved games
-	//if(chooseSave(MAINMENU_CONTINUEGAME))
-	{
+	const int slot = chooseSave(MAINMENU_CONTINUEGAME);
+	if (slot >= 0) {
 		_engine->_gameState->initEngineVars();
-		_engine->_gameState->loadGame();
+		_engine->loadSaveSlot(slot);
 		if (_engine->_scene->newHeroX == -1) {
 			_engine->_scene->heroPositionType = ScenePositionType::kNoPosition;
 		}
-		if (_engine->_gameState->gameChapter == 0 && _engine->_scene->currentSceneIdx == 0) {
+		if (_engine->_gameState->gameChapter == 0 && _engine->_scene->currentSceneIdx == LBA1SceneId::Citadel_Island_Prison) {
 			newGame();
 		} else {
 			_engine->_text->newGameVar5 = 0;
diff --git a/engines/twine/menuoptions.h b/engines/twine/menuoptions.h
index f819b55afd..78cb7e933e 100644
--- a/engines/twine/menuoptions.h
+++ b/engines/twine/menuoptions.h
@@ -32,12 +32,17 @@ class MenuOptions {
 private:
 	TwinEEngine *_engine;
 
-	int32 enterPlayerName(int32 textIdx);
+	int _onScreenKeyboardX = 0;
+	int _onScreenKeyboardY = 0;
+	bool _onScreenKeyboardLeaveViaOkButton = false;
+
+	bool enterPlayerName(int32 textIdx);
 	void drawSelectableCharacters();
 	void drawPlayerName(int32 centerx, int32 top, int32 type);
-	void drawSelectableCharacter(int32 x, int32 y, int32 arg);
+	void drawSelectableCharacter(int32 x, int32 y, bool selected);
 	void showCredits();
 	void newGame();
+	int chooseSave(int textIdx);
 
 public:
 	MenuOptions(TwinEEngine *engine) : _engine(engine) {}
diff --git a/engines/twine/scene.cpp b/engines/twine/scene.cpp
index 162b18911e..4b2ca275ae 100644
--- a/engines/twine/scene.cpp
+++ b/engines/twine/scene.cpp
@@ -304,7 +304,7 @@ void Scene::changeScene() {
 	if (previousSceneIdx != needChangeScene) {
 		_engine->_actor->previousHeroBehaviour = _engine->_actor->heroBehaviour;
 		_engine->_actor->previousHeroAngle = sceneHero->angle;
-		_engine->_gameState->saveGame();
+		_engine->autoSave();
 	}
 
 	_engine->_actor->restartHeroScene();
diff --git a/engines/twine/scene.h b/engines/twine/scene.h
index 5764c2dcf6..383cad00ca 100644
--- a/engines/twine/scene.h
+++ b/engines/twine/scene.h
@@ -248,8 +248,8 @@ public:
 	uint8 *currentScene = nullptr;
 
 	int32 needChangeScene = LBA1SceneId::Citadel_Island_Prison;
-	int32 currentSceneIdx = 0;
-	int32 previousSceneIdx = 0;
+	int32 currentSceneIdx = LBA1SceneId::Citadel_Island_Prison;
+	int32 previousSceneIdx = LBA1SceneId::Citadel_Island_Prison;
 
 	uint8 *spriteShadowPtr = nullptr;
 	uint8 *spriteBoundingBoxPtr = nullptr;
diff --git a/engines/twine/script_life.cpp b/engines/twine/script_life.cpp
index 098b530b19..50e23f2e7b 100644
--- a/engines/twine/script_life.cpp
+++ b/engines/twine/script_life.cpp
@@ -1396,11 +1396,11 @@ static int32 lTHE_END(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
 	engine->_gameState->inventoryNumLeafs = 0;
 	engine->_scene->sceneHero->life = 50;
 	engine->_gameState->inventoryMagicPoints = 80;
-	engine->_scene->currentSceneIdx = 113;
+	engine->_scene->currentSceneIdx = LBA1SceneId::Polar_Island_Final_Battle;
 	engine->_actor->heroBehaviour = engine->_actor->previousHeroBehaviour;
 	engine->_scene->newHeroX = -1;
 	engine->_scene->sceneHero->angle = engine->_actor->previousHeroAngle;
-	engine->_gameState->saveGame();
+	engine->autoSave();
 	return 1; // break;
 }
 
diff --git a/engines/twine/twine.cpp b/engines/twine/twine.cpp
index 69c94aefe3..481a3a4409 100644
--- a/engines/twine/twine.cpp
+++ b/engines/twine/twine.cpp
@@ -26,11 +26,14 @@
 #include "common/error.h"
 #include "common/events.h"
 #include "common/keyboard.h"
+#include "common/savefile.h"
 #include "common/str.h"
+#include "common/stream.h"
 #include "common/system.h"
 #include "common/textconsole.h"
 #include "common/translation.h"
 #include "engines/util.h"
+#include "engines/metaengine.h"
 #include "graphics/managed_surface.h"
 #include "graphics/palette.h"
 #include "graphics/pixelformat.h"
@@ -167,6 +170,36 @@ bool TwinEEngine::hasFeature(EngineFeature f) const {
 	return false;
 }
 
+bool TwinEEngine::hasSavedSlots() {
+	Common::SaveFileManager *saveFileMan = getSaveFileManager();
+	const Common::String pattern(getMetaEngine().getSavegameFilePattern(_targetName.c_str()));
+	return !saveFileMan->listSavefiles(pattern).empty();
+}
+
+void TwinEEngine::wipeSaveSlot(int slot) {
+	Common::SaveFileManager *saveFileMan = getSaveFileManager();
+	const Common::String& saveFile = getMetaEngine().getSavegameFile(slot, _targetName.c_str());
+	saveFileMan->removeSavefile(saveFile);
+}
+
+bool TwinEEngine::loadSaveSlot(int slot) {
+	Common::SaveFileManager *saveFileMan = getSaveFileManager();
+	const Common::String& saveFile = getMetaEngine().getSavegameFile(slot, _targetName.c_str());
+	Common::InSaveFile* file = saveFileMan->openForLoading(saveFile);
+	return _gameState->loadGame(file);
+}
+
+bool TwinEEngine::saveSlot(int slot) {
+	Common::SaveFileManager *saveFileMan = getSaveFileManager();
+	const Common::String& saveFile = getMetaEngine().getSavegameFile(slot, _targetName.c_str());
+	Common::OutSaveFile* file =  saveFileMan->openForSaving(saveFile);
+	return _gameState->saveGame(file);
+}
+
+void TwinEEngine::autoSave() {
+	// TODO:
+}
+
 void TwinEEngine::allocVideoMemory() {
 	const Graphics::PixelFormat format = Graphics::PixelFormat::createFormatCLUT8();
 	workVideoBuffer.create(SCREEN_WIDTH, SCREEN_HEIGHT, format);
@@ -362,7 +395,7 @@ int32 TwinEEngine::runGameEngine() { // mainLoopInteration
 				unfreezeTime();
 				_redraw->redrawEngineActions(1);
 				freezeTime();
-				_gameState->saveGame(); // auto save game
+				autoSave();
 				quitGame = 0;
 				unfreezeTime();
 				return 0;
@@ -705,7 +738,7 @@ int32 TwinEEngine::runGameEngine() { // mainLoopInteration
 								_scene->currentSceneIdx = _scene->previousSceneIdx;
 							}
 
-							_gameState->saveGame();
+							autoSave();
 							_gameState->processGameoverAnimation();
 							quitGame = 0;
 							return 0;
diff --git a/engines/twine/twine.h b/engines/twine/twine.h
index 9d965c38dd..af63546295 100644
--- a/engines/twine/twine.h
+++ b/engines/twine/twine.h
@@ -30,6 +30,7 @@
 #include "graphics/managed_surface.h"
 #include "graphics/pixelformat.h"
 #include "graphics/surface.h"
+#include "metaengine.h"
 #include "twine/actor.h"
 #include "twine/input.h"
 #include "twine/detection.h"
@@ -167,6 +168,12 @@ public:
 	Common::Error run() override;
 	bool hasFeature(EngineFeature f) const override;
 
+	void wipeSaveSlot(int slot);
+	bool hasSavedSlots();
+	bool loadSaveSlot(int slot);
+	bool saveSlot(int slot);
+	void autoSave();
+
 	bool isLBA1() const { return _gameType == TwineGameType::GType_LBA; };
 	bool isLBA2() const { return _gameType == TwineGameType::GType_LBA2; };
 


Commit: 934a250cfdcc15e6a8b3d2ed7accc21894fe964f
    https://github.com/scummvm/scummvm/commit/934a250cfdcc15e6a8b3d2ed7accc21894fe964f
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2020-10-26T18:11:15+01:00

Commit Message:
TWINE: fixed assert in drawPlayerName

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


diff --git a/engines/twine/debug.cpp b/engines/twine/debug.cpp
index 13861d66eb..3e6ce4f914 100644
--- a/engines/twine/debug.cpp
+++ b/engines/twine/debug.cpp
@@ -409,7 +409,7 @@ int32 Debug::debugProcessButton(int32 X, int32 Y) {
 
 void Debug::debugPlasmaWindow(const char *text, int32 color) {
 	int32 textSize;
-	_engine->_menu->processPlasmaEffect(0, 5, SCREEN_WIDTH, color);
+	_engine->_menu->processPlasmaEffect(0, 5, color);
 	if (!(_engine->getRandomNumber() % 5)) {
 		_engine->_menu->plasmaEffectPtr[_engine->getRandomNumber() % 320 * 10 + 6400] = 255;
 	}
diff --git a/engines/twine/menu.cpp b/engines/twine/menu.cpp
index 7a2dfdeef3..fa0f86fed4 100644
--- a/engines/twine/menu.cpp
+++ b/engines/twine/menu.cpp
@@ -228,10 +228,6 @@ static const int16 VolumeMenuSettings[] = {
 };
 } // namespace _priv
 
-#define PLASMA_WIDTH 320
-#define PLASMA_HEIGHT 50
-#define SCREEN_W 640
-
 static int16 *copySettings(const int16 *settings, size_t size) {
 	int16 *buf = (int16 *)malloc(size);
 	if (buf == nullptr) {
@@ -306,7 +302,7 @@ void Menu::plasmaEffectRenderFrame() {
 		*(dest++) = *(src++);
 }
 
-void Menu::processPlasmaEffect(int32 left, int32 top, int32 right, int32 color) {
+void Menu::processPlasmaEffect(int32 left, int32 top, int32 color) {
 	const int32 max_value = color + 15;
 
 	plasmaEffectRenderFrame();
@@ -318,11 +314,11 @@ void Menu::processPlasmaEffect(int32 left, int32 top, int32 right, int32 color)
 		for (int32 j = 0; j < kMainMenuButtonWidth; j++) {
 			const uint8 c = MIN(in[i * kMainMenuButtonWidth + j] / 2 + color, max_value);
 			/* 2x2 squares sharing the same pixel color: */
-			const int32 target = 2 * (i * SCREEN_W + j);
+			const int32 target = 2 * (i * DEFAULT_SCREEN_WIDTH + j);
 			out[target + 0] = c;
 			out[target + 1] = c;
-			out[target + SCREEN_W + 0] = c;
-			out[target + SCREEN_W + 1] = c;
+			out[target + DEFAULT_SCREEN_WIDTH + 0] = c;
+			out[target + DEFAULT_SCREEN_WIDTH + 1] = c;
 		}
 	}
 }
@@ -373,13 +369,13 @@ void Menu::drawButtonGfx(int32 width, int32 topheight, int32 buttonId, int32 tex
 			}
 			};
 
-			processPlasmaEffect(left, top, right, 80);
+			processPlasmaEffect(left, top, 80);
 			if (!(_engine->getRandomNumber() % 5)) {
 				plasmaEffectPtr[_engine->getRandomNumber() % 140 * 10 + 1900] = 255;
 			}
 			_engine->_interface->drawSplittedBox(newWidth, top, right, bottom, 68);
 		} else {
-			processPlasmaEffect(left, top, right, 64);
+			processPlasmaEffect(left, top, 64);
 			if (!(_engine->getRandomNumber() % 5)) {
 				plasmaEffectPtr[_engine->getRandomNumber() % 320 * 10 + 6400] = 255;
 			}
diff --git a/engines/twine/menu.h b/engines/twine/menu.h
index 90f98c4483..ed9fa98e75 100644
--- a/engines/twine/menu.h
+++ b/engines/twine/menu.h
@@ -38,6 +38,9 @@ enum MenuSettingsType {
 	MenuSettings_FirstButton = 5
 };
 
+#define PLASMA_WIDTH 320
+#define PLASMA_HEIGHT 50
+
 class Menu {
 private:
 	TwinEEngine *_engine;
@@ -116,7 +119,7 @@ public:
 	 * @param top top height where the effect will be draw in the front buffer
 	 * @param color plasma effect start color
 	 */
-	void processPlasmaEffect(int32 left, int32 top, int32 right, int32 color);
+	void processPlasmaEffect(int32 left, int32 top, int32 color);
 
 	/**
 	 * Draw the entire button box
diff --git a/engines/twine/menuoptions.cpp b/engines/twine/menuoptions.cpp
index 7f07c894dc..4b5a5ea4f8 100644
--- a/engines/twine/menuoptions.cpp
+++ b/engines/twine/menuoptions.cpp
@@ -154,22 +154,19 @@ void MenuOptions::drawSelectableCharacters() {
 	}
 }
 
-// 0001F18C
 void MenuOptions::drawPlayerName(int32 centerx, int32 top, int32 type) {
 	const int left = _engine->_text->dialTextBoxLeft;
-	const int right = _engine->_text->dialTextBoxRight;
 	if (type == 1) {
-		_engine->_menu->processPlasmaEffect(left, top, right, 32);
+		_engine->_menu->processPlasmaEffect(left, top, 32);
 	}
 
+	const int right = SCREEN_WIDTH - 1; //_engine->_text->dialTextBoxRight; // FIXME: dialTextBoxRight is 0 here
 	const int bottom = _engine->_text->dialTextBoxBottom;
 	_engine->_menu->drawBox(left, top, right, bottom);
 	_engine->_interface->drawTransparentBox(left + 1, top + 1, right - 1, bottom - 1, 3);
 
 	_engine->_text->drawText(centerx - _engine->_text->getTextSize(playerName) / 2, top, playerName);
-
-	_engine->flip();
-	// TODO: _engine->copyBlockPhys(left, top, right, bottom);
+	_engine->copyBlockPhys(left, top, right, top + PLASMA_HEIGHT);
 }
 
 bool MenuOptions::enterPlayerName(int32 textIdx) {
@@ -278,9 +275,9 @@ bool MenuOptions::enterPlayerName(int32 textIdx) {
 		if (_engine->shouldQuit()) {
 			break;
 		}
-		_engine->_system->delayMillis(10);
 		drawPlayerName(halfScreenWidth, 100, 1);
 		drawSelectableCharacters();
+		_engine->_system->delayMillis(1);
 	}
 	return false;
 }
diff --git a/engines/twine/twine.cpp b/engines/twine/twine.cpp
index 481a3a4409..d51f1cbf5c 100644
--- a/engines/twine/twine.cpp
+++ b/engines/twine/twine.cpp
@@ -860,6 +860,9 @@ void TwinEEngine::copyBlockPhys(int32 left, int32 top, int32 right, int32 bottom
 	assert(top <= bottom);
 	const int32 width = right - left + 1;
 	const int32 height = bottom - top + 1;
+	if (width <= 0 || height <= 0) {
+		return;
+	}
 	g_system->copyRectToScreen(frontVideoBuffer.getBasePtr(left, top), frontVideoBuffer.pitch, left, top, width, height);
 	g_system->updateScreen();
 }


Commit: b3070111700a06cd212a0c33e572867f93663b81
    https://github.com/scummvm/scummvm/commit/b3070111700a06cd212a0c33e572867f93663b81
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2020-10-26T18:11:15+01:00

Commit Message:
TWINE: cleanup input code and replaced magic numbers

Changed paths:
    engines/twine/actor.cpp
    engines/twine/actor.h
    engines/twine/input.cpp
    engines/twine/input.h
    engines/twine/movements.cpp
    engines/twine/movements.h
    engines/twine/scene.cpp
    engines/twine/script_life.cpp
    engines/twine/twine.cpp


diff --git a/engines/twine/actor.cpp b/engines/twine/actor.cpp
index cd843f5021..604bd169d9 100644
--- a/engines/twine/actor.cpp
+++ b/engines/twine/actor.cpp
@@ -42,7 +42,7 @@ Actor::Actor(TwinEEngine *engine) : _engine(engine) {
 }
 
 void Actor::restartHeroScene() {
-	_engine->_scene->sceneHero->controlMode = 1;
+	_engine->_scene->sceneHero->controlMode = ControlMode::kManual;
 	memset(&_engine->_scene->sceneHero->dynamicFlags, 0, sizeof(_engine->_scene->sceneHero->dynamicFlags));
 	memset(&_engine->_scene->sceneHero->staticFlags, 0, sizeof(_engine->_scene->sceneHero->staticFlags));
 
@@ -387,7 +387,7 @@ void Actor::resetActor(int16 actorIdx) {
 
 	actor->angle = 0;
 	actor->speed = 40;
-	actor->controlMode = 0;
+	actor->controlMode = ControlMode::kNoMove;
 
 	actor->info0 = 0;
 	actor->info1 = 0;
diff --git a/engines/twine/actor.h b/engines/twine/actor.h
index 5289fb10a9..d0a6798d81 100644
--- a/engines/twine/actor.h
+++ b/engines/twine/actor.h
@@ -147,6 +147,18 @@ struct DynamicFlagsStruct {
 	uint16 bUnk8000 : 1;          // 0x8000 unused
 };
 
+/** Control mode types */
+enum ControlMode {
+	kNoMove = 0,
+	kManual = 1,
+	kFollow = 2,
+	kTrack = 3,
+	kFollow2 = 4,
+	kTrackAttack = 5,
+	kSameXZ = 6,
+	kRandom = 7
+};
+
 /** Actors structure */
 struct ActorStruct {
 	StaticFlagsStruct staticFlags;
@@ -170,7 +182,7 @@ struct ActorStruct {
 	int32 bonusParameter = 0; // field_10
 	int32 angle = 0;
 	int32 speed = 0;
-	int32 controlMode = 0;
+	ControlMode controlMode = ControlMode::kNoMove;
 	int32 info0 = 0;         // cropLeft
 	int32 info1 = 0;         // cropTop
 	int32 info2 = 0;         // cropRight
diff --git a/engines/twine/input.cpp b/engines/twine/input.cpp
index 04560f3d15..1964212193 100644
--- a/engines/twine/input.cpp
+++ b/engines/twine/input.cpp
@@ -73,14 +73,6 @@ static const struct KeyProperties {
     {0x00, false, 0x00}};
 static_assert(ARRAYSIZE(pressedKeyCharMap) == 31, "Expected size of key char map");
 
-ScopedKeyMapperDisable::ScopedKeyMapperDisable() {
-	g_system->getEventManager()->getKeymapper()->setEnabled(false);
-}
-
-ScopedKeyMapperDisable::~ScopedKeyMapperDisable() {
-	g_system->getEventManager()->getKeymapper()->setEnabled(true);
-}
-
 ScopedKeyMap::ScopedKeyMap(TwinEEngine* engine, const char *id) : _engine(engine) {
 	_prevKeyMap = _engine->_input->currentKeyMap();
 	_engine->_input->enableKeyMap(cutsceneKeyMapId);
@@ -92,13 +84,6 @@ ScopedKeyMap::~ScopedKeyMap() {
 
 Input::Input(TwinEEngine *engine) : _engine(engine) {}
 
-bool Input::isPressed(Common::KeyCode keycode, bool onlyFirstTime) const {
-	if (onlyFirstTime) {
-		return _pressed[keycode] == 1;
-	}
-	return _pressed[keycode] > 0;
-}
-
 bool Input::isActionActive(TwinEActionType actionType, bool onlyFirstTime) const {
 	if (onlyFirstTime) {
 		return actionStates[actionType] == 1;
@@ -127,9 +112,6 @@ void Input::enableKeyMap(const char *id) {
 		return;
 	}
 
-	// switching the keymap must also disable all other action keys
-	memset(_pressed, 0, sizeof(_pressed));
-
 	Common::Keymapper *keymapper = g_system->getEventManager()->getKeymapper();
 	const Common::KeymapArray &keymaps = keymapper->getKeymaps();
 	for (Common::Keymap *keymap : keymaps) {
@@ -183,12 +165,6 @@ void Input::readKeys() {
 		case Common::EVENT_LBUTTONDOWN:
 			leftMouse = 1;
 			break;
-		case Common::EVENT_KEYDOWN:
-			_pressed[event.kbd.keycode] = 1 + event.kbdRepeat;
-			break;
-		case Common::EVENT_KEYUP:
-			_pressed[event.kbd.keycode] = 0;
-			break;
 		case Common::EVENT_RBUTTONDOWN:
 			rightMouse = 1;
 			break;
diff --git a/engines/twine/input.h b/engines/twine/input.h
index 20bd08c4df..4ab416032f 100644
--- a/engines/twine/input.h
+++ b/engines/twine/input.h
@@ -134,15 +134,6 @@ struct MouseStatusStruct {
 	int32 y = 0;
 };
 
-/**
- * @brief Whenever text input is needed (like the playername)
- * you have to disable the keymaps
- */
-struct ScopedKeyMapperDisable {
-	ScopedKeyMapperDisable();
-	~ScopedKeyMapperDisable();
-};
-
 /**
  * @brief Activates the given key map id that is registered in the meta engine
  */
@@ -158,7 +149,6 @@ public:
 class Input {
 private:
 	TwinEEngine *_engine;
-	uint8 _pressed[Common::KEYCODE_LAST]{0};
 	Common::String _currentKeyMap;
 
 	uint8 actionStates[TwinEActionType::Max]{false};
@@ -197,20 +187,6 @@ public:
 
 	bool toggleAbortAction();
 
-	/**
-	 * @param onlyFirstTime If this is set to @c true, repeating key press events are not taken into account here
-	 * This means, that even if the key is held down, this will return @c false. @c false as value for this parameter
-	 * will return @c true also for repeating key presses.
-	 *
-	 * @note You won't receive any pressed events if you have that key bound to a @c TwinEActionType value.
-	 * @sa isActionActive()
-	 */
-	bool isPressed(Common::KeyCode keycode, bool onlyFirstTime = true) const;
-
-	inline bool isPressedEnter(bool onlyFirstTime = true) const {
-		return isPressed(Common::KEYCODE_RETURN, onlyFirstTime) || isPressed(Common::KEYCODE_KP_ENTER, onlyFirstTime);
-	}
-
 	bool isQuickBehaviourActionActive() const;
 
 	/**
diff --git a/engines/twine/movements.cpp b/engines/twine/movements.cpp
index 7e3804a41a..18bc017352 100644
--- a/engines/twine/movements.cpp
+++ b/engines/twine/movements.cpp
@@ -281,7 +281,7 @@ void Movements::processActorMovements(int32 actorIdx) {
 		heroPressedKey = _engine->_input->key;
 	} else {
 		if (!actor->staticFlags.bIsSpriteActor) {
-			if (actor->controlMode != kManual) {
+			if (actor->controlMode != ControlMode::kManual) {
 				actor->angle = getRealAngle(&actor->move);
 			}
 		}
diff --git a/engines/twine/movements.h b/engines/twine/movements.h
index 154ffc9ae3..2774f74782 100644
--- a/engines/twine/movements.h
+++ b/engines/twine/movements.h
@@ -28,18 +28,6 @@
 
 namespace TwinE {
 
-/** Control mode types */
-enum ControlMode {
-	kNoMove = 0,
-	kManual = 1,
-	kFollow = 2,
-	kTrack = 3,
-	kFollow2 = 4,
-	kTrackAttack = 5,
-	kSameXZ = 6,
-	kRandom = 7
-};
-
 class TwinEEngine;
 
 class Movements {
diff --git a/engines/twine/scene.cpp b/engines/twine/scene.cpp
index 4b2ca275ae..e4db3883e3 100644
--- a/engines/twine/scene.cpp
+++ b/engines/twine/scene.cpp
@@ -170,7 +170,7 @@ bool Scene::loadSceneLBA1() {
 		act->bonusParameter &= 0xFE;
 		act->angle = stream.readUint16LE();
 		act->speed = stream.readUint16LE();
-		act->controlMode = stream.readUint16LE();
+		act->controlMode = (ControlMode)stream.readUint16LE();
 		act->info0 = stream.readUint16LE();
 		act->info1 = stream.readUint16LE();
 		act->info2 = stream.readUint16LE();
@@ -266,7 +266,7 @@ void Scene::changeScene() {
 	resetScene();
 	_engine->_actor->loadHeroEntities();
 
-	sceneHero->controlMode = 1;
+	sceneHero->controlMode = ControlMode::kManual;
 	sceneHero->zone = -1;
 	sceneHero->positionInLifeScript = 0;
 	sceneHero->positionInMoveScript = -1;
diff --git a/engines/twine/script_life.cpp b/engines/twine/script_life.cpp
index 50e23f2e7b..d1ec201509 100644
--- a/engines/twine/script_life.cpp
+++ b/engines/twine/script_life.cpp
@@ -589,8 +589,8 @@ static int32 lFALLABLE(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor)
 static int32 lSET_DIRMODE(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
 	int32 controlMode = *(scriptPtr++);
 
-	actor->controlMode = controlMode;
-	if (controlMode == kFollow) {
+	actor->controlMode = (ControlMode)controlMode;
+	if (actor->controlMode == ControlMode::kFollow) {
 		actor->followedActor = *(scriptPtr++);
 	}
 
@@ -602,9 +602,10 @@ static int32 lSET_DIRMODE_OBJ(TwinEEngine *engine, int32 actorIdx, ActorStruct *
 	int32 otherActorIdx = *(scriptPtr++);
 	int32 controlMode = *(scriptPtr++);
 
-	engine->_scene->getActor(otherActorIdx)->controlMode = controlMode;
-	if (controlMode == kFollow) {
-		engine->_scene->getActor(otherActorIdx)->followedActor = *(scriptPtr++);
+	ActorStruct *otherActor = engine->_scene->getActor(otherActorIdx);
+	otherActor->controlMode = (ControlMode)controlMode;
+	if (otherActor->controlMode == ControlMode::kFollow) {
+		otherActor->followedActor = *(scriptPtr++);
 	}
 
 	return 0;
diff --git a/engines/twine/twine.cpp b/engines/twine/twine.cpp
index d51f1cbf5c..8714adcc4a 100644
--- a/engines/twine/twine.cpp
+++ b/engines/twine/twine.cpp
@@ -419,7 +419,7 @@ int32 TwinEEngine::runGameEngine() { // mainLoopInteration
 
 		// inventory menu
 		loopInventoryItem = -1;
-		if (_input->isActionActive(TwinEActionType::InventoryMenu) && _scene->sceneHero->entity != -1 && _scene->sceneHero->controlMode == kManual) {
+		if (_input->isActionActive(TwinEActionType::InventoryMenu) && _scene->sceneHero->entity != -1 && _scene->sceneHero->controlMode == ControlMode::kManual) {
 			freezeTime();
 			_menu->processInventoryMenu();
 
@@ -535,7 +535,7 @@ int32 TwinEEngine::runGameEngine() { // mainLoopInteration
 		     _input->isActionActive(TwinEActionType::QuickBehaviourAthletic, false) ||
 		     _input->isActionActive(TwinEActionType::QuickBehaviourAggressive, false) ||
 		     _input->isActionActive(TwinEActionType::QuickBehaviourDiscreet, false)) &&
-		    _scene->sceneHero->entity != -1 && _scene->sceneHero->controlMode == kManual) {
+		    _scene->sceneHero->entity != -1 && _scene->sceneHero->controlMode == ControlMode::kManual) {
 			if (_input->isActionActive(TwinEActionType::QuickBehaviourNormal, false)) {
 				_actor->heroBehaviour = HeroBehaviourType::kNormal;
 			} else if (_input->isActionActive(TwinEActionType::QuickBehaviourAthletic, false)) {
@@ -627,7 +627,7 @@ int32 TwinEEngine::runGameEngine() { // mainLoopInteration
 			if (actor->life == 0) {
 				if (a == 0) { // if its hero who died
 					_animations->initAnim(kLandDeath, 4, 0, 0);
-					actor->controlMode = 0;
+					actor->controlMode = ControlMode::kNoMove;
 				} else {
 					_sound->playSample(37, getRandomNumber(2000) + 3096, 1, actor->x, actor->y, actor->z, a);
 
@@ -691,7 +691,7 @@ int32 TwinEEngine::runGameEngine() { // mainLoopInteration
 									_actor->cropBottomScreen = _renderer->projPosY;
 								}
 								_renderer->projectPositionOnScreen(actor->x - _grid->cameraX, actor->y - _grid->cameraY, actor->z - _grid->cameraZ);
-								actor->controlMode = 0;
+								actor->controlMode = ControlMode::kNoMove;
 								actor->life = -1;
 								_actor->cropBottomScreen = _renderer->projPosY;
 								actor->staticFlags.bCanDrown |= 0x10;


Commit: 632b794e2b2742c3c0e4357721a48fdba53a9811
    https://github.com/scummvm/scummvm/commit/632b794e2b2742c3c0e4357721a48fdba53a9811
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2020-10-26T18:11:15+01:00

Commit Message:
TWINE: converted to boolean

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


diff --git a/engines/twine/movements.cpp b/engines/twine/movements.cpp
index 18bc017352..1cf3559697 100644
--- a/engines/twine/movements.cpp
+++ b/engines/twine/movements.cpp
@@ -292,18 +292,18 @@ void Movements::processActorMovements(int32 actorIdx) {
 		case kManual:
 			// take this out when we want to give manual movements to other characters than Hero
 			if (actor == _engine->_scene->sceneHero) {
-				heroAction = 0;
+				heroAction = false;
 
 				// If press W for action
 				if (_engine->_input->isActionActive(TwinEActionType::SpecialAction)) {
-					heroAction = 1;
+					heroAction = true;
 				}
 
 				// Process hero actions
 				switch (_engine->_actor->heroBehaviour) {
 				case kNormal:
 					if (_engine->_input->isActionActive(TwinEActionType::ExecuteBehaviourAction)) {
-						heroAction = 1;
+						heroAction = true;
 					}
 					break;
 				case kAthletic:
diff --git a/engines/twine/movements.h b/engines/twine/movements.h
index 2774f74782..9a5484ec29 100644
--- a/engines/twine/movements.h
+++ b/engines/twine/movements.h
@@ -42,7 +42,7 @@ public:
 	/** Hero moved */
 	bool heroMoved = false; // twinsenMove
 	/** Hero Action */
-	int16 heroAction = 0; // action
+	bool heroAction = false; // action
 
 	/** Process actor.x coordinate */
 	int16 processActorX = 0;
diff --git a/engines/twine/scene.cpp b/engines/twine/scene.cpp
index e4db3883e3..2074181a2d 100644
--- a/engines/twine/scene.cpp
+++ b/engines/twine/scene.cpp
@@ -474,13 +474,13 @@ void Scene::processActorZones(int32 actorIdx) {
 				}
 				break;
 			case kObject:
-				if (!actorIdx && _engine->_movements->heroAction != 0) {
+				if (!actorIdx && _engine->_movements->heroAction) {
 					_engine->_animations->initAnim(kAction, 1, 0, 0);
 					processZoneExtraBonus(zone);
 				}
 				break;
 			case kText:
-				if (!actorIdx && _engine->_movements->heroAction != 0) {
+				if (!actorIdx && _engine->_movements->heroAction) {
 					_engine->freezeTime();
 					_engine->_text->setFontCrossColor(zone->infoData.DisplayText.textColor);
 					talkingActor = actorIdx;
diff --git a/engines/twine/script_life.cpp b/engines/twine/script_life.cpp
index d1ec201509..485970310f 100644
--- a/engines/twine/script_life.cpp
+++ b/engines/twine/script_life.cpp
@@ -237,7 +237,7 @@ static int32 processLifeConditions(TwinEEngine *engine, ActorStruct *actor) {
 		engine->_scene->currentScriptValue = actor->hitBy;
 		break;
 	case kcACTION:
-		engine->_scene->currentScriptValue = engine->_movements->heroAction;
+		engine->_scene->currentScriptValue = engine->_movements->heroAction ? 1 : 0;
 		break;
 	case kcFLAG_GAME: {
 		int32 flagIdx = *(scriptPtr++);


Commit: 471289413342afd4b45bd1d6a23313b50e5239cf
    https://github.com/scummvm/scummvm/commit/471289413342afd4b45bd1d6a23313b50e5239cf
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2020-10-26T18:11:15+01:00

Commit Message:
TWINE: make more or less private

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


diff --git a/engines/twine/input.cpp b/engines/twine/input.cpp
index 1964212193..a8176eb9ae 100644
--- a/engines/twine/input.cpp
+++ b/engines/twine/input.cpp
@@ -124,6 +124,52 @@ void Input::enableKeyMap(const char *id) {
 	debug("enable keymap %s", id);
 }
 
+// TODO: get rid of this table
+static constexpr const struct ActionMapping {
+	TwinEActionType action;
+	uint8 localKey;
+} twineactions[] = {
+    {Pause, 0x19},
+    {NextRoom, 0x13},
+    {PreviousRoom, 0x21},
+    {ApplyCellingGrid, 0x14},
+    {IncreaseCellingGridIndex, 0x22},
+    {DecreaseCellingGridIndex, 0x30},
+    {DebugGridCameraPressUp, 0x2E},
+    {DebugGridCameraPressDown, 0x2C},
+    {DebugGridCameraPressLeft, 0x1F},
+    {DebugGridCameraPressRight, 0x2D},
+    {QuickBehaviourNormal, 0x3B},
+    {QuickBehaviourAthletic, 0x3C},
+    {QuickBehaviourAggressive, 0x3D},
+    {QuickBehaviourDiscreet, 0x3E},
+    {ExecuteBehaviourAction, 0x39},
+    {BehaviourMenu, 0x1D},
+    {OptionsMenu, 0x40},
+    {RecenterScreenOnTwinsen, 0x1C},
+    {UseSelectedObject, 0x1C},
+    {ThrowMagicBall, 0x38},
+    {MoveForward, 0x48},
+    {MoveBackward, 0x50},
+    {TurnRight, 0x4D},
+    {TurnLeft, 0x4B},
+    {UseProtoPack, 0x24},
+    {OpenHolomap, 0x23},
+    {InventoryMenu, 0x36},
+    {SpecialAction, 0x11},
+    {Escape, 0x01},
+    {PageUp, 0x49}, // TODO: used for what?
+    {UIEnter, 0x00},
+    {UIAbort, 0x00},
+    {UILeft, 0x00},
+    {UIRight, 0x00},
+    {UIUp, 0x00},
+    {UIDown, 0x00},
+    {UINextPage, 0x00},
+    {CutsceneAbort, 0x00}};
+
+static_assert(ARRAYSIZE(twineactions) == TwinEActionType::Max, "Unexpected action mapping array size");
+
 uint8 Input::processCustomEngineEventStart(const Common::Event &event) {
 	if (!_engine->cfgfile.Debug) {
 		switch (event.customType) {
@@ -185,6 +231,7 @@ void Input::readKeys() {
 						pressedKey |= pressedKeyCharMap[i].high;
 					}
 				} else {
+					// they are handled as loop keys
 					skippedKey |= pressedKeyCharMap[i].high;
 				}
 				break;
diff --git a/engines/twine/input.h b/engines/twine/input.h
index 4ab416032f..81600055b9 100644
--- a/engines/twine/input.h
+++ b/engines/twine/input.h
@@ -81,52 +81,6 @@ enum TwinEActionType {
 	Max
 };
 
-// TODO: get rid of this table
-static constexpr const struct ActionMapping {
-	TwinEActionType action;
-	uint8 localKey;
-} twineactions[] = {
-    {Pause, 0x19},
-    {NextRoom, 0x13},
-    {PreviousRoom, 0x21},
-    {ApplyCellingGrid, 0x14},
-    {IncreaseCellingGridIndex, 0x22},
-    {DecreaseCellingGridIndex, 0x30},
-    {DebugGridCameraPressUp, 0x2E},
-    {DebugGridCameraPressDown, 0x2C},
-    {DebugGridCameraPressLeft, 0x1F},
-    {DebugGridCameraPressRight, 0x2D},
-    {QuickBehaviourNormal, 0x3B},
-    {QuickBehaviourAthletic, 0x3C},
-    {QuickBehaviourAggressive, 0x3D},
-    {QuickBehaviourDiscreet, 0x3E},
-    {ExecuteBehaviourAction, 0x39},
-    {BehaviourMenu, 0x1D},
-    {OptionsMenu, 0x40},
-    {RecenterScreenOnTwinsen, 0x1C},
-    {UseSelectedObject, 0x1C},
-    {ThrowMagicBall, 0x38},
-    {MoveForward, 0x48},
-    {MoveBackward, 0x50},
-    {TurnRight, 0x4D},
-    {TurnLeft, 0x4B},
-    {UseProtoPack, 0x24},
-    {OpenHolomap, 0x23},
-    {InventoryMenu, 0x36},
-    {SpecialAction, 0x11},
-    {Escape, 0x01},
-    {PageUp, 0x49}, // TODO: used for what?
-    {UIEnter, 0x00},
-    {UIAbort, 0x00},
-    {UILeft, 0x00},
-    {UIRight, 0x00},
-    {UIUp, 0x00},
-    {UIDown, 0x00},
-    {UINextPage, 0x00},
-    {CutsceneAbort, 0x00}};
-
-static_assert(ARRAYSIZE(twineactions) == TwinEActionType::Max, "Unexpected action mapping array size");
-
 struct MouseStatusStruct {
 	int32 left = 0;
 	int32 right = 0;


Commit: b90797e00d2379e43ab4fdcddaf649f903bb37c5
    https://github.com/scummvm/scummvm/commit/b90797e00d2379e43ab4fdcddaf649f903bb37c5
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2020-10-26T18:11:15+01:00

Commit Message:
TWINE: moved pressed key states into movements class

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


diff --git a/engines/twine/input.cpp b/engines/twine/input.cpp
index a8176eb9ae..e7d2864f73 100644
--- a/engines/twine/input.cpp
+++ b/engines/twine/input.cpp
@@ -37,41 +37,44 @@ const char *cutsceneKeyMapId = "cutsceneKeyMap";
 /** Pressed key char map - scanCodeTab2 */
 static const struct KeyProperties {
 	uint8 high;
-	bool pressed;
+	bool cursor;
 	uint8 key;
 } pressedKeyCharMap[] = {
-    {0x01, false, 0x48}, // up
-    {0x02, false, 0x50}, // down
-    {0x04, false, 0x4B}, // left
-    {0x08, false, 0x4D}, // right
-    {0x05, false, 0x47}, // home
-    {0x09, false, 0x49}, // pageup
-    {0x0A, false, 0x51}, // pagedown
-    {0x06, false, 0x4F}, // end
-    {0x01, true, 0x39},  // space bar
-    {0x02, true, 0x1C},  // enter
-    {0x04, true, 0x1D},  // ctrl
-    {0x08, true, 0x38},  // alt
-    {0x10, true, 0x53},  // del
-    {0x20, true, 0x2A},  // left shift
-    {0x20, true, 0x36},  // right shift
-    {0x01, true, 0x3B},  // F1
-    {0x02, true, 0x3C},  // F2
-    {0x04, true, 0x3D},  // F3
-    {0x08, true, 0x3E},  // F4
-    {0x10, true, 0x3F},  // F5
-    {0x20, true, 0x40},  // F6
-    {0x40, true, 0x41},  // F7
-    {0x80, true, 0x42},  // F8
-    {0x01, true, 0x43},  // F9
-    {0x02, true, 0x44},  // F10
-    {0x04, true, 0x57},  // ?
-    {0x08, true, 0x58},  // ?
-    {0x00, true, 0x2A},  // left shift
-    {0x00, true, 0x00},
-    {0x01, false, 0x01}, // esc
-    {0x00, false, 0x00}};
-static_assert(ARRAYSIZE(pressedKeyCharMap) == 31, "Expected size of key char map");
+    {0x01, true, 0x48}, // up
+    {0x02, true, 0x50}, // down
+    {0x04, true, 0x4B}, // left
+    {0x08, true, 0x4D}, // right
+	#if 0
+    {0x05, true, 0x47}, // home
+    {0x09, true, 0x49}, // pageup
+    {0x0A, true, 0x51}, // pagedown
+    {0x06, true, 0x4F}, // end
+	#endif
+    {0x01, false, 0x39},  // space bar
+    {0x02, false, 0x1C},  // enter
+    {0x04, false, 0x1D},  // ctrl
+    {0x08, false, 0x38},  // alt
+    {0x10, false, 0x53},  // del
+    {0x20, false, 0x2A},  // left shift
+    {0x20, false, 0x36},  // right shift
+	#if 0
+    {0x01, false, 0x3B},  // F1
+    {0x02, false, 0x3C},  // F2
+    {0x04, false, 0x3D},  // F3
+    {0x08, false, 0x3E},  // F4
+    {0x10, false, 0x3F},  // F5
+    {0x20, false, 0x40},  // F6
+    {0x40, false, 0x41},  // F7
+    {0x80, false, 0x42},  // F8
+    {0x01, false, 0x43},  // F9
+    {0x02, false, 0x44},  // F10
+    {0x04, false, 0x57},  // ?
+    {0x08, false, 0x58},  // ?
+    {0x00, false, 0x2A},  // left shift
+    {0x00, false, 0x00},
+	#endif
+    {0x01, true, 0x01}, // esc
+    {0x00, true, 0x00}};
 
 ScopedKeyMap::ScopedKeyMap(TwinEEngine* engine, const char *id) : _engine(engine) {
 	_prevKeyMap = _engine->_input->currentKeyMap();
@@ -196,7 +199,7 @@ uint8 Input::processCustomEngineEventEnd(const Common::Event &event) {
 }
 
 void Input::readKeys() {
-	skippedKey = 0;
+	cursorKeys = 0;
 
 	Common::Event event;
 	while (g_system->getEventManager()->pollEvent(event)) {
@@ -224,15 +227,14 @@ void Input::readKeys() {
 
 		for (int i = 0; i < ARRAYSIZE(pressedKeyCharMap); i++) {
 			if (pressedKeyCharMap[i].key == localKey) {
-				if (pressedKeyCharMap[i].pressed) {
+				if (pressedKeyCharMap[i].cursor) {
+					cursorKeys |= pressedKeyCharMap[i].high;
+				} else {
 					if (event.type == Common::EVENT_CUSTOM_ENGINE_ACTION_END) {
 						pressedKey &= ~pressedKeyCharMap[i].high;
 					} else {
 						pressedKey |= pressedKeyCharMap[i].high;
 					}
-				} else {
-					// they are handled as loop keys
-					skippedKey |= pressedKeyCharMap[i].high;
 				}
 				break;
 			}
diff --git a/engines/twine/input.h b/engines/twine/input.h
index 81600055b9..db1f175674 100644
--- a/engines/twine/input.h
+++ b/engines/twine/input.h
@@ -110,8 +110,7 @@ private:
 public:
 	Input(TwinEEngine *engine);
 
-	int16 key = 0;
-	int16 skippedKey = 0;
+	int16 cursorKeys = 0;
 	int16 pressedKey = 0;
 	int16 leftMouse = 0;
 	int16 rightMouse = 0;
diff --git a/engines/twine/movements.cpp b/engines/twine/movements.cpp
index 1cf3559697..dd48f88b26 100644
--- a/engines/twine/movements.cpp
+++ b/engines/twine/movements.cpp
@@ -258,6 +258,12 @@ void Movements::moveActor(int32 angleFrom, int32 angleTo, int32 speed, ActorMove
 	movePtr->timeOfChange = _engine->lbaTime;
 }
 
+void Movements::update() {
+	previousLoopCursorKeys = loopCursorKeys;
+	heroActionKey = _engine->_input->pressedKey;
+	loopCursorKeys = _engine->_input->cursorKeys;
+}
+
 void Movements::processActorMovements(int32 actorIdx) {
 	ActorStruct *actor = _engine->_scene->getActor(actorIdx);
 	if (actor->entity == -1) {
@@ -278,7 +284,7 @@ void Movements::processActorMovements(int32 actorIdx) {
 
 		moveActor(actor->angle, actor->angle + tempAngle, actor->speed, &actor->move);
 
-		heroPressedKey = _engine->_input->key;
+		heroPressedKey = heroActionKey;
 	} else {
 		if (!actor->staticFlags.bIsSpriteActor) {
 			if (actor->controlMode != ControlMode::kManual) {
@@ -316,8 +322,8 @@ void Movements::processActorMovements(int32 actorIdx) {
 						if (_engine->_actor->autoAgressive) {
 							heroMoved = true;
 							actor->angle = getRealAngle(&actor->move);
-							// TODO: previousLoopPressedKey must be handled properly
-							if (!(_engine->previousLoopPressedKey & 1) || !actor->anim) {
+							// TODO: previousLoopCursorKeys must be handled properly
+							if (!(previousLoopCursorKeys & 1) || !actor->anim) {
 								int32 aggresiveMode = _engine->getRandomNumber(3);
 
 								switch (aggresiveMode) {
@@ -377,14 +383,14 @@ void Movements::processActorMovements(int32 actorIdx) {
 				}
 			}
 
-			// TODO: remove loopPressedKey here
-			if (!_engine->loopPressedKey || heroAction) {
+			// TODO: remove loopCursorKeys here
+			if (!loopCursorKeys || heroAction) {
 				// if continue walking
 				if (_engine->_input->isActionActive(TwinEActionType::MoveForward) || _engine->_input->isActionActive(TwinEActionType::MoveBackward)) {
 					heroMoved = false; // don't break animation
 				}
 
-				if (_engine->_input->key != heroPressedKey || _engine->loopPressedKey != heroPressedKey2) {
+				if (heroActionKey != heroPressedKey || loopCursorKeys != heroPressedKey2) {
 					if (heroMoved) {
 						_engine->_animations->initAnim(kStanding, 0, 255, actorIdx);
 					}
@@ -434,8 +440,8 @@ void Movements::processActorMovements(int32 actorIdx) {
 
 			moveActor(actor->angle, actor->angle + tempAngle, actor->speed, &actor->move);
 
-			heroPressedKey = _engine->_input->key;
-			heroPressedKey2 = _engine->loopPressedKey;
+			heroPressedKey = heroActionKey;
+			heroPressedKey2 = loopCursorKeys;
 
 			break;
 		case kFollow: {
diff --git a/engines/twine/movements.h b/engines/twine/movements.h
index 9a5484ec29..d315af01f7 100644
--- a/engines/twine/movements.h
+++ b/engines/twine/movements.h
@@ -34,11 +34,22 @@ class Movements {
 private:
 	TwinEEngine *_engine;
 
+	// enter, space, ...
 	int32 heroPressedKey = 0;
+	// cursor buttons
 	int32 heroPressedKey2 = 0;
+	// enter, space, ...
+	int16 heroActionKey = 0;
+	// enter, space, ...
+	int32 loopCursorKeys = 0;
+	// cursor keys
+	int32 previousLoopCursorKeys = 0;
 
 public:
 	Movements(TwinEEngine *engine);
+
+	void update();
+
 	/** Hero moved */
 	bool heroMoved = false; // twinsenMove
 	/** Hero Action */
diff --git a/engines/twine/twine.cpp b/engines/twine/twine.cpp
index 8714adcc4a..a6d2a1000e 100644
--- a/engines/twine/twine.cpp
+++ b/engines/twine/twine.cpp
@@ -376,9 +376,7 @@ int32 TwinEEngine::runGameEngine() { // mainLoopInteration
 		_scene->changeScene();
 	}
 
-	previousLoopPressedKey = loopPressedKey;
-	_input->key = _input->pressedKey;
-	loopPressedKey = _input->skippedKey;
+	_movements->update();
 
 	_debug->processDebug();
 
diff --git a/engines/twine/twine.h b/engines/twine/twine.h
index af63546295..98a292642e 100644
--- a/engines/twine/twine.h
+++ b/engines/twine/twine.h
@@ -240,8 +240,6 @@ public:
 	/** temporary screen table */
 	int32 screenLookupTable[2000]{0};
 
-	int32 loopPressedKey = 0;
-	int32 previousLoopPressedKey = 0;
 	int32 loopInventoryItem = 0;
 	int32 loopActorStep = 0;
 


Commit: b2463be755ffed0e8602a313461efda44ffc7eed
    https://github.com/scummvm/scummvm/commit/b2463be755ffed0e8602a313461efda44ffc7eed
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2020-10-26T18:11:15+01:00

Commit Message:
TWINE: replaced magic number

Changed paths:
    engines/twine/movements.cpp


diff --git a/engines/twine/movements.cpp b/engines/twine/movements.cpp
index dd48f88b26..723a50b511 100644
--- a/engines/twine/movements.cpp
+++ b/engines/twine/movements.cpp
@@ -271,7 +271,7 @@ void Movements::processActorMovements(int32 actorIdx) {
 	}
 
 	if (actor->dynamicFlags.bIsFalling) {
-		if (actor->controlMode != 1) {
+		if (actor->controlMode != ControlMode::kManual) {
 			return;
 		}
 


Commit: 2cf3832bedd17d15dc2243ba0befb2863c079f20
    https://github.com/scummvm/scummvm/commit/2cf3832bedd17d15dc2243ba0befb2863c079f20
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2020-10-26T18:11:15+01:00

Commit Message:
TWINE: reduced scope

Changed paths:
    engines/twine/movements.cpp


diff --git a/engines/twine/movements.cpp b/engines/twine/movements.cpp
index 723a50b511..d66538a833 100644
--- a/engines/twine/movements.cpp
+++ b/engines/twine/movements.cpp
@@ -200,8 +200,9 @@ int32 Movements::getRealAngle(ActorMoveStruct *movePtr) {
 int32 Movements::getRealValue(ActorMoveStruct *movePtr) {
 	int32 tempStep;
 
-	if (!movePtr->numOfStep)
+	if (!movePtr->numOfStep) {
 		return movePtr->to;
+	}
 
 	if (!(_engine->lbaTime - movePtr->timeOfChange < movePtr->numOfStep)) {
 		movePtr->numOfStep = 0;
@@ -215,10 +216,10 @@ int32 Movements::getRealValue(ActorMoveStruct *movePtr) {
 	return tempStep + movePtr->from;
 }
 
-void Movements::rotateActor(int32 X, int32 Z, int32 angle) {
+void Movements::rotateActor(int32 x, int32 z, int32 angle) {
 	const double radians = 2 * M_PI * angle / 0x400;
-	_engine->_renderer->destX = (int32)(X * cos(radians) + Z * sin(radians));
-	_engine->_renderer->destZ = (int32)(-X * sin(radians) + Z * cos(radians));
+	_engine->_renderer->destX = (int32)(x * cos(radians) + z * sin(radians));
+	_engine->_renderer->destZ = (int32)(-x * sin(radians) + z * cos(radians));
 }
 
 int32 Movements::getDistance2D(int32 x1, int32 z1, int32 x2, int32 z2) {
@@ -230,19 +231,15 @@ int32 Movements::getDistance3D(int32 x1, int32 y1, int32 z1, int32 x2, int32 y2,
 }
 
 void Movements::moveActor(int32 angleFrom, int32 angleTo, int32 speed, ActorMoveStruct *movePtr) { // ManualRealAngle
-	int32 numOfStepInt;
-	int16 numOfStep;
-	int16 from;
-	int16 to;
-
-	from = angleFrom & 0x3FF;
-	to = angleTo & 0x3FF;
+	const int16 from = angleFrom & 0x3FF;
+	const int16 to = angleTo & 0x3FF;
 
 	movePtr->from = from;
 	movePtr->to = to;
 
-	numOfStep = (from - to) << 6;
+	const int16 numOfStep = (from - to) << 6;
 
+	int32 numOfStepInt;
 	if (numOfStep < 0) {
 		numOfStepInt = -numOfStep;
 	} else {


Commit: a8ca9e017bf90c83998ca1d46a490acd148b4a1f
    https://github.com/scummvm/scummvm/commit/a8ca9e017bf90c83998ca1d46a490acd148b4a1f
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2020-10-26T18:11:15+01:00

Commit Message:
TWINE: make cursorKeys obsolet

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


diff --git a/engines/twine/input.cpp b/engines/twine/input.cpp
index e7d2864f73..18ca45fb8a 100644
--- a/engines/twine/input.cpp
+++ b/engines/twine/input.cpp
@@ -110,6 +110,10 @@ bool Input::isQuickBehaviourActionActive() const {
 	return isActionActive(TwinEActionType::QuickBehaviourNormal) || isActionActive(TwinEActionType::QuickBehaviourAthletic) || isActionActive(TwinEActionType::QuickBehaviourAggressive) || isActionActive(TwinEActionType::QuickBehaviourDiscreet);
 }
 
+bool Input::isMoveOrTurnActionActive() const {
+	return isActionActive(TwinEActionType::TurnLeft) || isActionActive(TwinEActionType::TurnRight) || isActionActive(TwinEActionType::MoveBackward) || isActionActive(TwinEActionType::MoveForward);
+}
+
 void Input::enableKeyMap(const char *id) {
 	if (_currentKeyMap == id) {
 		return;
diff --git a/engines/twine/input.h b/engines/twine/input.h
index db1f175674..5134002065 100644
--- a/engines/twine/input.h
+++ b/engines/twine/input.h
@@ -141,6 +141,7 @@ public:
 	bool toggleAbortAction();
 
 	bool isQuickBehaviourActionActive() const;
+	bool isMoveOrTurnActionActive() const;
 
 	/**
 	 * Gets mouse positions
diff --git a/engines/twine/movements.cpp b/engines/twine/movements.cpp
index d66538a833..0632f6861c 100644
--- a/engines/twine/movements.cpp
+++ b/engines/twine/movements.cpp
@@ -258,7 +258,7 @@ void Movements::moveActor(int32 angleFrom, int32 angleTo, int32 speed, ActorMove
 void Movements::update() {
 	previousLoopCursorKeys = loopCursorKeys;
 	heroActionKey = _engine->_input->pressedKey;
-	loopCursorKeys = _engine->_input->cursorKeys;
+	loopCursorKeys = _engine->_input->isMoveOrTurnActionActive();
 }
 
 void Movements::processActorMovements(int32 actorIdx) {


Commit: afdee7237fae1ce268d579e132ad81d77f87c417
    https://github.com/scummvm/scummvm/commit/afdee7237fae1ce268d579e132ad81d77f87c417
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2020-10-26T18:11:15+01:00

Commit Message:
TWINE: moved actor pointer into actor class

Changed paths:
    engines/twine/actor.h
    engines/twine/animations.cpp
    engines/twine/collision.cpp
    engines/twine/movements.h


diff --git a/engines/twine/actor.h b/engines/twine/actor.h
index d0a6798d81..378e1d0ac1 100644
--- a/engines/twine/actor.h
+++ b/engines/twine/actor.h
@@ -244,6 +244,8 @@ public:
 	/** Table with all loaded sprite sizes */
 	uint32 spriteSizeTable[NUM_SPRITES] {0};
 
+	ActorStruct *processActorPtr = nullptr; // processActorVar1
+
 	/** Actor shadow X coordinate */
 	int32 shadowX = 0;
 	/** Actor shadow Y coordinate */
diff --git a/engines/twine/animations.cpp b/engines/twine/animations.cpp
index 2750291480..397765b40a 100644
--- a/engines/twine/animations.cpp
+++ b/engines/twine/animations.cpp
@@ -852,7 +852,7 @@ void Animations::processActorAnimations(int32 actorIdx) { // DoAnim
 	ActorStruct *actor = _engine->_scene->getActor(actorIdx);
 
 	currentlyProcessedActorIdx = actorIdx;
-	_engine->_movements->processActorPtr = actor;
+	_engine->_actor->processActorPtr = actor;
 
 	if (actor->entity == -1) {
 		return;
diff --git a/engines/twine/collision.cpp b/engines/twine/collision.cpp
index a363ac529c..55ad89e850 100644
--- a/engines/twine/collision.cpp
+++ b/engines/twine/collision.cpp
@@ -390,14 +390,14 @@ void Collision::checkHeroCollisionWithBricks(int32 X, int32 Y, int32 Z, int32 da
 
 	if (_engine->_movements->processActorX >= 0 && _engine->_movements->processActorZ >= 0 && _engine->_movements->processActorX <= 0x7E00 && _engine->_movements->processActorZ <= 0x7E00) {
 		reajustActorPosition(brickShape);
-		brickShape = _engine->_grid->getBrickShapeFull(_engine->_movements->processActorX, _engine->_movements->processActorY, _engine->_movements->processActorZ, _engine->_movements->processActorPtr->boudingBox.y.topRight);
+		brickShape = _engine->_grid->getBrickShapeFull(_engine->_movements->processActorX, _engine->_movements->processActorY, _engine->_movements->processActorZ, _engine->_actor->processActorPtr->boudingBox.y.topRight);
 
 		if (brickShape == kSolid) {
 			causeActorDamage |= damageMask;
-			brickShape = _engine->_grid->getBrickShapeFull(_engine->_movements->processActorX, _engine->_movements->processActorY, _engine->_movements->previousActorZ + Z, _engine->_movements->processActorPtr->boudingBox.y.topRight);
+			brickShape = _engine->_grid->getBrickShapeFull(_engine->_movements->processActorX, _engine->_movements->processActorY, _engine->_movements->previousActorZ + Z, _engine->_actor->processActorPtr->boudingBox.y.topRight);
 
 			if (brickShape == kSolid) {
-				brickShape = _engine->_grid->getBrickShapeFull(X + _engine->_movements->previousActorX, _engine->_movements->processActorY, _engine->_movements->processActorZ, _engine->_movements->processActorPtr->boudingBox.y.topRight);
+				brickShape = _engine->_grid->getBrickShapeFull(X + _engine->_movements->previousActorX, _engine->_movements->processActorY, _engine->_movements->processActorZ, _engine->_actor->processActorPtr->boudingBox.y.topRight);
 
 				if (brickShape != kSolid) {
 					processCollisionX = _engine->_movements->previousActorX;
@@ -454,12 +454,13 @@ void Collision::stopFalling() { // ReceptionObj()
 		fall = _engine->_scene->heroYBeforeFall - _engine->_movements->processActorY;
 
 		if (fall >= 0x1000) {
-			_engine->_extra->addExtraSpecial(_engine->_movements->processActorPtr->x, _engine->_movements->processActorPtr->y + 1000, _engine->_movements->processActorPtr->z, kHitStars);
-			_engine->_movements->processActorPtr->life--;
+			_engine->_extra->addExtraSpecial(_engine->_actor->processActorPtr->x, _engine->_actor->processActorPtr->y + 1000, _engine->_actor->processActorPtr->z, kHitStars);
+			_engine->_actor->processActorPtr->life--;
 			_engine->_animations->initAnim(kLandingHit, 2, 0, _engine->_animations->currentlyProcessedActorIdx);
 		} else if (fall >= 0x800) {
-			_engine->_extra->addExtraSpecial(_engine->_movements->processActorPtr->x, _engine->_movements->processActorPtr->y + 1000, _engine->_movements->processActorPtr->z, kHitStars);
-			_engine->_movements->processActorPtr->life--;
+			// TODO: the same as the other branch?
+			_engine->_extra->addExtraSpecial(_engine->_actor->processActorPtr->x, _engine->_actor->processActorPtr->y + 1000, _engine->_actor->processActorPtr->z, kHitStars);
+			_engine->_actor->processActorPtr->life--;
 			_engine->_animations->initAnim(kLandingHit, 2, 0, _engine->_animations->currentlyProcessedActorIdx);
 		} else if (fall > 10) {
 			_engine->_animations->initAnim(kLanding, 2, 0, _engine->_animations->currentlyProcessedActorIdx);
@@ -469,10 +470,10 @@ void Collision::stopFalling() { // ReceptionObj()
 
 		_engine->_scene->heroYBeforeFall = 0;
 	} else {
-		_engine->_animations->initAnim(kLanding, 2, _engine->_movements->processActorPtr->animExtra, _engine->_animations->currentlyProcessedActorIdx);
+		_engine->_animations->initAnim(kLanding, 2, _engine->_actor->processActorPtr->animExtra, _engine->_animations->currentlyProcessedActorIdx);
 	}
 
-	_engine->_movements->processActorPtr->dynamicFlags.bIsFalling = 0;
+	_engine->_actor->processActorPtr->dynamicFlags.bIsFalling = 0;
 }
 
 int32 Collision::checkExtraCollisionWithActors(ExtraListStruct *extra, int32 actorIdx) {
diff --git a/engines/twine/movements.h b/engines/twine/movements.h
index d315af01f7..6f2d0de41f 100644
--- a/engines/twine/movements.h
+++ b/engines/twine/movements.h
@@ -62,8 +62,6 @@ public:
 	/** Process actor.z coordinate */
 	int16 processActorZ = 0;
 
-	ActorStruct *processActorPtr = nullptr; // processActorVar1
-
 	/** Previous process actor.x coordinate */
 	int16 previousActorX = 0; // processActorVar2
 	/** Previous process actor.y coordinate */


Commit: 1eb3acf27a06d8209d953985584912ee5691df47
    https://github.com/scummvm/scummvm/commit/1eb3acf27a06d8209d953985584912ee5691df47
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2020-10-26T18:11:15+01:00

Commit Message:
TWINE: small helper method for the Input class

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


diff --git a/engines/twine/input.cpp b/engines/twine/input.cpp
index 18ca45fb8a..3096e6be83 100644
--- a/engines/twine/input.cpp
+++ b/engines/twine/input.cpp
@@ -114,6 +114,10 @@ bool Input::isMoveOrTurnActionActive() const {
 	return isActionActive(TwinEActionType::TurnLeft) || isActionActive(TwinEActionType::TurnRight) || isActionActive(TwinEActionType::MoveBackward) || isActionActive(TwinEActionType::MoveForward);
 }
 
+bool Input::isHeroActionActive() const {
+	return isActionActive(TwinEActionType::ExecuteBehaviourAction) || isActionActive(TwinEActionType::SpecialAction);
+}
+
 void Input::enableKeyMap(const char *id) {
 	if (_currentKeyMap == id) {
 		return;
diff --git a/engines/twine/input.h b/engines/twine/input.h
index 5134002065..e325e2ceca 100644
--- a/engines/twine/input.h
+++ b/engines/twine/input.h
@@ -142,6 +142,7 @@ public:
 
 	bool isQuickBehaviourActionActive() const;
 	bool isMoveOrTurnActionActive() const;
+	bool isHeroActionActive() const;
 
 	/**
 	 * Gets mouse positions


Commit: 69b06478b37457240834d927d67058709d153746
    https://github.com/scummvm/scummvm/commit/69b06478b37457240834d927d67058709d153746
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2020-10-26T18:11:15+01:00

Commit Message:
TWINE: restore old variable use - we're not yet there

Changed paths:
    engines/twine/movements.cpp


diff --git a/engines/twine/movements.cpp b/engines/twine/movements.cpp
index 0632f6861c..d66538a833 100644
--- a/engines/twine/movements.cpp
+++ b/engines/twine/movements.cpp
@@ -258,7 +258,7 @@ void Movements::moveActor(int32 angleFrom, int32 angleTo, int32 speed, ActorMove
 void Movements::update() {
 	previousLoopCursorKeys = loopCursorKeys;
 	heroActionKey = _engine->_input->pressedKey;
-	loopCursorKeys = _engine->_input->isMoveOrTurnActionActive();
+	loopCursorKeys = _engine->_input->cursorKeys;
 }
 
 void Movements::processActorMovements(int32 actorIdx) {


Commit: ea850b8c50deaccb74a17c05e3cb1e36cdbc30a2
    https://github.com/scummvm/scummvm/commit/ea850b8c50deaccb74a17c05e3cb1e36cdbc30a2
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2020-10-26T18:11:15+01:00

Commit Message:
TWINE: fixed previousLoopCursorKeys handling for attack animations

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


diff --git a/engines/twine/movements.cpp b/engines/twine/movements.cpp
index d66538a833..c199eadb24 100644
--- a/engines/twine/movements.cpp
+++ b/engines/twine/movements.cpp
@@ -256,7 +256,7 @@ void Movements::moveActor(int32 angleFrom, int32 angleTo, int32 speed, ActorMove
 }
 
 void Movements::update() {
-	previousLoopCursorKeys = loopCursorKeys;
+	previousLoopActionKey = heroActionKey;
 	heroActionKey = _engine->_input->pressedKey;
 	loopCursorKeys = _engine->_input->cursorKeys;
 }
@@ -319,9 +319,9 @@ void Movements::processActorMovements(int32 actorIdx) {
 						if (_engine->_actor->autoAgressive) {
 							heroMoved = true;
 							actor->angle = getRealAngle(&actor->move);
-							// TODO: previousLoopCursorKeys must be handled properly
-							if (!(previousLoopCursorKeys & 1) || !actor->anim) {
-								int32 aggresiveMode = _engine->getRandomNumber(3);
+							// TODO: previousLoopActionKey must be handled properly
+							if (!previousLoopActionKey || !actor->anim) {
+								const int32 aggresiveMode = _engine->getRandomNumber(3);
 
 								switch (aggresiveMode) {
 								case 0:
diff --git a/engines/twine/movements.h b/engines/twine/movements.h
index 6f2d0de41f..63a3e000ef 100644
--- a/engines/twine/movements.h
+++ b/engines/twine/movements.h
@@ -43,7 +43,7 @@ private:
 	// enter, space, ...
 	int32 loopCursorKeys = 0;
 	// cursor keys
-	int32 previousLoopCursorKeys = 0;
+	int32 previousLoopActionKey = 0;
 
 public:
 	Movements(TwinEEngine *engine);


Commit: 2ad34e17f1196fc3d4e3962324c8bbabc3313387
    https://github.com/scummvm/scummvm/commit/2ad34e17f1196fc3d4e3962324c8bbabc3313387
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2020-10-26T18:11:15+01:00

Commit Message:
TWINE: script cleanup - input cleanup

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


diff --git a/engines/twine/movements.cpp b/engines/twine/movements.cpp
index c199eadb24..83cf307c46 100644
--- a/engines/twine/movements.cpp
+++ b/engines/twine/movements.cpp
@@ -257,7 +257,7 @@ void Movements::moveActor(int32 angleFrom, int32 angleTo, int32 speed, ActorMove
 
 void Movements::update() {
 	previousLoopActionKey = heroActionKey;
-	heroActionKey = _engine->_input->pressedKey;
+	heroActionKey = _engine->_input->isHeroActionActive();
 	loopCursorKeys = _engine->_input->cursorKeys;
 }
 
diff --git a/engines/twine/script_life.cpp b/engines/twine/script_life.cpp
index 485970310f..01e4bba953 100644
--- a/engines/twine/script_life.cpp
+++ b/engines/twine/script_life.cpp
@@ -20,6 +20,7 @@
  *
  */
 
+#include "twine/script_life.h"
 #include "common/stream.h"
 #include "twine/actor.h"
 #include "twine/animations.h"
@@ -28,8 +29,8 @@
 #include "twine/gamestate.h"
 #include "twine/grid.h"
 #include "twine/holomap.h"
-#include "twine/interface.h"
 #include "twine/input.h"
+#include "twine/interface.h"
 #include "twine/movements.h"
 #include "twine/music.h"
 #include "twine/redraw.h"
@@ -37,9 +38,9 @@
 #include "twine/resources.h"
 #include "twine/scene.h"
 #include "twine/screens.h"
-#include "twine/script_life.h"
 #include "twine/sound.h"
 #include "twine/text.h"
+#include "twine/twine.h"
 
 namespace TwinE {
 
@@ -112,10 +113,8 @@ enum LifeScriptConditions {
 		1 - Condition value size (1 byte)
 		2 - Condition value size (2 byes) */
 static int32 processLifeConditions(TwinEEngine *engine, ActorStruct *actor) {
-	int32 conditionOpcode, conditionValueSize;
-
-	conditionValueSize = 1;
-	conditionOpcode = *(scriptPtr++);
+	int32 conditionValueSize = 1;
+	int32 conditionOpcode = *(scriptPtr++);
 
 	switch (conditionOpcode) {
 	case kcCOL:
@@ -132,7 +131,8 @@ static int32 processLifeConditions(TwinEEngine *engine, ActorStruct *actor) {
 		} else {
 			engine->_scene->currentScriptValue = engine->_scene->getActor(actorIdx)->collision;
 		}
-	} break;
+		break;
+	}
 	case kcDISTANCE: {
 		int32 actorIdx = *(scriptPtr++);
 		conditionValueSize = 2;
@@ -152,39 +152,45 @@ static int32 processLifeConditions(TwinEEngine *engine, ActorStruct *actor) {
 		} else {
 			engine->_scene->currentScriptValue = MAX_TARGET_ACTOR_DISTANCE;
 		}
-	} break;
+		break;
+	}
 	case kcZONE:
 		engine->_scene->currentScriptValue = actor->zone;
 		break;
 	case kcZONE_OBJ: {
 		int32 actorIdx = *(scriptPtr++);
 		engine->_scene->currentScriptValue = engine->_scene->getActor(actorIdx)->zone;
-	} break;
+		break;
+	}
 	case kcBODY:
 		engine->_scene->currentScriptValue = actor->body;
 		break;
 	case kcBODY_OBJ: {
 		int32 actorIdx = *(scriptPtr++);
 		engine->_scene->currentScriptValue = engine->_scene->getActor(actorIdx)->body;
-	} break;
+		break;
+	}
 	case kcANIM:
 		engine->_scene->currentScriptValue = actor->anim;
 		break;
 	case kcANIM_OBJ: {
 		int32 actorIdx = *(scriptPtr++);
 		engine->_scene->currentScriptValue = engine->_scene->getActor(actorIdx)->anim;
-	} break;
+		break;
+	}
 	case kcL_TRACK:
 		engine->_scene->currentScriptValue = actor->labelIdx;
 		break;
 	case kcL_TRACK_OBJ: {
 		int32 actorIdx = *(scriptPtr++);
 		engine->_scene->currentScriptValue = engine->_scene->getActor(actorIdx)->labelIdx;
-	} break;
+		break;
+	}
 	case kcFLAG_CUBE: {
 		int32 flagIdx = *(scriptPtr++);
 		engine->_scene->currentScriptValue = engine->_scene->sceneFlags[flagIdx];
-	} break;
+		break;
+	}
 	case kcCONE_VIEW: {
 		int32 newAngle = 0;
 		int32 targetActorIdx = *(scriptPtr++);
@@ -251,14 +257,16 @@ static int32 processLifeConditions(TwinEEngine *engine, ActorStruct *actor) {
 				engine->_scene->currentScriptValue = 0;
 			}
 		}
-	} break;
+		break;
+	}
 	case kcLIFE_POINT:
 		engine->_scene->currentScriptValue = actor->life;
 		break;
 	case kcLIFE_POINT_OBJ: {
 		int32 actorIdx = *(scriptPtr++);
 		engine->_scene->currentScriptValue = engine->_scene->getActor(actorIdx)->life;
-	} break;
+		break;
+	}
 	case kcNUM_LITTLE_KEYS:
 		engine->_scene->currentScriptValue = engine->_gameState->inventoryNumKeys;
 		break;
@@ -292,7 +300,8 @@ static int32 processLifeConditions(TwinEEngine *engine, ActorStruct *actor) {
 		} else {
 			engine->_scene->currentScriptValue = MAX_TARGET_ACTOR_DISTANCE;
 		}
-	} break;
+		break;
+	}
 	case 23: // unused
 	case 24:
 		break;
@@ -316,7 +325,8 @@ static int32 processLifeConditions(TwinEEngine *engine, ActorStruct *actor) {
 		} else {
 			engine->_scene->currentScriptValue = 0;
 		}
-	} break;
+		break;
+	}
 	case kcCHOICE:
 		conditionValueSize = 2;
 		engine->_scene->currentScriptValue = engine->_gameState->choiceAnswer;
@@ -331,7 +341,7 @@ static int32 processLifeConditions(TwinEEngine *engine, ActorStruct *actor) {
 		engine->_scene->currentScriptValue = 1;
 		break;
 	default:
-		error("Actor condition opcode %d\n", conditionOpcode);
+		error("Actor condition opcode %d", conditionOpcode);
 		break;
 	}
 
@@ -343,10 +353,9 @@ static int32 processLifeConditions(TwinEEngine *engine, ActorStruct *actor) {
 		0 - Condition false
 		1 - Condition true */
 static int32 processLifeOperators(TwinEEngine *engine, int32 valueSize) {
-	int32 operatorCode, conditionValue;
-
-	operatorCode = *(scriptPtr++);
+	int32 operatorCode = *(scriptPtr++);
 
+	int32 conditionValue;
 	if (valueSize == 1) {
 		conditionValue = *(scriptPtr++);
 	} else if (valueSize == 2) {
@@ -616,7 +625,7 @@ static int32 lCAM_FOLLOW(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor
 	int32 followedActorIdx = *(scriptPtr++);
 
 	if (engine->_scene->currentlyFollowedActor != followedActorIdx) {
-		const ActorStruct* followedActor = engine->_scene->getActor(followedActorIdx);
+		const ActorStruct *followedActor = engine->_scene->getActor(followedActorIdx);
 		engine->_grid->newCameraX = followedActor->x >> 9;
 		engine->_grid->newCameraY = followedActor->y >> 8;
 		engine->_grid->newCameraZ = followedActor->z >> 9;
@@ -958,7 +967,7 @@ static int32 lZOOM(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
 static int32 lPOS_POINT(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
 	int32 trackIdx = *(scriptPtr++);
 
-	const ScenePoint& sp = engine->_scene->sceneTracks[trackIdx];
+	const ScenePoint &sp = engine->_scene->sceneTracks[trackIdx];
 	engine->_renderer->destX = sp.x;
 	engine->_renderer->destY = sp.y;
 	engine->_renderer->destZ = sp.z;
@@ -1106,7 +1115,7 @@ static int32 lBIG_MESSAGE(TwinEEngine *engine, int32 actorIdx, ActorStruct *acto
 static int32 lINIT_PINGOUIN(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
 	int32 pingouinActor = *(scriptPtr++);
 	engine->_scene->mecaPinguinIdx = pingouinActor;
-	ActorStruct* mecaPinguin = engine->_scene->getActor(pingouinActor);
+	ActorStruct *mecaPinguin = engine->_scene->getActor(pingouinActor);
 	mecaPinguin->dynamicFlags.bIsDead = 1;
 	mecaPinguin->entity = -1;
 	mecaPinguin->zone = -1;
@@ -1459,8 +1468,8 @@ static int32 lTEXT(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
 		int32 textBoxRight = textSize;
 		engine->_text->setFontColor(15);
 		engine->_text->drawText(0, drawVar1, textStr);
-		if (textSize > 639) {
-			textBoxRight = 639;
+		if (textSize > DEFAULT_SCREEN_WIDTH - 1) {
+			textBoxRight = DEFAULT_SCREEN_WIDTH - 1;
 		}
 
 		drawVar1 += 40;


Commit: 927e6cc2d14544e8ad785659b4c6a222abf8bac2
    https://github.com/scummvm/scummvm/commit/927e6cc2d14544e8ad785659b4c6a222abf8bac2
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2020-10-26T18:11:15+01:00

Commit Message:
TWINE: cleanup in move script

Changed paths:
    engines/twine/script_move.cpp


diff --git a/engines/twine/script_move.cpp b/engines/twine/script_move.cpp
index d0ff850db0..4045d06735 100644
--- a/engines/twine/script_move.cpp
+++ b/engines/twine/script_move.cpp
@@ -40,6 +40,10 @@ static int32 scriptPosition = 0;
 static ActorMoveStruct *move = nullptr;
 static int32 numRepeatSample = 1;
 
+/** Returns:
+	   -1 - Need implementation
+		0 - Completed
+		1 - Break script */
 typedef int32 ScriptMoveFunc(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor);
 
 struct ScriptMoveFunction {
@@ -87,7 +91,7 @@ static int32 mGOTO_POINT(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor
 	actor->positionInMoveScript++;
 	engine->_scene->currentScriptValue = *(scriptPtr);
 
-	const ScenePoint& sp = engine->_scene->sceneTracks[engine->_scene->currentScriptValue];
+	const ScenePoint &sp = engine->_scene->sceneTracks[engine->_scene->currentScriptValue];
 	engine->_renderer->destX = sp.x;
 	engine->_renderer->destY = sp.y;
 	engine->_renderer->destZ = sp.z;
@@ -128,18 +132,19 @@ static int32 mLOOP(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
 /*0x07*/
 static int32 mANGLE(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
 	actor->positionInMoveScript += 2;
-	if (!actor->staticFlags.bIsSpriteActor) {
-		engine->_scene->currentScriptValue = *((int16 *)scriptPtr);
-		if (actor->move.numOfStep == 0) {
-			engine->_movements->moveActor(actor->angle, engine->_scene->currentScriptValue, actor->speed, move);
-		}
-		if (actor->angle == engine->_scene->currentScriptValue) {
-			engine->_movements->clearRealAngle(actor);
-			return 0;
-		}
-		continueMove = 0;
-		actor->positionInMoveScript -= 3;
+	if (actor->staticFlags.bIsSpriteActor) {
+		return 0;
 	}
+	engine->_scene->currentScriptValue = *((int16 *)scriptPtr);
+	if (actor->move.numOfStep == 0) {
+		engine->_movements->moveActor(actor->angle, engine->_scene->currentScriptValue, actor->speed, move);
+	}
+	if (actor->angle == engine->_scene->currentScriptValue) {
+		engine->_movements->clearRealAngle(actor);
+		return 0;
+	}
+	continueMove = 0;
+	actor->positionInMoveScript -= 3;
 	return 0;
 }
 
@@ -148,7 +153,7 @@ static int32 mPOS_POINT(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor)
 	actor->positionInMoveScript++;
 	engine->_scene->currentScriptValue = *(scriptPtr);
 
-	const ScenePoint& sp = engine->_scene->sceneTracks[engine->_scene->currentScriptValue];
+	const ScenePoint &sp = engine->_scene->sceneTracks[engine->_scene->currentScriptValue];
 	engine->_renderer->destX = sp.x;
 	engine->_renderer->destY = sp.y;
 	engine->_renderer->destZ = sp.z;
@@ -190,7 +195,7 @@ static int32 mGOTO_SYM_POINT(TwinEEngine *engine, int32 actorIdx, ActorStruct *a
 	actor->positionInMoveScript++;
 	engine->_scene->currentScriptValue = *(scriptPtr);
 
-	const ScenePoint& sp = engine->_scene->sceneTracks[engine->_scene->currentScriptValue];
+	const ScenePoint &sp = engine->_scene->sceneTracks[engine->_scene->currentScriptValue];
 	engine->_renderer->destX = sp.x;
 	engine->_renderer->destY = sp.y;
 	engine->_renderer->destZ = sp.z;
@@ -259,7 +264,7 @@ static int32 mGOTO_POINT_3D(TwinEEngine *engine, int32 actorIdx, ActorStruct *ac
 
 	engine->_scene->currentScriptValue = *(scriptPtr);
 
-	const ScenePoint& sp = engine->_scene->sceneTracks[engine->_scene->currentScriptValue];
+	const ScenePoint &sp = engine->_scene->sceneTracks[engine->_scene->currentScriptValue];
 	engine->_renderer->destX = sp.x;
 	engine->_renderer->destY = sp.y;
 	engine->_renderer->destZ = sp.z;
@@ -318,7 +323,7 @@ static int32 mBACKGROUND(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor
 static int32 mWAIT_NUM_SECOND(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
 	actor->positionInMoveScript += 5;
 
-	int32 numSeconds = *(scriptPtr++);
+	const int32 numSeconds = *(scriptPtr++);
 	int32 currentTime = *((int32 *)scriptPtr);
 
 	if (currentTime == 0) {
@@ -482,21 +487,22 @@ static int32 mSIMPLE_SAMPLE(TwinEEngine *engine, int32 actorIdx, ActorStruct *ac
 /*0x21*/
 static int32 mFACE_HERO(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
 	actor->positionInMoveScript += 2;
-	if (!actor->staticFlags.bIsSpriteActor) {
-		engine->_scene->currentScriptValue = *((int16 *)scriptPtr);
-		if (engine->_scene->currentScriptValue == -1 && actor->move.numOfStep == 0) {
-			engine->_scene->currentScriptValue = engine->_movements->getAngleAndSetTargetActorDistance(actor->x, actor->z, engine->_scene->sceneHero->x, engine->_scene->sceneHero->z);
-			engine->_movements->moveActor(actor->angle, engine->_scene->currentScriptValue, actor->speed, &actor->move);
-			*((int16 *)scriptPtr) = engine->_scene->currentScriptValue;
-		}
+	if (actor->staticFlags.bIsSpriteActor) {
+		return 0;
+	}
+	engine->_scene->currentScriptValue = *((int16 *)scriptPtr);
+	if (engine->_scene->currentScriptValue == -1 && actor->move.numOfStep == 0) {
+		engine->_scene->currentScriptValue = engine->_movements->getAngleAndSetTargetActorDistance(actor->x, actor->z, engine->_scene->sceneHero->x, engine->_scene->sceneHero->z);
+		engine->_movements->moveActor(actor->angle, engine->_scene->currentScriptValue, actor->speed, &actor->move);
+		*((int16 *)scriptPtr) = engine->_scene->currentScriptValue;
+	}
 
-		if (actor->angle != engine->_scene->currentScriptValue) {
-			continueMove = 0;
-			actor->positionInMoveScript -= 3;
-		} else {
-			engine->_movements->clearRealAngle(actor);
-			*((int16 *)scriptPtr) = -1;
-		}
+	if (actor->angle != engine->_scene->currentScriptValue) {
+		continueMove = 0;
+		actor->positionInMoveScript -= 3;
+	} else {
+		engine->_movements->clearRealAngle(actor);
+		*((int16 *)scriptPtr) = -1;
 	}
 	return 0;
 }


Commit: bb76f5ed991c8be2edb1a41932c89a917c64400c
    https://github.com/scummvm/scummvm/commit/bb76f5ed991c8be2edb1a41932c89a917c64400c
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2020-10-26T18:11:15+01:00

Commit Message:
TWINE: don't use the global var

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


diff --git a/engines/twine/script_move.cpp b/engines/twine/script_move.cpp
index 4045d06735..706acc6c1d 100644
--- a/engines/twine/script_move.cpp
+++ b/engines/twine/script_move.cpp
@@ -592,7 +592,7 @@ void ScriptMove::processMoveScript(int32 actorIdx) {
 	do {
 		scriptPosition = actor->positionInMoveScript;
 		// TODO: use Common::MemoryReadStream for the script parsing
-		scriptPtr = actor->moveScript + scriptPosition;
+		scriptPtr = actor->moveScript + actor->positionInMoveScript;
 		int32 scriptOpcode = *(scriptPtr++);
 
 		actor->positionInMoveScript++;
diff --git a/engines/twine/twine.h b/engines/twine/twine.h
index 98a292642e..4bf1265c36 100644
--- a/engines/twine/twine.h
+++ b/engines/twine/twine.h
@@ -49,7 +49,7 @@ namespace TwinE {
 /** Original screen height */
 #define DEFAULT_SCREEN_HEIGHT 480
 /** Scale screen to double size */
-#define SCALE 1
+#define SCALE 1 // TODO: remove me or support me
 /** Original screen width */
 #define SCREEN_WIDTH DEFAULT_SCREEN_WIDTH *SCALE
 /** Original screen height */


Commit: b15064e6d98df88cd5d0c1079e3f595a49cfcc13
    https://github.com/scummvm/scummvm/commit/b15064e6d98df88cd5d0c1079e3f595a49cfcc13
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2020-10-26T18:12:03+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 706acc6c1d..651ac4bf7d 100644
--- a/engines/twine/script_move.cpp
+++ b/engines/twine/script_move.cpp
@@ -510,31 +510,32 @@ static int32 mFACE_HERO(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor)
 /*0x22*/
 static int32 mANGLE_RND(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
 	actor->positionInMoveScript += 4;
-	if (!actor->staticFlags.bIsSpriteActor) {
-		engine->_scene->currentScriptValue = *((int16 *)scriptPtr + 2);
-
-		if (engine->_scene->currentScriptValue == -1 && actor->move.numOfStep == 0) {
-			if (engine->getRandomNumber() & 1) {
-				engine->_scene->currentScriptValue = *((int16 *)scriptPtr);
-				const int32 newAngle = actor->angle + 0x100 + (ABS(engine->_scene->currentScriptValue) >> 1);
-				engine->_scene->currentScriptValue = (newAngle - engine->getRandomNumber(engine->_scene->currentScriptValue)) & 0x3FF;
-			} else {
-				engine->_scene->currentScriptValue = *((int16 *)scriptPtr);
-				const int32 newAngle = actor->angle - 0x100 + (ABS(engine->_scene->currentScriptValue) >> 1);
-				engine->_scene->currentScriptValue = (newAngle - engine->getRandomNumber(engine->_scene->currentScriptValue)) & 0x3FF;
-			}
-
-			engine->_movements->moveActor(actor->angle, engine->_scene->currentScriptValue, actor->speed, &actor->move);
-			*((int16 *)scriptPtr + 2) = engine->_scene->currentScriptValue;
-		}
+	if (actor->staticFlags.bIsSpriteActor) {
+		return 0;
+	}
+	engine->_scene->currentScriptValue = *((int16 *)scriptPtr + 2);
 
-		if (actor->angle != engine->_scene->currentScriptValue) {
-			continueMove = 0;
-			actor->positionInMoveScript -= 5;
+	if (engine->_scene->currentScriptValue == -1 && actor->move.numOfStep == 0) {
+		if (engine->getRandomNumber() & 1) {
+			engine->_scene->currentScriptValue = *((int16 *)scriptPtr);
+			const int32 newAngle = actor->angle + 0x100 + (ABS(engine->_scene->currentScriptValue) >> 1);
+			engine->_scene->currentScriptValue = (newAngle - engine->getRandomNumber(engine->_scene->currentScriptValue)) & 0x3FF;
 		} else {
-			engine->_movements->clearRealAngle(actor);
-			*((int16 *)scriptPtr + 2) = -1;
+			engine->_scene->currentScriptValue = *((int16 *)scriptPtr);
+			const int32 newAngle = actor->angle - 0x100 + (ABS(engine->_scene->currentScriptValue) >> 1);
+			engine->_scene->currentScriptValue = (newAngle - engine->getRandomNumber(engine->_scene->currentScriptValue)) & 0x3FF;
 		}
+
+		engine->_movements->moveActor(actor->angle, engine->_scene->currentScriptValue, actor->speed, &actor->move);
+		*((int16 *)scriptPtr + 2) = engine->_scene->currentScriptValue;
+	}
+
+	if (actor->angle != engine->_scene->currentScriptValue) {
+		continueMove = 0;
+		actor->positionInMoveScript -= 5;
+	} else {
+		engine->_movements->clearRealAngle(actor);
+		*((int16 *)scriptPtr + 2) = -1;
 	}
 	return 0;
 }




More information about the Scummvm-git-logs mailing list