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

mgerhardy martin.gerhardy at gmail.com
Sun Oct 10 09:52:58 UTC 2021


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

Summary:
e8680cee24 TWINE: fixed warnings
46a810558e TWINE: play midi track 1 while showing introd fla
ae07194e58 TWINE: fixed polygon filler type enums
b39e1c260d TWINE: implemented most of the polygon details mappings
efc5e0bcf5 TWINE: added low poly details render methods
da0e5a8193 TWINE: improved polygon render methods
87d9232202 TWINE: renamed variables
d157596665 TWINE: started to implement polygon render types for circles
010a29a413 TWINE: prepare for color blending in marble fill method
808516dc2f TWINE: circle rendering is using proper fill methods now
2d6abce5ca TWINE: renamed method
40dc338671 TWINE: fixed low detail render method
37c48f7e44 TWINE: fixed filler methods
002de89fad TWINE: the color values can contain two values - start and end color
1a6ac67be1 TWINE: todo comment
8296ad436f TWINE: fixed restoring the menu texts after quitting the credits scene
d8761a1bd0 TWINE: forward color as int16


Commit: e8680cee24c080d21378e2ff65012ad92a3c4045
    https://github.com/scummvm/scummvm/commit/e8680cee24c080d21378e2ff65012ad92a3c4045
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2021-10-10T11:52:38+02:00

Commit Message:
TWINE: fixed warnings

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


diff --git a/engines/twine/holomap.cpp b/engines/twine/holomap.cpp
index 1bfa3ddb0d..069e986df3 100644
--- a/engines/twine/holomap.cpp
+++ b/engines/twine/holomap.cpp
@@ -62,18 +62,18 @@ static const float zDistanceTrajectory = 5300.0f;
 
 Holomap::Holomap(TwinEEngine *engine) : _engine(engine) {}
 
-int32 Holomap::distance(int32 distance) const {
+int32 Holomap::distance(float distance) const {
 	const float w = (float)_engine->width() / (float)ORIGINAL_WIDTH;
 	const float h = (float)_engine->height() / (float)ORIGINAL_HEIGHT;
 	const float f = MIN<float>(w, h);
-	return (int32)((float)distance / f);
+	return (int32)(distance / f);
 }
 
-int32 Holomap::scale(int32 val) const {
+int32 Holomap::scale(float val) const {
 	const float w = (float)_engine->width() / (float)ORIGINAL_WIDTH;
 	const float h = (float)_engine->height() / (float)ORIGINAL_HEIGHT;
 	const float f = MIN<float>(w, h);
-	return (int32)((float)val * f);
+	return (int32)(val * f);
 }
 
 bool Holomap::loadLocations() {
diff --git a/engines/twine/holomap.h b/engines/twine/holomap.h
index 05c368b5e7..972146e348 100644
--- a/engines/twine/holomap.h
+++ b/engines/twine/holomap.h
@@ -102,8 +102,8 @@ private:
 	/**
 	 * Controls the size/zoom of the holomap planet
 	 */
-	int32 distance(int32 distance) const;
-	int32 scale(int32 val) const;
+	int32 distance(float distance) const;
+	int32 scale(float val) const;
 
 public:
 	Holomap(TwinEEngine *engine);


Commit: 46a810558e214eaa486f79af5ff62de8fe82b1fd
    https://github.com/scummvm/scummvm/commit/46a810558e214eaa486f79af5ff62de8fe82b1fd
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2021-10-10T11:52:38+02:00

Commit Message:
TWINE: play midi track 1 while showing introd fla

Changed paths:
    engines/twine/audio/music.cpp
    engines/twine/menu/menuoptions.cpp


diff --git a/engines/twine/audio/music.cpp b/engines/twine/audio/music.cpp
index 34a1e811cd..5dcd71bf9f 100644
--- a/engines/twine/audio/music.cpp
+++ b/engines/twine/audio/music.cpp
@@ -171,10 +171,12 @@ void Music::stopTrackMusic() {
 
 bool Music::playMidiMusic(int32 midiIdx, int32 loop) {
 	if (!_engine->_cfgfile.Sound || _engine->_cfgfile.MidiType == MIDIFILE_NONE) {
+		debug("midi disabled - skip playing %i", midiIdx);
 		return false;
 	}
 
 	if (midiIdx == currentMusic) {
+		debug("already playing %i", midiIdx);
 		return true;
 	}
 
@@ -206,8 +208,10 @@ bool Music::playMidiMusic(int32 midiIdx, int32 loop) {
 
 	int32 midiSize = HQR::getAllocEntry(&midiPtr, filename, midiIdx);
 	if (midiSize == 0) {
+		debug("Could not find midi file for index %i", midiIdx);
 		return false;
 	}
+	debug("Play midi file for index %i", midiIdx);
 	_midiPlayer.play(midiPtr, midiSize);
 	return true;
 }
diff --git a/engines/twine/menu/menuoptions.cpp b/engines/twine/menu/menuoptions.cpp
index 0b39a6ffd9..31cb62cb5a 100644
--- a/engines/twine/menu/menuoptions.cpp
+++ b/engines/twine/menu/menuoptions.cpp
@@ -80,7 +80,7 @@ void MenuOptions::newGame() {
 	_engine->_screens->clearScreen();
 
 	if (!aborted) {
-		// _engine->_music->playMidiMusic(1);
+		_engine->_music->playMidiMusic(1);
 		_engine->_flaMovies->playFlaMovie(FLA_INTROD);
 	}
 


Commit: ae07194e58980ac3a3872b09f126db133ff3a7be
    https://github.com/scummvm/scummvm/commit/ae07194e58980ac3a3872b09f126db133ff3a7be
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2021-10-10T11:52:39+02:00

Commit Message:
TWINE: fixed polygon filler type enums

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


diff --git a/engines/twine/renderer/renderer.h b/engines/twine/renderer/renderer.h
index 8242cc4070..f7a54bda71 100644
--- a/engines/twine/renderer/renderer.h
+++ b/engines/twine/renderer/renderer.h
@@ -30,11 +30,11 @@
 #include "twine/twine.h"
 
 #define POLYGONTYPE_FLAT 0
+#define POLYGONTYPE_TELE 1
 // horizontal color adjustment with changing pattern over the polygon
-#define POLYGONTYPE_COPPER 1
-#define POLYGONTYPE_BOPPER 2
-#define POLYGONTYPE_MARBLE 3
-#define POLYGONTYPE_TELE 4
+#define POLYGONTYPE_COPPER 2
+#define POLYGONTYPE_BOPPER 3
+#define POLYGONTYPE_MARBLE 4
 #define POLYGONTYPE_TRAS 5
 #define POLYGONTYPE_TRAME 6
 #define POLYGONTYPE_GOURAUD 7


Commit: b39e1c260da2a1404e24181ec39e524f77420452
    https://github.com/scummvm/scummvm/commit/b39e1c260da2a1404e24181ec39e524f77420452
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2021-10-10T11:52:39+02:00

Commit Message:
TWINE: implemented most of the polygon details mappings

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


diff --git a/engines/twine/renderer/renderer.cpp b/engines/twine/renderer/renderer.cpp
index 9af6b33448..c18a454aca 100644
--- a/engines/twine/renderer/renderer.cpp
+++ b/engines/twine/renderer/renderer.cpp
@@ -1093,10 +1093,19 @@ void Renderer::renderPolygons(const CmdRenderPolygon &polygon, Vertex *vertices,
 
 	const int32 vsize = vbottom - vtop + 1;
 
+	// TODO: POLYGONTYPE_GOURAUD and POLYGONTYPE_DITHER are replaced with a simpler polygon fill function that
+	// is not yet reversed.
 	switch (polygon.renderType) {
 	case POLYGONTYPE_FLAT:
 		renderPolygonsFlat(vtop, vsize, polygon.colorIndex);
 		break;
+	case POLYGONTYPE_TELE:
+		if (_engine->_cfgfile.PolygonDetails == 0) {
+			renderPolygonsFlat(vtop, vsize, polygon.colorIndex);
+		} else {
+			renderPolygonsTele(vtop, vsize, polygon.colorIndex);
+		}
+		break;
 	case POLYGONTYPE_COPPER:
 		// TODO: activate again after POLYGONTYPE_BOPPER is fixed
 		//renderPolygonsCopper(vtop, vsize, polygon.colorIndex);
@@ -1106,9 +1115,6 @@ void Renderer::renderPolygons(const CmdRenderPolygon &polygon, Vertex *vertices,
 		// TODO: fix this render method:
 		// renderPolygonsBopper(vtop, vsize, polygon.colorIndex);
 		break;
-	case POLYGONTYPE_TELE:
-		renderPolygonsTele(vtop, vsize, polygon.colorIndex);
-		break;
 	case POLYGONTYPE_TRAS:
 		renderPolygonsTras(vtop, vsize, polygon.colorIndex);
 		break;
@@ -1119,7 +1125,11 @@ void Renderer::renderPolygons(const CmdRenderPolygon &polygon, Vertex *vertices,
 		renderPolygonsGouraud(vtop, vsize);
 		break;
 	case POLYGONTYPE_DITHER:
-		renderPolygonsDither(vtop, vsize);
+		if (_engine->_cfgfile.PolygonDetails < 2) {
+			renderPolygonsGouraud(vtop, vsize);
+		} else {
+			renderPolygonsDither(vtop, vsize);
+		}
 		break;
 	case POLYGONTYPE_MARBLE:
 		renderPolygonsMarble(vtop, vsize, polygon.colorIndex);


Commit: efc5e0bcf51dce6643f466aaceeb46d6f17e1e07
    https://github.com/scummvm/scummvm/commit/efc5e0bcf51dce6643f466aaceeb46d6f17e1e07
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2021-10-10T11:52:39+02:00

Commit Message:
TWINE: added low poly details render methods

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


diff --git a/engines/twine/renderer/renderer.cpp b/engines/twine/renderer/renderer.cpp
index c18a454aca..c4e7600c0b 100644
--- a/engines/twine/renderer/renderer.cpp
+++ b/engines/twine/renderer/renderer.cpp
@@ -1088,13 +1088,40 @@ void Renderer::renderPolygonsMarble(int vtop, int32 vsize, uint8 color) const {
 	}
 }
 
+void Renderer::renderPolygonsTriche(int vtop, int32 vsize, uint8 color) const {
+	uint8 *out = (uint8 *)_engine->_frontVideoBuffer.getBasePtr(0, vtop);
+	const int16 *ptr1 = &_polyTab[vtop];
+	const int16 *ptr2 = &_colorProgressionBuffer[vtop];
+	const int screenWidth = _engine->width();
+	const int screenHeight = _engine->height();
+
+	int32 renderLoop = vsize;
+	if (vtop < 0) {
+		out += screenWidth * ABS(vtop);
+		renderLoop -= ABS(vtop);
+	}
+	if (renderLoop > screenHeight) {
+		renderLoop = screenHeight;
+	}
+	for (int32 currentLine = 0; currentLine < renderLoop; ++currentLine) {
+		uint16 xMin = ptr1[0];
+		const uint16 xMax = ptr1[screenHeight];
+		uint8 *pDest = out + xMin;
+
+		color = (*ptr2++) >> 8;
+		for (; xMin <= xMax; xMin++) {
+			*pDest++ = color;
+		}
+
+		out += screenWidth;
+	}
+}
+
 void Renderer::renderPolygons(const CmdRenderPolygon &polygon, Vertex *vertices, int vtop, int vbottom) {
 	computePolygons(polygon.renderType, vertices, polygon.numVertices);
 
 	const int32 vsize = vbottom - vtop + 1;
 
-	// TODO: POLYGONTYPE_GOURAUD and POLYGONTYPE_DITHER are replaced with a simpler polygon fill function that
-	// is not yet reversed.
 	switch (polygon.renderType) {
 	case POLYGONTYPE_FLAT:
 		renderPolygonsFlat(vtop, vsize, polygon.colorIndex);
@@ -1122,10 +1149,16 @@ void Renderer::renderPolygons(const CmdRenderPolygon &polygon, Vertex *vertices,
 		renderPolygonsTrame(vtop, vsize, polygon.colorIndex);
 		break;
 	case POLYGONTYPE_GOURAUD:
-		renderPolygonsGouraud(vtop, vsize);
+		if (_engine->_cfgfile.PolygonDetails == 0) {
+			renderPolygonsTriche(vtop, vsize, polygon.colorIndex);
+		} else {
+			renderPolygonsGouraud(vtop, vsize);
+		}
 		break;
 	case POLYGONTYPE_DITHER:
-		if (_engine->_cfgfile.PolygonDetails < 2) {
+		if (_engine->_cfgfile.PolygonDetails == 0) {
+			renderPolygonsTriche(vtop, vsize, polygon.colorIndex);
+		} else if (_engine->_cfgfile.PolygonDetails == 1) {
 			renderPolygonsGouraud(vtop, vsize);
 		} else {
 			renderPolygonsDither(vtop, vsize);
diff --git a/engines/twine/renderer/renderer.h b/engines/twine/renderer/renderer.h
index f7a54bda71..2a9944430a 100644
--- a/engines/twine/renderer/renderer.h
+++ b/engines/twine/renderer/renderer.h
@@ -192,7 +192,7 @@ private:
 	void renderPolygonsGouraud(int vtop, int32 vsize) const;
 	void renderPolygonsDither(int vtop, int32 vsize) const;
 	void renderPolygonsMarble(int vtop, int32 vsize, uint8 color) const;
-
+	void renderPolygonsTriche(int vtop, int32 vsize, uint8 color) const;
 	void computePolygons(int16 polyRenderType, const Vertex *vertices, int32 numVertices);
 
 	const RenderCommand *depthSortRenderCommands(int32 numOfPrimitives);


Commit: da0e5a8193b61db3fcd9d410d73cacd70a9e0c8a
    https://github.com/scummvm/scummvm/commit/da0e5a8193b61db3fcd9d410d73cacd70a9e0c8a
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2021-10-10T11:52:39+02:00

Commit Message:
TWINE: improved polygon render methods

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


diff --git a/engines/twine/renderer/renderer.cpp b/engines/twine/renderer/renderer.cpp
index c4e7600c0b..b13d9172df 100644
--- a/engines/twine/renderer/renderer.cpp
+++ b/engines/twine/renderer/renderer.cpp
@@ -597,11 +597,9 @@ void Renderer::renderPolygonsFlat(int vtop, int32 vsize, uint8 color) const {
 		ptr1++;
 		const int32 hsize = stop - start;
 
-		if (hsize >= 0) {
-			for (int32 j = start; j <= hsize + start; j++) {
-				if (j >= 0 && j < screenWidth) {
-					out[j] = color;
-				}
+		for (int32 j = start; j <= hsize + start; j++) {
+			if (j >= 0 && j < screenWidth) {
+				out[j] = color;
 			}
 		}
 		out += screenWidth;
@@ -685,16 +683,13 @@ void Renderer::renderPolygonsTele(int vtop, int32 vsize, uint8 color) const {
 	} while (renderLoop);
 }
 
-// FIXME: buggy
-void Renderer::renderPolygonsTras(int vtop, int32 vsize, uint8 color) const {
+void Renderer::renderPolygonsTrans(int vtop, int32 vsize, uint8 color) const {
 	uint8 *out = (uint8 *)_engine->_frontVideoBuffer.getBasePtr(0, vtop);
 	const int16 *ptr1 = &_polyTab[vtop];
 	const int screenWidth = _engine->width();
 	const int screenHeight = _engine->height();
 
 	do {
-		unsigned short int bx;
-
 		int16 start = ptr1[0];
 		int16 stop = ptr1[screenHeight];
 
@@ -704,30 +699,17 @@ void Renderer::renderPolygonsTras(int vtop, int32 vsize, uint8 color) const {
 		if (hsize >= 0) {
 			hsize++;
 			uint8 *out2 = start + out;
-
-			if (hsize / 2 < 0) {
-				bx = color;
-				bx = bx * 256;
-				bx += color;
-				for (int32 j = 0; j < hsize; j++) {
-					*(out2) = (*(out2)&0x0F0F) | bx;
-					// TODO: check for potential out2++ here
-				}
-			} else {
-				*out2 = (*(out2)&0x0F) | color;
-				out2++;
-			}
+			*out2 = (*(out2)&0x0F) | color;
+			out2++;
 		}
 		out += screenWidth;
 	} while (--vsize);
 }
 
-// FIXME: buggy
 // Used e.g for the legs of the horse or the ears of most characters
 void Renderer::renderPolygonsTrame(int vtop, int32 vsize, uint8 color) const {
 	uint8 *out = (uint8 *)_engine->_frontVideoBuffer.getBasePtr(0, vtop);
 	const int16 *ptr1 = &_polyTab[vtop];
-	unsigned char bh = 0;
 	const int screenWidth = _engine->width();
 	const int screenHeight = _engine->height();
 
@@ -739,32 +721,25 @@ void Renderer::renderPolygonsTrame(int vtop, int32 vsize, uint8 color) const {
 	if (renderLoop > screenHeight) {
 		renderLoop = screenHeight;
 	}
+	int32 pair = 0;
 	for (int32 currentLine = 0; currentLine < renderLoop; ++currentLine) {
 		int16 start = ptr1[0];
 		int16 stop = ptr1[screenHeight];
 		ptr1++;
-		int32 hsize = stop - start;
-
-		if (hsize >= 0) {
-			hsize++;
-			uint8 *out2 = start + out;
-
-			hsize /= 2;
-			if (hsize > 1) {
-				uint16 ax;
-				bh ^= 1;
-				ax = (uint16)(*out2);
-				ax &= 1;
-				if (ax ^ bh) {
-					out2++;
-				}
+		uint8 *out2 = start + out;
+		stop = ((stop - start) + 1) / 2;
+		if (stop > 0) {
+			pair ^= 1; // paire/impair
+			if ((start & 1) ^ pair) {
+				out2++;
+			}
 
-				for (int32 j = 0; j < hsize; j++) {
-					*out2 = color;
-					out2 += 2;
-				}
+			for (; stop > 0; stop--) {
+				*out2 = color;
+				out2 += 2;
 			}
 		}
+
 		out += screenWidth;
 	}
 }
@@ -1142,8 +1117,8 @@ void Renderer::renderPolygons(const CmdRenderPolygon &polygon, Vertex *vertices,
 		// TODO: fix this render method:
 		// renderPolygonsBopper(vtop, vsize, polygon.colorIndex);
 		break;
-	case POLYGONTYPE_TRAS:
-		renderPolygonsTras(vtop, vsize, polygon.colorIndex);
+	case POLYGONTYPE_TRANS:
+		renderPolygonsTrans(vtop, vsize, polygon.colorIndex);
 		break;
 	case POLYGONTYPE_TRAME:
 		renderPolygonsTrame(vtop, vsize, polygon.colorIndex);
diff --git a/engines/twine/renderer/renderer.h b/engines/twine/renderer/renderer.h
index 2a9944430a..1580a74f14 100644
--- a/engines/twine/renderer/renderer.h
+++ b/engines/twine/renderer/renderer.h
@@ -35,7 +35,7 @@
 #define POLYGONTYPE_COPPER 2
 #define POLYGONTYPE_BOPPER 3
 #define POLYGONTYPE_MARBLE 4
-#define POLYGONTYPE_TRAS 5
+#define POLYGONTYPE_TRANS 5
 #define POLYGONTYPE_TRAME 6
 #define POLYGONTYPE_GOURAUD 7
 #define POLYGONTYPE_DITHER 8
@@ -187,7 +187,7 @@ private:
 	void renderPolygonsBopper(int vtop, int32 vsize, uint8 color) const;
 	void renderPolygonsFlat(int vtop, int32 vsize, uint8 color) const;
 	void renderPolygonsTele(int vtop, int32 vsize, uint8 color) const;
-	void renderPolygonsTras(int vtop, int32 vsize, uint8 color) const;
+	void renderPolygonsTrans(int vtop, int32 vsize, uint8 color) const;
 	void renderPolygonsTrame(int vtop, int32 vsize, uint8 color) const;
 	void renderPolygonsGouraud(int vtop, int32 vsize) const;
 	void renderPolygonsDither(int vtop, int32 vsize) const;


Commit: 87d9232202d49f2c02a2c4a03e8b5aa31b1b50cc
    https://github.com/scummvm/scummvm/commit/87d9232202d49f2c02a2c4a03e8b5aa31b1b50cc
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2021-10-10T11:52:39+02:00

Commit Message:
TWINE: renamed variables

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


diff --git a/engines/twine/renderer/renderer.cpp b/engines/twine/renderer/renderer.cpp
index b13d9172df..2494991883 100644
--- a/engines/twine/renderer/renderer.cpp
+++ b/engines/twine/renderer/renderer.cpp
@@ -87,19 +87,19 @@ IVec3 &Renderer::projectPositionOnScreen(int32 cX, int32 cY, int32 cZ) {
 		posZ = 0x7FFF;
 	}
 
-	_projPos.x = (cX * _cameraScaleY) / posZ + _orthoProjPos.x;
-	_projPos.y = (-cY * _cameraScaleZ) / posZ + _orthoProjPos.y;
+	_projPos.x = (cX * _cameraScaleX) / posZ + _orthoProjPos.x;
+	_projPos.y = (-cY * _cameraScaleY) / posZ + _orthoProjPos.y;
 	_projPos.z = posZ;
 	return _projPos;
 }
 
-void Renderer::setCameraPosition(int32 x, int32 y, int32 depthOffset, int32 scaleY, int32 scaleZ) {
+void Renderer::setCameraPosition(int32 x, int32 y, int32 depthOffset, int32 scaleX, int32 scaleY) {
 	_orthoProjPos.x = x;
 	_orthoProjPos.y = y;
 
 	_cameraDepthOffset = depthOffset;
+	_cameraScaleX = scaleX;
 	_cameraScaleY = scaleY;
-	_cameraScaleZ = scaleZ;
 
 	_isUsingOrthoProjection = false;
 }
@@ -1333,13 +1333,14 @@ bool Renderer::renderModelElements(int32 numOfPrimitives, const BodyData &bodyDa
 			int32 radius = sphere->radius;
 
 			if (_isUsingOrthoProjection) {
+				// * sqrt(sx+sy) / 512 (IsoScale)
 				radius = (radius * 34) / 512;
 			} else {
 				int32 delta = _cameraDepthOffset + sphere->z;
-				if (delta <= 0) {
+				if (delta == 0) {
 					radius = 0;
 				} else {
-					radius = ((sphere->radius * _cameraScaleY) / delta) & 0xFFFF;
+					radius = (sphere->radius * _cameraScaleX) / delta;
 				}
 			}
 
@@ -1455,7 +1456,7 @@ bool Renderer::renderAnimatedModel(ModelData *modelData, const BodyData &bodyDat
 
 			// X projection
 			{
-				coX = _orthoProjPos.x + ((coX * _cameraScaleY) / coZ);
+				coX = _orthoProjPos.x + ((coX * _cameraScaleX) / coZ);
 
 				if (coX > 0xFFFF) {
 					coX = 0x7FFF;
@@ -1474,7 +1475,7 @@ bool Renderer::renderAnimatedModel(ModelData *modelData, const BodyData &bodyDat
 
 			// Y projection
 			{
-				coY = _orthoProjPos.y + ((-coY * _cameraScaleZ) / coZ);
+				coY = _orthoProjPos.y + ((-coY * _cameraScaleY) / coZ);
 
 				if (coY > 0xFFFF) {
 					coY = 0x7FFF;
diff --git a/engines/twine/renderer/renderer.h b/engines/twine/renderer/renderer.h
index 1580a74f14..be6341028a 100644
--- a/engines/twine/renderer/renderer.h
+++ b/engines/twine/renderer/renderer.h
@@ -155,8 +155,8 @@ private:
 	IVec3 _orthoProjPos;
 
 	int32 _cameraDepthOffset = 0;
+	int32 _cameraScaleX = 0;
 	int32 _cameraScaleY = 0;
-	int32 _cameraScaleZ = 0;
 
 	IMatrix3x3 _baseMatrix;
 	IMatrix3x3 _matricesTable[30 + 1];
@@ -232,7 +232,7 @@ public:
 
 	IVec3 &projectPositionOnScreen(int32 cX, int32 cY, int32 cZ);
 
-	void setCameraPosition(int32 x, int32 y, int32 depthOffset, int32 scaleY, int32 scaleZ);
+	void setCameraPosition(int32 x, int32 y, int32 depthOffset, int32 scaleX, int32 scaleY);
 	void setCameraAngle(int32 transPosX, int32 transPosY, int32 transPosZ, int32 rotPosX, int32 rotPosY, int32 rotPosZ, int32 param6);
 	IVec3 updateCameraAnglePositions(int zShift = 0);
 	void setBaseTranslation(int32 x, int32 y, int32 z);


Commit: d1575966651f9aa428dba07fa76d8a557450d630
    https://github.com/scummvm/scummvm/commit/d1575966651f9aa428dba07fa76d8a557450d630
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2021-10-10T11:52:39+02:00

Commit Message:
TWINE: started to implement polygon render types for circles

Changed paths:
    engines/twine/parser/body.cpp
    engines/twine/parser/bodytypes.h
    engines/twine/renderer/renderer.cpp
    engines/twine/renderer/renderer.h


diff --git a/engines/twine/parser/body.cpp b/engines/twine/parser/body.cpp
index 9edab0143e..40c1fe98b8 100644
--- a/engines/twine/parser/body.cpp
+++ b/engines/twine/parser/body.cpp
@@ -165,9 +165,10 @@ void BodyData::loadSpheres(Common::SeekableReadStream &stream) {
 	_spheres.reserve(numSpheres);
 	for (uint16 i = 0; i < numSpheres; ++i) {
 		BodySphere sphere;
-		sphere.unk1 = stream.readByte();
-		sphere.color = stream.readByte();
-		sphere.unk2 = stream.readUint16LE();
+		sphere.fillType = stream.readByte();
+		sphere.colorStart = stream.readByte();
+		sphere.colorEnd = stream.readByte();
+		stream.readByte();
 		sphere.radius = stream.readUint16LE();
 		sphere.vertex = stream.readUint16LE() / 6;
 		_spheres.push_back(sphere);
diff --git a/engines/twine/parser/bodytypes.h b/engines/twine/parser/bodytypes.h
index edf077310e..53bb0061d4 100644
--- a/engines/twine/parser/bodytypes.h
+++ b/engines/twine/parser/bodytypes.h
@@ -46,11 +46,11 @@ struct BodyLine {
 };
 
 struct BodySphere {
-	// TODO: intensity??
-	uint8 unk1;
-	uint8 color;
-	uint16 unk2;
-	uint16 radius;
+	uint8 fillType;
+	uint8 colorStart;
+	uint8 colorEnd;
+	// fill byte here
+	int16 radius;
 	uint16 vertex;
 };
 
diff --git a/engines/twine/renderer/renderer.cpp b/engines/twine/renderer/renderer.cpp
index 2494991883..8e1cb92712 100644
--- a/engines/twine/renderer/renderer.cpp
+++ b/engines/twine/renderer/renderer.cpp
@@ -1096,43 +1096,46 @@ void Renderer::renderPolygons(const CmdRenderPolygon &polygon, Vertex *vertices,
 	computePolygons(polygon.renderType, vertices, polygon.numVertices);
 
 	const int32 vsize = vbottom - vtop + 1;
+	fillVertices(vtop, vsize, polygon.renderType, polygon.colorIndex);
+}
 
-	switch (polygon.renderType) {
+void Renderer::fillVertices(int vtop, int32 vsize, uint8 renderType, uint16 color) {
+	switch (renderType) {
 	case POLYGONTYPE_FLAT:
-		renderPolygonsFlat(vtop, vsize, polygon.colorIndex);
+		renderPolygonsFlat(vtop, vsize, color);
 		break;
 	case POLYGONTYPE_TELE:
 		if (_engine->_cfgfile.PolygonDetails == 0) {
-			renderPolygonsFlat(vtop, vsize, polygon.colorIndex);
+			renderPolygonsFlat(vtop, vsize, color);
 		} else {
-			renderPolygonsTele(vtop, vsize, polygon.colorIndex);
+			renderPolygonsTele(vtop, vsize, color);
 		}
 		break;
 	case POLYGONTYPE_COPPER:
 		// TODO: activate again after POLYGONTYPE_BOPPER is fixed
-		//renderPolygonsCopper(vtop, vsize, polygon.colorIndex);
+		//renderPolygonsCopper(vtop, vsize, color);
 		//break;
 	case POLYGONTYPE_BOPPER:
-		renderPolygonsCopper(vtop, vsize, polygon.colorIndex);
+		renderPolygonsCopper(vtop, vsize, color);
 		// TODO: fix this render method:
-		// renderPolygonsBopper(vtop, vsize, polygon.colorIndex);
+		// renderPolygonsBopper(vtop, vsize, color);
 		break;
 	case POLYGONTYPE_TRANS:
-		renderPolygonsTrans(vtop, vsize, polygon.colorIndex);
+		renderPolygonsTrans(vtop, vsize, color);
 		break;
 	case POLYGONTYPE_TRAME:
-		renderPolygonsTrame(vtop, vsize, polygon.colorIndex);
+		renderPolygonsTrame(vtop, vsize, color);
 		break;
 	case POLYGONTYPE_GOURAUD:
 		if (_engine->_cfgfile.PolygonDetails == 0) {
-			renderPolygonsTriche(vtop, vsize, polygon.colorIndex);
+			renderPolygonsTriche(vtop, vsize, color);
 		} else {
 			renderPolygonsGouraud(vtop, vsize);
 		}
 		break;
 	case POLYGONTYPE_DITHER:
 		if (_engine->_cfgfile.PolygonDetails == 0) {
-			renderPolygonsTriche(vtop, vsize, polygon.colorIndex);
+			renderPolygonsTriche(vtop, vsize, color);
 		} else if (_engine->_cfgfile.PolygonDetails == 1) {
 			renderPolygonsGouraud(vtop, vsize);
 		} else {
@@ -1140,15 +1143,15 @@ void Renderer::renderPolygons(const CmdRenderPolygon &polygon, Vertex *vertices,
 		}
 		break;
 	case POLYGONTYPE_MARBLE:
-		renderPolygonsMarble(vtop, vsize, polygon.colorIndex);
+		renderPolygonsMarble(vtop, vsize, color);
 		break;
 	default:
-		warning("RENDER WARNING: Unsupported render type %d", polygon.renderType);
+		warning("RENDER WARNING: Unsupported render type %d", renderType);
 		break;
 	}
 }
 
-void Renderer::circleFill(int32 x, int32 y, int32 radius, uint8 color) {
+void Renderer::circleFill(int32 x, int32 y, int32 radius, uint8 colorStart, uint8 colorEnd) {
 	if (radius <= 0) {
 		return;
 	}
@@ -1163,14 +1166,15 @@ void Renderer::circleFill(int32 x, int32 y, int32 radius, uint8 color) {
 			width = 0.0;
 		}
 
-		_engine->_interface->drawLine((int32)(x - width), currentLine + y, (int32)(x + width), currentLine + y, color);
+		_engine->_interface->drawLine((int32)(x - width), currentLine + y, (int32)(x + width), currentLine + y, colorStart);
 	}
 }
 
 uint8 *Renderer::prepareSpheres(const Common::Array<BodySphere> &spheres, int32 &numOfPrimitives, RenderCommand **renderCmds, uint8 *renderBufferPtr, ModelData *modelData) {
 	for (const BodySphere &sphere : spheres) {
 		CmdRenderSphere *cmd = (CmdRenderSphere *)renderBufferPtr;
-		cmd->colorIndex = sphere.color;
+		cmd->colorIndexStart = sphere.colorStart;
+		cmd->colorIndexEnd = sphere.colorEnd;
 		cmd->radius = sphere.radius;
 		const int16 centerIndex = sphere.vertex;
 		cmd->x = modelData->flattenPoints[centerIndex].x;
@@ -1344,8 +1348,6 @@ bool Renderer::renderModelElements(int32 numOfPrimitives, const BodyData &bodyDa
 				}
 			}
 
-			radius += 3;
-
 			if (sphere->x + radius > modelRect.right) {
 				modelRect.right = sphere->x + radius;
 			}
@@ -1362,9 +1364,7 @@ bool Renderer::renderModelElements(int32 numOfPrimitives, const BodyData &bodyDa
 				modelRect.top = sphere->y - radius;
 			}
 
-			radius -= 3;
-
-			circleFill(sphere->x, sphere->y, radius, sphere->colorIndex);
+			circleFill(sphere->x, sphere->y, radius, sphere->colorIndexStart, sphere->colorIndexEnd);
 			break;
 		}
 		default:
diff --git a/engines/twine/renderer/renderer.h b/engines/twine/renderer/renderer.h
index be6341028a..2674f28e19 100644
--- a/engines/twine/renderer/renderer.h
+++ b/engines/twine/renderer/renderer.h
@@ -122,7 +122,8 @@ private:
 	 * @sa RenderCommand
 	 */
 	struct CmdRenderSphere {
-		int8 colorIndex = 0;
+		uint8 colorIndexStart = 0;
+		uint8 colorIndexEnd = 0;
 		int16 radius = 0;
 		int16 x = 0;
 		int16 y = 0;
@@ -138,7 +139,7 @@ private:
 	ModelData _modelData;
 
 	bool renderAnimatedModel(ModelData *modelData, const BodyData &bodyData, RenderCommand *renderCmds, const IVec3 &angleVec, const IVec3 &renderPos, Common::Rect &modelRect);
-	void circleFill(int32 x, int32 y, int32 radius, uint8 color);
+	void circleFill(int32 x, int32 y, int32 radius, uint8 colorStart, uint8 colorEnd);
 	bool renderModelElements(int32 numOfPrimitives, const BodyData &bodyData, RenderCommand **renderCmds, ModelData *modelData, Common::Rect &modelRect);
 	IVec3 getCameraAnglePositions(int32 x, int32 y, int32 z);
 	inline IVec3 getCameraAnglePositions(const IVec3 &vec) {
@@ -224,6 +225,7 @@ public:
 		return getBaseRotationPosition(vec.x, vec.y, vec.z);
 	}
 
+	void fillVertices(int vtop, int32 vsize, uint8 renderType, uint16 color);
 	void renderPolygons(const CmdRenderPolygon &polygon, Vertex *vertices, int vtop, int vbottom);
 
 	inline IVec3 &projectPositionOnScreen(const IVec3& pos) {


Commit: 010a29a413413f597a36486eeec0c85da6e96c5b
    https://github.com/scummvm/scummvm/commit/010a29a413413f597a36486eeec0c85da6e96c5b
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2021-10-10T11:52:39+02:00

Commit Message:
TWINE: prepare for color blending in marble fill method

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


diff --git a/engines/twine/renderer/renderer.cpp b/engines/twine/renderer/renderer.cpp
index 8e1cb92712..d06148dc1f 100644
--- a/engines/twine/renderer/renderer.cpp
+++ b/engines/twine/renderer/renderer.cpp
@@ -961,105 +961,45 @@ void Renderer::renderPolygonsDither(int vtop, int32 vsize) const {
 	}
 }
 
-void Renderer::renderPolygonsMarble(int vtop, int32 vsize, uint8 color) const {
+void Renderer::renderPolygonsMarble(int vtop, int32 vsize, uint8 colorStart, uint8 colorEnd) const {
 	const int screenWidth = _engine->width();
 	const int screenHeight = _engine->height();
 
 	uint8 *out = (uint8 *)_engine->_frontVideoBuffer.getBasePtr(0, vtop);
-	const int16 *ptr1 = &_polyTab[vtop];
-	int height = vsize;
-
-	uint16 color2 = color;
-	uint16 v29 = 2;
-	while (2) {
-		const uint16 stop = *(const uint16 *)(ptr1 + screenHeight);
-		const uint16 start = *(const uint16 *)ptr1;
-		++ptr1;
-		if (stop < start) {
-			out += screenWidth;
-			--height;
-			if (!height) {
-				return;
-			}
-			continue;
-		}
-		const uint16 hsize = stop - start;
-		uint16 width = hsize + 1;
-		uint8 *out2 = start + out;
-		if ((uintptr)out2 & 1) {
-			*out2++ = color2;
-			--width;
-		}
-		for (uint16 k = width / 2; k; --k) {
-			*out2++ = color2;
-			*out2++ = color2;
-		}
-		const uint16 v34 = width & 1;
-		for (uint16 l = v34; l; --l) {
-			*out2++ = color2;
-		}
-		--v29;
-		if (v29 || (v29 = 2, ++color2, color2 & 0xF)) {
-			out += screenWidth;
-			--height;
-			if (!height) {
-				return;
-			}
-			continue;
-		}
-		v29 = 2;
-		--color2;
-		if (!(color2 & 0xF)) {
-			out += screenWidth;
-			--height;
-			if (!height) {
-				return;
-			}
-			continue;
-		}
-		break;
-	}
-	while (1) {
-		out += screenWidth;
-		--height;
-		if (!height) {
-			return;
-		}
-		const uint16 stop = *(const uint16 *)(ptr1 + screenHeight);
-		const uint16 start = *(const uint16 *)ptr1;
-		++ptr1;
-		if (stop >= start) {
-			const uint16 hsize = stop - start;
-			uint16 width = hsize + 1;
-			uint8 *out2 = start + out;
-			if ((uintptr)out2 & 1) {
-				*out2++ = color2;
-				--width;
-			}
-			for (uint16 m = width / 2; m; --m) {
-				*out2++ = color2;
-				*out2++ = color2;
+	int16 *ptr1 = &_polyTab[vtop];
+
+	int16 xMin, xMax;
+	int16 y = vtop;
+	uint8 *pDestLine = out;
+	uint8 *pDest;
+	int16 *pVerticG = ptr1;
+	int16 *pVerticD = &ptr1[screenHeight];
+
+	uint16 start = colorStart;
+	uint16 end = colorEnd;
+	uint16 delta = end - start + 1; // delta intensity
+	int32 step, dc;
+
+	for (; y <= vsize; y++) {
+		xMin = *pVerticG++;
+		xMax = *pVerticD++;
+		pDest = pDestLine + xMin;
+
+		dc = xMax - xMin;
+		if (dc == 0) {
+			// just one
+			*pDest++ = (uint8)(end >> 8);
+		} else if (dc > 0) {
+			step = delta / (dc + 1);
+			uint16 color = start;
+
+			for (; xMin <= xMax; xMin++) {
+				*pDest++ = (uint8)(color >> 8);
+				color += step;
 			}
-			const uint16 v41 = width & 1;
-			for (uint16 n = v41; n; --n) {
-				*out2++ = color2;
-			}
-			--v29;
-			if (v29) {
-				continue;
-			}
-		}
-		v29 = 2;
-		--color2;
-		if (!(color2 & 0xF)) {
-			out += screenWidth;
-			--height;
-			if (!height) {
-				return;
-			}
-			continue;
 		}
-		break;
+
+		pDestLine += screenWidth;
 	}
 }
 
@@ -1096,46 +1036,46 @@ void Renderer::renderPolygons(const CmdRenderPolygon &polygon, Vertex *vertices,
 	computePolygons(polygon.renderType, vertices, polygon.numVertices);
 
 	const int32 vsize = vbottom - vtop + 1;
-	fillVertices(vtop, vsize, polygon.renderType, polygon.colorIndex);
+	fillVertices(vtop, vsize, polygon.renderType, polygon.colorIndex, polygon.colorIndex);
 }
 
-void Renderer::fillVertices(int vtop, int32 vsize, uint8 renderType, uint16 color) {
+void Renderer::fillVertices(int vtop, int32 vsize, uint8 renderType, uint8 colorStart, uint8 colorEnd) {
 	switch (renderType) {
 	case POLYGONTYPE_FLAT:
-		renderPolygonsFlat(vtop, vsize, color);
+		renderPolygonsFlat(vtop, vsize, colorStart);
 		break;
 	case POLYGONTYPE_TELE:
 		if (_engine->_cfgfile.PolygonDetails == 0) {
-			renderPolygonsFlat(vtop, vsize, color);
+			renderPolygonsFlat(vtop, vsize, colorStart);
 		} else {
-			renderPolygonsTele(vtop, vsize, color);
+			renderPolygonsTele(vtop, vsize, colorStart);
 		}
 		break;
 	case POLYGONTYPE_COPPER:
 		// TODO: activate again after POLYGONTYPE_BOPPER is fixed
-		//renderPolygonsCopper(vtop, vsize, color);
+		//renderPolygonsCopper(vtop, vsize, colorStart);
 		//break;
 	case POLYGONTYPE_BOPPER:
-		renderPolygonsCopper(vtop, vsize, color);
+		renderPolygonsCopper(vtop, vsize, colorStart);
 		// TODO: fix this render method:
-		// renderPolygonsBopper(vtop, vsize, color);
+		// renderPolygonsBopper(vtop, vsize, colorStart);
 		break;
 	case POLYGONTYPE_TRANS:
-		renderPolygonsTrans(vtop, vsize, color);
+		renderPolygonsTrans(vtop, vsize, colorStart);
 		break;
-	case POLYGONTYPE_TRAME:
-		renderPolygonsTrame(vtop, vsize, color);
+	case POLYGONTYPE_TRAME: // raster
+		renderPolygonsTrame(vtop, vsize, colorStart);
 		break;
 	case POLYGONTYPE_GOURAUD:
 		if (_engine->_cfgfile.PolygonDetails == 0) {
-			renderPolygonsTriche(vtop, vsize, color);
+			renderPolygonsTriche(vtop, vsize, colorStart);
 		} else {
 			renderPolygonsGouraud(vtop, vsize);
 		}
 		break;
 	case POLYGONTYPE_DITHER:
 		if (_engine->_cfgfile.PolygonDetails == 0) {
-			renderPolygonsTriche(vtop, vsize, color);
+			renderPolygonsTriche(vtop, vsize, colorStart);
 		} else if (_engine->_cfgfile.PolygonDetails == 1) {
 			renderPolygonsGouraud(vtop, vsize);
 		} else {
@@ -1143,7 +1083,7 @@ void Renderer::fillVertices(int vtop, int32 vsize, uint8 renderType, uint16 colo
 		}
 		break;
 	case POLYGONTYPE_MARBLE:
-		renderPolygonsMarble(vtop, vsize, color);
+		renderPolygonsMarble(vtop, vsize, colorStart, colorEnd);
 		break;
 	default:
 		warning("RENDER WARNING: Unsupported render type %d", renderType);
@@ -1175,6 +1115,7 @@ uint8 *Renderer::prepareSpheres(const Common::Array<BodySphere> &spheres, int32
 		CmdRenderSphere *cmd = (CmdRenderSphere *)renderBufferPtr;
 		cmd->colorIndexStart = sphere.colorStart;
 		cmd->colorIndexEnd = sphere.colorEnd;
+		cmd->polyRenderType = sphere.fillType;
 		cmd->radius = sphere.radius;
 		const int16 centerIndex = sphere.vertex;
 		cmd->x = modelData->flattenPoints[centerIndex].x;
@@ -1348,6 +1289,8 @@ bool Renderer::renderModelElements(int32 numOfPrimitives, const BodyData &bodyDa
 				}
 			}
 
+			radius += 3;
+
 			if (sphere->x + radius > modelRect.right) {
 				modelRect.right = sphere->x + radius;
 			}
@@ -1364,6 +1307,8 @@ bool Renderer::renderModelElements(int32 numOfPrimitives, const BodyData &bodyDa
 				modelRect.top = sphere->y - radius;
 			}
 
+			radius -= 3;
+
 			circleFill(sphere->x, sphere->y, radius, sphere->colorIndexStart, sphere->colorIndexEnd);
 			break;
 		}
diff --git a/engines/twine/renderer/renderer.h b/engines/twine/renderer/renderer.h
index 2674f28e19..9379831c88 100644
--- a/engines/twine/renderer/renderer.h
+++ b/engines/twine/renderer/renderer.h
@@ -124,6 +124,7 @@ private:
 	struct CmdRenderSphere {
 		uint8 colorIndexStart = 0;
 		uint8 colorIndexEnd = 0;
+		uint8 polyRenderType = 0;
 		int16 radius = 0;
 		int16 x = 0;
 		int16 y = 0;
@@ -192,7 +193,7 @@ private:
 	void renderPolygonsTrame(int vtop, int32 vsize, uint8 color) const;
 	void renderPolygonsGouraud(int vtop, int32 vsize) const;
 	void renderPolygonsDither(int vtop, int32 vsize) const;
-	void renderPolygonsMarble(int vtop, int32 vsize, uint8 color) const;
+	void renderPolygonsMarble(int vtop, int32 vsize, uint8 colorStart, uint8 colorEnd) const;
 	void renderPolygonsTriche(int vtop, int32 vsize, uint8 color) const;
 	void computePolygons(int16 polyRenderType, const Vertex *vertices, int32 numVertices);
 
@@ -225,7 +226,7 @@ public:
 		return getBaseRotationPosition(vec.x, vec.y, vec.z);
 	}
 
-	void fillVertices(int vtop, int32 vsize, uint8 renderType, uint16 color);
+	void fillVertices(int vtop, int32 vsize, uint8 renderType, uint8 colorStart, uint8 colorEnd);
 	void renderPolygons(const CmdRenderPolygon &polygon, Vertex *vertices, int vtop, int vbottom);
 
 	inline IVec3 &projectPositionOnScreen(const IVec3& pos) {


Commit: 808516dc2f7552a83556ac1c8f5252c1d84f2f79
    https://github.com/scummvm/scummvm/commit/808516dc2f7552a83556ac1c8f5252c1d84f2f79
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2021-10-10T11:52:39+02:00

Commit Message:
TWINE: circle rendering is using proper fill methods now

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


diff --git a/engines/twine/renderer/renderer.cpp b/engines/twine/renderer/renderer.cpp
index d06148dc1f..ef9691952a 100644
--- a/engines/twine/renderer/renderer.cpp
+++ b/engines/twine/renderer/renderer.cpp
@@ -1091,23 +1091,100 @@ void Renderer::fillVertices(int vtop, int32 vsize, uint8 renderType, uint8 color
 	}
 }
 
-void Renderer::circleFill(int32 x, int32 y, int32 radius, uint8 colorStart, uint8 colorEnd) {
+bool Renderer::prepareCircle(int32 x, int32 y, int32 radius, uint8 colorStart, uint8 colorEnd) {
 	if (radius <= 0) {
-		return;
+		return false;
 	}
-	radius += 1;
+	int16 left = (int16)(x - radius);
+	int16 right = (int16)(y - radius);
+	int16 bottom = (int16)(x + radius);
+	int16 top = (int16)(y + radius);
+	const Common::Rect &clip = _engine->_interface->_clip;
+	int16 cleft = clip.left;
+	int16 cright = clip.right;
+	int16 ctop = clip.top;
+	int16 cbottom = clip.bottom;
+
+	if (left <= cright && bottom >= cleft && right <= cbottom && top >= ctop) {
+		if (left < cleft) {
+			left = cleft;
+		}
+		if (bottom > cright) {
+			bottom = cright;
+		}
+		if (right < ctop) {
+			right = ctop;
+		}
+		if (top > cbottom) {
+			top = cbottom;
+		}
 
-	for (int32 currentLine = -radius; currentLine <= radius; currentLine++) {
-		double width;
+		int32 r = 0;
+		int32 acc = -radius;
 
-		if (ABS(currentLine) != radius) {
-			width = ABS(sin(acos((float)currentLine / (float)radius)) * radius);
-		} else {
-			width = 0.0;
+		int16 *start = _polyTab;
+		int16 *end = &_polyTab[_engine->height()];
+
+		while (r <= radius) {
+			int32 x1 = x - radius;
+			if (x1 < cleft) {
+				x1 = cleft;
+			}
+
+			int32 x2 = x + radius;
+			if (x2 > cright) {
+				x2 = cright;
+			}
+
+			int32 ny = y - r;
+			if ((ny >= ctop) && (ny <= cbottom)) {
+				start[ny] = (int16)x1;
+				end[ny] = (int16)x2;
+			}
+
+			ny = y + r;
+			if ((ny >= ctop) && (ny <= cbottom)) {
+				start[ny] = (int16)x1;
+				end[ny] = (int16)x2;
+			}
+
+			if (acc < 0) {
+				acc += r;
+				if (acc >= 0) {
+					x1 = x - r;
+					if (x1 < cleft) {
+						x1 = cleft;
+					}
+
+					x2 = x + r;
+					if (x2 > cright) {
+						x2 = cright;
+					}
+
+					ny = y - radius;
+					if ((ny >= ctop) && (ny <= cbottom)) {
+						start[ny] = (int16)x1;
+						end[ny] = (int16)x2;
+					}
+
+					ny = y + radius;
+					if ((ny >= ctop) && (ny <= cbottom)) {
+						start[ny] = (int16)x1;
+						end[ny] = (int16)x2;
+					}
+
+					--radius;
+					acc -= radius;
+				}
+			}
+
+			++r;
 		}
 
-		_engine->_interface->drawLine((int32)(x - width), currentLine + y, (int32)(x + width), currentLine + y, colorStart);
+		return true;
 	}
+
+	return false;
 }
 
 uint8 *Renderer::prepareSpheres(const Common::Array<BodySphere> &spheres, int32 &numOfPrimitives, RenderCommand **renderCmds, uint8 *renderBufferPtr, ModelData *modelData) {
@@ -1278,15 +1355,14 @@ bool Renderer::renderModelElements(int32 numOfPrimitives, const BodyData &bodyDa
 			int32 radius = sphere->radius;
 
 			if (_isUsingOrthoProjection) {
-				// * sqrt(sx+sy) / 512 (IsoScale)
+				// * sqrt(sx+sy) / 512 (isometric scale)
 				radius = (radius * 34) / 512;
 			} else {
 				int32 delta = _cameraDepthOffset + sphere->z;
 				if (delta == 0) {
-					radius = 0;
-				} else {
-					radius = (sphere->radius * _cameraScaleX) / delta;
+					break;
 				}
+				radius = (sphere->radius * _cameraScaleX) / delta;
 			}
 
 			radius += 3;
@@ -1309,7 +1385,10 @@ bool Renderer::renderModelElements(int32 numOfPrimitives, const BodyData &bodyDa
 
 			radius -= 3;
 
-			circleFill(sphere->x, sphere->y, radius, sphere->colorIndexStart, sphere->colorIndexEnd);
+			if (prepareCircle(sphere->x, sphere->y, radius, sphere->colorIndexStart, sphere->colorIndexEnd)) {
+				const int32 vsize = 2 * radius;
+				fillVertices(sphere->y - radius, vsize, sphere->polyRenderType, sphere->colorIndexStart, sphere->colorIndexEnd);
+			}
 			break;
 		}
 		default:
diff --git a/engines/twine/renderer/renderer.h b/engines/twine/renderer/renderer.h
index 9379831c88..655fc4fc17 100644
--- a/engines/twine/renderer/renderer.h
+++ b/engines/twine/renderer/renderer.h
@@ -140,7 +140,7 @@ private:
 	ModelData _modelData;
 
 	bool renderAnimatedModel(ModelData *modelData, const BodyData &bodyData, RenderCommand *renderCmds, const IVec3 &angleVec, const IVec3 &renderPos, Common::Rect &modelRect);
-	void circleFill(int32 x, int32 y, int32 radius, uint8 colorStart, uint8 colorEnd);
+	bool prepareCircle(int32 x, int32 y, int32 radius, uint8 colorStart, uint8 colorEnd);
 	bool renderModelElements(int32 numOfPrimitives, const BodyData &bodyData, RenderCommand **renderCmds, ModelData *modelData, Common::Rect &modelRect);
 	IVec3 getCameraAnglePositions(int32 x, int32 y, int32 z);
 	inline IVec3 getCameraAnglePositions(const IVec3 &vec) {


Commit: 2d6abce5cac1e4ebb1cdbd88025edd8c1b400897
    https://github.com/scummvm/scummvm/commit/2d6abce5cac1e4ebb1cdbd88025edd8c1b400897
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2021-10-10T11:52:39+02:00

Commit Message:
TWINE: renamed method

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


diff --git a/engines/twine/renderer/renderer.cpp b/engines/twine/renderer/renderer.cpp
index ef9691952a..68ed97f6c0 100644
--- a/engines/twine/renderer/renderer.cpp
+++ b/engines/twine/renderer/renderer.cpp
@@ -1003,7 +1003,7 @@ void Renderer::renderPolygonsMarble(int vtop, int32 vsize, uint8 colorStart, uin
 	}
 }
 
-void Renderer::renderPolygonsTriche(int vtop, int32 vsize, uint8 color) const {
+void Renderer::renderPolygonsSimplified(int vtop, int32 vsize, uint8 color) const {
 	uint8 *out = (uint8 *)_engine->_frontVideoBuffer.getBasePtr(0, vtop);
 	const int16 *ptr1 = &_polyTab[vtop];
 	const int16 *ptr2 = &_colorProgressionBuffer[vtop];
@@ -1068,14 +1068,14 @@ void Renderer::fillVertices(int vtop, int32 vsize, uint8 renderType, uint8 color
 		break;
 	case POLYGONTYPE_GOURAUD:
 		if (_engine->_cfgfile.PolygonDetails == 0) {
-			renderPolygonsTriche(vtop, vsize, colorStart);
+			renderPolygonsSimplified(vtop, vsize, colorStart);
 		} else {
 			renderPolygonsGouraud(vtop, vsize);
 		}
 		break;
 	case POLYGONTYPE_DITHER:
 		if (_engine->_cfgfile.PolygonDetails == 0) {
-			renderPolygonsTriche(vtop, vsize, colorStart);
+			renderPolygonsSimplified(vtop, vsize, colorStart);
 		} else if (_engine->_cfgfile.PolygonDetails == 1) {
 			renderPolygonsGouraud(vtop, vsize);
 		} else {
diff --git a/engines/twine/renderer/renderer.h b/engines/twine/renderer/renderer.h
index 655fc4fc17..6cce4141e2 100644
--- a/engines/twine/renderer/renderer.h
+++ b/engines/twine/renderer/renderer.h
@@ -194,7 +194,7 @@ private:
 	void renderPolygonsGouraud(int vtop, int32 vsize) const;
 	void renderPolygonsDither(int vtop, int32 vsize) const;
 	void renderPolygonsMarble(int vtop, int32 vsize, uint8 colorStart, uint8 colorEnd) const;
-	void renderPolygonsTriche(int vtop, int32 vsize, uint8 color) const;
+	void renderPolygonsSimplified(int vtop, int32 vsize, uint8 color) const;
 	void computePolygons(int16 polyRenderType, const Vertex *vertices, int32 numVertices);
 
 	const RenderCommand *depthSortRenderCommands(int32 numOfPrimitives);


Commit: 40dc3386711c9ea4a5c3ba28c912169bf2cb64db
    https://github.com/scummvm/scummvm/commit/40dc3386711c9ea4a5c3ba28c912169bf2cb64db
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2021-10-10T11:52:39+02:00

Commit Message:
TWINE: fixed low detail render method

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


diff --git a/engines/twine/renderer/renderer.cpp b/engines/twine/renderer/renderer.cpp
index 68ed97f6c0..194b91d2cc 100644
--- a/engines/twine/renderer/renderer.cpp
+++ b/engines/twine/renderer/renderer.cpp
@@ -1019,14 +1019,15 @@ void Renderer::renderPolygonsSimplified(int vtop, int32 vsize, uint8 color) cons
 		renderLoop = screenHeight;
 	}
 	for (int32 currentLine = 0; currentLine < renderLoop; ++currentLine) {
-		uint16 xMin = ptr1[0];
-		const uint16 xMax = ptr1[screenHeight];
+		int16 xMin = MAX<int16>(0, ptr1[0]);
+		const int16 xMax = MIN<int16>((int16)(screenWidth - 1), ptr1[screenHeight]);
 		uint8 *pDest = out + xMin;
 
 		color = (*ptr2++) >> 8;
 		for (; xMin <= xMax; xMin++) {
 			*pDest++ = color;
 		}
+		++ptr1;
 
 		out += screenWidth;
 	}


Commit: 37c48f7e44a3ea10e786cb1d2932b14fb31a591e
    https://github.com/scummvm/scummvm/commit/37c48f7e44a3ea10e786cb1d2932b14fb31a591e
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2021-10-10T11:52:39+02:00

Commit Message:
TWINE: fixed filler methods

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


diff --git a/engines/twine/renderer/renderer.cpp b/engines/twine/renderer/renderer.cpp
index 194b91d2cc..96ba4f45a7 100644
--- a/engines/twine/renderer/renderer.cpp
+++ b/engines/twine/renderer/renderer.cpp
@@ -473,79 +473,31 @@ void Renderer::renderPolygonsCopper(int vtop, int32 vsize, uint8 color) const {
 	if (renderLoop > screenHeight) {
 		renderLoop = screenHeight;
 	}
+	int32 sens = 1;
+
 	for (int32 currentLine = 0; currentLine < renderLoop; ++currentLine) {
-		int16 start = ptr1[0];
-		int16 stop = ptr1[screenHeight];
+		int16 xMin = ptr1[0];
+		int16 xMax = ptr1[screenHeight];
 
 		ptr1++;
-		int32 hsize = stop - start;
+		uint8 *pDest = out + xMin;
 
-		if (hsize >= 0) {
-			uint16 mask = 0x43DB;
+		for (; xMin <= xMax; xMin++) {
+			*pDest++ = (uint8)color;
+		}
 
-			hsize++;
-			const int32 startCopy = start;
-
-			for (int32 j = startCopy; j < hsize + startCopy; j++) {
-				start += mask;
-				start = (start & 0xFF00) | ((start & 0xFF) & 3U);
-				start = (start & 0xFF00) | ((start & 0xFF) + color);
-				if (j >= 0 && j < screenWidth) {
-					out[j] = start & 0xFF;
-				}
-				mask = (mask * 4) | (mask / SCENE_SIZE_HALF);
-				mask++;
+		color += sens;
+		if (!(color & 0xF)) {
+			sens = -sens;
+			if (sens < 0) {
+				color += sens;
 			}
 		}
-		out += screenWidth;
+		pDest += screenWidth;
 	}
 }
 
 void Renderer::renderPolygonsBopper(int vtop, int32 vsize, uint8 color) const {
-#if 0
-	uint8 *out = (uint8 *)_engine->_frontVideoBuffer.getBasePtr(0, vtop);
-	const int16 *ptr1 = &_polyTab[vtop];
-
-	const int screenWidth = _engine->width();
-	const int screenHeight = _engine->height();
-
-	int32 j = 0;
-
-	do {
-		uint16 stop = *(const uint16 *)(ptr1 + screenHeight);
-		uint16 start = *(const uint16 *)ptr1;
-		++ptr1;
-		if (stop >= start) {
-			++j;
-			uint8 *out2 = out + start;
-			memset(out2, color, j);
-			++color;
-			if (!(color & 0xF)) {
-				while (1) {
-					--color;
-					if (!(color & 0xF)) {
-						break;
-					}
-					out += screenWidth;
-					--vsize;
-					if (!vsize) {
-						return;
-					}
-					stop = *(const uint16 *)(ptr1 + screenHeight);
-					start = *(const uint16 *)ptr1;
-					++ptr1;
-					if (stop >= start) {
-						++j;
-						out2 = out + start;
-						memset(out2, color, j);
-					}
-				}
-			}
-		}
-		out += screenWidth;
-		--vsize;
-	} while (vsize);
-#else
 	uint8 *out = (uint8 *)_engine->_frontVideoBuffer.getBasePtr(0, vtop);
 	const int16 *ptr1 = &_polyTab[vtop];
 	const int screenWidth = _engine->width();
@@ -558,24 +510,32 @@ void Renderer::renderPolygonsBopper(int vtop, int32 vsize, uint8 color) const {
 	if (renderLoop > screenHeight) {
 		renderLoop = screenHeight;
 	}
+	int32 sens = 1;
+	int32 line = 2;
 	for (int32 currentLine = 0; currentLine < renderLoop; ++currentLine) {
-		int16 start = ptr1[0];
-		int16 stop = ptr1[screenHeight];
+		int16 xMin = ptr1[0];
+		int16 xMax = ptr1[screenHeight];
 		ptr1++;
-		const int32 hsize = stop - start;
 
-		if (start & 1) {
-			if (hsize >= 0) {
-				for (int32 j = start; j <= hsize + start; j++) {
-					if (j >= 0 && j < screenWidth) {
-						out[j] = color;
-					}
+		uint8 *pDest = out + xMin;
+
+		for (; xMin <= xMax; xMin++) {
+			*pDest++ = (uint8)color;
+		}
+
+		line--;
+		if (!line) {
+			line = 2;
+			color += sens;
+			if (!(color & 0xF)) {
+				sens = -sens;
+				if (sens < 0) {
+					color += sens;
 				}
 			}
 		}
 		out += screenWidth;
 	}
-#endif
 }
 
 void Renderer::renderPolygonsFlat(int vtop, int32 vsize, uint8 color) const {
@@ -1053,13 +1013,10 @@ void Renderer::fillVertices(int vtop, int32 vsize, uint8 renderType, uint8 color
 		}
 		break;
 	case POLYGONTYPE_COPPER:
-		// TODO: activate again after POLYGONTYPE_BOPPER is fixed
-		//renderPolygonsCopper(vtop, vsize, colorStart);
-		//break;
-	case POLYGONTYPE_BOPPER:
 		renderPolygonsCopper(vtop, vsize, colorStart);
-		// TODO: fix this render method:
-		// renderPolygonsBopper(vtop, vsize, colorStart);
+		break;
+	case POLYGONTYPE_BOPPER:
+		renderPolygonsBopper(vtop, vsize, colorStart);
 		break;
 	case POLYGONTYPE_TRANS:
 		renderPolygonsTrans(vtop, vsize, colorStart);


Commit: 002de89fad8a8b388cf77d83582ded7be98a9df0
    https://github.com/scummvm/scummvm/commit/002de89fad8a8b388cf77d83582ded7be98a9df0
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2021-10-10T11:52:39+02:00

Commit Message:
TWINE: the color values can contain two values - start and end color

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


diff --git a/engines/twine/renderer/renderer.cpp b/engines/twine/renderer/renderer.cpp
index 96ba4f45a7..52ffb467cc 100644
--- a/engines/twine/renderer/renderer.cpp
+++ b/engines/twine/renderer/renderer.cpp
@@ -459,7 +459,7 @@ void Renderer::computePolygons(int16 polyRenderType, const Vertex *vertices, int
 	}
 }
 
-void Renderer::renderPolygonsCopper(int vtop, int32 vsize, uint8 color) const {
+void Renderer::renderPolygonsCopper(int vtop, int32 vsize, uint16 color) const {
 	uint8 *out = (uint8 *)_engine->_frontVideoBuffer.getBasePtr(0, vtop);
 	const int16 *ptr1 = &_polyTab[vtop];
 	const int screenWidth = _engine->width();
@@ -497,7 +497,7 @@ void Renderer::renderPolygonsCopper(int vtop, int32 vsize, uint8 color) const {
 	}
 }
 
-void Renderer::renderPolygonsBopper(int vtop, int32 vsize, uint8 color) const {
+void Renderer::renderPolygonsBopper(int vtop, int32 vsize, uint16 color) const {
 	uint8 *out = (uint8 *)_engine->_frontVideoBuffer.getBasePtr(0, vtop);
 	const int16 *ptr1 = &_polyTab[vtop];
 	const int screenWidth = _engine->width();
@@ -538,7 +538,7 @@ void Renderer::renderPolygonsBopper(int vtop, int32 vsize, uint8 color) const {
 	}
 }
 
-void Renderer::renderPolygonsFlat(int vtop, int32 vsize, uint8 color) const {
+void Renderer::renderPolygonsFlat(int vtop, int32 vsize, uint16 color) const {
 	uint8 *out = (uint8 *)_engine->_frontVideoBuffer.getBasePtr(0, vtop);
 	const int16 *ptr1 = &_polyTab[vtop];
 	const int screenWidth = _engine->width();
@@ -566,7 +566,7 @@ void Renderer::renderPolygonsFlat(int vtop, int32 vsize, uint8 color) const {
 	}
 }
 
-void Renderer::renderPolygonsTele(int vtop, int32 vsize, uint8 color) const {
+void Renderer::renderPolygonsTele(int vtop, int32 vsize, uint16 color) const {
 	uint8 *out = (uint8 *)_engine->_frontVideoBuffer.getBasePtr(0, vtop);
 	const int16 *ptr1 = &_polyTab[vtop];
 	int bx = (uint16)color << 16;
@@ -643,7 +643,7 @@ void Renderer::renderPolygonsTele(int vtop, int32 vsize, uint8 color) const {
 	} while (renderLoop);
 }
 
-void Renderer::renderPolygonsTrans(int vtop, int32 vsize, uint8 color) const {
+void Renderer::renderPolygonsTrans(int vtop, int32 vsize, uint16 color) const {
 	uint8 *out = (uint8 *)_engine->_frontVideoBuffer.getBasePtr(0, vtop);
 	const int16 *ptr1 = &_polyTab[vtop];
 	const int screenWidth = _engine->width();
@@ -667,7 +667,7 @@ void Renderer::renderPolygonsTrans(int vtop, int32 vsize, uint8 color) const {
 }
 
 // Used e.g for the legs of the horse or the ears of most characters
-void Renderer::renderPolygonsTrame(int vtop, int32 vsize, uint8 color) const {
+void Renderer::renderPolygonsTrame(int vtop, int32 vsize, uint16 color) const {
 	uint8 *out = (uint8 *)_engine->_frontVideoBuffer.getBasePtr(0, vtop);
 	const int16 *ptr1 = &_polyTab[vtop];
 	const int screenWidth = _engine->width();
@@ -963,7 +963,7 @@ void Renderer::renderPolygonsMarble(int vtop, int32 vsize, uint8 colorStart, uin
 	}
 }
 
-void Renderer::renderPolygonsSimplified(int vtop, int32 vsize, uint8 color) const {
+void Renderer::renderPolygonsSimplified(int vtop, int32 vsize, uint16 color) const {
 	uint8 *out = (uint8 *)_engine->_frontVideoBuffer.getBasePtr(0, vtop);
 	const int16 *ptr1 = &_polyTab[vtop];
 	const int16 *ptr2 = &_colorProgressionBuffer[vtop];
diff --git a/engines/twine/renderer/renderer.h b/engines/twine/renderer/renderer.h
index 6cce4141e2..c6204d1145 100644
--- a/engines/twine/renderer/renderer.h
+++ b/engines/twine/renderer/renderer.h
@@ -185,16 +185,16 @@ private:
 
 	bool _isUsingOrthoProjection = false;
 
-	void renderPolygonsCopper(int vtop, int32 vsize, uint8 color) const;
-	void renderPolygonsBopper(int vtop, int32 vsize, uint8 color) const;
-	void renderPolygonsFlat(int vtop, int32 vsize, uint8 color) const;
-	void renderPolygonsTele(int vtop, int32 vsize, uint8 color) const;
-	void renderPolygonsTrans(int vtop, int32 vsize, uint8 color) const;
-	void renderPolygonsTrame(int vtop, int32 vsize, uint8 color) const;
+	void renderPolygonsCopper(int vtop, int32 vsize, uint16 color) const;
+	void renderPolygonsBopper(int vtop, int32 vsize, uint16 color) const;
+	void renderPolygonsFlat(int vtop, int32 vsize, uint16 color) const;
+	void renderPolygonsTele(int vtop, int32 vsize, uint16 color) const;
+	void renderPolygonsTrans(int vtop, int32 vsize, uint16 color) const;
+	void renderPolygonsTrame(int vtop, int32 vsize, uint16 color) const;
 	void renderPolygonsGouraud(int vtop, int32 vsize) const;
 	void renderPolygonsDither(int vtop, int32 vsize) const;
 	void renderPolygonsMarble(int vtop, int32 vsize, uint8 colorStart, uint8 colorEnd) const;
-	void renderPolygonsSimplified(int vtop, int32 vsize, uint8 color) const;
+	void renderPolygonsSimplified(int vtop, int32 vsize, uint16 color) const;
 	void computePolygons(int16 polyRenderType, const Vertex *vertices, int32 numVertices);
 
 	const RenderCommand *depthSortRenderCommands(int32 numOfPrimitives);


Commit: 1a6ac67be1f6afd6e39c09db2e77c978910e24e8
    https://github.com/scummvm/scummvm/commit/1a6ac67be1f6afd6e39c09db2e77c978910e24e8
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2021-10-10T11:52:39+02:00

Commit Message:
TWINE: todo comment

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


diff --git a/engines/twine/menu/menuoptions.cpp b/engines/twine/menu/menuoptions.cpp
index 31cb62cb5a..08e6f36af5 100644
--- a/engines/twine/menu/menuoptions.cpp
+++ b/engines/twine/menu/menuoptions.cpp
@@ -111,6 +111,7 @@ void MenuOptions::showCredits() {
 	_engine->_screens->clearScreen();
 
 	_engine->_input->enableKeyMap(uiKeyMapId);
+	// TODO: quitting the credits scene doesn't restore the menu texts
 }
 
 void MenuOptions::showEndSequence() {


Commit: 8296ad436f133a22e23cea088efcfbbab2312e0c
    https://github.com/scummvm/scummvm/commit/8296ad436f133a22e23cea088efcfbbab2312e0c
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2021-10-10T11:52:39+02:00

Commit Message:
TWINE: fixed restoring the menu texts after quitting the credits scene

when the credits scene is shown from the menu, we have to restore the proper
menu text - otherwise the scene text is still active

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


diff --git a/engines/twine/menu/menu.cpp b/engines/twine/menu/menu.cpp
index b123497ab6..2a24e6ad3d 100644
--- a/engines/twine/menu/menu.cpp
+++ b/engines/twine/menu/menu.cpp
@@ -591,6 +591,8 @@ int32 Menu::processMenu(MenuSettings *menuSettings, bool showCredits) {
 		}
 		if (showCredits && loopMillis - startMillis > 11650) {
 			_engine->_menuOptions->showCredits();
+			_engine->_text->initTextBank(TextBankId::Options_and_menus);
+
 			// TODO the original game also performs these actions:
 			// play FLA_DRAGON3 fla
 			// display RESSHQR_INTROSCREEN1IMG
diff --git a/engines/twine/menu/menuoptions.cpp b/engines/twine/menu/menuoptions.cpp
index 08e6f36af5..31cb62cb5a 100644
--- a/engines/twine/menu/menuoptions.cpp
+++ b/engines/twine/menu/menuoptions.cpp
@@ -111,7 +111,6 @@ void MenuOptions::showCredits() {
 	_engine->_screens->clearScreen();
 
 	_engine->_input->enableKeyMap(uiKeyMapId);
-	// TODO: quitting the credits scene doesn't restore the menu texts
 }
 
 void MenuOptions::showEndSequence() {


Commit: d8761a1bd03b7d0bf9673c54678d59988692a40b
    https://github.com/scummvm/scummvm/commit/d8761a1bd03b7d0bf9673c54678d59988692a40b
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2021-10-10T11:52:39+02:00

Commit Message:
TWINE: forward color as int16

because some of the polygon fill methods rely on the color value being a range
from start to end

Changed paths:
    engines/twine/parser/body.cpp
    engines/twine/parser/bodytypes.h
    engines/twine/renderer/renderer.cpp
    engines/twine/renderer/renderer.h


diff --git a/engines/twine/parser/body.cpp b/engines/twine/parser/body.cpp
index 40c1fe98b8..ed70811d1d 100644
--- a/engines/twine/parser/body.cpp
+++ b/engines/twine/parser/body.cpp
@@ -166,8 +166,7 @@ void BodyData::loadSpheres(Common::SeekableReadStream &stream) {
 	for (uint16 i = 0; i < numSpheres; ++i) {
 		BodySphere sphere;
 		sphere.fillType = stream.readByte();
-		sphere.colorStart = stream.readByte();
-		sphere.colorEnd = stream.readByte();
+		sphere.color = stream.readUint16LE();
 		stream.readByte();
 		sphere.radius = stream.readUint16LE();
 		sphere.vertex = stream.readUint16LE() / 6;
diff --git a/engines/twine/parser/bodytypes.h b/engines/twine/parser/bodytypes.h
index 53bb0061d4..4dc94cf40a 100644
--- a/engines/twine/parser/bodytypes.h
+++ b/engines/twine/parser/bodytypes.h
@@ -47,8 +47,7 @@ struct BodyLine {
 
 struct BodySphere {
 	uint8 fillType;
-	uint8 colorStart;
-	uint8 colorEnd;
+	uint16 color; // start and end color index
 	// fill byte here
 	int16 radius;
 	uint16 vertex;
diff --git a/engines/twine/renderer/renderer.cpp b/engines/twine/renderer/renderer.cpp
index 52ffb467cc..e01d8ed64e 100644
--- a/engines/twine/renderer/renderer.cpp
+++ b/engines/twine/renderer/renderer.cpp
@@ -921,7 +921,7 @@ void Renderer::renderPolygonsDither(int vtop, int32 vsize) const {
 	}
 }
 
-void Renderer::renderPolygonsMarble(int vtop, int32 vsize, uint8 colorStart, uint8 colorEnd) const {
+void Renderer::renderPolygonsMarble(int vtop, int32 vsize, uint16 color) const {
 	const int screenWidth = _engine->width();
 	const int screenHeight = _engine->height();
 
@@ -935,8 +935,8 @@ void Renderer::renderPolygonsMarble(int vtop, int32 vsize, uint8 colorStart, uin
 	int16 *pVerticG = ptr1;
 	int16 *pVerticD = &ptr1[screenHeight];
 
-	uint16 start = colorStart;
-	uint16 end = colorEnd;
+	uint16 start = (color & 0xFF) << 8;
+	uint16 end = color & 0xFF00;
 	uint16 delta = end - start + 1; // delta intensity
 	int32 step, dc;
 
@@ -951,7 +951,7 @@ void Renderer::renderPolygonsMarble(int vtop, int32 vsize, uint8 colorStart, uin
 			*pDest++ = (uint8)(end >> 8);
 		} else if (dc > 0) {
 			step = delta / (dc + 1);
-			uint16 color = start;
+			color = start;
 
 			for (; xMin <= xMax; xMin++) {
 				*pDest++ = (uint8)(color >> 8);
@@ -997,43 +997,43 @@ void Renderer::renderPolygons(const CmdRenderPolygon &polygon, Vertex *vertices,
 	computePolygons(polygon.renderType, vertices, polygon.numVertices);
 
 	const int32 vsize = vbottom - vtop + 1;
-	fillVertices(vtop, vsize, polygon.renderType, polygon.colorIndex, polygon.colorIndex);
+	fillVertices(vtop, vsize, polygon.renderType, polygon.colorIndex);
 }
 
-void Renderer::fillVertices(int vtop, int32 vsize, uint8 renderType, uint8 colorStart, uint8 colorEnd) {
+void Renderer::fillVertices(int vtop, int32 vsize, uint8 renderType, uint16 color) {
 	switch (renderType) {
 	case POLYGONTYPE_FLAT:
-		renderPolygonsFlat(vtop, vsize, colorStart);
+		renderPolygonsFlat(vtop, vsize, color);
 		break;
 	case POLYGONTYPE_TELE:
 		if (_engine->_cfgfile.PolygonDetails == 0) {
-			renderPolygonsFlat(vtop, vsize, colorStart);
+			renderPolygonsFlat(vtop, vsize, color);
 		} else {
-			renderPolygonsTele(vtop, vsize, colorStart);
+			renderPolygonsTele(vtop, vsize, color);
 		}
 		break;
 	case POLYGONTYPE_COPPER:
-		renderPolygonsCopper(vtop, vsize, colorStart);
+		renderPolygonsCopper(vtop, vsize, color);
 		break;
 	case POLYGONTYPE_BOPPER:
-		renderPolygonsBopper(vtop, vsize, colorStart);
+		renderPolygonsBopper(vtop, vsize, color);
 		break;
 	case POLYGONTYPE_TRANS:
-		renderPolygonsTrans(vtop, vsize, colorStart);
+		renderPolygonsTrans(vtop, vsize, color);
 		break;
 	case POLYGONTYPE_TRAME: // raster
-		renderPolygonsTrame(vtop, vsize, colorStart);
+		renderPolygonsTrame(vtop, vsize, color);
 		break;
 	case POLYGONTYPE_GOURAUD:
 		if (_engine->_cfgfile.PolygonDetails == 0) {
-			renderPolygonsSimplified(vtop, vsize, colorStart);
+			renderPolygonsSimplified(vtop, vsize, color);
 		} else {
 			renderPolygonsGouraud(vtop, vsize);
 		}
 		break;
 	case POLYGONTYPE_DITHER:
 		if (_engine->_cfgfile.PolygonDetails == 0) {
-			renderPolygonsSimplified(vtop, vsize, colorStart);
+			renderPolygonsSimplified(vtop, vsize, color);
 		} else if (_engine->_cfgfile.PolygonDetails == 1) {
 			renderPolygonsGouraud(vtop, vsize);
 		} else {
@@ -1041,7 +1041,7 @@ void Renderer::fillVertices(int vtop, int32 vsize, uint8 renderType, uint8 color
 		}
 		break;
 	case POLYGONTYPE_MARBLE:
-		renderPolygonsMarble(vtop, vsize, colorStart, colorEnd);
+		renderPolygonsMarble(vtop, vsize, color);
 		break;
 	default:
 		warning("RENDER WARNING: Unsupported render type %d", renderType);
@@ -1049,7 +1049,7 @@ void Renderer::fillVertices(int vtop, int32 vsize, uint8 renderType, uint8 color
 	}
 }
 
-bool Renderer::prepareCircle(int32 x, int32 y, int32 radius, uint8 colorStart, uint8 colorEnd) {
+bool Renderer::prepareCircle(int32 x, int32 y, int32 radius) {
 	if (radius <= 0) {
 		return false;
 	}
@@ -1148,8 +1148,7 @@ bool Renderer::prepareCircle(int32 x, int32 y, int32 radius, uint8 colorStart, u
 uint8 *Renderer::prepareSpheres(const Common::Array<BodySphere> &spheres, int32 &numOfPrimitives, RenderCommand **renderCmds, uint8 *renderBufferPtr, ModelData *modelData) {
 	for (const BodySphere &sphere : spheres) {
 		CmdRenderSphere *cmd = (CmdRenderSphere *)renderBufferPtr;
-		cmd->colorIndexStart = sphere.colorStart;
-		cmd->colorIndexEnd = sphere.colorEnd;
+		cmd->color = sphere.color;
 		cmd->polyRenderType = sphere.fillType;
 		cmd->radius = sphere.radius;
 		const int16 centerIndex = sphere.vertex;
@@ -1343,9 +1342,9 @@ bool Renderer::renderModelElements(int32 numOfPrimitives, const BodyData &bodyDa
 
 			radius -= 3;
 
-			if (prepareCircle(sphere->x, sphere->y, radius, sphere->colorIndexStart, sphere->colorIndexEnd)) {
+			if (prepareCircle(sphere->x, sphere->y, radius)) {
 				const int32 vsize = 2 * radius;
-				fillVertices(sphere->y - radius, vsize, sphere->polyRenderType, sphere->colorIndexStart, sphere->colorIndexEnd);
+				fillVertices(sphere->y - radius, vsize, sphere->polyRenderType, sphere->color);
 			}
 			break;
 		}
diff --git a/engines/twine/renderer/renderer.h b/engines/twine/renderer/renderer.h
index c6204d1145..ac19d0bfed 100644
--- a/engines/twine/renderer/renderer.h
+++ b/engines/twine/renderer/renderer.h
@@ -122,8 +122,7 @@ private:
 	 * @sa RenderCommand
 	 */
 	struct CmdRenderSphere {
-		uint8 colorIndexStart = 0;
-		uint8 colorIndexEnd = 0;
+		uint16 color = 0; // color start and end values
 		uint8 polyRenderType = 0;
 		int16 radius = 0;
 		int16 x = 0;
@@ -140,7 +139,7 @@ private:
 	ModelData _modelData;
 
 	bool renderAnimatedModel(ModelData *modelData, const BodyData &bodyData, RenderCommand *renderCmds, const IVec3 &angleVec, const IVec3 &renderPos, Common::Rect &modelRect);
-	bool prepareCircle(int32 x, int32 y, int32 radius, uint8 colorStart, uint8 colorEnd);
+	bool prepareCircle(int32 x, int32 y, int32 radius);
 	bool renderModelElements(int32 numOfPrimitives, const BodyData &bodyData, RenderCommand **renderCmds, ModelData *modelData, Common::Rect &modelRect);
 	IVec3 getCameraAnglePositions(int32 x, int32 y, int32 z);
 	inline IVec3 getCameraAnglePositions(const IVec3 &vec) {
@@ -193,7 +192,7 @@ private:
 	void renderPolygonsTrame(int vtop, int32 vsize, uint16 color) const;
 	void renderPolygonsGouraud(int vtop, int32 vsize) const;
 	void renderPolygonsDither(int vtop, int32 vsize) const;
-	void renderPolygonsMarble(int vtop, int32 vsize, uint8 colorStart, uint8 colorEnd) const;
+	void renderPolygonsMarble(int vtop, int32 vsize, uint16 color) const;
 	void renderPolygonsSimplified(int vtop, int32 vsize, uint16 color) const;
 	void computePolygons(int16 polyRenderType, const Vertex *vertices, int32 numVertices);
 
@@ -226,7 +225,7 @@ public:
 		return getBaseRotationPosition(vec.x, vec.y, vec.z);
 	}
 
-	void fillVertices(int vtop, int32 vsize, uint8 renderType, uint8 colorStart, uint8 colorEnd);
+	void fillVertices(int vtop, int32 vsize, uint8 renderType, uint16 color);
 	void renderPolygons(const CmdRenderPolygon &polygon, Vertex *vertices, int vtop, int vbottom);
 
 	inline IVec3 &projectPositionOnScreen(const IVec3& pos) {




More information about the Scummvm-git-logs mailing list