[Scummvm-git-logs] scummvm branch-2-7 -> 8b1448d70dc765eb2d2370f17ff16752b2fc5f3e

neuromancer noreply at scummvm.org
Mon Mar 20 10:08:08 UTC 2023


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

Summary:
486a6de365 FREESCAPE: refactor to use executeMovementConditions instead of executeLocalGlobalConditions directly
cf2e7ef2e6 FREESCAPE: read strings from dark EGA releases (and demo)
ad46a1dd29 FREESCAPE: refactor game bits handling and set bit 31 when colliding
cc0832e739 FREESCAPE: improve dark UI for dos release and demo
8b0cfe0f4b FREESCAPE: implemented area connections in dark
d207536738 FREESCAPE: implemented fullscreen messages in dark dos demo
875940674e FREESCAPE: load some? global objects in dark for dos (and demo)
7b307e562b FREESCAPE: drafted code that reads title image of driller US release for DOS
523bc141fe FREESCAPE: initial implementation of image parsing for title/borders in driller
2e652a9861 FREESCAPE: load title/borders images in driller dos directly from the game data
05f7253af3 FREESCAPE: load title/borders images in driller EGA directly from the game data
cc42bc2efb FREESCAPE: load title/borders images in dark side EGA (and demo) directly from the game data
76c2a780a4 FREESCAPE: load title/borders images in total eclipse EGA directly from the game data
94c52bf7bf FREESCAPE: implemented scr image loader and read title/borders images in driller for zx directly from the game data
71e6e2b1f1 FREESCAPE: renamed game data file for driller detection in several platforms
a62b58adca FREESCAPE: small adjustments for driller ui for zx
752d202f46 FREESCAPE: refactored deobfuscation code for driller cpc
11dfbe8b72 FREESCAPE: fixed image loader and read title in driller for ega and updated freescape.dat
caa6e9c104 FREESCAPE: refactored driller dos code into a directory
fa75a25946 FREESCAPE: refactored driller cpc code into a directory
563c6b35bd FREESCAPE: refactored driller zx code into a directory
3e5d0a3ad0 FREESCAPE: refactored driller amiga/atari code into a directory
6ae0763ee4 FREESCAPE: refactored/moved driller code for loading assets in different platforms code
edc1322b0b FREESCAPE: refactored/moved driller code specific for the atari release
c22636621e FREESCAPE: fixed artifacts when using stipple effect in opengl
366c5c6bba FREESCAPE: fixed _lastMinute initialization for driller amiga/atari
e539c32167 FREESCAPE: simplified loading of data files in driller cpc
8a0acc1440 FREESCAPE: enable some spfx effects for different platforms (zx, cpc)
8227c50b44 FREESCAPE: use managed surfaces for border and title images
9b0f5b3de3 FREESCAPE: allow to change the palette of title and border per level using managed surfaces
d909a548e4 FREESCAPE: load original images and adjust ui for driller cpc
4633fd4874 FREESCAPE: load correct border palette for certain driller releases
6dc129dc34 FREESCAPE: color and ui fixes for driller cpc
c77e280500 FREESCAPE: correctly parse images in dos driller demo and removed extra files from freescape.dat
ef1a07d8f5 FREESCAPE: removed edsk related code to parse cpc releases of driller
cc7bb7d660 FREESCAPE: load and show driller dos demo title image
b4f7bc818d FREESCAPE: moved dark side related code to its own directory
82813e11d6 FREESCAPE: moved some functions to the main freescape class and reorganized game code
98a2bbb4f0 FREESCAPE: moved more functions to the main freescape class and reorganized game code
3b135c9ed8 FREESCAPE: moved code from dark dos release into its dedicated file
0154df5c8b FREESCAPE: simplified driller cpc color handling code
35492b4673 FREESCAPE: commented unused variable
55ae8e4096 FREESCAPE: pregenerate and show stipple patterns for driller in zx, cpc and cga
3dfd360667 FREESCAPE: improved stipple generation
e6b033b409 FREESCAPE: improved and optimized stipple pattern usage
59cae6551a FREESCAPE: avoid crash selecting a missing palette in driller demo for amiga/atari
8b1448d70d FREESCAPE: disallow crossair to be outside the view area


Commit: 486a6de365539d92ee77ad4b05f1e0b9dc66a2f3
    https://github.com/scummvm/scummvm/commit/486a6de365539d92ee77ad4b05f1e0b9dc66a2f3
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-03-20T09:11:45+01:00

Commit Message:
FREESCAPE: refactor to use executeMovementConditions instead of executeLocalGlobalConditions directly

Changed paths:
    engines/freescape/freescape.cpp
    engines/freescape/freescape.h
    engines/freescape/games/dark.cpp
    engines/freescape/movement.cpp


diff --git a/engines/freescape/freescape.cpp b/engines/freescape/freescape.cpp
index af8278fcbca..c542f5ab4d6 100644
--- a/engines/freescape/freescape.cpp
+++ b/engines/freescape/freescape.cpp
@@ -517,6 +517,11 @@ void FreescapeEngine::processInput() {
 	}
 }
 
+void FreescapeEngine::executeMovementConditions() {
+	// Only execute "on collision" room/global conditions
+	executeLocalGlobalConditions(false, true);
+}
+
 void FreescapeEngine::updateTimeVariables() {
 	int seconds, minutes, hours;
 	getTimeFromCountdown(seconds, minutes, hours);
diff --git a/engines/freescape/freescape.h b/engines/freescape/freescape.h
index b4641f73912..5747f2825aa 100644
--- a/engines/freescape/freescape.h
+++ b/engines/freescape/freescape.h
@@ -237,6 +237,7 @@ public:
 
 	bool checkCollisions(bool executeCode);
 	Math::Vector3d _objExecutingCodeSize;
+	virtual void executeMovementConditions();
 	void executeObjectConditions(GeometricObject *obj, bool shot, bool collided);
 	void executeLocalGlobalConditions(bool shot, bool collided);
 	void executeCode(FCLInstructionVector &code, bool shot, bool collided);
@@ -356,7 +357,7 @@ public:
 	int _lastMinute;
 
 	void getTimeFromCountdown(int &seconds, int &minutes, int &hours);
-	void updateTimeVariables();
+	virtual void updateTimeVariables();
 
 	// Cheats
 	bool _useExtendedTimer;
@@ -438,11 +439,16 @@ public:
 	DarkEngine(OSystem *syst, const ADGameDescription *gd);
 
 	void loadAssets() override;
+	void initGameState() override;
+
 	void gotoArea(uint16 areaID, int entranceID) override;
 	void pressedKey(const int keycode) override;
 
 	void loadAssetsDemo();
 	void loadAssetsFullGame();
+	int _lastTenSeconds;
+	void updateTimeVariables() override;
+	void executeMovementConditions() override;
 
 	void drawUI() override;
 	Common::Error saveGameStreamExtended(Common::WriteStream *stream, bool isAutosave = false) override;
diff --git a/engines/freescape/games/dark.cpp b/engines/freescape/games/dark.cpp
index cf338790f29..55d33f0bead 100644
--- a/engines/freescape/games/dark.cpp
+++ b/engines/freescape/games/dark.cpp
@@ -35,6 +35,7 @@ DarkEngine::DarkEngine(OSystem *syst, const ADGameDescription *gd) : FreescapeEn
 	_playerHeight = _playerHeights[_playerHeightNumber];
 	_playerWidth = 12;
 	_playerDepth = 32;
+	_lastTenSeconds = -1;
 }
 
 void DarkEngine::loadAssets() {
@@ -67,6 +68,31 @@ void DarkEngine::loadAssetsDemo() {
 		error("Invalid or unsupported render mode %s for Dark Side", Common::getRenderModeDescription(_renderMode));
 }
 
+void DarkEngine::initGameState() {
+	_flyMode = false;
+	_noClipMode = false;
+	_shootingFrames = 0;
+	_underFireFrames = 0;
+	_yaw = 0;
+	_pitch = 0;
+
+	for (int i = 0; i < k8bitMaxVariable; i++) // TODO: check maximum variable
+		_gameStateVars[i] = 0;
+
+	for (auto &it : _areaMap) {
+		it._value->resetArea();
+		_gameStateBits[it._key] = 0;
+	}
+
+	_playerHeightNumber = 1;
+	_playerHeight = _playerHeights[_playerHeightNumber];
+	removeTimers();
+	startCountdown(_initialCountdown);
+	_lastMinute = 0;
+	_demoIndex = 0;
+	_demoEvents.clear();
+}
+
 void DarkEngine::loadAssetsFullGame() {
 	Common::File file;
 	if (_renderMode == Common::kRenderEGA) {
@@ -155,6 +181,30 @@ void DarkEngine::pressedKey(const int keycode) {
 	}
 }
 
+void DarkEngine::executeMovementConditions() {
+	// Only execute "on collision" room/global conditions
+	if (_currentArea->getAreaFlags() == 1)
+		executeLocalGlobalConditions(false, true);
+}
+
+void DarkEngine::updateTimeVariables() {
+	// This function only executes "on collision" room/global conditions
+	int seconds, minutes, hours;
+	getTimeFromCountdown(seconds, minutes, hours);
+	if (_lastTenSeconds != seconds / 10) {
+		_lastTenSeconds = seconds / 10;
+		if (_currentArea->getAreaFlags() == 0)
+			executeLocalGlobalConditions(false, true);
+	}
+
+	if (_lastMinute != minutes) {
+		_lastMinute = minutes;
+		_gameStateVars[0x1e] += 1;
+		_gameStateVars[0x1f] += 1;
+		executeLocalGlobalConditions(false, true);
+	}
+}
+
 void DarkEngine::drawUI() {
 	uint32 gray = _gfx->_texturePixelFormat.ARGBToColor(0x00, 0xA0, 0xA0, 0xA0);
 	uint32 yellow = _gfx->_texturePixelFormat.ARGBToColor(0xFF, 0xFF, 0xFF, 0x55);
diff --git a/engines/freescape/movement.cpp b/engines/freescape/movement.cpp
index d3db2059aaf..69f7c3b1561 100644
--- a/engines/freescape/movement.cpp
+++ b/engines/freescape/movement.cpp
@@ -149,7 +149,7 @@ void FreescapeEngine::rise() {
 
 	_lastPosition = _position;
 	debugC(1, kFreescapeDebugMove, "new player position: %f, %f, %f", _position.x(), _position.y(), _position.z());
-	executeLocalGlobalConditions(false, true); // Only execute "on collision" room/global conditions
+	executeMovementConditions();
 }
 
 void FreescapeEngine::lower() {
@@ -174,7 +174,7 @@ void FreescapeEngine::lower() {
 
 	_lastPosition = _position;
 	debugC(1, kFreescapeDebugMove, "new player position: %f, %f, %f", _position.x(), _position.y(), _position.z());
-	executeLocalGlobalConditions(false, true); // Only execute "on collision" room/global conditions
+	executeMovementConditions();
 }
 
 void FreescapeEngine::move(CameraMovement direction, uint8 scale, float deltaTime) {
@@ -267,7 +267,7 @@ void FreescapeEngine::move(CameraMovement direction, uint8 scale, float deltaTim
 	debugC(1, kFreescapeDebugMove, "new player position: %f, %f, %f", _position.x(), _position.y(), _position.z());
 	//debugC(1, kFreescapeDebugMove, "player height: %f", _position.y() - areaScale * _playerHeight);
 	if (_currentArea->getAreaID() == previousAreaID)
-		executeLocalGlobalConditions(false, true); // Only execute "on collision" room/global conditions
+		executeMovementConditions();
 }
 
 bool FreescapeEngine::checkFloor(Math::Vector3d currentPosition) {


Commit: cf2e7ef2e66cbab6719b45a84b7b03135e29f39f
    https://github.com/scummvm/scummvm/commit/cf2e7ef2e66cbab6719b45a84b7b03135e29f39f
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-03-20T09:11:58+01:00

Commit Message:
FREESCAPE: read strings from dark EGA releases (and demo)

Changed paths:
    engines/freescape/games/dark.cpp


diff --git a/engines/freescape/games/dark.cpp b/engines/freescape/games/dark.cpp
index 55d33f0bead..70307ccc113 100644
--- a/engines/freescape/games/dark.cpp
+++ b/engines/freescape/games/dark.cpp
@@ -53,7 +53,7 @@ void DarkEngine::loadAssetsDemo() {
 
 		if (!file.isOpen())
 			error("Failed to open DSIDEE.EXE");
-
+		loadMessagesFixedSize(&file, 0x4525, 16, 27);
 		loadFonts(&file, 0xa598);
 		load8bitBinary(&file, 0xa700, 16);
 	} else if (isDOS() && _renderMode == Common::kRenderCGA) {
@@ -103,6 +103,7 @@ void DarkEngine::loadAssetsFullGame() {
 			error("Failed to open DSIDEE.EXE");
 
 		loadFonts(&file, 0xa113);
+		loadMessagesFixedSize(&file, 0x4525, 16, 27);
 		load8bitBinary(&file, 0xa280, 16);
 	} else if (_renderMode == Common::kRenderCGA) {
 		loadBundledImages();


Commit: ad46a1dd2921a44035ee400a1375c2085911a5fa
    https://github.com/scummvm/scummvm/commit/ad46a1dd2921a44035ee400a1375c2085911a5fa
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-03-20T09:12:06+01:00

Commit Message:
FREESCAPE: refactor game bits handling and set bit 31 when colliding

Changed paths:
    engines/freescape/freescape.cpp
    engines/freescape/freescape.h
    engines/freescape/language/instruction.cpp
    engines/freescape/movement.cpp


diff --git a/engines/freescape/freescape.cpp b/engines/freescape/freescape.cpp
index c542f5ab4d6..f02e22ff73f 100644
--- a/engines/freescape/freescape.cpp
+++ b/engines/freescape/freescape.cpp
@@ -645,6 +645,19 @@ bool FreescapeEngine::checkIfGameEnded() {
 	return false; // TODO
 }
 
+void FreescapeEngine::setGameBit(int index) {
+	_gameStateBits[_currentArea->getAreaID()] |= (1 << (index - 1));
+}
+
+void FreescapeEngine::clearGameBit(int index) {
+	_gameStateBits[_currentArea->getAreaID()] &= ~(1 << (index - 1));
+}
+
+void FreescapeEngine::toggleGameBit(int index) {
+	_gameStateBits[_currentArea->getAreaID()] ^= (1 << (index - 1));
+}
+
+
 void FreescapeEngine::initGameState() {
 	for (int i = 0; i < k8bitMaxVariable; i++) // TODO: check maximum variable
 		_gameStateVars[i] = 0;
diff --git a/engines/freescape/freescape.h b/engines/freescape/freescape.h
index 5747f2825aa..8403333de22 100644
--- a/engines/freescape/freescape.h
+++ b/engines/freescape/freescape.h
@@ -325,6 +325,10 @@ public:
 
 	// Game state
 	virtual void initGameState();
+	void setGameBit(int index);
+	void clearGameBit(int index);
+	void toggleGameBit(int index);
+
 	StateVars _gameStateVars;
 	StateBits _gameStateBits;
 	virtual bool checkIfGameEnded();
diff --git a/engines/freescape/language/instruction.cpp b/engines/freescape/language/instruction.cpp
index ef9e656ffa9..3389ca99493 100644
--- a/engines/freescape/language/instruction.cpp
+++ b/engines/freescape/language/instruction.cpp
@@ -446,23 +446,23 @@ void FreescapeEngine::executeGoto(FCLInstruction &instruction) {
 }
 
 void FreescapeEngine::executeSetBit(FCLInstruction &instruction) {
-	uint16 index = instruction._source - 1; // Starts in 1
-	assert(index < 32);
-	_gameStateBits[_currentArea->getAreaID()] |= (1 << index);
+	uint16 index = instruction._source; // Starts at 1
+	assert(index > 0 && index <= 32);
+	setGameBit(index);
 	debugC(1, kFreescapeDebugCode, "Setting bit %d", index);
-	// debug("v: %d", (_gameStateBits[_currentArea->getAreaID()] & (1 << index)));
 }
 
 void FreescapeEngine::executeClearBit(FCLInstruction &instruction) {
-	uint16 index = instruction._source - 1; // Starts in 1
-	assert(index < 32);
-	_gameStateBits[_currentArea->getAreaID()] &= ~(1 << index);
+	uint16 index = instruction._source; // Starts at 1
+	assert(index > 0 && index <= 32);
+	clearGameBit(index);
 	debugC(1, kFreescapeDebugCode, "Clearing bit %d", index);
 }
 
 void FreescapeEngine::executeToggleBit(FCLInstruction &instruction) {
-	uint16 index = instruction._source - 1; // Starts in 1
-	_gameStateBits[_currentArea->getAreaID()] ^= (1 << index);
+	uint16 index = instruction._source; // Starts at 1
+	assert(index > 0 && index <= 32);
+	toggleGameBit(index);
 	debugC(1, kFreescapeDebugCode, "Toggling bit %d", index);
 }
 
diff --git a/engines/freescape/movement.cpp b/engines/freescape/movement.cpp
index 69f7c3b1561..35e537ff8d2 100644
--- a/engines/freescape/movement.cpp
+++ b/engines/freescape/movement.cpp
@@ -239,10 +239,12 @@ void FreescapeEngine::move(CameraMovement direction, uint8 scale, float deltaTim
 				playSound(3, false);
 		}
 		debugC(1, kFreescapeDebugCode, "Runing effects:");
+		if (_flyMode)
+			setGameBit(31);
 		checkCollisions(true); // run the effects
 	} else {
 		debugC(1, kFreescapeDebugCode, "Runing effects: at: %f, %f, %f", _position.x(), _position.y(), _position.z());
-
+		setGameBit(31);
 		checkCollisions(true); // run the effects
 		if (_currentArea->getAreaID() == previousAreaID) {
 			if (_flyMode)
@@ -268,6 +270,7 @@ void FreescapeEngine::move(CameraMovement direction, uint8 scale, float deltaTim
 	//debugC(1, kFreescapeDebugMove, "player height: %f", _position.y() - areaScale * _playerHeight);
 	if (_currentArea->getAreaID() == previousAreaID)
 		executeMovementConditions();
+	clearGameBit(31);
 }
 
 bool FreescapeEngine::checkFloor(Math::Vector3d currentPosition) {


Commit: cc0832e739ec82b4a4c5e4f2af47a82c22f15e13
    https://github.com/scummvm/scummvm/commit/cc0832e739ec82b4a4c5e4f2af47a82c22f15e13
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-03-20T09:12:18+01:00

Commit Message:
FREESCAPE: improve dark UI for dos release and demo

Changed paths:
    engines/freescape/freescape.h
    engines/freescape/games/dark.cpp
    engines/freescape/loaders/8bitBinaryLoader.cpp


diff --git a/engines/freescape/freescape.h b/engines/freescape/freescape.h
index 8403333de22..1ac2e84d572 100644
--- a/engines/freescape/freescape.h
+++ b/engines/freescape/freescape.h
@@ -442,6 +442,9 @@ class DarkEngine : public FreescapeEngine {
 public:
 	DarkEngine(OSystem *syst, const ADGameDescription *gd);
 
+	uint32 _initialFuel;
+	uint32 _initialShield;
+
 	void loadAssets() override;
 	void initGameState() override;
 
@@ -455,6 +458,7 @@ public:
 	void executeMovementConditions() override;
 
 	void drawUI() override;
+	void drawDOSUI(Graphics::Surface *surface);
 	Common::Error saveGameStreamExtended(Common::WriteStream *stream, bool isAutosave = false) override;
 	Common::Error loadGameStreamExtended(Common::SeekableReadStream *stream) override;
 };
diff --git a/engines/freescape/games/dark.cpp b/engines/freescape/games/dark.cpp
index 70307ccc113..55dfb12d2a8 100644
--- a/engines/freescape/games/dark.cpp
+++ b/engines/freescape/games/dark.cpp
@@ -36,6 +36,16 @@ DarkEngine::DarkEngine(OSystem *syst, const ADGameDescription *gd) : FreescapeEn
 	_playerWidth = 12;
 	_playerDepth = 32;
 	_lastTenSeconds = -1;
+
+	_angleRotations.push_back(5);
+	_angleRotations.push_back(10);
+	_angleRotations.push_back(15);
+	_angleRotations.push_back(30);
+	_angleRotations.push_back(45);
+	_angleRotations.push_back(90);
+
+	_initialFuel = 11;
+	_initialShield = 15;
 }
 
 void DarkEngine::loadAssets() {
@@ -84,6 +94,9 @@ void DarkEngine::initGameState() {
 		_gameStateBits[it._key] = 0;
 	}
 
+	_gameStateVars[k8bitVariableEnergy] = _initialFuel;
+	_gameStateVars[k8bitVariableShield] = _initialShield;
+
 	_playerHeightNumber = 1;
 	_playerHeight = _playerHeights[_playerHeightNumber];
 	removeTimers();
@@ -206,13 +219,73 @@ void DarkEngine::updateTimeVariables() {
 	}
 }
 
-void DarkEngine::drawUI() {
-	uint32 gray = _gfx->_texturePixelFormat.ARGBToColor(0x00, 0xA0, 0xA0, 0xA0);
-	uint32 yellow = _gfx->_texturePixelFormat.ARGBToColor(0xFF, 0xFF, 0xFF, 0x55);
-	uint32 black = _gfx->_texturePixelFormat.ARGBToColor(0xFF, 0x00, 0x00, 0x00);
+void DarkEngine::drawDOSUI(Graphics::Surface *surface) {
+	uint32 color = _renderMode == Common::kRenderCGA ? 1 : 14;
+	uint8 r, g, b;
+
+	_gfx->readFromPalette(color, r, g, b);
+	uint32 front = _gfx->_texturePixelFormat.ARGBToColor(0xFF, r, g, b);
+
+	color = _currentArea->_usualBackgroundColor;
+	if (_gfx->_colorRemaps && _gfx->_colorRemaps->contains(color)) {
+		color = (*_gfx->_colorRemaps)[color];
+	}
+
+	_gfx->readFromPalette(color, r, g, b);
+	uint32 back = _gfx->_texturePixelFormat.ARGBToColor(0xFF, r, g, b);
+
+	int score = _gameStateVars[k8bitVariableScore];
+	drawStringInSurface(Common::String::format("%04d", int(2 * _position.x())), 199, 137, front, back, surface);
+	drawStringInSurface(Common::String::format("%04d", int(2 * _position.z())), 199, 145, front, back, surface);
+	drawStringInSurface(Common::String::format("%04d", int(2 * _position.y())), 199, 153, front, back, surface);
+
+	drawStringInSurface(Common::String::format("%02d", int(_angleRotations[_angleRotationIndex])), 71, 168, front, back, surface);
+	drawStringInSurface(Common::String::format("%3d", _playerSteps[_playerStepIndex]), 71, 177, front, back, surface);
+	drawStringInSurface(Common::String::format("%07d", score), 95, 8, front, back, surface);
+
+	int seconds, minutes, hours;
+	getTimeFromCountdown(seconds, minutes, hours);
+	// TODO: implement binary clock
+
+	Common::String message;
+	int deadline;
+	getLatestMessages(message, deadline);
+	if (deadline <= _countdown) {
+		drawStringInSurface(message, 112, 177, back, front, surface);
+		_temporaryMessages.push_back(message);
+		_temporaryMessageDeadlines.push_back(deadline);
+	} else
+		drawStringInSurface(_currentArea->_name, 112, 177, front, back, surface);
+
+	int energy = _gameStateVars[k8bitVariableEnergy]; // called fuel in this game
+	int shield = _gameStateVars[k8bitVariableShield];
+
+	_gfx->readFromPalette(9, r, g, b);
+	uint32 blue = _gfx->_texturePixelFormat.ARGBToColor(0xFF, r, g, b);
+
+	if (shield >= 0) {
+		Common::Rect shieldBar;
+		shieldBar = Common::Rect(72, 139, 151 - (k8bitMaxShield - shield), 146);
+		surface->fillRect(shieldBar, front);
+
+		shieldBar = Common::Rect(72, 140, 151 - (k8bitMaxShield - shield), 145);
+		surface->fillRect(shieldBar, blue);
+	}
+
+	if (energy >= 0) {
+		Common::Rect energyBar;
+		energyBar = Common::Rect(72, 147, 151 - (k8bitMaxEnergy - energy), 154);
+		surface->fillRect(energyBar, front);
 
+		energyBar = Common::Rect(72, 148, 151 - (k8bitMaxEnergy - energy), 153);
+		surface->fillRect(energyBar, blue);
+	}
+}
+
+void DarkEngine::drawUI() {
 	Graphics::Surface *surface = nullptr;
-	if (_border) {
+	if (_border) { // This can be removed when all the borders are loaded
+		uint32 gray = _gfx->_texturePixelFormat.ARGBToColor(0x00, 0xA0, 0xA0, 0xA0);
 		surface = new Graphics::Surface();
 		surface->create(_screenW, _screenH, _gfx->_texturePixelFormat);
 		surface->fillRect(_fullscreenViewArea, gray);
@@ -220,14 +293,10 @@ void DarkEngine::drawUI() {
 	} else
 		return;
 
-	if (_currentAreaMessages.size() == 1) {
-		int score = _gameStateVars[k8bitVariableScore];
-		drawStringInSurface(_currentAreaMessages[0], 112, 177, yellow, black, surface);
-		drawStringInSurface(Common::String::format("%04d", 2 * int(_position.x())), 199, 137, yellow, black, surface);
-		drawStringInSurface(Common::String::format("%04d", 2 * int(_position.z())), 199, 145, yellow, black, surface);
-		drawStringInSurface(Common::String::format("%04d", 2 * int(_position.y())), 199, 153, yellow, black, surface);
-		drawStringInSurface(Common::String::format("%07d", score), 95, 8, yellow, black, surface);
-	}
+	if (isDOS())
+		drawDOSUI(surface);
+	else
+		error("UI not implemented yet");
 
 	if (!_uiTexture)
 		_uiTexture = _gfx->createTexture(surface);
diff --git a/engines/freescape/loaders/8bitBinaryLoader.cpp b/engines/freescape/loaders/8bitBinaryLoader.cpp
index ff395a1a2ce..80a5e6b6fbb 100644
--- a/engines/freescape/loaders/8bitBinaryLoader.cpp
+++ b/engines/freescape/loaders/8bitBinaryLoader.cpp
@@ -438,6 +438,15 @@ void FreescapeEngine::load8bitBinary(Common::SeekableReadStream *file, int offse
 	debugC(1, kFreescapeDebugParser, "Start area: %d", startArea);
 	uint8 startEntrance = readField(file, 8);
 	debugC(1, kFreescapeDebugParser, "Entrace area: %d", startEntrance);
+	readField(file, 8); // Unknown
+
+	uint8 initialEnergy1 = readField(file, 8);
+	uint8 initialShield1 = readField(file, 8);
+	uint8 initialEnergy2 = readField(file, 8);
+	uint8 initialShield2 = readField(file, 8);
+
+	debugC(1, kFreescapeDebugParser, "Initial levels of energy: %d and shield: %d", initialEnergy1, initialShield1);
+	debugC(1, kFreescapeDebugParser, "Initial levels of energy: %d and shield: %d", initialEnergy2, initialShield2);
 
 	if (isAmiga() || isAtariST())
 		file->seek(offset + 0x14);


Commit: 8b0cfe0f4be35b9237a593f2bcd19a9d047a19d7
    https://github.com/scummvm/scummvm/commit/8b0cfe0f4be35b9237a593f2bcd19a9d047a19d7
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-03-20T09:12:28+01:00

Commit Message:
FREESCAPE: implemented area connections in dark

Changed paths:
  A engines/freescape/objects/connections.h
    engines/freescape/freescape.h
    engines/freescape/games/dark.cpp
    engines/freescape/loaders/8bitBinaryLoader.cpp
    engines/freescape/movement.cpp


diff --git a/engines/freescape/freescape.h b/engines/freescape/freescape.h
index 1ac2e84d572..a7ec3096b61 100644
--- a/engines/freescape/freescape.h
+++ b/engines/freescape/freescape.h
@@ -187,6 +187,7 @@ public:
 	void generateDemoInput();
 	virtual void pressedKey(const int keycode);
 	void move(CameraMovement direction, uint8 scale, float deltaTime);
+	virtual void checkIfStillInArea();
 	void changePlayerHeight(int index);
 	void increaseStepSize();
 	void decreaseStepSize();
@@ -449,6 +450,7 @@ public:
 	void initGameState() override;
 
 	void gotoArea(uint16 areaID, int entranceID) override;
+	void checkIfStillInArea() override;
 	void pressedKey(const int keycode) override;
 
 	void loadAssetsDemo();
diff --git a/engines/freescape/games/dark.cpp b/engines/freescape/games/dark.cpp
index 55dfb12d2a8..60e1b86bfd0 100644
--- a/engines/freescape/games/dark.cpp
+++ b/engines/freescape/games/dark.cpp
@@ -23,6 +23,7 @@
 
 #include "freescape/freescape.h"
 #include "freescape/language/8bitDetokeniser.h"
+#include "freescape/objects/connections.h"
 
 namespace Freescape {
 
@@ -195,6 +196,30 @@ void DarkEngine::pressedKey(const int keycode) {
 	}
 }
 
+void DarkEngine::checkIfStillInArea() {
+	AreaConnections *cons = (AreaConnections *)_currentArea->entranceWithID(254);
+	if (!cons) {
+		FreescapeEngine::checkIfStillInArea();
+		return;
+	}
+
+	int nextAreaID = 0;
+
+	if (_position.z() >= 4064 - 16)
+		nextAreaID = cons->_connections[1];
+	else if (_position.x() >= 4064 - 16)
+		nextAreaID = cons->_connections[3];
+	else if (_position.z() <= 16)
+		nextAreaID = cons->_connections[5];
+	else if (_position.x() <= 16)
+		nextAreaID = cons->_connections[7];
+
+	if (nextAreaID > 0)
+		gotoArea(nextAreaID, 0);
+	else
+		FreescapeEngine::checkIfStillInArea();
+}
+
 void DarkEngine::executeMovementConditions() {
 	// Only execute "on collision" room/global conditions
 	if (_currentArea->getAreaFlags() == 1)
diff --git a/engines/freescape/loaders/8bitBinaryLoader.cpp b/engines/freescape/loaders/8bitBinaryLoader.cpp
index 80a5e6b6fbb..b0b2edefc0c 100644
--- a/engines/freescape/loaders/8bitBinaryLoader.cpp
+++ b/engines/freescape/loaders/8bitBinaryLoader.cpp
@@ -26,6 +26,7 @@
 
 #include "freescape/freescape.h"
 #include "freescape/language/8bitDetokeniser.h"
+#include "freescape/objects/connections.h"
 #include "freescape/objects/global.h"
 #include "freescape/objects/group.h"
 #include "freescape/objects/sensor.h"
@@ -115,6 +116,21 @@ Object *FreescapeEngine::load8bitObject(Common::SeekableReadStream *file) {
 		while(--byteSizeOfObject > 0)
 			structureArray.push_back(file->readByte());
 		return new GlobalStructure(structureArray);
+	} else if (objectID == 254 && objectType == ObjectType::kEntranceType) {
+		debugC(1, kFreescapeDebugParser, "Found the area connections (objectID: 254 with size %d)", byteSizeOfObject + 6);
+		Common::Array<uint8> connectionsArray;
+		connectionsArray.push_back(uint8(position.x()));
+		connectionsArray.push_back(uint8(position.y()));
+		connectionsArray.push_back(uint8(position.z()));
+
+		connectionsArray.push_back(uint8(v.x()));
+		connectionsArray.push_back(uint8(v.y()));
+		connectionsArray.push_back(uint8(v.z()));
+
+		byteSizeOfObject++;
+		while(--byteSizeOfObject > 0)
+			connectionsArray.push_back(file->readByte());
+		return new AreaConnections(connectionsArray);
 	}
 
 	debugC(1, kFreescapeDebugParser, "Object %d ; type %d ; size %d", objectID, (int)objectType, byteSizeOfObject);
diff --git a/engines/freescape/movement.cpp b/engines/freescape/movement.cpp
index 35e537ff8d2..c9055e80248 100644
--- a/engines/freescape/movement.cpp
+++ b/engines/freescape/movement.cpp
@@ -177,6 +177,17 @@ void FreescapeEngine::lower() {
 	executeMovementConditions();
 }
 
+void FreescapeEngine::checkIfStillInArea() {
+	for (int i = 0; i < 3; i++) {
+		if (_position.getValue(i) < 0)
+			_position.setValue(i, 0);
+		else if (_position.getValue(i) > 8128)
+			_position.setValue(i, 8128);
+	}
+	if (_position.y() >= 2016)
+		_position.y() = _lastPosition.z();
+}
+
 void FreescapeEngine::move(CameraMovement direction, uint8 scale, float deltaTime) {
 	debugC(1, kFreescapeDebugMove, "old player position: %f, %f, %f", _position.x(), _position.y(), _position.z());
 	int previousAreaID = _currentArea->getAreaID();
@@ -207,14 +218,9 @@ void FreescapeEngine::move(CameraMovement direction, uint8 scale, float deltaTim
 	if (!_flyMode)
 		_position.set(_position.x(), positionY, _position.z());
 
-	for (int i = 0; i < 3; i++) {
-		if (_position.getValue(i) < 0)
-			_position.setValue(i, 0);
-		else if (_position.getValue(i) > 8128)
-			_position.setValue(i, 8128);
-	}
-	if (_position.y() >= 2016)
-		_position.y() = _lastPosition.z();
+	checkIfStillInArea();
+	if (_currentArea->getAreaID() != previousAreaID)
+		return;
 
 	bool collided = checkCollisions(false);
 
diff --git a/engines/freescape/objects/connections.h b/engines/freescape/objects/connections.h
new file mode 100644
index 00000000000..75e705fcceb
--- /dev/null
+++ b/engines/freescape/objects/connections.h
@@ -0,0 +1,45 @@
+/* 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 3 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, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef FREESCAPE_CONNECTIONS_H
+#define FREESCAPE_CONNECTIONS_H
+
+#include "freescape/objects/object.h"
+
+namespace Freescape {
+
+class AreaConnections : public Object {
+public:
+	Common::Array<byte> _connections;
+	AreaConnections(const Common::Array<byte> connections_) {
+		_objectID = 254;
+		_connections = connections_;
+	}
+
+	ObjectType getType() override { return ObjectType::kEntranceType; };
+	void draw(Freescape::Renderer *gfx) override { error("cannot render AreaConnections"); };
+	void scale(int factor) override { warning("cannot scale AreaConnections"); };
+	Object *duplicate() override { error("cannot duplicate AreaConnections"); };
+};
+
+} // End of namespace Freescape
+
+#endif // FREESCAPE_CONNECTIONS_H
\ No newline at end of file


Commit: d2075367385609ec049a3715c4934e2c79c95e2d
    https://github.com/scummvm/scummvm/commit/d2075367385609ec049a3715c4934e2c79c95e2d
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-03-20T09:12:47+01:00

Commit Message:
FREESCAPE: implemented fullscreen messages in dark dos demo

Changed paths:
    engines/freescape/freescape.h
    engines/freescape/games/dark.cpp
    engines/freescape/loaders/8bitBinaryLoader.cpp


diff --git a/engines/freescape/freescape.h b/engines/freescape/freescape.h
index a7ec3096b61..2388a153ddc 100644
--- a/engines/freescape/freescape.h
+++ b/engines/freescape/freescape.h
@@ -263,7 +263,7 @@ public:
 	bool executeEndIfBitNotEqual(FCLInstruction &instruction);
 	bool executeEndIfVisibilityIsEqual(FCLInstruction &instruction);
 	void executeSwapJet(FCLInstruction &instruction);
-	void executePrint(FCLInstruction &instruction);
+	virtual void executePrint(FCLInstruction &instruction);
 	void executeSPFX(FCLInstruction &instruction);
 
 	// Sound
@@ -448,10 +448,12 @@ public:
 
 	void loadAssets() override;
 	void initGameState() override;
+	void borderScreen() override;
 
 	void gotoArea(uint16 areaID, int entranceID) override;
 	void checkIfStillInArea() override;
 	void pressedKey(const int keycode) override;
+	void executePrint(FCLInstruction &instruction) override;
 
 	void loadAssetsDemo();
 	void loadAssetsFullGame();
@@ -461,6 +463,7 @@ public:
 
 	void drawUI() override;
 	void drawDOSUI(Graphics::Surface *surface);
+	void drawFullscreenMessage(Common::String message);
 	Common::Error saveGameStreamExtended(Common::WriteStream *stream, bool isAutosave = false) override;
 	Common::Error loadGameStreamExtended(Common::SeekableReadStream *stream) override;
 };
diff --git a/engines/freescape/games/dark.cpp b/engines/freescape/games/dark.cpp
index 60e1b86bfd0..5b200097680 100644
--- a/engines/freescape/games/dark.cpp
+++ b/engines/freescape/games/dark.cpp
@@ -65,6 +65,7 @@ void DarkEngine::loadAssetsDemo() {
 		if (!file.isOpen())
 			error("Failed to open DSIDEE.EXE");
 		loadMessagesFixedSize(&file, 0x4525, 16, 27);
+		loadMessagesFixedSize(&file, 0x9959, 307, 5);
 		loadFonts(&file, 0xa598);
 		load8bitBinary(&file, 0xa700, 16);
 	} else if (isDOS() && _renderMode == Common::kRenderCGA) {
@@ -135,6 +136,13 @@ void DarkEngine::gotoArea(uint16 areaID, int entranceID) {
 	if (!_gameStateBits.contains(areaID))
 		_gameStateBits[areaID] = 0;
 
+	if (isDemo()) {
+		if (!_areaMap.contains(areaID)) {
+			drawFullscreenMessage(_messagesList[30]);
+			return;
+		}
+	}
+
 	assert(_areaMap.contains(areaID));
 	_currentArea = _areaMap[areaID];
 	_currentArea->show();
@@ -336,6 +344,110 @@ void DarkEngine::drawUI() {
 	delete surface;
 }
 
+void DarkEngine::borderScreen() {
+	if (_border) {
+		drawBorder();
+		if (isDemo()) {
+			drawFullscreenMessage(_messagesList[27]);
+			drawFullscreenMessage(_messagesList[28]);
+			drawFullscreenMessage(_messagesList[29]);
+		} else {
+			_gfx->flipBuffer();
+			g_system->updateScreen();
+			g_system->delayMillis(3000);
+		}
+	}
+}
+
+void DarkEngine::executePrint(FCLInstruction &instruction) {
+	uint16 index = instruction._source - 1;
+	debugC(1, kFreescapeDebugCode, "Printing message %d", index);
+	_currentAreaMessages.clear();
+	if (index > 127) {
+		index = _messagesList.size() - (index - 254) - 2;
+		drawFullscreenMessage(_messagesList[index]);
+		return;
+	}
+	_currentAreaMessages.push_back(_messagesList[index]);
+}
+
+void DarkEngine::drawFullscreenMessage(Common::String message) {
+	_savedScreen = _gfx->getScreenshot();
+
+	uint32 color = _gfx->_texturePixelFormat.ARGBToColor(0x00, 0x00, 0x00, 0x00);
+	Graphics::Surface *surface = new Graphics::Surface();
+	surface->create(_screenW, _screenH, _gfx->_texturePixelFormat);
+	surface->fillRect(_fullscreenViewArea, color);
+
+	uint32 black = _gfx->_texturePixelFormat.ARGBToColor(0xFF, 0x00, 0x00, 0x00);
+	surface->fillRect(_viewArea, black);
+
+	switch (_renderMode) {
+		case Common::kRenderCGA:
+			color = 1;
+			break;
+		case Common::kRenderZX:
+			color = 6;
+			break;
+		default:
+			color = 14;
+	}
+	uint8 r, g, b;
+	_gfx->readFromPalette(color, r, g, b);
+	uint32 front = _gfx->_texturePixelFormat.ARGBToColor(0xFF, r, g, b);
+
+	int x, y;
+	x = 42;
+	y = 30;
+	for (int i = 0; i < 8; i++) {
+		Common::String line = message.substr(28 * i, 28);
+		debug("'%s' %d", line.c_str(), line.size());
+		drawStringInSurface(line, x, y, front, black, surface);
+		y = y + 12;
+	}
+
+	if (!_uiTexture)
+		_uiTexture = _gfx->createTexture(surface);
+	else
+		_uiTexture->update(surface);
+
+	_gfx->setViewport(_fullscreenViewArea);
+	_gfx->drawTexturedRect2D(_fullscreenViewArea, _fullscreenViewArea, _uiTexture);
+	_gfx->setViewport(_viewArea);
+
+	_gfx->flipBuffer();
+	g_system->updateScreen();
+
+	Common::Event event;
+	bool cont = true;
+	while (!shouldQuit() && cont) {
+		while (g_system->getEventManager()->pollEvent(event)) {
+
+			// Events
+			switch (event.type) {
+			case Common::EVENT_KEYDOWN:
+				if (event.kbd.keycode == Common::KEYCODE_SPACE) {
+					cont = false;
+				}
+				break;
+			case Common::EVENT_SCREEN_CHANGED:
+				_gfx->computeScreenViewport();
+				// TODO: properly refresh screen
+				break;
+
+			default:
+				break;
+			}
+		}
+		g_system->delayMillis(10);
+	}
+
+	_savedScreen->free();
+	delete _savedScreen;
+	surface->free();
+	delete surface;
+}
+
 Common::Error DarkEngine::saveGameStreamExtended(Common::WriteStream *stream, bool isAutosave) {
 	return Common::kNoError;
 }
diff --git a/engines/freescape/loaders/8bitBinaryLoader.cpp b/engines/freescape/loaders/8bitBinaryLoader.cpp
index b0b2edefc0c..1e5a7f48126 100644
--- a/engines/freescape/loaders/8bitBinaryLoader.cpp
+++ b/engines/freescape/loaders/8bitBinaryLoader.cpp
@@ -659,7 +659,7 @@ void FreescapeEngine::loadMessagesFixedSize(Common::SeekableReadStream *file, in
 		file->read(buffer, size);
 		Common::String message = (const char *)buffer;
 		_messagesList.push_back(message);
-		debugC(1, kFreescapeDebugParser, "%s", _messagesList[i].c_str());
+		debugC(1, kFreescapeDebugParser, "%s", _messagesList[_messagesList.size() - 1].c_str());
 	}
 	free(buffer);
 }


Commit: 875940674e7fce6924aee9e16ae823a5182afb4c
    https://github.com/scummvm/scummvm/commit/875940674e7fce6924aee9e16ae823a5182afb4c
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-03-20T09:12:58+01:00

Commit Message:
FREESCAPE: load some? global objects in dark for dos (and demo)

Changed paths:
    engines/freescape/freescape.h
    engines/freescape/games/dark.cpp


diff --git a/engines/freescape/freescape.h b/engines/freescape/freescape.h
index 2388a153ddc..ac30334df92 100644
--- a/engines/freescape/freescape.h
+++ b/engines/freescape/freescape.h
@@ -466,6 +466,9 @@ public:
 	void drawFullscreenMessage(Common::String message);
 	Common::Error saveGameStreamExtended(Common::WriteStream *stream, bool isAutosave = false) override;
 	Common::Error loadGameStreamExtended(Common::SeekableReadStream *stream) override;
+
+private:
+	void loadGlobalObjects(Common::SeekableReadStream *file, int offset);
 };
 
 class EclipseEngine : public FreescapeEngine {
diff --git a/engines/freescape/games/dark.cpp b/engines/freescape/games/dark.cpp
index 5b200097680..edd1d0bcfe4 100644
--- a/engines/freescape/games/dark.cpp
+++ b/engines/freescape/games/dark.cpp
@@ -67,6 +67,7 @@ void DarkEngine::loadAssetsDemo() {
 		loadMessagesFixedSize(&file, 0x4525, 16, 27);
 		loadMessagesFixedSize(&file, 0x9959, 307, 5);
 		loadFonts(&file, 0xa598);
+		loadGlobalObjects(&file, 0x3d04);
 		load8bitBinary(&file, 0xa700, 16);
 	} else if (isDOS() && _renderMode == Common::kRenderCGA) {
 		//loadBundledImages();
@@ -80,6 +81,23 @@ void DarkEngine::loadAssetsDemo() {
 		error("Invalid or unsupported render mode %s for Dark Side", Common::getRenderModeDescription(_renderMode));
 }
 
+
+void DarkEngine::loadGlobalObjects(Common::SeekableReadStream *file, int offset) {
+	assert(!_areaMap.contains(255));
+	ObjectMap *globalObjectsByID = new ObjectMap;
+	file->seek(offset);
+	for (int i = 0; i < 22; i++) {
+		Object *gobj = load8bitObject(file);
+		assert(gobj);
+		assert(!globalObjectsByID->contains(gobj->getObjectID()));
+		debugC(1, kFreescapeDebugParser, "Adding global object: %d", gobj->getObjectID());
+		(*globalObjectsByID)[gobj->getObjectID()] = gobj;
+	}
+
+	_areaMap[255] = new Area(255, 0, globalObjectsByID, nullptr);
+}
+
+
 void DarkEngine::initGameState() {
 	_flyMode = false;
 	_noClipMode = false;
@@ -119,7 +137,14 @@ void DarkEngine::loadAssetsFullGame() {
 
 		loadFonts(&file, 0xa113);
 		loadMessagesFixedSize(&file, 0x4525, 16, 27);
+		loadGlobalObjects(&file, 0x3d04);
 		load8bitBinary(&file, 0xa280, 16);
+		// TODO: load objects
+		/*for (auto &it : _areaMap) {
+			if (!it._value->entranceWithID(255))
+				continue;
+			it._value->addStructure(_areaMap[255]);
+		}*/
 	} else if (_renderMode == Common::kRenderCGA) {
 		loadBundledImages();
 		file.open("DSIDEC.EXE");


Commit: 7b307e562b9dca79de2abbeee8763f4e70d76e67
    https://github.com/scummvm/scummvm/commit/7b307e562b9dca79de2abbeee8763f4e70d76e67
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-03-20T09:13:10+01:00

Commit Message:
FREESCAPE: drafted code that reads title image of driller US release for DOS

Changed paths:
    engines/freescape/freescape.h
    engines/freescape/games/driller.cpp
    engines/freescape/loaders/8bitBinaryLoader.cpp


diff --git a/engines/freescape/freescape.h b/engines/freescape/freescape.h
index ac30334df92..6772c476c23 100644
--- a/engines/freescape/freescape.h
+++ b/engines/freescape/freescape.h
@@ -164,6 +164,9 @@ public:
 	void load8bitBinary(Common::SeekableReadStream *file, int offset, int ncolors);
 	Area *load8bitArea(Common::SeekableReadStream *file, uint16 ncolors);
 	Object *load8bitObject(Common::SeekableReadStream *file);
+	void renderPixels8bitImage(Graphics::Surface *surface, int &i, int &j, int pixels);
+	uint32 getPixel8bitImage(int index);
+	Graphics::Surface *load8bitImage(Common::SeekableReadStream *file, int ncolors, int offset);
 
 	// Areas
 	uint16 _startArea;
diff --git a/engines/freescape/games/driller.cpp b/engines/freescape/games/driller.cpp
index a30e97a8087..b154dc77ee6 100644
--- a/engines/freescape/games/driller.cpp
+++ b/engines/freescape/games/driller.cpp
@@ -660,6 +660,12 @@ void DrillerEngine::loadAssetsFullGame() {
 
 	} else if (_renderMode == Common::kRenderCGA) {
 		loadBundledImages();
+		_title->free();
+		delete _title;
+		file.open("CGATITLE.RL");
+		_title = load8bitImage(&file, 4, 0x1b3);
+
+		file.close();
 		file.open("DRILLC.EXE");
 
 		if (!file.isOpen())
@@ -669,6 +675,7 @@ void DrillerEngine::loadAssetsFullGame() {
 		loadMessagesFixedSize(&file, 0x2585, 14, 20);
 		load8bitBinary(&file, 0x7bb0, 4);
 		loadGlobalObjects(&file, 0x1fa2);
+		//_border = load8bitImage(&file, 4, 0x261);
 	} else
 		error("Invalid or unsupported render mode %s for Driller", Common::getRenderModeDescription(_renderMode));
 
diff --git a/engines/freescape/loaders/8bitBinaryLoader.cpp b/engines/freescape/loaders/8bitBinaryLoader.cpp
index 1e5a7f48126..7ae1b7cd240 100644
--- a/engines/freescape/loaders/8bitBinaryLoader.cpp
+++ b/engines/freescape/loaders/8bitBinaryLoader.cpp
@@ -298,6 +298,154 @@ static const char *eclipseRoomName[] = {
 	"ILLUSION",
 	"????????"};
 
+byte kCGAPalettePinkBlueWhiteData[4][3] = {
+	{0x00, 0x00, 0x00},
+	{0x55, 0xff, 0xff},
+	{0xff, 0x55, 0xff},
+	{0xff, 0xff, 0xff},
+};
+
+uint32 FreescapeEngine::getPixel8bitImage(int index) {
+	uint8 r, g, b;
+	if (index < 4) {
+		_gfx->readFromPalette(0, r, g, b);
+		return _gfx->_currentPixelFormat.ARGBToColor(0xFF, r, g, b);
+	}
+	_gfx->readFromPalette(index / 4, r, g, b);
+	return _gfx->_currentPixelFormat.ARGBToColor(0xFF, r, g, b);
+}
+
+void FreescapeEngine::renderPixels8bitImage(Graphics::Surface *surface, int &i, int &j, int pixels) {
+	int c1 = pixels >> 4;
+	int c2 = pixels & 0xf;
+
+	if (i == 320) {
+		return;
+	}
+
+	surface->setPixel(i, j, getPixel8bitImage(c1));
+	i++;
+
+	if (i == 320) {
+		return;
+	}
+
+	surface->setPixel(i, j, getPixel8bitImage(c1));
+	i++;
+
+	if (i == 320) {
+		return;
+	}
+
+	surface->setPixel(i, j, getPixel8bitImage(c2));
+	i++;
+
+	if (i == 320) {
+		return;
+	}
+
+	surface->setPixel(i, j, getPixel8bitImage(c2));
+	i++;
+}
+
+Graphics::Surface *FreescapeEngine::load8bitImage(Common::SeekableReadStream *file, int ncolors, int offset) {
+	Graphics::Surface *surface = new Graphics::Surface();
+	assert(ncolors == 4);
+	_gfx->_palette = (byte *)kCGAPalettePinkBlueWhiteData;
+	surface->create(_screenW, _screenH, _gfx->_currentPixelFormat);
+	uint32 black = _gfx->_currentPixelFormat.ARGBToColor(0xFF, 0, 0, 0);
+	surface->fillRect(Common::Rect(0, 0, 320, 200), black);
+
+	int i = 0;
+	int j = 0;
+	int command = -1;
+	int singlePixelsToProcess = 0;
+	bool repeatedPixelsToProcess = false;
+	file->seek(offset);
+	while (!file->eos()) {
+		assert(i <= 320);
+		int pixels = -1;
+		int repetition = -1;
+
+		if (singlePixelsToProcess == 0 && !repeatedPixelsToProcess) {
+			if (command < 0)
+				command = file->readByte();
+
+			//debug("reading command: %x at %lx", command, file->pos() - 1);
+
+			assert(command >= 0x7f);
+			singlePixelsToProcess = (0xff - command + 2) * 2;
+			//debug("single Pixels to process: %d", singlePixelsToProcess);
+
+			repeatedPixelsToProcess = true;
+			if (i == 320) {
+				j++;
+				i = 0;
+			}
+			command = -1;
+			continue;
+		}
+
+		if (singlePixelsToProcess > 0) {
+			singlePixelsToProcess--;
+			pixels = file->readByte();
+			//debug("reading pixels: %x at %d, %d", pixels, i, j);
+			renderPixels8bitImage(surface, i, j, pixels);
+		} else if (repeatedPixelsToProcess) {
+			repetition = file->readByte() + 1;
+			//debug("reading repetition: %x", repetition - 1);
+			assert(repetition > 0);
+			if (repetition >= 0x80) {
+				command = repetition - 1;
+				repeatedPixelsToProcess = false;
+				continue;
+			}
+
+			if (i == 320) {
+				j++;
+				i = 0;
+				continue;
+			}
+
+			int pixels1 = file->readByte();
+			//debug("reading pixels: %x", pixels1);
+
+			int pixels2 = file->readByte();
+			//debug("reading pixels: %x", pixels2);
+
+			if (repetition >= 1) {
+				while (repetition > 0) {
+					repetition--;
+
+					if (i == 320) {
+						j++;
+						i = 0;
+					}
+
+					if (j == 200)
+						return surface;
+
+					//sdebug("repeating pixels: %x at %d, %d", pixels1, i, j);
+					renderPixels8bitImage(surface, i, j, pixels1);
+
+					if (i == 320) {
+						j++;
+						i = 0;
+					}
+
+					if (j == 200)
+						return surface;
+
+					//debug("repeating pixels: %x at %d, %d", pixels2, i, j);
+					renderPixels8bitImage(surface, i, j, pixels2);
+				}
+			}
+		}
+	}
+
+	return surface;
+}
+
 Area *FreescapeEngine::load8bitArea(Common::SeekableReadStream *file, uint16 ncolors) {
 
 	Common::String name;


Commit: 523bc141fe4c922d59600ef9d2bd7f18ab0a8938
    https://github.com/scummvm/scummvm/commit/523bc141fe4c922d59600ef9d2bd7f18ab0a8938
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-03-20T09:13:18+01:00

Commit Message:
FREESCAPE: initial implementation of image parsing for title/borders in driller

Changed paths:
    engines/freescape/freescape.h
    engines/freescape/games/driller.cpp
    engines/freescape/loaders/8bitBinaryLoader.cpp


diff --git a/engines/freescape/freescape.h b/engines/freescape/freescape.h
index 6772c476c23..9e876ddf56d 100644
--- a/engines/freescape/freescape.h
+++ b/engines/freescape/freescape.h
@@ -164,9 +164,13 @@ public:
 	void load8bitBinary(Common::SeekableReadStream *file, int offset, int ncolors);
 	Area *load8bitArea(Common::SeekableReadStream *file, uint16 ncolors);
 	Object *load8bitObject(Common::SeekableReadStream *file);
-	void renderPixels8bitImage(Graphics::Surface *surface, int &i, int &j, int pixels);
+	void renderPixels8bitTitleImage(Graphics::Surface *surface, int &i, int &j, int pixels);
+	void renderPixels8bitBinImage(Graphics::Surface *surface, int &i, int &j, int pixels, int color);
+
 	uint32 getPixel8bitImage(int index);
-	Graphics::Surface *load8bitImage(Common::SeekableReadStream *file, int ncolors, int offset);
+	Graphics::Surface *load8bitBinImage(Common::SeekableReadStream *file, int ncolors, int offset);
+	Graphics::Surface *load8bitTitleImage(Common::SeekableReadStream *file, int ncolors, int offset);
+
 
 	// Areas
 	uint16 _startArea;
diff --git a/engines/freescape/games/driller.cpp b/engines/freescape/games/driller.cpp
index b154dc77ee6..73cc894f7cb 100644
--- a/engines/freescape/games/driller.cpp
+++ b/engines/freescape/games/driller.cpp
@@ -663,7 +663,7 @@ void DrillerEngine::loadAssetsFullGame() {
 		_title->free();
 		delete _title;
 		file.open("CGATITLE.RL");
-		_title = load8bitImage(&file, 4, 0x1b3);
+		_title = load8bitTitleImage(&file, 4, 0x1b3);
 
 		file.close();
 		file.open("DRILLC.EXE");
@@ -675,7 +675,7 @@ void DrillerEngine::loadAssetsFullGame() {
 		loadMessagesFixedSize(&file, 0x2585, 14, 20);
 		load8bitBinary(&file, 0x7bb0, 4);
 		loadGlobalObjects(&file, 0x1fa2);
-		//_border = load8bitImage(&file, 4, 0x261);
+		_border = load8bitBinImage(&file, 4, 0x210);
 	} else
 		error("Invalid or unsupported render mode %s for Driller", Common::getRenderModeDescription(_renderMode));
 
diff --git a/engines/freescape/loaders/8bitBinaryLoader.cpp b/engines/freescape/loaders/8bitBinaryLoader.cpp
index 7ae1b7cd240..33ac4291d90 100644
--- a/engines/freescape/loaders/8bitBinaryLoader.cpp
+++ b/engines/freescape/loaders/8bitBinaryLoader.cpp
@@ -308,14 +308,14 @@ byte kCGAPalettePinkBlueWhiteData[4][3] = {
 uint32 FreescapeEngine::getPixel8bitImage(int index) {
 	uint8 r, g, b;
 	if (index < 4) {
-		_gfx->readFromPalette(0, r, g, b);
+		_gfx->readFromPalette(index, r, g, b);
 		return _gfx->_currentPixelFormat.ARGBToColor(0xFF, r, g, b);
 	}
 	_gfx->readFromPalette(index / 4, r, g, b);
 	return _gfx->_currentPixelFormat.ARGBToColor(0xFF, r, g, b);
 }
 
-void FreescapeEngine::renderPixels8bitImage(Graphics::Surface *surface, int &i, int &j, int pixels) {
+void FreescapeEngine::renderPixels8bitTitleImage(Graphics::Surface *surface, int &i, int &j, int pixels) {
 	int c1 = pixels >> 4;
 	int c2 = pixels & 0xf;
 
@@ -323,7 +323,7 @@ void FreescapeEngine::renderPixels8bitImage(Graphics::Surface *surface, int &i,
 		return;
 	}
 
-	surface->setPixel(i, j, getPixel8bitImage(c1));
+	surface->setPixel(i, j, getPixel8bitImage(c1 / 4));
 	i++;
 
 	if (i == 320) {
@@ -337,7 +337,7 @@ void FreescapeEngine::renderPixels8bitImage(Graphics::Surface *surface, int &i,
 		return;
 	}
 
-	surface->setPixel(i, j, getPixel8bitImage(c2));
+	surface->setPixel(i, j, getPixel8bitImage(c2 / 4));
 	i++;
 
 	if (i == 320) {
@@ -348,7 +348,7 @@ void FreescapeEngine::renderPixels8bitImage(Graphics::Surface *surface, int &i,
 	i++;
 }
 
-Graphics::Surface *FreescapeEngine::load8bitImage(Common::SeekableReadStream *file, int ncolors, int offset) {
+Graphics::Surface *FreescapeEngine::load8bitTitleImage(Common::SeekableReadStream *file, int ncolors, int offset) {
 	Graphics::Surface *surface = new Graphics::Surface();
 	assert(ncolors == 4);
 	_gfx->_palette = (byte *)kCGAPalettePinkBlueWhiteData;
@@ -390,7 +390,7 @@ Graphics::Surface *FreescapeEngine::load8bitImage(Common::SeekableReadStream *fi
 			singlePixelsToProcess--;
 			pixels = file->readByte();
 			//debug("reading pixels: %x at %d, %d", pixels, i, j);
-			renderPixels8bitImage(surface, i, j, pixels);
+			renderPixels8bitTitleImage(surface, i, j, pixels);
 		} else if (repeatedPixelsToProcess) {
 			repetition = file->readByte() + 1;
 			//debug("reading repetition: %x", repetition - 1);
@@ -426,7 +426,7 @@ Graphics::Surface *FreescapeEngine::load8bitImage(Common::SeekableReadStream *fi
 						return surface;
 
 					//sdebug("repeating pixels: %x at %d, %d", pixels1, i, j);
-					renderPixels8bitImage(surface, i, j, pixels1);
+					renderPixels8bitTitleImage(surface, i, j, pixels1);
 
 					if (i == 320) {
 						j++;
@@ -437,7 +437,7 @@ Graphics::Surface *FreescapeEngine::load8bitImage(Common::SeekableReadStream *fi
 						return surface;
 
 					//debug("repeating pixels: %x at %d, %d", pixels2, i, j);
-					renderPixels8bitImage(surface, i, j, pixels2);
+					renderPixels8bitTitleImage(surface, i, j, pixels2);
 				}
 			}
 		}
@@ -446,6 +446,104 @@ Graphics::Surface *FreescapeEngine::load8bitImage(Common::SeekableReadStream *fi
 	return surface;
 }
 
+void FreescapeEngine::renderPixels8bitBinImage(Graphics::Surface *surface, int &i, int &j, int pixels, int color) {
+	if (i >= 320) {
+		//debug("cannot continue, stopping here at row %d!", j);
+		return;
+	}
+
+	int acc = 1 << 7;
+	while (acc > 0) {
+		assert(i < 320);
+		if (acc & pixels)
+			surface->setPixel(i, j, getPixel8bitImage(color));
+		i++;
+		acc = acc >> 1;
+	}
+
+}
+
+Graphics::Surface *FreescapeEngine::load8bitBinImage(Common::SeekableReadStream *file, int ncolors, int offset) {
+	Graphics::Surface *surface = new Graphics::Surface();
+	assert(ncolors == 4);
+	_gfx->_palette = (byte *)kCGAPalettePinkBlueWhiteData;
+	surface->create(_screenW, _screenH, _gfx->_currentPixelFormat);
+	uint32 black = _gfx->_currentPixelFormat.ARGBToColor(0xFF, 0, 0, 0);
+	surface->fillRect(Common::Rect(0, 0, 320, 200), black);
+
+	file->seek(offset);
+	int imageSize = file->readUint16BE();
+
+	int i = 0;
+	int j = 0;
+	int hPixelsWritten = 0;
+	int color = 1;
+	int command = 0;
+	while (file->pos() <= offset + imageSize) {
+		debug("pos: %lx", file->pos());
+		command = file->readByte();
+
+		color = hPixelsWritten < 320 ? 1 : 2;
+		//debug("command: %x with j: %d", command, j);
+		if (j >= 200)
+			return surface;
+
+		if (command <= 0x7f) {
+			//debug("starting singles at i: %d j: %d", i, j);
+			int start = i;
+			while (command-- >= 0) {
+				int pixels = file->readByte();
+				//debug("single pixels command: %d with pixels: %x", command, pixels);
+				renderPixels8bitBinImage(surface, i, j, pixels, color);
+			}
+			hPixelsWritten = hPixelsWritten + i - start;
+		} else if (command <= 0xff && command >= 0xf0) {
+			int size = 136 - 8*(command - 0xf0);
+			int start = i;
+			int pixels = file->readByte();
+			//debug("starting 0xfX: at i: %d j: %d with pixels: %x", i, j, pixels);
+			while (size > 0) {
+				renderPixels8bitBinImage(surface, i, j, pixels, color);
+				size = size - 8;
+			}
+			hPixelsWritten = hPixelsWritten + i - start;
+			assert(i <= 320);
+		} else if (command <= 0xef && command >= 0xe0) {
+			int size = 264 - 8*(command - 0xe0);
+			int start = i;
+			int pixels = file->readByte();
+			//debug("starting 0xeX: at i: %d j: %d with pixels: %x", i, j, pixels);
+			while (size > 0) {
+				renderPixels8bitBinImage(surface, i, j, pixels, color);
+				size = size - 8;
+			}
+			hPixelsWritten = hPixelsWritten + i - start;
+		} else if (command <= 0xdf && command >= 0xd0) {
+			int size = 272 + 8*(0xdf - command);
+			int start = i;
+			int pixels = file->readByte();
+			while (size > 0) {
+				renderPixels8bitBinImage(surface, i, j, pixels, color);
+				size = size - 8;
+			}
+			hPixelsWritten = hPixelsWritten + i - start;
+		} else {
+			error("unknown command: %x", command);
+		}
+
+		if (i >= 320) {
+			i = 0;
+			if (hPixelsWritten >= 640) {
+				j++;
+				hPixelsWritten = 0;
+			}
+		}
+
+
+	}
+	return surface;
+}
+
 Area *FreescapeEngine::load8bitArea(Common::SeekableReadStream *file, uint16 ncolors) {
 
 	Common::String name;


Commit: 2e652a9861b67b02fc273e1ee3d0b32f960d0f1e
    https://github.com/scummvm/scummvm/commit/2e652a9861b67b02fc273e1ee3d0b32f960d0f1e
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-03-20T09:13:26+01:00

Commit Message:
FREESCAPE: load title/borders images in driller dos directly from the game data

Changed paths:
    engines/freescape/games/driller.cpp


diff --git a/engines/freescape/games/driller.cpp b/engines/freescape/games/driller.cpp
index 73cc894f7cb..c68f09aa60c 100644
--- a/engines/freescape/games/driller.cpp
+++ b/engines/freescape/games/driller.cpp
@@ -659,12 +659,15 @@ void DrillerEngine::loadAssetsFullGame() {
 		load8bitBinary(&file, 0x9b40, 16);
 
 	} else if (_renderMode == Common::kRenderCGA) {
-		loadBundledImages();
-		_title->free();
-		delete _title;
+		file.open("SCN1C.DAT");
+		if (file.isOpen()) {
+			_title = load8bitBinImage(&file, 4, 0x0);
+		}
+		file.close();
 		file.open("CGATITLE.RL");
-		_title = load8bitTitleImage(&file, 4, 0x1b3);
-
+		if (file.isOpen()) {
+			_title = load8bitTitleImage(&file, 4, 0x1b3);
+		}
 		file.close();
 		file.open("DRILLC.EXE");
 


Commit: 05f7253af33c40b02d6a35d4b67de47ac8ca4920
    https://github.com/scummvm/scummvm/commit/05f7253af33c40b02d6a35d4b67de47ac8ca4920
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-03-20T09:13:33+01:00

Commit Message:
FREESCAPE: load title/borders images in driller EGA directly from the game data

Changed paths:
    engines/freescape/freescape.h
    engines/freescape/games/driller.cpp
    engines/freescape/loaders/8bitBinaryLoader.cpp


diff --git a/engines/freescape/freescape.h b/engines/freescape/freescape.h
index 9e876ddf56d..1e177654887 100644
--- a/engines/freescape/freescape.h
+++ b/engines/freescape/freescape.h
@@ -165,11 +165,14 @@ public:
 	Area *load8bitArea(Common::SeekableReadStream *file, uint16 ncolors);
 	Object *load8bitObject(Common::SeekableReadStream *file);
 	void renderPixels8bitTitleImage(Graphics::Surface *surface, int &i, int &j, int pixels);
-	void renderPixels8bitBinImage(Graphics::Surface *surface, int &i, int &j, int pixels, int color);
+	void renderPixels8bitBinImage(Graphics::Surface *surface, int &i, int &j, uint8 pixels, int color);
+
+	void renderPixels8bitBinCGAImage(Graphics::Surface *surface, int &i, int &j, uint8 pixels, int color);
+	void renderPixels8bitBinEGAImage(Graphics::Surface *surface, int &i, int &j, uint8 pixels, int color);
 
 	uint32 getPixel8bitImage(int index);
-	Graphics::Surface *load8bitBinImage(Common::SeekableReadStream *file, int ncolors, int offset);
-	Graphics::Surface *load8bitTitleImage(Common::SeekableReadStream *file, int ncolors, int offset);
+	Graphics::Surface *load8bitBinImage(Common::SeekableReadStream *file, int offset);
+	Graphics::Surface *load8bitTitleImage(Common::SeekableReadStream *file, int offset);
 
 
 	// Areas
diff --git a/engines/freescape/games/driller.cpp b/engines/freescape/games/driller.cpp
index c68f09aa60c..902000f563d 100644
--- a/engines/freescape/games/driller.cpp
+++ b/engines/freescape/games/driller.cpp
@@ -647,7 +647,11 @@ void DrillerEngine::loadAssetsFullGame() {
 			loadGlobalObjects(&file, 0x1855 - 0x400);
 		}
 	} else if (_renderMode == Common::kRenderEGA) {
-		loadBundledImages();
+		file.open("SCN1E.DAT");
+		if (file.isOpen()) {
+			_title = load8bitBinImage(&file, 0x0);
+		}
+		file.close();
 		file.open("DRILLE.EXE");
 
 		if (!file.isOpen())
@@ -657,16 +661,16 @@ void DrillerEngine::loadAssetsFullGame() {
 		loadFonts(&file, 0x99dd);
 		loadGlobalObjects(&file, 0x3b42);
 		load8bitBinary(&file, 0x9b40, 16);
-
+		_border = load8bitBinImage(&file, 0x210);
 	} else if (_renderMode == Common::kRenderCGA) {
 		file.open("SCN1C.DAT");
 		if (file.isOpen()) {
-			_title = load8bitBinImage(&file, 4, 0x0);
+			_title = load8bitBinImage(&file, 0x0);
 		}
 		file.close();
 		file.open("CGATITLE.RL");
 		if (file.isOpen()) {
-			_title = load8bitTitleImage(&file, 4, 0x1b3);
+			_title = load8bitTitleImage(&file, 0x1b3);
 		}
 		file.close();
 		file.open("DRILLC.EXE");
@@ -678,7 +682,7 @@ void DrillerEngine::loadAssetsFullGame() {
 		loadMessagesFixedSize(&file, 0x2585, 14, 20);
 		load8bitBinary(&file, 0x7bb0, 4);
 		loadGlobalObjects(&file, 0x1fa2);
-		_border = load8bitBinImage(&file, 4, 0x210);
+		_border = load8bitBinImage(&file, 0x210);
 	} else
 		error("Invalid or unsupported render mode %s for Driller", Common::getRenderModeDescription(_renderMode));
 
diff --git a/engines/freescape/loaders/8bitBinaryLoader.cpp b/engines/freescape/loaders/8bitBinaryLoader.cpp
index 33ac4291d90..1f29750bbff 100644
--- a/engines/freescape/loaders/8bitBinaryLoader.cpp
+++ b/engines/freescape/loaders/8bitBinaryLoader.cpp
@@ -305,6 +305,24 @@ byte kCGAPalettePinkBlueWhiteData[4][3] = {
 	{0xff, 0xff, 0xff},
 };
 
+byte kEGADefaultPaletteData[16][3] = {
+	{0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xaa},
+	{0x00, 0xaa, 0x00},
+	{0xaa, 0x00, 0x00},
+	{0xaa, 0x00, 0xaa},
+	{0xaa, 0x55, 0x00},
+	{0x55, 0xff, 0x55},
+	{0xff, 0x55, 0x55},
+	{0x12, 0x34, 0x56},
+	{0xff, 0xff, 0x55},
+	{0xff, 0xff, 0xff},
+	{0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00}
+};
+
 uint32 FreescapeEngine::getPixel8bitImage(int index) {
 	uint8 r, g, b;
 	if (index < 4) {
@@ -348,9 +366,9 @@ void FreescapeEngine::renderPixels8bitTitleImage(Graphics::Surface *surface, int
 	i++;
 }
 
-Graphics::Surface *FreescapeEngine::load8bitTitleImage(Common::SeekableReadStream *file, int ncolors, int offset) {
+Graphics::Surface *FreescapeEngine::load8bitTitleImage(Common::SeekableReadStream *file, int offset) {
 	Graphics::Surface *surface = new Graphics::Surface();
-	assert(ncolors == 4);
+	assert(_renderMode == Common::kRenderCGA);
 	_gfx->_palette = (byte *)kCGAPalettePinkBlueWhiteData;
 	surface->create(_screenW, _screenH, _gfx->_currentPixelFormat);
 	uint32 black = _gfx->_currentPixelFormat.ARGBToColor(0xFF, 0, 0, 0);
@@ -446,7 +464,7 @@ Graphics::Surface *FreescapeEngine::load8bitTitleImage(Common::SeekableReadStrea
 	return surface;
 }
 
-void FreescapeEngine::renderPixels8bitBinImage(Graphics::Surface *surface, int &i, int &j, int pixels, int color) {
+void FreescapeEngine::renderPixels8bitBinImage(Graphics::Surface *surface, int &i, int &j, uint8 pixels, int color) {
 	if (i >= 320) {
 		//debug("cannot continue, stopping here at row %d!", j);
 		return;
@@ -455,18 +473,30 @@ void FreescapeEngine::renderPixels8bitBinImage(Graphics::Surface *surface, int &
 	int acc = 1 << 7;
 	while (acc > 0) {
 		assert(i < 320);
-		if (acc & pixels)
-			surface->setPixel(i, j, getPixel8bitImage(color));
+		if (acc & pixels) {
+			uint8 r, g, b;
+			uint32 previousPixel = surface->getPixel(i, j);
+			_gfx->_currentPixelFormat.colorToRGB(previousPixel, r, g, b);
+			int previousColor = _gfx->indexFromColor(r, g, b);
+			//debug("index: %d", previousColor + color);
+			_gfx->readFromPalette(previousColor + color, r, g, b);
+			surface->setPixel(i, j, _gfx->_currentPixelFormat.ARGBToColor(0xFF, r, g, b));
+		}
 		i++;
 		acc = acc >> 1;
 	}
 
 }
 
-Graphics::Surface *FreescapeEngine::load8bitBinImage(Common::SeekableReadStream *file, int ncolors, int offset) {
+Graphics::Surface *FreescapeEngine::load8bitBinImage(Common::SeekableReadStream *file, int offset) {
 	Graphics::Surface *surface = new Graphics::Surface();
-	assert(ncolors == 4);
-	_gfx->_palette = (byte *)kCGAPalettePinkBlueWhiteData;
+	if (_renderMode == Common::kRenderCGA)
+		_gfx->_palette = (byte *)kCGAPalettePinkBlueWhiteData;
+	else if (_renderMode == Common::kRenderEGA)
+		_gfx->_palette = (byte *)kEGADefaultPaletteData;
+	else
+		error("Invalid render mode: %d", _renderMode);
+
 	surface->create(_screenW, _screenH, _gfx->_currentPixelFormat);
 	uint32 black = _gfx->_currentPixelFormat.ARGBToColor(0xFF, 0, 0, 0);
 	surface->fillRect(Common::Rect(0, 0, 320, 200), black);
@@ -480,10 +510,10 @@ Graphics::Surface *FreescapeEngine::load8bitBinImage(Common::SeekableReadStream
 	int color = 1;
 	int command = 0;
 	while (file->pos() <= offset + imageSize) {
-		debug("pos: %lx", file->pos());
+		//debug("pos: %lx", file->pos());
 		command = file->readByte();
 
-		color = hPixelsWritten < 320 ? 1 : 2;
+		color = 1 + hPixelsWritten / 320;
 		//debug("command: %x with j: %d", command, j);
 		if (j >= 200)
 			return surface;
@@ -498,33 +528,33 @@ Graphics::Surface *FreescapeEngine::load8bitBinImage(Common::SeekableReadStream
 			}
 			hPixelsWritten = hPixelsWritten + i - start;
 		} else if (command <= 0xff && command >= 0xf0) {
-			int size = 136 - 8*(command - 0xf0);
+			int size = (136 - 8*(command - 0xf0)) / 2;
 			int start = i;
 			int pixels = file->readByte();
 			//debug("starting 0xfX: at i: %d j: %d with pixels: %x", i, j, pixels);
 			while (size > 0) {
 				renderPixels8bitBinImage(surface, i, j, pixels, color);
-				size = size - 8;
+				size = size - 4;
 			}
 			hPixelsWritten = hPixelsWritten + i - start;
 			assert(i <= 320);
 		} else if (command <= 0xef && command >= 0xe0) {
-			int size = 264 - 8*(command - 0xe0);
+			int size = (264 - 8*(command - 0xe0)) / 2;
 			int start = i;
 			int pixels = file->readByte();
 			//debug("starting 0xeX: at i: %d j: %d with pixels: %x", i, j, pixels);
 			while (size > 0) {
 				renderPixels8bitBinImage(surface, i, j, pixels, color);
-				size = size - 8;
+				size = size - 4;
 			}
 			hPixelsWritten = hPixelsWritten + i - start;
 		} else if (command <= 0xdf && command >= 0xd0) {
-			int size = 272 + 8*(0xdf - command);
+			int size = (272 + 8*(0xdf - command)) / 2;
 			int start = i;
 			int pixels = file->readByte();
 			while (size > 0) {
 				renderPixels8bitBinImage(surface, i, j, pixels, color);
-				size = size - 8;
+				size = size - 4;
 			}
 			hPixelsWritten = hPixelsWritten + i - start;
 		} else {
@@ -533,7 +563,7 @@ Graphics::Surface *FreescapeEngine::load8bitBinImage(Common::SeekableReadStream
 
 		if (i >= 320) {
 			i = 0;
-			if (hPixelsWritten >= 640) {
+			if (hPixelsWritten >= (_renderMode == Common::kRenderCGA ? 640 : 1280)) {
 				j++;
 				hPixelsWritten = 0;
 			}


Commit: cc42bc2efbbe01a625a4aea090dd07fe7fd928f8
    https://github.com/scummvm/scummvm/commit/cc42bc2efbbe01a625a4aea090dd07fe7fd928f8
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-03-20T09:13:44+01:00

Commit Message:
FREESCAPE: load title/borders images in dark side EGA (and demo) directly from the game data

Changed paths:
    engines/freescape/freescape.h
    engines/freescape/games/dark.cpp


diff --git a/engines/freescape/freescape.h b/engines/freescape/freescape.h
index 1e177654887..1bd2c977df9 100644
--- a/engines/freescape/freescape.h
+++ b/engines/freescape/freescape.h
@@ -459,6 +459,7 @@ public:
 	void loadAssets() override;
 	void initGameState() override;
 	void borderScreen() override;
+	void titleScreen() override;
 
 	void gotoArea(uint16 areaID, int entranceID) override;
 	void checkIfStillInArea() override;
diff --git a/engines/freescape/games/dark.cpp b/engines/freescape/games/dark.cpp
index edd1d0bcfe4..1a10368adb1 100644
--- a/engines/freescape/games/dark.cpp
+++ b/engines/freescape/games/dark.cpp
@@ -49,6 +49,18 @@ DarkEngine::DarkEngine(OSystem *syst, const ADGameDescription *gd) : FreescapeEn
 	_initialShield = 15;
 }
 
+void DarkEngine::titleScreen() {
+	if (isAmiga() || isAtariST()) // These releases has their own screens
+		return;
+
+	if (_title) {
+		drawTitle();
+		_gfx->flipBuffer();
+		g_system->updateScreen();
+		g_system->delayMillis(3000);
+	}
+}
+
 void DarkEngine::loadAssets() {
 	if (isDemo())
 		loadAssetsDemo();
@@ -59,7 +71,10 @@ void DarkEngine::loadAssets() {
 void DarkEngine::loadAssetsDemo() {
 	Common::File file;
 	if (isDOS() && _renderMode == Common::kRenderEGA) {
-		loadBundledImages();
+		file.open("SCN1E.DAT");
+		if (file.isOpen())
+			_title = load8bitBinImage(&file, 0x0);
+		file.close();
 		file.open("DSIDEE.EXE");
 
 		if (!file.isOpen())
@@ -69,6 +84,7 @@ void DarkEngine::loadAssetsDemo() {
 		loadFonts(&file, 0xa598);
 		loadGlobalObjects(&file, 0x3d04);
 		load8bitBinary(&file, 0xa700, 16);
+		_border = load8bitBinImage(&file, 0x210);
 	} else if (isDOS() && _renderMode == Common::kRenderCGA) {
 		//loadBundledImages();
 		file.open("DSIDEC.EXE");
@@ -129,7 +145,10 @@ void DarkEngine::initGameState() {
 void DarkEngine::loadAssetsFullGame() {
 	Common::File file;
 	if (_renderMode == Common::kRenderEGA) {
-		loadBundledImages();
+		file.open("SCN1E.DAT");
+		if (file.isOpen())
+			_title = load8bitBinImage(&file, 0x0);
+		file.close();
 		file.open("DSIDEE.EXE");
 
 		if (!file.isOpen())
@@ -139,6 +158,8 @@ void DarkEngine::loadAssetsFullGame() {
 		loadMessagesFixedSize(&file, 0x4525, 16, 27);
 		loadGlobalObjects(&file, 0x3d04);
 		load8bitBinary(&file, 0xa280, 16);
+		_border = load8bitBinImage(&file, 0x210);
+
 		// TODO: load objects
 		/*for (auto &it : _areaMap) {
 			if (!it._value->entranceWithID(255))


Commit: 76c2a780a4ba09c22996e01dd1137600688e379c
    https://github.com/scummvm/scummvm/commit/76c2a780a4ba09c22996e01dd1137600688e379c
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-03-20T09:13:50+01:00

Commit Message:
FREESCAPE: load title/borders images in total eclipse EGA directly from the game data

Changed paths:
    engines/freescape/freescape.h
    engines/freescape/games/eclipse.cpp


diff --git a/engines/freescape/freescape.h b/engines/freescape/freescape.h
index 1bd2c977df9..975f8c9d5e3 100644
--- a/engines/freescape/freescape.h
+++ b/engines/freescape/freescape.h
@@ -487,6 +487,7 @@ public:
 	EclipseEngine(OSystem *syst, const ADGameDescription *gd);
 
 	void loadAssets() override;
+	void titleScreen() override;
 
 	void gotoArea(uint16 areaID, int entranceID) override;
 
diff --git a/engines/freescape/games/eclipse.cpp b/engines/freescape/games/eclipse.cpp
index 9e4e47a2d00..56baa42f46b 100644
--- a/engines/freescape/games/eclipse.cpp
+++ b/engines/freescape/games/eclipse.cpp
@@ -99,10 +99,26 @@ EclipseEngine::EclipseEngine(OSystem *syst, const ADGameDescription *gd) : Frees
 	}
 }
 
+void EclipseEngine::titleScreen() {
+	if (isAmiga() || isAtariST()) // These releases has their own screens
+		return;
+
+	if (_title) {
+		drawTitle();
+		_gfx->flipBuffer();
+		g_system->updateScreen();
+		g_system->delayMillis(3000);
+	}
+}
+
 void EclipseEngine::loadAssets() {
 	Common::File file;
 	if (_renderMode == Common::kRenderEGA) {
-		loadBundledImages();
+		file.open("SCN1E.DAT");
+		if (file.isOpen()) {
+			_title = load8bitBinImage(&file, 0x0);
+		}
+		file.close();
 		file.open("TOTEE.EXE");
 
 		if (!file.isOpen())
@@ -112,7 +128,7 @@ void EclipseEngine::loadAssets() {
 		load8bitBinary(&file, 0x3ce0, 16);
 		for (auto &it : _areaMap)
 			it._value->addStructure(_areaMap[255]);
-
+		_border = load8bitBinImage(&file, 0x210);
 	} else if (_renderMode == Common::kRenderCGA) {
 		loadBundledImages();
 		file.open("TOTEC.EXE");


Commit: 94c52bf7bf0b76f68d1b05aceb6a46fb7d99a0f9
    https://github.com/scummvm/scummvm/commit/94c52bf7bf0b76f68d1b05aceb6a46fb7d99a0f9
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-03-20T09:13:58+01:00

Commit Message:
FREESCAPE: implemented scr image loader and read title/borders images in driller for zx directly from the game data

Changed paths:
  A engines/freescape/scr.cpp
  A engines/freescape/scr.h
    engines/freescape/freescape.cpp
    engines/freescape/freescape.h
    engines/freescape/games/driller.cpp
    engines/freescape/module.mk


diff --git a/engines/freescape/freescape.cpp b/engines/freescape/freescape.cpp
index f02e22ff73f..851ed926571 100644
--- a/engines/freescape/freescape.cpp
+++ b/engines/freescape/freescape.cpp
@@ -30,6 +30,7 @@
 #include "freescape/freescape.h"
 #include "freescape/language/8bitDetokeniser.h"
 #include "freescape/neo.h"
+#include "freescape/scr.h"
 #include "freescape/objects/sensor.h"
 
 namespace Freescape {
@@ -185,7 +186,6 @@ void FreescapeEngine::drawBorder() {
 		return;
 
 	_gfx->setViewport(_fullscreenViewArea);
-
 	assert(_borderTexture);
 	_gfx->drawTexturedRect2D(_fullscreenViewArea, _fullscreenViewArea, _borderTexture);
 	_gfx->setViewport(_viewArea);
@@ -879,6 +879,16 @@ Graphics::Surface *FreescapeEngine::loadAndConvertNeoImage(Common::SeekableReadS
 	return surface;
 }
 
+Graphics::Surface *FreescapeEngine::loadAndCenterScrImage(Common::SeekableReadStream *stream) {
+	ScrDecoder decoder;
+	decoder.loadStream(*stream);
+	Graphics::Surface *surface = new Graphics::Surface();
+	const Graphics::Surface *decoded = decoder.getSurface();
+	surface->create(320, 200, decoded->format);
+	surface->copyRectToSurface(*decoded, (320 - decoded->w) / 2, (200 - decoded->h) / 2, Common::Rect(decoded->w, decoded->h));
+	return surface;
+}
+
 void FreescapeEngine::getTimeFromCountdown(int &seconds, int &minutes, int &hours) {
 	int countdown = _countdown;
 	int h = countdown <= 0 ? 0 : countdown / 3600;
diff --git a/engines/freescape/freescape.h b/engines/freescape/freescape.h
index 975f8c9d5e3..5a255ca3b3d 100644
--- a/engines/freescape/freescape.h
+++ b/engines/freescape/freescape.h
@@ -140,6 +140,7 @@ public:
 	void loadBundledImages();
 	byte *getPaletteFromNeoImage(Common::SeekableReadStream *stream, int offset);
 	Graphics::Surface *loadAndConvertNeoImage(Common::SeekableReadStream *stream, int offset, byte *palette = nullptr);
+	Graphics::Surface *loadAndCenterScrImage(Common::SeekableReadStream *stream);
 	void loadPalettes(Common::SeekableReadStream *file, int offset);
 	void swapPalette(uint16 areaID);
 	Common::HashMap<uint16, byte *> _paletteByArea;
diff --git a/engines/freescape/games/driller.cpp b/engines/freescape/games/driller.cpp
index 902000f563d..5650a51e3a5 100644
--- a/engines/freescape/games/driller.cpp
+++ b/engines/freescape/games/driller.cpp
@@ -538,7 +538,21 @@ void DrillerEngine::loadAssetsFullGame() {
 		loadPalettes(&file, 0x296fa);
 		loadSoundsFx(&file, 0x30da6, 25);
 	} else if (isSpectrum()) {
-		loadBundledImages();
+		file.open("driller.zx.title");
+		if (file.isOpen()) {
+			_title = loadAndCenterScrImage(&file);
+		} else
+			error("Unable to find driller.zx.title");
+
+		file.close();
+
+		file.open("driller.zx.border");
+		if (file.isOpen()) {
+			_border = loadAndCenterScrImage(&file);
+		} else
+			error("Unable to find driller.zx.border");
+		file.close();
+
 		file.open("driller.zx.extracted");
 
 		if (!file.isOpen())
diff --git a/engines/freescape/module.mk b/engines/freescape/module.mk
index 9b3b656ce6c..556a28f6efa 100644
--- a/engines/freescape/module.mk
+++ b/engines/freescape/module.mk
@@ -18,6 +18,7 @@ MODULE_OBJS := \
 	neo.o \
 	objects/geometricobject.o \
 	objects/sensor.o \
+	scr.o \
 	sound.o
 
 ifdef USE_TINYGL
diff --git a/engines/freescape/scr.cpp b/engines/freescape/scr.cpp
new file mode 100644
index 00000000000..1621363fe30
--- /dev/null
+++ b/engines/freescape/scr.cpp
@@ -0,0 +1,105 @@
+/* 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 3 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, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "common/stream.h"
+#include "common/textconsole.h"
+#include "graphics/pixelformat.h"
+#include "graphics/surface.h"
+
+#include "freescape/scr.h"
+
+namespace Freescape {
+
+ScrDecoder::ScrDecoder() {
+	_surface = nullptr;
+}
+
+ScrDecoder::~ScrDecoder() {
+	destroy();
+}
+
+void ScrDecoder::destroy() {
+	if (_surface) {
+		_surface->free();
+		delete _surface;
+		_surface = nullptr;
+	}
+}
+
+uint32 ScrDecoder::getPixelAddress(int x, int y) {
+	uint32 y76 = y & 0xc0;
+	uint32 y53 = y & 0x38;
+	uint32 y20 = y & 0x07;
+	return (y76 << 5) + (y20 << 8) + (y53 << 2) + (x >> 3);
+}
+
+uint32 ScrDecoder::getAttributeAddress(int x, int y) {
+	uint32 y73 = y & 0xf8;
+	return (y73 << 2) + (x >> 3);
+}
+
+bool ScrDecoder::loadStream(Common::SeekableReadStream &stream) {
+	destroy();
+
+	if (stream.size() != 6912)
+		warning("Header check failed for reading scr image");
+
+	byte *data = (byte *)malloc(6144 * sizeof(byte));
+	byte *attributes = (byte *)malloc(768 * sizeof(byte));
+
+	stream.read(data, 6144);
+	stream.read(attributes, 768);
+
+	int width = 256;
+	int height = 192;
+	Graphics::PixelFormat format(4, 8, 8, 8, 8, 24, 16, 8, 0);
+
+	_surface = new Graphics::Surface();
+	_surface->create(width, height, format);
+
+    for (int y = 0; y < height; y++) {
+		for (int col = 0; col < width >> 3; col++) {
+			int x = col << 3;
+			byte byt = data[getPixelAddress(x, y)];
+			byte attr = attributes[getAttributeAddress(x, y)];
+			byte ink = attr & 0x07;
+			byte paper = (attr >> 3) & 0x07;
+			byte bright = (attr >> 6) & 1;
+			byte val = bright ? 0xff : 0xcd;
+			for (int bit = 0; bit < 8; bit++) {
+				bool set = (byt >> (7 - bit)) & 1;
+				int color = set ? ink : paper;
+
+				byte r = val * (color >> 1 & 1);
+				byte g = val * (color >> 2 & 1);
+				byte b = val * (color >> 0 & 1);
+
+				_surface->setPixel(x + bit, y, format.ARGBToColor(0xFF, r, g, b));
+			}
+		}
+	}
+
+	free(data);
+	free(attributes);
+	return true;
+}
+
+} // End of namespace Freescape
diff --git a/engines/freescape/scr.h b/engines/freescape/scr.h
new file mode 100644
index 00000000000..054dc0a16de
--- /dev/null
+++ b/engines/freescape/scr.h
@@ -0,0 +1,54 @@
+/* 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 3 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, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef FREESCAPE_SCR_H
+#define FREESCAPE_SCR_H
+
+#include "image/image_decoder.h"
+
+/*
+ZX-Spectrum SCREEN$ decoder based on:
+https://gist.github.com/alexanderk23/f459c76847d9412548f7
+*/
+
+namespace Common {
+class SeekableReadStream;
+}
+
+namespace Freescape {
+
+class ScrDecoder : public Image::ImageDecoder {
+public:
+	ScrDecoder();
+	virtual ~ScrDecoder();
+
+	// ImageDecoder API
+	void destroy();
+	virtual bool loadStream(Common::SeekableReadStream &stream);
+	virtual const Graphics::Surface *getSurface() const { return _surface; }
+private:
+	Graphics::Surface *_surface;
+	uint32 getPixelAddress(int x, int y);
+	uint32 getAttributeAddress(int x, int y);
+};
+} // End of namespace Freescape
+
+#endif // FREESCAPE_SCR_H


Commit: 71e6e2b1f13530693ff75772512b50564b25a412
    https://github.com/scummvm/scummvm/commit/71e6e2b1f13530693ff75772512b50564b25a412
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-03-20T09:15:38+01:00

Commit Message:
FREESCAPE: renamed game data file for driller detection in several platforms

Changed paths:
    engines/freescape/detection.cpp
    engines/freescape/games/driller.cpp


diff --git a/engines/freescape/detection.cpp b/engines/freescape/detection.cpp
index 7dd8000c377..f3faa281ae6 100644
--- a/engines/freescape/detection.cpp
+++ b/engines/freescape/detection.cpp
@@ -39,7 +39,7 @@ static const ADGameDescription gameDescriptions[] = {
 		"driller",
 		"",
 		{
-			{"DRILLER.ZX.EXTRACTED", 0, "396c1789a7da3db5058d18eb8d2d35a3", 37590},
+			{"DRILLER.ZX.DATA", 0, "396c1789a7da3db5058d18eb8d2d35a3", 37590},
 			AD_LISTEND
 		},
 		Common::EN_ANY,
@@ -51,7 +51,7 @@ static const ADGameDescription gameDescriptions[] = {
 		"driller",
 		"",
 		{
-			{"DRILLER.ZX.EXTRACTED", 0, "6876fc03e754137f428bd4d5f16452b5", 37888},
+			{"DRILLER.ZX.DATA", 0, "6876fc03e754137f428bd4d5f16452b5", 37888},
 			AD_LISTEND
 		},
 		Common::EN_ANY,
@@ -63,7 +63,7 @@ static const ADGameDescription gameDescriptions[] = {
 		"driller",
 		"",
 		{
-			{"DRILLER.ZX.EXTRACTED", 0, "2b996ab877f45414f8e2ae4c862746f3", 35214},
+			{"DRILLER.ZX.DATA", 0, "2b996ab877f45414f8e2ae4c862746f3", 35214},
 			AD_LISTEND
 		},
 		Common::EN_ANY,
@@ -123,7 +123,7 @@ static const ADGameDescription gameDescriptions[] = {
 		"spacestationoblivion",
 		"",
 		{
-			{"SPACESTATIONOBLIVION.C64.EXTRACTED", 0, "85680576865e211f868885e9997a08b8", 22782},
+			{"SPACESTATIONOBLIVION.C64.DATA", 0, "85680576865e211f868885e9997a08b8", 22782},
 			AD_LISTEND
 		},
 		Common::EN_ANY,
@@ -136,7 +136,7 @@ static const ADGameDescription gameDescriptions[] = {
 		"spacestationoblivion",
 		"",
 		{
-			{"SPACESTATIONOBLIVION.C64.EXTRACTED", 0, "2b3537e21b8b871ec074df2962999781", 64514},
+			{"SPACESTATIONOBLIVION.C64.DATA", 0, "2b3537e21b8b871ec074df2962999781", 64514},
 			AD_LISTEND
 		},
 		Common::EN_ANY,
@@ -148,7 +148,7 @@ static const ADGameDescription gameDescriptions[] = {
 		"driller", // Commodore Force - Jan 94
 		"",
 		{
-			{"DRILLER.C64.EXTRACTED", 0, "511778d3167ff7504d905df507a03ac5", 63490},
+			{"DRILLER.C64.DATA", 0, "511778d3167ff7504d905df507a03ac5", 63490},
 			AD_LISTEND
 		},
 		Common::EN_ANY,
@@ -160,7 +160,7 @@ static const ADGameDescription gameDescriptions[] = {
 		"driller",
 		"",
 		{
-			{"DRILLER.C64.EXTRACTED", 0, "73a6f206e54fb13245fe6d92f60fbb34", 41071},
+			{"DRILLER.C64.DATA", 0, "73a6f206e54fb13245fe6d92f60fbb34", 41071},
 			AD_LISTEND
 		},
 		Common::EN_ANY,
diff --git a/engines/freescape/games/driller.cpp b/engines/freescape/games/driller.cpp
index 5650a51e3a5..ba40a2a0975 100644
--- a/engines/freescape/games/driller.cpp
+++ b/engines/freescape/games/driller.cpp
@@ -553,10 +553,10 @@ void DrillerEngine::loadAssetsFullGame() {
 			error("Unable to find driller.zx.border");
 		file.close();
 
-		file.open("driller.zx.extracted");
+		file.open("driller.zx.data");
 
 		if (!file.isOpen())
-			error("Failed to open driller.zx.extracted");
+			error("Failed to open driller.zx.data");
 
 		if (_variant & GF_ZX_DISC)
 			loadMessagesFixedSize(&file, 0x2164, 14, 20);
@@ -648,13 +648,13 @@ void DrillerEngine::loadAssetsFullGame() {
 	} else if (isC64()) {
 		if (_targetName.hasPrefix("spacestationoblivion")) {
 			loadBundledImages();
-			file.open("spacestationoblivion.c64.extracted");
+			file.open("spacestationoblivion.c64.data");
 			loadMessagesFixedSize(&file, 0x167a, 14, 20);
 			//loadFonts(&file, 0xae54);
 			load8bitBinary(&file, 0x8e02, 4);
 			loadGlobalObjects(&file, 0x1855);
 		} else if (_targetName.hasPrefix("driller")) {
-			file.open("driller.c64.extracted");
+			file.open("driller.c64.data");
 			loadMessagesFixedSize(&file, 0x167a - 0x400, 14, 20);
 			//loadFonts(&file, 0xae54);
 			load8bitBinary(&file, 0x8e02 - 0x400, 4);


Commit: a62b58adcaaa520dff292ce7500e204dd176a79b
    https://github.com/scummvm/scummvm/commit/a62b58adcaaa520dff292ce7500e204dd176a79b
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-03-20T09:15:47+01:00

Commit Message:
FREESCAPE: small adjustments for driller ui for zx

Changed paths:
    engines/freescape/games/driller.cpp


diff --git a/engines/freescape/games/driller.cpp b/engines/freescape/games/driller.cpp
index ba40a2a0975..ddc463130ce 100644
--- a/engines/freescape/games/driller.cpp
+++ b/engines/freescape/games/driller.cpp
@@ -106,7 +106,7 @@ DrillerEngine::DrillerEngine(OSystem *syst, const ADGameDescription *gd) : Frees
 	else if (isAmiga() || isAtariST())
 		_viewArea = Common::Rect(36, 16, 284, 118);
 	else if (isSpectrum())
-		_viewArea = Common::Rect(58, 20, 266, 124);
+		_viewArea = Common::Rect(56, 20, 264, 124);
 	else if (isCPC())
 		_viewArea = Common::Rect(36, 19, 284, 120);
 	else if (isC64())
@@ -1037,30 +1037,30 @@ void DrillerEngine::drawZXUI(Graphics::Surface *surface) {
 	uint32 white = _gfx->_texturePixelFormat.ARGBToColor(0xFF, 0xFF, 0xFF, 0xFF);
 
 	int score = _gameStateVars[k8bitVariableScore];
-	drawStringInSurface(_currentArea->_name, 176, 188, front, back, surface);
-	drawStringInSurface(Common::String::format("%04d", int(2 * _position.x())), 152, 149, front, back, surface);
-	drawStringInSurface(Common::String::format("%04d", int(2 * _position.z())), 152, 157, front, back, surface);
-	drawStringInSurface(Common::String::format("%04d", int(2 * _position.y())), 152, 165, front, back, surface);
+	drawStringInSurface(_currentArea->_name, 174, 188, front, back, surface);
+	drawStringInSurface(Common::String::format("%04d", int(2 * _position.x())), 150, 149, front, back, surface);
+	drawStringInSurface(Common::String::format("%04d", int(2 * _position.z())), 150, 157, front, back, surface);
+	drawStringInSurface(Common::String::format("%04d", int(2 * _position.y())), 150, 165, front, back, surface);
 	if (_playerHeightNumber >= 0)
-		drawStringInSurface(Common::String::format("%d", _playerHeightNumber), 74, 165, front, back, surface);
+		drawStringInSurface(Common::String::format("%d", _playerHeightNumber), 72, 165, front, back, surface);
 	else
-		drawStringInSurface(Common::String::format("%s", "J"), 74, 165, front, back, surface);
+		drawStringInSurface(Common::String::format("%s", "J"), 72, 165, front, back, surface);
 
-	drawStringInSurface(Common::String::format("%02d", int(_angleRotations[_angleRotationIndex])), 64, 149, front, back, surface);
-	drawStringInSurface(Common::String::format("%3d", _playerSteps[_playerStepIndex]), 65, 157, front, back, surface);
-	drawStringInSurface(Common::String::format("%07d", score), 217, 133, white, back, surface);
+	drawStringInSurface(Common::String::format("%02d", int(_angleRotations[_angleRotationIndex])), 62, 149, front, back, surface);
+	drawStringInSurface(Common::String::format("%3d", _playerSteps[_playerStepIndex]), 63, 157, front, back, surface);
+	drawStringInSurface(Common::String::format("%07d", score), 215, 133, white, back, surface);
 
 	int seconds, minutes, hours;
 	getTimeFromCountdown(seconds, minutes, hours);
-	drawStringInSurface(Common::String::format("%02d", hours), 187, 12, front, back, surface);
-	drawStringInSurface(Common::String::format("%02d", minutes), 209, 12, front, back, surface);
-	drawStringInSurface(Common::String::format("%02d", seconds), 232, 12, front, back, surface);
+	drawStringInSurface(Common::String::format("%02d", hours), 185, 12, front, back, surface);
+	drawStringInSurface(Common::String::format("%02d", minutes), 207, 12, front, back, surface);
+	drawStringInSurface(Common::String::format("%02d", seconds), 230, 12, front, back, surface);
 
 	Common::String message;
 	int deadline;
 	getLatestMessages(message, deadline);
 	if (deadline <= _countdown) {
-		drawStringInSurface(message, 169, 181, back, front, surface);
+		drawStringInSurface(message, 167, 181, back, front, surface);
 		_temporaryMessages.push_back(message);
 		_temporaryMessageDeadlines.push_back(deadline);
 	} else {
@@ -1071,24 +1071,24 @@ void DrillerEngine::drawZXUI(Graphics::Surface *surface) {
 		else
 			message = _messagesList[1];
 
-		drawStringInSurface(message, 169, 181, front, back, surface);
+		drawStringInSurface(message, 167, 181, front, back, surface);
 	}
 
 	int energy = _gameStateVars[k8bitVariableEnergy];
 	int shield = _gameStateVars[k8bitVariableShield];
 
 	if (energy >= 0) {
-		Common::Rect backBar(45, 188, 109 - energy, 194);
+		Common::Rect backBar(43, 188, 107 - energy, 194);
 		surface->fillRect(backBar, back);
-		Common::Rect energyBar(108 - energy, 188, 108, 194);
+		Common::Rect energyBar(106 - energy, 188, 106, 194);
 		surface->fillRect(energyBar, front);
 	}
 
 	if (shield >= 0) {
-		Common::Rect backBar(45, 181, 109 - shield, 187);
+		Common::Rect backBar(43, 181, 107 - shield, 187);
 		surface->fillRect(backBar, back);
 
-		Common::Rect shieldBar(108 - shield, 181, 108, 187);
+		Common::Rect shieldBar(106 - shield, 181, 106, 187);
 		surface->fillRect(shieldBar, front);
 	}
 }


Commit: 752d202f4622df93620ec46581449753a488a422
    https://github.com/scummvm/scummvm/commit/752d202f4622df93620ec46581449753a488a422
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-03-20T09:16:06+01:00

Commit Message:
FREESCAPE: refactored deobfuscation code for driller cpc

Changed paths:
    engines/freescape/games/driller.cpp


diff --git a/engines/freescape/games/driller.cpp b/engines/freescape/games/driller.cpp
index ddc463130ce..e6de67e06f7 100644
--- a/engines/freescape/games/driller.cpp
+++ b/engines/freescape/games/driller.cpp
@@ -393,7 +393,6 @@ void DrillerEngine::loadAssetsDemo() {
 	_angleRotationIndex = 0;
 }
 
-
 byte *parseEDSK(const Common::String filename, int &size) {
 	debugC(1, kFreescapeDebugParser, "Trying to parse edsk file: %s", filename.c_str());
 	Common::File file;
@@ -457,6 +456,38 @@ byte *parseEDSK(const Common::String filename, int &size) {
 	return memBuffer;
 }
 
+void deobfuscateDrillerCPCVirtualWorlds(byte *memBuffer) {
+	// Deofuscation / loader code
+	for (int j = 0; j < 0x200; j++) {
+		memBuffer[0x14000 + j] = memBuffer[0x14200 + j];
+		memBuffer[0x14200 + j] = memBuffer[0x13400 + j];
+		memBuffer[0x14400 + j] = memBuffer[0x13800 + j];
+		memBuffer[0x14600 + j] = memBuffer[0x13c00 + j];
+	}
+
+	for (int j = 0; j < 0x200; j++) {
+		memBuffer[0x13c00 + j] = memBuffer[0x13a00 + j];
+		memBuffer[0x13a00 + j] = memBuffer[0x13600 + j];
+		memBuffer[0x13800 + j] = memBuffer[0x13200 + j];
+		memBuffer[0x13600 + j] = memBuffer[0x12e00 + j];
+		memBuffer[0x12e00 + j] = memBuffer[0x13000 + j];
+		memBuffer[0x13000 + j] = memBuffer[0x12200 + j];
+		memBuffer[0x13200 + j] = memBuffer[0x12600 + j];
+		memBuffer[0x13400 + j] = memBuffer[0x12a00 + j];
+	}
+
+	for (int i = 6; i >= 0; i--) {
+		//debug("copying 0x200 bytes to %x from %x", 0x12000 + 0x200*i, 0x11400 + 0x400*i);
+		for (int j = 0; j < 0x200; j++) {
+			memBuffer[0x12000 + 0x200*i + j] = memBuffer[0x11400 + 0x400*i + j];
+		}
+	}
+
+	for (int j = 0; j < 0x200; j++) {
+		memBuffer[0x11c00 + j] = memBuffer[0x11e00 + j];
+		memBuffer[0x11e00 + j] = memBuffer[0x11000 + j];
+	}
+}
 
 void DrillerEngine::loadAssetsFullGame() {
 	Common::File file;
@@ -590,37 +621,7 @@ void DrillerEngine::loadAssetsFullGame() {
 		int memSize = 0;
 		if (_variant & GF_CPC_VIRTUALWORLDS) {
 			memBuffer = parseEDSK("virtualworlds.A.cpc.edsk", memSize);
-
-			// Deofuscation / loader code
-			for (int j = 0; j < 0x200; j++) {
-				memBuffer[0x14000 + j] = memBuffer[0x14200 + j];
-				memBuffer[0x14200 + j] = memBuffer[0x13400 + j];
-				memBuffer[0x14400 + j] = memBuffer[0x13800 + j];
-				memBuffer[0x14600 + j] = memBuffer[0x13c00 + j];
-			}
-
-			for (int j = 0; j < 0x200; j++) {
-				memBuffer[0x13c00 + j] = memBuffer[0x13a00 + j];
-				memBuffer[0x13a00 + j] = memBuffer[0x13600 + j];
-				memBuffer[0x13800 + j] = memBuffer[0x13200 + j];
-				memBuffer[0x13600 + j] = memBuffer[0x12e00 + j];
-				memBuffer[0x12e00 + j] = memBuffer[0x13000 + j];
-				memBuffer[0x13000 + j] = memBuffer[0x12200 + j];
-				memBuffer[0x13200 + j] = memBuffer[0x12600 + j];
-				memBuffer[0x13400 + j] = memBuffer[0x12a00 + j];
-			}
-
-			for (int i = 6; i >= 0; i--) {
-				//debug("copying 0x200 bytes to %x from %x", 0x12000 + 0x200*i, 0x11400 + 0x400*i);
-				for (int j = 0; j < 0x200; j++) {
-					memBuffer[0x12000 + 0x200*i + j] = memBuffer[0x11400 + 0x400*i + j];
-				}
-			}
-
-			for (int j = 0; j < 0x200; j++) {
-				memBuffer[0x11c00 + j] = memBuffer[0x11e00 + j];
-				memBuffer[0x11e00 + j] = memBuffer[0x11000 + j];
-			}
+			deobfuscateDrillerCPCVirtualWorlds(memBuffer);
 		} else
 			memBuffer = parseEDSK("driller.cpc.edsk", memSize);
 		assert(memSize > 0);


Commit: 11dfbe8b7245d9e2e41bbbfd4af9d6dcc2d8db12
    https://github.com/scummvm/scummvm/commit/11dfbe8b7245d9e2e41bbbfd4af9d6dcc2d8db12
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-03-20T09:16:17+01:00

Commit Message:
FREESCAPE: fixed image loader and read title in driller for ega and updated freescape.dat

Changed paths:
  R devtools/create_freescape/darkside_ega.bmp
  R devtools/create_freescape/driller_cga_title.bmp
  R devtools/create_freescape/driller_ega.bmp
  R devtools/create_freescape/driller_ega_title.bmp
  R devtools/create_freescape/driller_zx.bmp
  R devtools/create_freescape/driller_zx_title.bmp
  R devtools/create_freescape/spacestationoblivion_cga.bmp
  R devtools/create_freescape/spacestationoblivion_cga_title.bmp
  R devtools/create_freescape/spacestationoblivion_ega.bmp
  R devtools/create_freescape/spacestationoblivion_ega_title.bmp
  R devtools/create_freescape/totaleclipse_ega.bmp
    devtools/create_freescape/version
    dists/engine-data/freescape.dat
    engines/freescape/freescape.cpp
    engines/freescape/freescape.h
    engines/freescape/games/driller.cpp
    engines/freescape/loaders/8bitBinaryLoader.cpp


diff --git a/devtools/create_freescape/darkside_ega.bmp b/devtools/create_freescape/darkside_ega.bmp
deleted file mode 100644
index 7622c9e58b2..00000000000
Binary files a/devtools/create_freescape/darkside_ega.bmp and /dev/null differ
diff --git a/devtools/create_freescape/driller_cga_title.bmp b/devtools/create_freescape/driller_cga_title.bmp
deleted file mode 100644
index 2741613f4a5..00000000000
Binary files a/devtools/create_freescape/driller_cga_title.bmp and /dev/null differ
diff --git a/devtools/create_freescape/driller_ega.bmp b/devtools/create_freescape/driller_ega.bmp
deleted file mode 100644
index ec3df6b4bb7..00000000000
Binary files a/devtools/create_freescape/driller_ega.bmp and /dev/null differ
diff --git a/devtools/create_freescape/driller_ega_title.bmp b/devtools/create_freescape/driller_ega_title.bmp
deleted file mode 100644
index b0ad1adc1f8..00000000000
Binary files a/devtools/create_freescape/driller_ega_title.bmp and /dev/null differ
diff --git a/devtools/create_freescape/driller_zx.bmp b/devtools/create_freescape/driller_zx.bmp
deleted file mode 100644
index 6cc207a6913..00000000000
Binary files a/devtools/create_freescape/driller_zx.bmp and /dev/null differ
diff --git a/devtools/create_freescape/driller_zx_title.bmp b/devtools/create_freescape/driller_zx_title.bmp
deleted file mode 100644
index 6421d62d97c..00000000000
Binary files a/devtools/create_freescape/driller_zx_title.bmp and /dev/null differ
diff --git a/devtools/create_freescape/spacestationoblivion_cga.bmp b/devtools/create_freescape/spacestationoblivion_cga.bmp
deleted file mode 100644
index 26efd4ce64a..00000000000
Binary files a/devtools/create_freescape/spacestationoblivion_cga.bmp and /dev/null differ
diff --git a/devtools/create_freescape/spacestationoblivion_cga_title.bmp b/devtools/create_freescape/spacestationoblivion_cga_title.bmp
deleted file mode 100644
index 2cdb371cde7..00000000000
Binary files a/devtools/create_freescape/spacestationoblivion_cga_title.bmp and /dev/null differ
diff --git a/devtools/create_freescape/spacestationoblivion_ega.bmp b/devtools/create_freescape/spacestationoblivion_ega.bmp
deleted file mode 100644
index 5965512fc9e..00000000000
Binary files a/devtools/create_freescape/spacestationoblivion_ega.bmp and /dev/null differ
diff --git a/devtools/create_freescape/spacestationoblivion_ega_title.bmp b/devtools/create_freescape/spacestationoblivion_ega_title.bmp
deleted file mode 100644
index 41c667015b6..00000000000
Binary files a/devtools/create_freescape/spacestationoblivion_ega_title.bmp and /dev/null differ
diff --git a/devtools/create_freescape/totaleclipse_ega.bmp b/devtools/create_freescape/totaleclipse_ega.bmp
deleted file mode 100644
index 738d6af20b4..00000000000
Binary files a/devtools/create_freescape/totaleclipse_ega.bmp and /dev/null differ
diff --git a/devtools/create_freescape/version b/devtools/create_freescape/version
index 56a6051ca2b..d8263ee9860 100644
--- a/devtools/create_freescape/version
+++ b/devtools/create_freescape/version
@@ -1 +1 @@
-1
\ No newline at end of file
+2
\ No newline at end of file
diff --git a/dists/engine-data/freescape.dat b/dists/engine-data/freescape.dat
index 301c12a46c6..322725f9b14 100644
Binary files a/dists/engine-data/freescape.dat and b/dists/engine-data/freescape.dat differ
diff --git a/engines/freescape/freescape.cpp b/engines/freescape/freescape.cpp
index 851ed926571..2c5b96da6aa 100644
--- a/engines/freescape/freescape.cpp
+++ b/engines/freescape/freescape.cpp
@@ -833,7 +833,7 @@ void FreescapeEngine::loadDataBundle() {
 	char *versionData = (char *)malloc((versionFile->size() + 1) * sizeof(char));
 	versionFile->read(versionData, versionFile->size());
 	versionData[versionFile->size()] = '\0';
-	Common::String expectedVersion = "1";
+	Common::String expectedVersion = "2";
 	if (versionData != expectedVersion)
 		error("Unexpected version number for freescape.dat: expecting '%s' but found '%s'", expectedVersion.c_str(), versionData);
 	free(versionData);
diff --git a/engines/freescape/freescape.h b/engines/freescape/freescape.h
index 5a255ca3b3d..058551b1981 100644
--- a/engines/freescape/freescape.h
+++ b/engines/freescape/freescape.h
@@ -171,7 +171,7 @@ public:
 	void renderPixels8bitBinCGAImage(Graphics::Surface *surface, int &i, int &j, uint8 pixels, int color);
 	void renderPixels8bitBinEGAImage(Graphics::Surface *surface, int &i, int &j, uint8 pixels, int color);
 
-	uint32 getPixel8bitImage(int index);
+	uint32 getPixel8bitTitleImage(int index);
 	Graphics::Surface *load8bitBinImage(Common::SeekableReadStream *file, int offset);
 	Graphics::Surface *load8bitTitleImage(Common::SeekableReadStream *file, int offset);
 
diff --git a/engines/freescape/games/driller.cpp b/engines/freescape/games/driller.cpp
index e6de67e06f7..3c172bff970 100644
--- a/engines/freescape/games/driller.cpp
+++ b/engines/freescape/games/driller.cpp
@@ -667,6 +667,12 @@ void DrillerEngine::loadAssetsFullGame() {
 			_title = load8bitBinImage(&file, 0x0);
 		}
 		file.close();
+		file.open("EGATITLE.RL");
+		if (file.isOpen()) {
+			_title = load8bitTitleImage(&file, 0x1b3);
+		}
+		file.close();
+
 		file.open("DRILLE.EXE");
 
 		if (!file.isOpen())
diff --git a/engines/freescape/loaders/8bitBinaryLoader.cpp b/engines/freescape/loaders/8bitBinaryLoader.cpp
index 1f29750bbff..e22eaad1f00 100644
--- a/engines/freescape/loaders/8bitBinaryLoader.cpp
+++ b/engines/freescape/loaders/8bitBinaryLoader.cpp
@@ -323,9 +323,9 @@ byte kEGADefaultPaletteData[16][3] = {
 	{0x00, 0x00, 0x00}
 };
 
-uint32 FreescapeEngine::getPixel8bitImage(int index) {
+uint32 FreescapeEngine::getPixel8bitTitleImage(int index) {
 	uint8 r, g, b;
-	if (index < 4) {
+	if (index < 4 || _renderMode == Common::kRenderEGA) {
 		_gfx->readFromPalette(index, r, g, b);
 		return _gfx->_currentPixelFormat.ARGBToColor(0xFF, r, g, b);
 	}
@@ -341,35 +341,42 @@ void FreescapeEngine::renderPixels8bitTitleImage(Graphics::Surface *surface, int
 		return;
 	}
 
-	surface->setPixel(i, j, getPixel8bitImage(c1 / 4));
-	i++;
-
-	if (i == 320) {
-		return;
+	if (_renderMode == Common::kRenderCGA) {
+		surface->setPixel(i, j, getPixel8bitTitleImage(c1 / 4));
+		i++;
+		if (i == 320) {
+			return;
+		}
 	}
 
-	surface->setPixel(i, j, getPixel8bitImage(c1));
+	surface->setPixel(i, j, getPixel8bitTitleImage(c1));
 	i++;
 
 	if (i == 320) {
 		return;
 	}
 
-	surface->setPixel(i, j, getPixel8bitImage(c2 / 4));
-	i++;
+	if (_renderMode == Common::kRenderCGA) {
+		surface->setPixel(i, j, getPixel8bitTitleImage(c2 / 4));
+		i++;
 
-	if (i == 320) {
-		return;
+		if (i == 320) {
+			return;
+		}
 	}
 
-	surface->setPixel(i, j, getPixel8bitImage(c2));
+	surface->setPixel(i, j, getPixel8bitTitleImage(c2));
 	i++;
 }
 
 Graphics::Surface *FreescapeEngine::load8bitTitleImage(Common::SeekableReadStream *file, int offset) {
 	Graphics::Surface *surface = new Graphics::Surface();
-	assert(_renderMode == Common::kRenderCGA);
-	_gfx->_palette = (byte *)kCGAPalettePinkBlueWhiteData;
+	if (_renderMode == Common::kRenderCGA)
+		_gfx->_palette = (byte *)kCGAPalettePinkBlueWhiteData;
+	else if (_renderMode == Common::kRenderEGA)
+		_gfx->_palette = (byte *)kEGADefaultPaletteData;
+	else
+		error("Invalid render mode: %d", _renderMode);
 	surface->create(_screenW, _screenH, _gfx->_currentPixelFormat);
 	uint32 black = _gfx->_currentPixelFormat.ARGBToColor(0xFF, 0, 0, 0);
 	surface->fillRect(Common::Rect(0, 0, 320, 200), black);


Commit: caa6e9c104faf9d8a81bdbd5f9d18e98bbb8df0b
    https://github.com/scummvm/scummvm/commit/caa6e9c104faf9d8a81bdbd5f9d18e98bbb8df0b
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-03-20T09:16:26+01:00

Commit Message:
FREESCAPE: refactored driller dos code into a directory

Changed paths:
  A engines/freescape/games/driller/dos.cpp
  A engines/freescape/games/driller/driller.cpp
  R engines/freescape/games/driller.cpp
    engines/freescape/freescape.h
    engines/freescape/loaders/8bitBinaryLoader.cpp
    engines/freescape/module.mk


diff --git a/engines/freescape/freescape.h b/engines/freescape/freescape.h
index 058551b1981..f45c683dfc4 100644
--- a/engines/freescape/freescape.h
+++ b/engines/freescape/freescape.h
@@ -165,16 +165,12 @@ public:
 	void load8bitBinary(Common::SeekableReadStream *file, int offset, int ncolors);
 	Area *load8bitArea(Common::SeekableReadStream *file, uint16 ncolors);
 	Object *load8bitObject(Common::SeekableReadStream *file);
-	void renderPixels8bitTitleImage(Graphics::Surface *surface, int &i, int &j, int pixels);
 	void renderPixels8bitBinImage(Graphics::Surface *surface, int &i, int &j, uint8 pixels, int color);
 
 	void renderPixels8bitBinCGAImage(Graphics::Surface *surface, int &i, int &j, uint8 pixels, int color);
 	void renderPixels8bitBinEGAImage(Graphics::Surface *surface, int &i, int &j, uint8 pixels, int color);
 
-	uint32 getPixel8bitTitleImage(int index);
 	Graphics::Surface *load8bitBinImage(Common::SeekableReadStream *file, int offset);
-	Graphics::Surface *load8bitTitleImage(Common::SeekableReadStream *file, int offset);
-
 
 	// Areas
 	uint16 _startArea;
@@ -448,6 +444,10 @@ private:
 	void drawCPCUI(Graphics::Surface *surface);
 	void drawC64UI(Graphics::Surface *surface);
 	void drawAmigaAtariSTUI(Graphics::Surface *surface);
+
+	Graphics::Surface *load8bitTitleImage(Common::SeekableReadStream *file, int offset);
+	uint32 getPixel8bitTitleImage(int index);
+	void renderPixels8bitTitleImage(Graphics::Surface *surface, int &i, int &j, int pixels);
 };
 
 class DarkEngine : public FreescapeEngine {
diff --git a/engines/freescape/games/driller/dos.cpp b/engines/freescape/games/driller/dos.cpp
new file mode 100644
index 00000000000..ad61fa078d0
--- /dev/null
+++ b/engines/freescape/games/driller/dos.cpp
@@ -0,0 +1,254 @@
+/* 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 3 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, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "freescape/freescape.h"
+#include "freescape/language/8bitDetokeniser.h"
+
+namespace Freescape {
+
+extern byte kCGAPalettePinkBlueWhiteData[4][3];
+extern byte kEGADefaultPaletteData[16][3];
+
+/*
+ The following functions are only used for decoding title images for
+ the US release of Driller ("Space Station Oblivion")
+*/
+
+uint32 DrillerEngine::getPixel8bitTitleImage(int index) {
+	uint8 r, g, b;
+	if (index < 4 || _renderMode == Common::kRenderEGA) {
+		_gfx->readFromPalette(index, r, g, b);
+		return _gfx->_currentPixelFormat.ARGBToColor(0xFF, r, g, b);
+	}
+	_gfx->readFromPalette(index / 4, r, g, b);
+	return _gfx->_currentPixelFormat.ARGBToColor(0xFF, r, g, b);
+}
+
+void DrillerEngine::renderPixels8bitTitleImage(Graphics::Surface *surface, int &i, int &j, int pixels) {
+	int c1 = pixels >> 4;
+	int c2 = pixels & 0xf;
+
+	if (i == 320) {
+		return;
+	}
+
+	if (_renderMode == Common::kRenderCGA) {
+		surface->setPixel(i, j, getPixel8bitTitleImage(c1 / 4));
+		i++;
+		if (i == 320) {
+			return;
+		}
+	}
+
+	surface->setPixel(i, j, getPixel8bitTitleImage(c1));
+	i++;
+
+	if (i == 320) {
+		return;
+	}
+
+	if (_renderMode == Common::kRenderCGA) {
+		surface->setPixel(i, j, getPixel8bitTitleImage(c2 / 4));
+		i++;
+
+		if (i == 320) {
+			return;
+		}
+	}
+
+	surface->setPixel(i, j, getPixel8bitTitleImage(c2));
+	i++;
+}
+
+Graphics::Surface *DrillerEngine::load8bitTitleImage(Common::SeekableReadStream *file, int offset) {
+	Graphics::Surface *surface = new Graphics::Surface();
+	if (_renderMode == Common::kRenderCGA)
+		_gfx->_palette = (byte *)kCGAPalettePinkBlueWhiteData;
+	else if (_renderMode == Common::kRenderEGA)
+		_gfx->_palette = (byte *)kEGADefaultPaletteData;
+	else
+		error("Invalid render mode: %d", _renderMode);
+	surface->create(_screenW, _screenH, _gfx->_currentPixelFormat);
+	uint32 black = _gfx->_currentPixelFormat.ARGBToColor(0xFF, 0, 0, 0);
+	surface->fillRect(Common::Rect(0, 0, 320, 200), black);
+
+	int i = 0;
+	int j = 0;
+	int command = -1;
+	int singlePixelsToProcess = 0;
+	bool repeatedPixelsToProcess = false;
+	file->seek(offset);
+	while (!file->eos()) {
+		assert(i <= 320);
+		int pixels = -1;
+		int repetition = -1;
+
+		if (singlePixelsToProcess == 0 && !repeatedPixelsToProcess) {
+			if (command < 0)
+				command = file->readByte();
+
+			//debug("reading command: %x at %lx", command, file->pos() - 1);
+
+			assert(command >= 0x7f);
+			singlePixelsToProcess = (0xff - command + 2) * 2;
+			//debug("single Pixels to process: %d", singlePixelsToProcess);
+
+			repeatedPixelsToProcess = true;
+			if (i == 320) {
+				j++;
+				i = 0;
+			}
+			command = -1;
+			continue;
+		}
+
+		if (singlePixelsToProcess > 0) {
+			singlePixelsToProcess--;
+			pixels = file->readByte();
+			//debug("reading pixels: %x at %d, %d", pixels, i, j);
+			renderPixels8bitTitleImage(surface, i, j, pixels);
+		} else if (repeatedPixelsToProcess) {
+			repetition = file->readByte() + 1;
+			//debug("reading repetition: %x", repetition - 1);
+			assert(repetition > 0);
+			if (repetition >= 0x80) {
+				command = repetition - 1;
+				repeatedPixelsToProcess = false;
+				continue;
+			}
+
+			if (i == 320) {
+				j++;
+				i = 0;
+				continue;
+			}
+
+			int pixels1 = file->readByte();
+			//debug("reading pixels: %x", pixels1);
+
+			int pixels2 = file->readByte();
+			//debug("reading pixels: %x", pixels2);
+
+			if (repetition >= 1) {
+				while (repetition > 0) {
+					repetition--;
+
+					if (i == 320) {
+						j++;
+						i = 0;
+					}
+
+					if (j == 200)
+						return surface;
+
+					//sdebug("repeating pixels: %x at %d, %d", pixels1, i, j);
+					renderPixels8bitTitleImage(surface, i, j, pixels1);
+
+					if (i == 320) {
+						j++;
+						i = 0;
+					}
+
+					if (j == 200)
+						return surface;
+
+					//debug("repeating pixels: %x at %d, %d", pixels2, i, j);
+					renderPixels8bitTitleImage(surface, i, j, pixels2);
+				}
+			}
+		}
+	}
+	return surface;
+}
+
+void DrillerEngine::drawDOSUI(Graphics::Surface *surface) {
+	uint32 color = _renderMode == Common::kRenderCGA ? 1 : 14;
+	uint8 r, g, b;
+
+	_gfx->readFromPalette(color, r, g, b);
+	uint32 front = _gfx->_texturePixelFormat.ARGBToColor(0xFF, r, g, b);
+
+	color = _currentArea->_usualBackgroundColor;
+	if (_gfx->_colorRemaps && _gfx->_colorRemaps->contains(color)) {
+		color = (*_gfx->_colorRemaps)[color];
+	}
+
+	_gfx->readFromPalette(color, r, g, b);
+	uint32 back = _gfx->_texturePixelFormat.ARGBToColor(0xFF, r, g, b);
+
+	int score = _gameStateVars[k8bitVariableScore];
+	drawStringInSurface(_currentArea->_name, 196, 185, front, back, surface);
+	drawStringInSurface(Common::String::format("%04d", int(2 * _position.x())), 150, 145, front, back, surface);
+	drawStringInSurface(Common::String::format("%04d", int(2 * _position.z())), 150, 153, front, back, surface);
+	drawStringInSurface(Common::String::format("%04d", int(2 * _position.y())), 150, 161, front, back, surface);
+	if (_playerHeightNumber >= 0)
+		drawStringInSurface(Common::String::format("%d", _playerHeightNumber), 57, 161, front, back, surface);
+	else
+		drawStringInSurface(Common::String::format("%s", "J"), 57, 161, front, back, surface);
+
+	drawStringInSurface(Common::String::format("%02d", int(_angleRotations[_angleRotationIndex])), 46, 145, front, back, surface);
+	drawStringInSurface(Common::String::format("%3d", _playerSteps[_playerStepIndex]), _renderMode == Common::kRenderCGA ? 44 : 46, 153, front, back, surface);
+	drawStringInSurface(Common::String::format("%07d", score), 238, 129, front, back, surface);
+
+	int seconds, minutes, hours;
+	getTimeFromCountdown(seconds, minutes, hours);
+	drawStringInSurface(Common::String::format("%02d", hours), 208, 8, front, back, surface);
+	drawStringInSurface(Common::String::format("%02d", minutes), 230, 8, front, back, surface);
+	drawStringInSurface(Common::String::format("%02d", seconds), 254, 8, front, back, surface);
+
+	Common::String message;
+	int deadline;
+	getLatestMessages(message, deadline);
+	if (deadline <= _countdown) {
+		drawStringInSurface(message, 190, 177, back, front, surface);
+		_temporaryMessages.push_back(message);
+		_temporaryMessageDeadlines.push_back(deadline);
+	} else {
+		if (_currentArea->_gasPocketRadius == 0)
+			message = _messagesList[2];
+		else if (_drillStatusByArea[_currentArea->getAreaID()])
+			message = _messagesList[0];
+		else
+			message = _messagesList[1];
+
+		drawStringInSurface(message, 191, 177, front, back, surface);
+	}
+
+	int energy = _gameStateVars[k8bitVariableEnergy];
+	int shield = _gameStateVars[k8bitVariableShield];
+
+	if (energy >= 0) {
+		Common::Rect backBar(20, 185, 88 - energy, 191);
+		surface->fillRect(backBar, back);
+		Common::Rect energyBar(87 - energy, 185, 88, 191);
+		surface->fillRect(energyBar, front);
+	}
+
+	if (shield >= 0) {
+		Common::Rect backBar(20, 177, 88 - shield, 183);
+		surface->fillRect(backBar, back);
+
+		Common::Rect shieldBar(87 - shield, 177, 88, 183);
+		surface->fillRect(shieldBar, front);
+	}
+}
+
+} // End of namespace Freescape
\ No newline at end of file
diff --git a/engines/freescape/games/driller.cpp b/engines/freescape/games/driller/driller.cpp
similarity index 94%
rename from engines/freescape/games/driller.cpp
rename to engines/freescape/games/driller/driller.cpp
index 3c172bff970..06fe7489531 100644
--- a/engines/freescape/games/driller.cpp
+++ b/engines/freescape/games/driller/driller.cpp
@@ -811,78 +811,6 @@ void DrillerEngine::drawUI() {
 	delete surface;
 }
 
-void DrillerEngine::drawDOSUI(Graphics::Surface *surface) {
-	uint32 color = _renderMode == Common::kRenderCGA ? 1 : 14;
-	uint8 r, g, b;
-
-	_gfx->readFromPalette(color, r, g, b);
-	uint32 front = _gfx->_texturePixelFormat.ARGBToColor(0xFF, r, g, b);
-
-	color = _currentArea->_usualBackgroundColor;
-	if (_gfx->_colorRemaps && _gfx->_colorRemaps->contains(color)) {
-		color = (*_gfx->_colorRemaps)[color];
-	}
-
-	_gfx->readFromPalette(color, r, g, b);
-	uint32 back = _gfx->_texturePixelFormat.ARGBToColor(0xFF, r, g, b);
-
-	int score = _gameStateVars[k8bitVariableScore];
-	drawStringInSurface(_currentArea->_name, 196, 185, front, back, surface);
-	drawStringInSurface(Common::String::format("%04d", int(2 * _position.x())), 150, 145, front, back, surface);
-	drawStringInSurface(Common::String::format("%04d", int(2 * _position.z())), 150, 153, front, back, surface);
-	drawStringInSurface(Common::String::format("%04d", int(2 * _position.y())), 150, 161, front, back, surface);
-	if (_playerHeightNumber >= 0)
-		drawStringInSurface(Common::String::format("%d", _playerHeightNumber), 57, 161, front, back, surface);
-	else
-		drawStringInSurface(Common::String::format("%s", "J"), 57, 161, front, back, surface);
-
-	drawStringInSurface(Common::String::format("%02d", int(_angleRotations[_angleRotationIndex])), 46, 145, front, back, surface);
-	drawStringInSurface(Common::String::format("%3d", _playerSteps[_playerStepIndex]), _renderMode == Common::kRenderCGA ? 44 : 46, 153, front, back, surface);
-	drawStringInSurface(Common::String::format("%07d", score), 238, 129, front, back, surface);
-
-	int seconds, minutes, hours;
-	getTimeFromCountdown(seconds, minutes, hours);
-	drawStringInSurface(Common::String::format("%02d", hours), 208, 8, front, back, surface);
-	drawStringInSurface(Common::String::format("%02d", minutes), 230, 8, front, back, surface);
-	drawStringInSurface(Common::String::format("%02d", seconds), 254, 8, front, back, surface);
-
-	Common::String message;
-	int deadline;
-	getLatestMessages(message, deadline);
-	if (deadline <= _countdown) {
-		drawStringInSurface(message, 190, 177, back, front, surface);
-		_temporaryMessages.push_back(message);
-		_temporaryMessageDeadlines.push_back(deadline);
-	} else {
-		if (_currentArea->_gasPocketRadius == 0)
-			message = _messagesList[2];
-		else if (_drillStatusByArea[_currentArea->getAreaID()])
-			message = _messagesList[0];
-		else
-			message = _messagesList[1];
-
-		drawStringInSurface(message, 191, 177, front, back, surface);
-	}
-
-	int energy = _gameStateVars[k8bitVariableEnergy];
-	int shield = _gameStateVars[k8bitVariableShield];
-
-	if (energy >= 0) {
-		Common::Rect backBar(20, 185, 88 - energy, 191);
-		surface->fillRect(backBar, back);
-		Common::Rect energyBar(87 - energy, 185, 88, 191);
-		surface->fillRect(energyBar, front);
-	}
-
-	if (shield >= 0) {
-		Common::Rect backBar(20, 177, 88 - shield, 183);
-		surface->fillRect(backBar, back);
-
-		Common::Rect shieldBar(87 - shield, 177, 88, 183);
-		surface->fillRect(shieldBar, front);
-	}
-}
-
 void DrillerEngine::drawCPCUI(Graphics::Surface *surface) {
 	uint32 color = 1;
 	uint8 r, g, b;
diff --git a/engines/freescape/loaders/8bitBinaryLoader.cpp b/engines/freescape/loaders/8bitBinaryLoader.cpp
index e22eaad1f00..b39cd64c2e3 100644
--- a/engines/freescape/loaders/8bitBinaryLoader.cpp
+++ b/engines/freescape/loaders/8bitBinaryLoader.cpp
@@ -323,154 +323,6 @@ byte kEGADefaultPaletteData[16][3] = {
 	{0x00, 0x00, 0x00}
 };
 
-uint32 FreescapeEngine::getPixel8bitTitleImage(int index) {
-	uint8 r, g, b;
-	if (index < 4 || _renderMode == Common::kRenderEGA) {
-		_gfx->readFromPalette(index, r, g, b);
-		return _gfx->_currentPixelFormat.ARGBToColor(0xFF, r, g, b);
-	}
-	_gfx->readFromPalette(index / 4, r, g, b);
-	return _gfx->_currentPixelFormat.ARGBToColor(0xFF, r, g, b);
-}
-
-void FreescapeEngine::renderPixels8bitTitleImage(Graphics::Surface *surface, int &i, int &j, int pixels) {
-	int c1 = pixels >> 4;
-	int c2 = pixels & 0xf;
-
-	if (i == 320) {
-		return;
-	}
-
-	if (_renderMode == Common::kRenderCGA) {
-		surface->setPixel(i, j, getPixel8bitTitleImage(c1 / 4));
-		i++;
-		if (i == 320) {
-			return;
-		}
-	}
-
-	surface->setPixel(i, j, getPixel8bitTitleImage(c1));
-	i++;
-
-	if (i == 320) {
-		return;
-	}
-
-	if (_renderMode == Common::kRenderCGA) {
-		surface->setPixel(i, j, getPixel8bitTitleImage(c2 / 4));
-		i++;
-
-		if (i == 320) {
-			return;
-		}
-	}
-
-	surface->setPixel(i, j, getPixel8bitTitleImage(c2));
-	i++;
-}
-
-Graphics::Surface *FreescapeEngine::load8bitTitleImage(Common::SeekableReadStream *file, int offset) {
-	Graphics::Surface *surface = new Graphics::Surface();
-	if (_renderMode == Common::kRenderCGA)
-		_gfx->_palette = (byte *)kCGAPalettePinkBlueWhiteData;
-	else if (_renderMode == Common::kRenderEGA)
-		_gfx->_palette = (byte *)kEGADefaultPaletteData;
-	else
-		error("Invalid render mode: %d", _renderMode);
-	surface->create(_screenW, _screenH, _gfx->_currentPixelFormat);
-	uint32 black = _gfx->_currentPixelFormat.ARGBToColor(0xFF, 0, 0, 0);
-	surface->fillRect(Common::Rect(0, 0, 320, 200), black);
-
-	int i = 0;
-	int j = 0;
-	int command = -1;
-	int singlePixelsToProcess = 0;
-	bool repeatedPixelsToProcess = false;
-	file->seek(offset);
-	while (!file->eos()) {
-		assert(i <= 320);
-		int pixels = -1;
-		int repetition = -1;
-
-		if (singlePixelsToProcess == 0 && !repeatedPixelsToProcess) {
-			if (command < 0)
-				command = file->readByte();
-
-			//debug("reading command: %x at %lx", command, file->pos() - 1);
-
-			assert(command >= 0x7f);
-			singlePixelsToProcess = (0xff - command + 2) * 2;
-			//debug("single Pixels to process: %d", singlePixelsToProcess);
-
-			repeatedPixelsToProcess = true;
-			if (i == 320) {
-				j++;
-				i = 0;
-			}
-			command = -1;
-			continue;
-		}
-
-		if (singlePixelsToProcess > 0) {
-			singlePixelsToProcess--;
-			pixels = file->readByte();
-			//debug("reading pixels: %x at %d, %d", pixels, i, j);
-			renderPixels8bitTitleImage(surface, i, j, pixels);
-		} else if (repeatedPixelsToProcess) {
-			repetition = file->readByte() + 1;
-			//debug("reading repetition: %x", repetition - 1);
-			assert(repetition > 0);
-			if (repetition >= 0x80) {
-				command = repetition - 1;
-				repeatedPixelsToProcess = false;
-				continue;
-			}
-
-			if (i == 320) {
-				j++;
-				i = 0;
-				continue;
-			}
-
-			int pixels1 = file->readByte();
-			//debug("reading pixels: %x", pixels1);
-
-			int pixels2 = file->readByte();
-			//debug("reading pixels: %x", pixels2);
-
-			if (repetition >= 1) {
-				while (repetition > 0) {
-					repetition--;
-
-					if (i == 320) {
-						j++;
-						i = 0;
-					}
-
-					if (j == 200)
-						return surface;
-
-					//sdebug("repeating pixels: %x at %d, %d", pixels1, i, j);
-					renderPixels8bitTitleImage(surface, i, j, pixels1);
-
-					if (i == 320) {
-						j++;
-						i = 0;
-					}
-
-					if (j == 200)
-						return surface;
-
-					//debug("repeating pixels: %x at %d, %d", pixels2, i, j);
-					renderPixels8bitTitleImage(surface, i, j, pixels2);
-				}
-			}
-		}
-	}
-
-	return surface;
-}
-
 void FreescapeEngine::renderPixels8bitBinImage(Graphics::Surface *surface, int &i, int &j, uint8 pixels, int color) {
 	if (i >= 320) {
 		//debug("cannot continue, stopping here at row %d!", j);
diff --git a/engines/freescape/module.mk b/engines/freescape/module.mk
index 556a28f6efa..52433360c8e 100644
--- a/engines/freescape/module.mk
+++ b/engines/freescape/module.mk
@@ -6,7 +6,8 @@ MODULE_OBJS := \
 	freescape.o \
 	games/castle.o \
 	games/dark.o \
-	games/driller.o \
+	games/driller/dos.o \
+	games/driller/driller.o \
 	games/eclipse.o \
 	games/palettes.o \
 	gfx.o \


Commit: fa75a25946e15f39912ea0ae26ed40ff38b85407
    https://github.com/scummvm/scummvm/commit/fa75a25946e15f39912ea0ae26ed40ff38b85407
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-03-20T09:16:41+01:00

Commit Message:
FREESCAPE: refactored driller cpc code into a directory

Changed paths:
  A engines/freescape/games/driller/cpc.cpp
    engines/freescape/games/driller/driller.cpp
    engines/freescape/module.mk


diff --git a/engines/freescape/games/driller/cpc.cpp b/engines/freescape/games/driller/cpc.cpp
new file mode 100644
index 00000000000..dce9d4a6110
--- /dev/null
+++ b/engines/freescape/games/driller/cpc.cpp
@@ -0,0 +1,197 @@
+/* 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 3 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, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "common/file.h"
+
+#include "freescape/freescape.h"
+#include "freescape/language/8bitDetokeniser.h"
+
+namespace Freescape {
+
+byte *parseEDSK(const Common::String filename, int &size) {
+	debugC(1, kFreescapeDebugParser, "Trying to parse edsk file: %s", filename.c_str());
+	Common::File file;
+	file.open(filename);
+	if (!file.isOpen())
+		error("Failed to open %s", filename.c_str());
+
+	int totalSize = file.size();
+	byte *edskBuffer = (byte *)malloc(totalSize);
+	file.read(edskBuffer, totalSize);
+	file.close();
+
+	// We don't know the final size, but we allocate enough
+	byte *memBuffer = (byte *)malloc(totalSize);
+
+	byte nsides = edskBuffer[49];
+	assert(nsides == 1);
+	int ntracks = 0;
+	int i = 256;
+	int j = 0;
+	while (i + 1 < totalSize) {
+		byte ssize = edskBuffer[i + 0x14];
+		debugC(1, kFreescapeDebugParser, "i: %x ssize: %d, number: %d", i, ssize, edskBuffer[i + 0x10]);
+		assert(ssize == 3 || edskBuffer[i + 0x0] == 'T');
+		assert(ssize == 3 || edskBuffer[i + 0x1] == 'r');
+		assert(ssize == 3 || edskBuffer[i + 0x2] == 'a');
+		//assert(ssize == 3 || ntracks == edskBuffer[i + 0x10]);
+		int start = i + 0x100;
+		debugC(1, kFreescapeDebugParser, "sector size: %d", ssize);
+		if (ssize == 2) {
+			i = i + 9 * 512 + 256;
+		} else if (ssize == 5) {
+			i = i + 8 * 512 + 256;
+		} else if (ssize == 0) {
+			i = totalSize - 1;
+		} else if (ssize == 3) {
+			break; // Not sure
+		} else {
+			error("ssize: %d", ssize);
+		}
+		int osize = i - start;
+		debugC(1, kFreescapeDebugParser, "copying track %d start: %x size: %x, dest: %x", ntracks, start, osize, j);
+		memcpy(memBuffer + j, edskBuffer + start, osize);
+		j = j + osize;
+		ntracks++;
+	}
+	size = j;
+
+	if (0) { // Useful to debug where exactly each object is located in memory once it is parsed
+		i = 0;
+		while(i < j) {
+			debugN("%05x: ", i);
+			for (int k = 0; k <= 16; k++) {
+				debugN("%02x ", memBuffer[i]);
+				i++;
+			}
+			debugN("\n");
+		}
+	}
+	free(edskBuffer);
+	return memBuffer;
+}
+
+void deobfuscateDrillerCPCVirtualWorlds(byte *memBuffer) {
+	// Deofuscation / loader code
+	for (int j = 0; j < 0x200; j++) {
+		memBuffer[0x14000 + j] = memBuffer[0x14200 + j];
+		memBuffer[0x14200 + j] = memBuffer[0x13400 + j];
+		memBuffer[0x14400 + j] = memBuffer[0x13800 + j];
+		memBuffer[0x14600 + j] = memBuffer[0x13c00 + j];
+	}
+
+	for (int j = 0; j < 0x200; j++) {
+		memBuffer[0x13c00 + j] = memBuffer[0x13a00 + j];
+		memBuffer[0x13a00 + j] = memBuffer[0x13600 + j];
+		memBuffer[0x13800 + j] = memBuffer[0x13200 + j];
+		memBuffer[0x13600 + j] = memBuffer[0x12e00 + j];
+		memBuffer[0x12e00 + j] = memBuffer[0x13000 + j];
+		memBuffer[0x13000 + j] = memBuffer[0x12200 + j];
+		memBuffer[0x13200 + j] = memBuffer[0x12600 + j];
+		memBuffer[0x13400 + j] = memBuffer[0x12a00 + j];
+	}
+
+	for (int i = 6; i >= 0; i--) {
+		//debug("copying 0x200 bytes to %x from %x", 0x12000 + 0x200*i, 0x11400 + 0x400*i);
+		for (int j = 0; j < 0x200; j++) {
+			memBuffer[0x12000 + 0x200*i + j] = memBuffer[0x11400 + 0x400*i + j];
+		}
+	}
+
+	for (int j = 0; j < 0x200; j++) {
+		memBuffer[0x11c00 + j] = memBuffer[0x11e00 + j];
+		memBuffer[0x11e00 + j] = memBuffer[0x11000 + j];
+	}
+}
+
+void DrillerEngine::drawCPCUI(Graphics::Surface *surface) {
+	uint32 color = 1;
+	uint8 r, g, b;
+
+	_gfx->selectColorFromFourColorPalette(color, r, g, b);
+	uint32 front = _gfx->_texturePixelFormat.ARGBToColor(0xFF, r, g, b);
+
+	color = 0;
+	if (_gfx->_colorRemaps && _gfx->_colorRemaps->contains(color)) {
+		color = (*_gfx->_colorRemaps)[color];
+	}
+
+	_gfx->readFromPalette(color, r, g, b);
+	uint32 back = _gfx->_texturePixelFormat.ARGBToColor(0xFF, r, g, b);
+
+	int score = _gameStateVars[k8bitVariableScore];
+	drawStringInSurface(_currentArea->_name, 200, 188, front, back, surface);
+	drawStringInSurface(Common::String::format("%04d", int(2 * _position.x())), 149, 148, front, back, surface);
+	drawStringInSurface(Common::String::format("%04d", int(2 * _position.z())), 149, 156, front, back, surface);
+	drawStringInSurface(Common::String::format("%04d", int(2 * _position.y())), 149, 164, front, back, surface);
+	if (_playerHeightNumber >= 0)
+		drawStringInSurface(Common::String::format("%d", _playerHeightNumber), 54, 164, front, back, surface);
+	else
+		drawStringInSurface(Common::String::format("%s", "J"), 54, 164, front, back, surface);
+
+	drawStringInSurface(Common::String::format("%02d", int(_angleRotations[_angleRotationIndex])), 46, 148, front, back, surface);
+	drawStringInSurface(Common::String::format("%3d", _playerSteps[_playerStepIndex]), 44, 156, front, back, surface);
+	drawStringInSurface(Common::String::format("%07d", score), 239, 132, front, back, surface);
+
+	int seconds, minutes, hours;
+	getTimeFromCountdown(seconds, minutes, hours);
+	drawStringInSurface(Common::String::format("%02d", hours), 209, 11, front, back, surface);
+	drawStringInSurface(Common::String::format("%02d", minutes), 232, 11, front, back, surface);
+	drawStringInSurface(Common::String::format("%02d", seconds), 254, 11, front, back, surface);
+
+	Common::String message;
+	int deadline;
+	getLatestMessages(message, deadline);
+	if (deadline <= _countdown) {
+		drawStringInSurface(message, 191, 180, back, front, surface);
+		_temporaryMessages.push_back(message);
+		_temporaryMessageDeadlines.push_back(deadline);
+	} else if (_messagesList.size() > 0) {
+		if (_currentArea->_gasPocketRadius == 0)
+			message = _messagesList[2];
+		else if (_drillStatusByArea[_currentArea->getAreaID()])
+			message = _messagesList[0];
+		else
+			message = _messagesList[1];
+
+		drawStringInSurface(message, 191, 180, front, back, surface);
+	}
+
+	int energy = _gameStateVars[k8bitVariableEnergy];
+	int shield = _gameStateVars[k8bitVariableShield];
+
+	if (energy >= 0) {
+		Common::Rect backBar(25, 187, 89 - energy, 194);
+		surface->fillRect(backBar, back);
+		Common::Rect energyBar(88 - energy, 187, 88, 194);
+		surface->fillRect(energyBar, front);
+	}
+
+	if (shield >= 0) {
+		Common::Rect backBar(25, 180, 89 - shield, 186);
+		surface->fillRect(backBar, back);
+
+		Common::Rect shieldBar(88 - shield, 180, 88, 186);
+		surface->fillRect(shieldBar, front);
+	}
+}
+
+} // End of namespace Freescape
\ No newline at end of file
diff --git a/engines/freescape/games/driller/driller.cpp b/engines/freescape/games/driller/driller.cpp
index 06fe7489531..4e8f5cab455 100644
--- a/engines/freescape/games/driller/driller.cpp
+++ b/engines/freescape/games/driller/driller.cpp
@@ -393,101 +393,8 @@ void DrillerEngine::loadAssetsDemo() {
 	_angleRotationIndex = 0;
 }
 
-byte *parseEDSK(const Common::String filename, int &size) {
-	debugC(1, kFreescapeDebugParser, "Trying to parse edsk file: %s", filename.c_str());
-	Common::File file;
-	file.open(filename);
-	if (!file.isOpen())
-		error("Failed to open %s", filename.c_str());
-
-	int totalSize = file.size();
-	byte *edskBuffer = (byte *)malloc(totalSize);
-	file.read(edskBuffer, totalSize);
-	file.close();
-
-	// We don't know the final size, but we allocate enough
-	byte *memBuffer = (byte *)malloc(totalSize);
-
-	byte nsides = edskBuffer[49];
-	assert(nsides == 1);
-	int ntracks = 0;
-	int i = 256;
-	int j = 0;
-	while (i + 1 < totalSize) {
-		byte ssize = edskBuffer[i + 0x14];
-		debug("i: %x ssize: %d, number: %d", i, ssize, edskBuffer[i + 0x10]);
-		assert(ssize == 3 || edskBuffer[i + 0x0] == 'T');
-		assert(ssize == 3 || edskBuffer[i + 0x1] == 'r');
-		assert(ssize == 3 || edskBuffer[i + 0x2] == 'a');
-		//assert(ssize == 3 || ntracks == edskBuffer[i + 0x10]);
-		int start = i + 0x100;
-		debugC(1, kFreescapeDebugParser, "sector size: %d", ssize);
-		if (ssize == 2) {
-			i = i + 9 * 512 + 256;
-		} else if (ssize == 5) {
-			i = i + 8 * 512 + 256;
-		} else if (ssize == 0) {
-			i = totalSize - 1;
-		} else if (ssize == 3) {
-			break; // Not sure
-		} else {
-			error("ssize: %d", ssize);
-		}
-		int osize = i - start;
-		debugC(1, kFreescapeDebugParser, "copying track %d start: %x size: %x, dest: %x", ntracks, start, osize, j);
-		memcpy(memBuffer + j, edskBuffer + start, osize);
-		j = j + osize;
-		ntracks++;
-	}
-	size = j;
-
-	if (0) { // Useful to debug where exactly each object is located in memory once it is parsed
-		i = 0;
-		while(i < j) {
-			debugN("%05x: ", i);
-			for (int k = 0; k <= 16; k++) {
-				debugN("%02x ", memBuffer[i]);
-				i++;
-			}
-			debugN("\n");
-		}
-	}
-	free(edskBuffer);
-	return memBuffer;
-}
-
-void deobfuscateDrillerCPCVirtualWorlds(byte *memBuffer) {
-	// Deofuscation / loader code
-	for (int j = 0; j < 0x200; j++) {
-		memBuffer[0x14000 + j] = memBuffer[0x14200 + j];
-		memBuffer[0x14200 + j] = memBuffer[0x13400 + j];
-		memBuffer[0x14400 + j] = memBuffer[0x13800 + j];
-		memBuffer[0x14600 + j] = memBuffer[0x13c00 + j];
-	}
-
-	for (int j = 0; j < 0x200; j++) {
-		memBuffer[0x13c00 + j] = memBuffer[0x13a00 + j];
-		memBuffer[0x13a00 + j] = memBuffer[0x13600 + j];
-		memBuffer[0x13800 + j] = memBuffer[0x13200 + j];
-		memBuffer[0x13600 + j] = memBuffer[0x12e00 + j];
-		memBuffer[0x12e00 + j] = memBuffer[0x13000 + j];
-		memBuffer[0x13000 + j] = memBuffer[0x12200 + j];
-		memBuffer[0x13200 + j] = memBuffer[0x12600 + j];
-		memBuffer[0x13400 + j] = memBuffer[0x12a00 + j];
-	}
-
-	for (int i = 6; i >= 0; i--) {
-		//debug("copying 0x200 bytes to %x from %x", 0x12000 + 0x200*i, 0x11400 + 0x400*i);
-		for (int j = 0; j < 0x200; j++) {
-			memBuffer[0x12000 + 0x200*i + j] = memBuffer[0x11400 + 0x400*i + j];
-		}
-	}
-
-	for (int j = 0; j < 0x200; j++) {
-		memBuffer[0x11c00 + j] = memBuffer[0x11e00 + j];
-		memBuffer[0x11e00 + j] = memBuffer[0x11000 + j];
-	}
-}
+extern byte *parseEDSK(const Common::String filename, int &size);
+extern void deobfuscateDrillerCPCVirtualWorlds(byte *memBuffer);
 
 void DrillerEngine::loadAssetsFullGame() {
 	Common::File file;
@@ -811,78 +718,6 @@ void DrillerEngine::drawUI() {
 	delete surface;
 }
 
-void DrillerEngine::drawCPCUI(Graphics::Surface *surface) {
-	uint32 color = 1;
-	uint8 r, g, b;
-
-	_gfx->selectColorFromFourColorPalette(color, r, g, b);
-	uint32 front = _gfx->_texturePixelFormat.ARGBToColor(0xFF, r, g, b);
-
-	color = 0;
-	if (_gfx->_colorRemaps && _gfx->_colorRemaps->contains(color)) {
-		color = (*_gfx->_colorRemaps)[color];
-	}
-
-	_gfx->readFromPalette(color, r, g, b);
-	uint32 back = _gfx->_texturePixelFormat.ARGBToColor(0xFF, r, g, b);
-
-	int score = _gameStateVars[k8bitVariableScore];
-	drawStringInSurface(_currentArea->_name, 200, 188, front, back, surface);
-	drawStringInSurface(Common::String::format("%04d", int(2 * _position.x())), 149, 148, front, back, surface);
-	drawStringInSurface(Common::String::format("%04d", int(2 * _position.z())), 149, 156, front, back, surface);
-	drawStringInSurface(Common::String::format("%04d", int(2 * _position.y())), 149, 164, front, back, surface);
-	if (_playerHeightNumber >= 0)
-		drawStringInSurface(Common::String::format("%d", _playerHeightNumber), 54, 164, front, back, surface);
-	else
-		drawStringInSurface(Common::String::format("%s", "J"), 54, 164, front, back, surface);
-
-	drawStringInSurface(Common::String::format("%02d", int(_angleRotations[_angleRotationIndex])), 46, 148, front, back, surface);
-	drawStringInSurface(Common::String::format("%3d", _playerSteps[_playerStepIndex]), 44, 156, front, back, surface);
-	drawStringInSurface(Common::String::format("%07d", score), 239, 132, front, back, surface);
-
-	int seconds, minutes, hours;
-	getTimeFromCountdown(seconds, minutes, hours);
-	drawStringInSurface(Common::String::format("%02d", hours), 209, 11, front, back, surface);
-	drawStringInSurface(Common::String::format("%02d", minutes), 232, 11, front, back, surface);
-	drawStringInSurface(Common::String::format("%02d", seconds), 254, 11, front, back, surface);
-
-	Common::String message;
-	int deadline;
-	getLatestMessages(message, deadline);
-	if (deadline <= _countdown) {
-		drawStringInSurface(message, 191, 180, back, front, surface);
-		_temporaryMessages.push_back(message);
-		_temporaryMessageDeadlines.push_back(deadline);
-	} else if (_messagesList.size() > 0) {
-		if (_currentArea->_gasPocketRadius == 0)
-			message = _messagesList[2];
-		else if (_drillStatusByArea[_currentArea->getAreaID()])
-			message = _messagesList[0];
-		else
-			message = _messagesList[1];
-
-		drawStringInSurface(message, 191, 180, front, back, surface);
-	}
-
-	int energy = _gameStateVars[k8bitVariableEnergy];
-	int shield = _gameStateVars[k8bitVariableShield];
-
-	if (energy >= 0) {
-		Common::Rect backBar(25, 187, 89 - energy, 194);
-		surface->fillRect(backBar, back);
-		Common::Rect energyBar(88 - energy, 187, 88, 194);
-		surface->fillRect(energyBar, front);
-	}
-
-	if (shield >= 0) {
-		Common::Rect backBar(25, 180, 89 - shield, 186);
-		surface->fillRect(backBar, back);
-
-		Common::Rect shieldBar(88 - shield, 180, 88, 186);
-		surface->fillRect(shieldBar, front);
-	}
-}
-
 void DrillerEngine::drawC64UI(Graphics::Surface *surface) {
 	uint32 color = 1;
 	uint8 r, g, b;
diff --git a/engines/freescape/module.mk b/engines/freescape/module.mk
index 52433360c8e..bb36272aaa4 100644
--- a/engines/freescape/module.mk
+++ b/engines/freescape/module.mk
@@ -6,6 +6,7 @@ MODULE_OBJS := \
 	freescape.o \
 	games/castle.o \
 	games/dark.o \
+	games/driller/cpc.o \
 	games/driller/dos.o \
 	games/driller/driller.o \
 	games/eclipse.o \


Commit: 563c6b35bd1f6b07c7e42781e0dd92dc188d07db
    https://github.com/scummvm/scummvm/commit/563c6b35bd1f6b07c7e42781e0dd92dc188d07db
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-03-20T09:16:52+01:00

Commit Message:
FREESCAPE: refactored driller zx code into a directory

Changed paths:
  A engines/freescape/games/driller/zx.cpp
    engines/freescape/games/driller/driller.cpp
    engines/freescape/module.mk


diff --git a/engines/freescape/games/driller/driller.cpp b/engines/freescape/games/driller/driller.cpp
index 4e8f5cab455..0ece48d0123 100644
--- a/engines/freescape/games/driller/driller.cpp
+++ b/engines/freescape/games/driller/driller.cpp
@@ -790,79 +790,6 @@ void DrillerEngine::drawC64UI(Graphics::Surface *surface) {
 	}
 }
 
-void DrillerEngine::drawZXUI(Graphics::Surface *surface) {
-	uint32 color = 5;
-	uint8 r, g, b;
-
-	_gfx->readFromPalette(color, r, g, b);
-	uint32 front = _gfx->_texturePixelFormat.ARGBToColor(0xFF, r, g, b);
-
-	color = _currentArea->_usualBackgroundColor;
-	if (_gfx->_colorRemaps && _gfx->_colorRemaps->contains(color)) {
-		color = (*_gfx->_colorRemaps)[color];
-	}
-
-	_gfx->readFromPalette(color, r, g, b);
-	uint32 back = _gfx->_texturePixelFormat.ARGBToColor(0xFF, r, g, b);
-	uint32 white = _gfx->_texturePixelFormat.ARGBToColor(0xFF, 0xFF, 0xFF, 0xFF);
-
-	int score = _gameStateVars[k8bitVariableScore];
-	drawStringInSurface(_currentArea->_name, 174, 188, front, back, surface);
-	drawStringInSurface(Common::String::format("%04d", int(2 * _position.x())), 150, 149, front, back, surface);
-	drawStringInSurface(Common::String::format("%04d", int(2 * _position.z())), 150, 157, front, back, surface);
-	drawStringInSurface(Common::String::format("%04d", int(2 * _position.y())), 150, 165, front, back, surface);
-	if (_playerHeightNumber >= 0)
-		drawStringInSurface(Common::String::format("%d", _playerHeightNumber), 72, 165, front, back, surface);
-	else
-		drawStringInSurface(Common::String::format("%s", "J"), 72, 165, front, back, surface);
-
-	drawStringInSurface(Common::String::format("%02d", int(_angleRotations[_angleRotationIndex])), 62, 149, front, back, surface);
-	drawStringInSurface(Common::String::format("%3d", _playerSteps[_playerStepIndex]), 63, 157, front, back, surface);
-	drawStringInSurface(Common::String::format("%07d", score), 215, 133, white, back, surface);
-
-	int seconds, minutes, hours;
-	getTimeFromCountdown(seconds, minutes, hours);
-	drawStringInSurface(Common::String::format("%02d", hours), 185, 12, front, back, surface);
-	drawStringInSurface(Common::String::format("%02d", minutes), 207, 12, front, back, surface);
-	drawStringInSurface(Common::String::format("%02d", seconds), 230, 12, front, back, surface);
-
-	Common::String message;
-	int deadline;
-	getLatestMessages(message, deadline);
-	if (deadline <= _countdown) {
-		drawStringInSurface(message, 167, 181, back, front, surface);
-		_temporaryMessages.push_back(message);
-		_temporaryMessageDeadlines.push_back(deadline);
-	} else {
-		if (_currentArea->_gasPocketRadius == 0)
-			message = _messagesList[2];
-		else if (_drillStatusByArea[_currentArea->getAreaID()])
-			message = _messagesList[0];
-		else
-			message = _messagesList[1];
-
-		drawStringInSurface(message, 167, 181, front, back, surface);
-	}
-
-	int energy = _gameStateVars[k8bitVariableEnergy];
-	int shield = _gameStateVars[k8bitVariableShield];
-
-	if (energy >= 0) {
-		Common::Rect backBar(43, 188, 107 - energy, 194);
-		surface->fillRect(backBar, back);
-		Common::Rect energyBar(106 - energy, 188, 106, 194);
-		surface->fillRect(energyBar, front);
-	}
-
-	if (shield >= 0) {
-		Common::Rect backBar(43, 181, 107 - shield, 187);
-		surface->fillRect(backBar, back);
-
-		Common::Rect shieldBar(106 - shield, 181, 106, 187);
-		surface->fillRect(shieldBar, front);
-	}
-}
-
 void DrillerEngine::drawAmigaAtariSTUI(Graphics::Surface *surface) {
 	uint32 white = _gfx->_texturePixelFormat.ARGBToColor(0xFF, 0xFF, 0xFF, 0xFF);
 	uint32 yellow = _gfx->_texturePixelFormat.ARGBToColor(0xFF, 0xFF, 0xFF, 0x55);
diff --git a/engines/freescape/games/driller/zx.cpp b/engines/freescape/games/driller/zx.cpp
new file mode 100644
index 00000000000..482bde642bc
--- /dev/null
+++ b/engines/freescape/games/driller/zx.cpp
@@ -0,0 +1,100 @@
+/* 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 3 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, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "freescape/freescape.h"
+#include "freescape/language/8bitDetokeniser.h"
+
+namespace Freescape {
+
+void DrillerEngine::drawZXUI(Graphics::Surface *surface) {
+	uint32 color = 5;
+	uint8 r, g, b;
+
+	_gfx->readFromPalette(color, r, g, b);
+	uint32 front = _gfx->_texturePixelFormat.ARGBToColor(0xFF, r, g, b);
+
+	color = _currentArea->_usualBackgroundColor;
+	if (_gfx->_colorRemaps && _gfx->_colorRemaps->contains(color)) {
+		color = (*_gfx->_colorRemaps)[color];
+	}
+
+	_gfx->readFromPalette(color, r, g, b);
+	uint32 back = _gfx->_texturePixelFormat.ARGBToColor(0xFF, r, g, b);
+	uint32 white = _gfx->_texturePixelFormat.ARGBToColor(0xFF, 0xFF, 0xFF, 0xFF);
+
+	int score = _gameStateVars[k8bitVariableScore];
+	drawStringInSurface(_currentArea->_name, 174, 188, front, back, surface);
+	drawStringInSurface(Common::String::format("%04d", int(2 * _position.x())), 150, 149, front, back, surface);
+	drawStringInSurface(Common::String::format("%04d", int(2 * _position.z())), 150, 157, front, back, surface);
+	drawStringInSurface(Common::String::format("%04d", int(2 * _position.y())), 150, 165, front, back, surface);
+	if (_playerHeightNumber >= 0)
+		drawStringInSurface(Common::String::format("%d", _playerHeightNumber), 72, 165, front, back, surface);
+	else
+		drawStringInSurface(Common::String::format("%s", "J"), 72, 165, front, back, surface);
+
+	drawStringInSurface(Common::String::format("%02d", int(_angleRotations[_angleRotationIndex])), 62, 149, front, back, surface);
+	drawStringInSurface(Common::String::format("%3d", _playerSteps[_playerStepIndex]), 63, 157, front, back, surface);
+	drawStringInSurface(Common::String::format("%07d", score), 215, 133, white, back, surface);
+
+	int seconds, minutes, hours;
+	getTimeFromCountdown(seconds, minutes, hours);
+	drawStringInSurface(Common::String::format("%02d", hours), 185, 12, front, back, surface);
+	drawStringInSurface(Common::String::format("%02d", minutes), 207, 12, front, back, surface);
+	drawStringInSurface(Common::String::format("%02d", seconds), 230, 12, front, back, surface);
+
+	Common::String message;
+	int deadline;
+	getLatestMessages(message, deadline);
+	if (deadline <= _countdown) {
+		drawStringInSurface(message, 167, 181, back, front, surface);
+		_temporaryMessages.push_back(message);
+		_temporaryMessageDeadlines.push_back(deadline);
+	} else {
+		if (_currentArea->_gasPocketRadius == 0)
+			message = _messagesList[2];
+		else if (_drillStatusByArea[_currentArea->getAreaID()])
+			message = _messagesList[0];
+		else
+			message = _messagesList[1];
+
+		drawStringInSurface(message, 167, 181, front, back, surface);
+	}
+
+	int energy = _gameStateVars[k8bitVariableEnergy];
+	int shield = _gameStateVars[k8bitVariableShield];
+
+	if (energy >= 0) {
+		Common::Rect backBar(43, 188, 107 - energy, 194);
+		surface->fillRect(backBar, back);
+		Common::Rect energyBar(106 - energy, 188, 106, 194);
+		surface->fillRect(energyBar, front);
+	}
+
+	if (shield >= 0) {
+		Common::Rect backBar(43, 181, 107 - shield, 187);
+		surface->fillRect(backBar, back);
+
+		Common::Rect shieldBar(106 - shield, 181, 106, 187);
+		surface->fillRect(shieldBar, front);
+	}
+}
+
+} // End of namespace Freescape
\ No newline at end of file
diff --git a/engines/freescape/module.mk b/engines/freescape/module.mk
index bb36272aaa4..fd52dedacf2 100644
--- a/engines/freescape/module.mk
+++ b/engines/freescape/module.mk
@@ -9,6 +9,7 @@ MODULE_OBJS := \
 	games/driller/cpc.o \
 	games/driller/dos.o \
 	games/driller/driller.o \
+	games/driller/zx.o \
 	games/eclipse.o \
 	games/palettes.o \
 	gfx.o \


Commit: 3e5d0a3ad047d7148cb0246b1e3d26df6419f0a7
    https://github.com/scummvm/scummvm/commit/3e5d0a3ad047d7148cb0246b1e3d26df6419f0a7
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-03-20T09:17:01+01:00

Commit Message:
FREESCAPE: refactored driller amiga/atari code into a directory

Changed paths:
  A engines/freescape/games/driller/amiga.cpp
    engines/freescape/games/driller/driller.cpp
    engines/freescape/module.mk


diff --git a/engines/freescape/games/driller/amiga.cpp b/engines/freescape/games/driller/amiga.cpp
new file mode 100644
index 00000000000..913c267c33b
--- /dev/null
+++ b/engines/freescape/games/driller/amiga.cpp
@@ -0,0 +1,114 @@
+/* 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 3 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, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "freescape/freescape.h"
+#include "freescape/language/8bitDetokeniser.h"
+
+/*
+This file contains specific code for both Ammiga and AtariST implementations of Driller
+*/
+
+namespace Freescape {
+
+void DrillerEngine::drawAmigaAtariSTUI(Graphics::Surface *surface) {
+	uint32 white = _gfx->_texturePixelFormat.ARGBToColor(0xFF, 0xFF, 0xFF, 0xFF);
+	uint32 yellow = _gfx->_texturePixelFormat.ARGBToColor(0xFF, 0xFF, 0xFF, 0x55);
+	uint32 brownish = _gfx->_texturePixelFormat.ARGBToColor(0xFF, 0x9E, 0x80, 0x20);
+	uint32 brown = _gfx->_texturePixelFormat.ARGBToColor(0xFF, 0x7E, 0x60, 0x19);
+	uint32 black = _gfx->_texturePixelFormat.ARGBToColor(0xFF, 0x00, 0x00, 0x00);
+	uint32 transparent = _gfx->_texturePixelFormat.ARGBToColor(0x00, 0x00, 0x00, 0x00);
+
+	int score = _gameStateVars[k8bitVariableScore];
+	Common::String coords;
+
+	if (!isDemo()) { // It seems demos will not include the complete font?
+		drawStringInSurface("x", 37, 18, white, transparent, surface, 82);
+		coords = Common::String::format("%04d", 2 * int(_position.x()));
+		for (int i = 0; i < 4; i++)
+			drawStringInSurface(Common::String(coords[i]), 47 + 6*i, 18, white, transparent, surface, 112);
+
+		drawStringInSurface("y", 37, 26, white, transparent, surface, 82);
+		coords = Common::String::format("%04d", 2 * int(_position.z())); // Coords y and z are swapped!
+		for (int i = 0; i < 4; i++)
+			drawStringInSurface(Common::String(coords[i]), 47 + 6*i, 26, white, transparent, surface, 112);
+
+		drawStringInSurface("z", 37, 34, white, transparent, surface, 82);
+		coords = Common::String::format("%04d", 2 * int(_position.y())); // Coords y and z are swapped!
+		for (int i = 0; i < 4; i++)
+			drawStringInSurface(Common::String(coords[i]), 47 + 6*i, 34, white, transparent, surface, 112);
+	}
+
+	drawStringInSurface(_currentArea->_name, 188, 185, yellow, black, surface);
+	drawStringInSurface(Common::String::format("%07d", score), 240, 129, yellow, black, surface);
+
+	int seconds, minutes, hours;
+	getTimeFromCountdown(seconds, minutes, hours);
+	drawStringInSurface(Common::String::format("%02d:", hours), 208, 7, yellow, black, surface);
+	drawStringInSurface(Common::String::format("%02d:", minutes), 230, 7, yellow, black, surface);
+	drawStringInSurface(Common::String::format("%02d", seconds), 254, 7, yellow, black, surface);
+
+	Common::String message;
+	int deadline;
+	getLatestMessages(message, deadline);
+	if (deadline <= _countdown) {
+		drawStringInSurface(message, 188, 177, black, yellow, surface);
+		_temporaryMessages.push_back(message);
+		_temporaryMessageDeadlines.push_back(deadline);
+	} else {
+		if (_currentArea->_gasPocketRadius == 0)
+			message = _messagesList[2];
+		else if (_drillStatusByArea[_currentArea->getAreaID()])
+			message = _messagesList[0];
+		else
+			message = _messagesList[1];
+
+		drawStringInSurface(message, 188, 177, yellow, black, surface);
+	}
+
+	int energy = _gameStateVars[k8bitVariableEnergy];
+	int shield = _gameStateVars[k8bitVariableShield];
+
+	if (shield >= 0) {
+		Common::Rect shieldBar;
+		shieldBar = Common::Rect(11, 178, 76 - (k8bitMaxShield - shield), 184);
+		surface->fillRect(shieldBar, brown);
+
+		shieldBar = Common::Rect(11, 179, 76 - (k8bitMaxShield - shield), 183);
+		surface->fillRect(shieldBar, brownish);
+
+		shieldBar = Common::Rect(11, 180, 76 - (k8bitMaxShield - shield), 182);
+		surface->fillRect(shieldBar, yellow);
+	}
+
+	if (energy >= 0) {
+		Common::Rect energyBar;
+		energyBar = Common::Rect(11, 186, 75 - (k8bitMaxEnergy - energy), 192);
+		surface->fillRect(energyBar, brown);
+
+		energyBar = Common::Rect(11, 187, 75 - (k8bitMaxEnergy - energy), 191);
+		surface->fillRect(energyBar, brownish);
+
+		energyBar = Common::Rect(11, 188, 75 - (k8bitMaxEnergy - energy), 190);
+		surface->fillRect(energyBar, yellow);
+	}
+}
+
+} // End of namespace Freescape
\ No newline at end of file
diff --git a/engines/freescape/games/driller/driller.cpp b/engines/freescape/games/driller/driller.cpp
index 0ece48d0123..73179d250e4 100644
--- a/engines/freescape/games/driller/driller.cpp
+++ b/engines/freescape/games/driller/driller.cpp
@@ -790,89 +790,6 @@ void DrillerEngine::drawC64UI(Graphics::Surface *surface) {
 	}
 }
 
-void DrillerEngine::drawAmigaAtariSTUI(Graphics::Surface *surface) {
-	uint32 white = _gfx->_texturePixelFormat.ARGBToColor(0xFF, 0xFF, 0xFF, 0xFF);
-	uint32 yellow = _gfx->_texturePixelFormat.ARGBToColor(0xFF, 0xFF, 0xFF, 0x55);
-	uint32 brownish = _gfx->_texturePixelFormat.ARGBToColor(0xFF, 0x9E, 0x80, 0x20);
-	uint32 brown = _gfx->_texturePixelFormat.ARGBToColor(0xFF, 0x7E, 0x60, 0x19);
-	uint32 black = _gfx->_texturePixelFormat.ARGBToColor(0xFF, 0x00, 0x00, 0x00);
-	uint32 transparent = _gfx->_texturePixelFormat.ARGBToColor(0x00, 0x00, 0x00, 0x00);
-
-	int score = _gameStateVars[k8bitVariableScore];
-	Common::String coords;
-
-	if (!isDemo()) { // It seems demos will not include the complete font?
-		drawStringInSurface("x", 37, 18, white, transparent, surface, 82);
-		coords = Common::String::format("%04d", 2 * int(_position.x()));
-		for (int i = 0; i < 4; i++)
-			drawStringInSurface(Common::String(coords[i]), 47 + 6*i, 18, white, transparent, surface, 112);
-
-		drawStringInSurface("y", 37, 26, white, transparent, surface, 82);
-		coords = Common::String::format("%04d", 2 * int(_position.z())); // Coords y and z are swapped!
-		for (int i = 0; i < 4; i++)
-			drawStringInSurface(Common::String(coords[i]), 47 + 6*i, 26, white, transparent, surface, 112);
-
-		drawStringInSurface("z", 37, 34, white, transparent, surface, 82);
-		coords = Common::String::format("%04d", 2 * int(_position.y())); // Coords y and z are swapped!
-		for (int i = 0; i < 4; i++)
-			drawStringInSurface(Common::String(coords[i]), 47 + 6*i, 34, white, transparent, surface, 112);
-	}
-
-	drawStringInSurface(_currentArea->_name, 188, 185, yellow, black, surface);
-	drawStringInSurface(Common::String::format("%07d", score), 240, 129, yellow, black, surface);
-
-	int seconds, minutes, hours;
-	getTimeFromCountdown(seconds, minutes, hours);
-	drawStringInSurface(Common::String::format("%02d:", hours), 208, 7, yellow, black, surface);
-	drawStringInSurface(Common::String::format("%02d:", minutes), 230, 7, yellow, black, surface);
-	drawStringInSurface(Common::String::format("%02d", seconds), 254, 7, yellow, black, surface);
-
-	Common::String message;
-	int deadline;
-	getLatestMessages(message, deadline);
-	if (deadline <= _countdown) {
-		drawStringInSurface(message, 188, 177, black, yellow, surface);
-		_temporaryMessages.push_back(message);
-		_temporaryMessageDeadlines.push_back(deadline);
-	} else {
-		if (_currentArea->_gasPocketRadius == 0)
-			message = _messagesList[2];
-		else if (_drillStatusByArea[_currentArea->getAreaID()])
-			message = _messagesList[0];
-		else
-			message = _messagesList[1];
-
-		drawStringInSurface(message, 188, 177, yellow, black, surface);
-	}
-
-	int energy = _gameStateVars[k8bitVariableEnergy];
-	int shield = _gameStateVars[k8bitVariableShield];
-
-	if (shield >= 0) {
-		Common::Rect shieldBar;
-		shieldBar = Common::Rect(11, 178, 76 - (k8bitMaxShield - shield), 184);
-		surface->fillRect(shieldBar, brown);
-
-		shieldBar = Common::Rect(11, 179, 76 - (k8bitMaxShield - shield), 183);
-		surface->fillRect(shieldBar, brownish);
-
-		shieldBar = Common::Rect(11, 180, 76 - (k8bitMaxShield - shield), 182);
-		surface->fillRect(shieldBar, yellow);
-	}
-
-	if (energy >= 0) {
-		Common::Rect energyBar;
-		energyBar = Common::Rect(11, 186, 75 - (k8bitMaxEnergy - energy), 192);
-		surface->fillRect(energyBar, brown);
-
-		energyBar = Common::Rect(11, 187, 75 - (k8bitMaxEnergy - energy), 191);
-		surface->fillRect(energyBar, brownish);
-
-		energyBar = Common::Rect(11, 188, 75 - (k8bitMaxEnergy - energy), 190);
-		surface->fillRect(energyBar, yellow);
-	}
-}
-
 void DrillerEngine::drawInfoMenu() {
 	_savedScreen = _gfx->getScreenshot();
 
diff --git a/engines/freescape/module.mk b/engines/freescape/module.mk
index fd52dedacf2..b3baab38526 100644
--- a/engines/freescape/module.mk
+++ b/engines/freescape/module.mk
@@ -6,6 +6,7 @@ MODULE_OBJS := \
 	freescape.o \
 	games/castle.o \
 	games/dark.o \
+	games/driller/amiga.o \
 	games/driller/cpc.o \
 	games/driller/dos.o \
 	games/driller/driller.o \


Commit: 6ae0763ee4ee42897071b9ed68b63226fe9aab6d
    https://github.com/scummvm/scummvm/commit/6ae0763ee4ee42897071b9ed68b63226fe9aab6d
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-03-20T09:17:11+01:00

Commit Message:
FREESCAPE: refactored/moved driller code for loading assets in different platforms code

Changed paths:
    engines/freescape/freescape.h
    engines/freescape/games/driller/amiga.cpp
    engines/freescape/games/driller/cpc.cpp
    engines/freescape/games/driller/dos.cpp
    engines/freescape/games/driller/driller.cpp
    engines/freescape/games/driller/zx.cpp


diff --git a/engines/freescape/freescape.h b/engines/freescape/freescape.h
index f45c683dfc4..8b05dd4291b 100644
--- a/engines/freescape/freescape.h
+++ b/engines/freescape/freescape.h
@@ -439,6 +439,18 @@ private:
 	void loadAssetsDemo();
 	void loadAssetsFullGame();
 
+	void loadAssetsAmigaFullGame();
+	void loadAssetsAmigaDemo();
+
+	void loadAssetsDOSFullGame();
+	void loadAssetsDOSDemo();
+
+	void loadAssetsZXFullGame();
+	void loadAssetsZXDemo();
+
+	void loadAssetsCPCFullGame();
+	void loadAssetsCPCDemo();
+
 	void drawDOSUI(Graphics::Surface *surface);
 	void drawZXUI(Graphics::Surface *surface);
 	void drawCPCUI(Graphics::Surface *surface);
diff --git a/engines/freescape/games/driller/amiga.cpp b/engines/freescape/games/driller/amiga.cpp
index 913c267c33b..f1a6e01b542 100644
--- a/engines/freescape/games/driller/amiga.cpp
+++ b/engines/freescape/games/driller/amiga.cpp
@@ -18,16 +18,122 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  *
  */
+#include "common/file.h"
 
 #include "freescape/freescape.h"
 #include "freescape/language/8bitDetokeniser.h"
 
+namespace Freescape {
+
+void DrillerEngine::loadAssetsAmigaFullGame() {
+	Common::File file;
+	if (_variant & GF_AMIGA_RETAIL) {
+		file.open("driller");
+
+		if (!file.isOpen())
+			error("Failed to open 'driller' executable for Amiga");
+
+		_border = loadAndConvertNeoImage(&file, 0x137f4);
+		byte *palette = (byte *)malloc(16 * 3);
+		for (int i = 0; i < 16; i++) { // gray scale palette
+			palette[i * 3 + 0] = i * (255 / 16);
+			palette[i * 3 + 1] = i * (255 / 16);
+			palette[i * 3 + 2] = i * (255 / 16);
+		}
+		_title = loadAndConvertNeoImage(&file, 0x10, palette);
+
+		loadFonts(&file, 0x8940);
+		loadMessagesFixedSize(&file, 0xc66e, 14, 20);
+		loadGlobalObjects(&file, 0xbd62);
+		load8bitBinary(&file, 0x29c16, 16);
+		loadPalettes(&file, 0x297d4);
+		loadSoundsFx(&file, 0x30e80, 25);
+	} else if (_variant & GF_AMIGA_BUDGET) {
+		file.open("lift.neo");
+		if (!file.isOpen())
+			error("Failed to open 'lift.neo' file");
+
+		_title = loadAndConvertNeoImage(&file, 0);
+
+		file.close();
+		file.open("console.neo");
+		if (!file.isOpen())
+			error("Failed to open 'console.neo' file");
+
+		_border = loadAndConvertNeoImage(&file, 0);
+
+		file.close();
+		file.open("driller");
+		if (!file.isOpen())
+			error("Failed to open 'driller' executable for Amiga");
+
+		loadFonts(&file, 0xa62);
+		loadMessagesFixedSize(&file, 0x499a, 14, 20);
+		loadGlobalObjects(&file, 0x4098);
+		load8bitBinary(&file, 0x21a3e, 16);
+		loadPalettes(&file, 0x215fc);
+
+		file.close();
+		file.open("soundfx");
+		if (!file.isOpen())
+			error("Failed to open 'soundfx' executable for Amiga");
+
+		loadSoundsFx(&file, 0, 25);
+	} else
+		error("Invalid or unknown Amiga release");
+}
+
+void DrillerEngine::loadAssetsAmigaDemo() {
+	Common::File file;
+	file.open("lift.neo");
+	if (!file.isOpen())
+		error("Failed to open 'lift.neo' file");
+
+	_title = loadAndConvertNeoImage(&file, 0);
+
+	file.close();
+	file.open("console.neo");
+	if (!file.isOpen())
+		error("Failed to open 'console.neo' file");
+
+	_border = loadAndConvertNeoImage(&file, 0);
+
+	file.close();
+	file.open("demo.cmd");
+	if (!file.isOpen())
+		error("Failed to open 'demo.cmd' file");
+
+	loadDemoData(&file, 0, 0x1000);
+
+	file.close();
+	file.open("data");
+	if (!file.isOpen())
+		error("Failed to open 'data' file");
+
+	load8bitBinary(&file, 0x442, 16);
+	loadPalettes(&file, 0x0);
+
+	file.close();
+	file.open("driller");
+	if (!file.isOpen())
+		error("Failed to open 'driller' file");
+
+	loadFonts(&file, 0xa30);
+	loadMessagesFixedSize(&file, 0x3960, 14, 20);
+	loadGlobalObjects(&file, 0x3716);
+
+	file.close();
+	file.open("soundfx");
+	if (!file.isOpen())
+		error("Failed to open 'soundfx' executable for Amiga");
+
+	loadSoundsFx(&file, 0, 25);
+}
+
 /*
-This file contains specific code for both Ammiga and AtariST implementations of Driller
+The following function contains specific UI code for both Amiga and AtariST
 */
 
-namespace Freescape {
-
 void DrillerEngine::drawAmigaAtariSTUI(Graphics::Surface *surface) {
 	uint32 white = _gfx->_texturePixelFormat.ARGBToColor(0xFF, 0xFF, 0xFF, 0xFF);
 	uint32 yellow = _gfx->_texturePixelFormat.ARGBToColor(0xFF, 0xFF, 0xFF, 0x55);
diff --git a/engines/freescape/games/driller/cpc.cpp b/engines/freescape/games/driller/cpc.cpp
index dce9d4a6110..8bf22b5df99 100644
--- a/engines/freescape/games/driller/cpc.cpp
+++ b/engines/freescape/games/driller/cpc.cpp
@@ -20,6 +20,7 @@
  */
 
 #include "common/file.h"
+#include "common/memstream.h"
 
 #include "freescape/freescape.h"
 #include "freescape/language/8bitDetokeniser.h"
@@ -122,6 +123,41 @@ void deobfuscateDrillerCPCVirtualWorlds(byte *memBuffer) {
 	}
 }
 
+void DrillerEngine::loadAssetsCPCFullGame() {
+	Common::File file;
+
+	loadBundledImages();
+	byte *memBuffer;
+	int memSize = 0;
+	if (_variant & GF_CPC_VIRTUALWORLDS) {
+		memBuffer = parseEDSK("virtualworlds.A.cpc.edsk", memSize);
+		deobfuscateDrillerCPCVirtualWorlds(memBuffer);
+	} else
+		memBuffer = parseEDSK("driller.cpc.edsk", memSize);
+	assert(memSize > 0);
+	Common::SeekableReadStream *stream = new Common::MemoryReadStream((const byte*)memBuffer, memSize);
+
+	if (_variant & GF_CPC_RETAIL) {
+		loadMessagesFixedSize(stream, 0xb0f7, 14, 20);
+		loadFonts(stream, 0xeb14);
+		load8bitBinary(stream, 0xec76, 4);
+		loadGlobalObjects(stream, 0xacb2);
+	} else if (_variant & GF_CPC_RETAIL2) {
+		loadMessagesFixedSize(stream, 0xb0f7 - 0x3fab, 14, 20);
+		loadFonts(stream, 0xeb14 - 0x3fab);
+		load8bitBinary(stream, 0xaccb, 4);
+		loadGlobalObjects(stream, 0xacb2 - 0x3fab);
+	} else if (_variant & _variant & GF_CPC_VIRTUALWORLDS) {
+		load8bitBinary(stream, 0x11acb, 4);
+	} else if (_variant & GF_CPC_BUDGET) {
+		loadMessagesFixedSize(stream, 0x9ef7, 14, 20);
+		loadFonts(stream, 0xd914);
+		load8bitBinary(stream, 0xda76, 4);
+		loadGlobalObjects(stream, 0x9ab2);
+	} else
+		error("Unknown Amstrad CPC variant");
+}
+
 void DrillerEngine::drawCPCUI(Graphics::Surface *surface) {
 	uint32 color = 1;
 	uint8 r, g, b;
diff --git a/engines/freescape/games/driller/dos.cpp b/engines/freescape/games/driller/dos.cpp
index ad61fa078d0..bb3f0b52d32 100644
--- a/engines/freescape/games/driller/dos.cpp
+++ b/engines/freescape/games/driller/dos.cpp
@@ -19,6 +19,8 @@
  *
  */
 
+#include "common/file.h"
+
 #include "freescape/freescape.h"
 #include "freescape/language/8bitDetokeniser.h"
 
@@ -178,6 +180,76 @@ Graphics::Surface *DrillerEngine::load8bitTitleImage(Common::SeekableReadStream
 	}
 	return surface;
 }
+void DrillerEngine::loadAssetsDOSFullGame() {
+	Common::File file;
+	if (_renderMode == Common::kRenderEGA) {
+		file.open("SCN1E.DAT");
+		if (file.isOpen()) {
+			_title = load8bitBinImage(&file, 0x0);
+		}
+		file.close();
+		file.open("EGATITLE.RL");
+		if (file.isOpen()) {
+			_title = load8bitTitleImage(&file, 0x1b3);
+		}
+		file.close();
+
+		file.open("DRILLE.EXE");
+
+		if (!file.isOpen())
+			error("Failed to open DRILLE.EXE");
+
+		loadMessagesFixedSize(&file, 0x4135, 14, 20);
+		loadFonts(&file, 0x99dd);
+		loadGlobalObjects(&file, 0x3b42);
+		load8bitBinary(&file, 0x9b40, 16);
+		_border = load8bitBinImage(&file, 0x210);
+	} else if (_renderMode == Common::kRenderCGA) {
+		file.open("SCN1C.DAT");
+		if (file.isOpen()) {
+			_title = load8bitBinImage(&file, 0x0);
+		}
+		file.close();
+		file.open("CGATITLE.RL");
+		if (file.isOpen()) {
+			_title = load8bitTitleImage(&file, 0x1b3);
+		}
+		file.close();
+		file.open("DRILLC.EXE");
+
+		if (!file.isOpen())
+			error("Failed to open DRILLC.EXE");
+
+		loadFonts(&file, 0x07a4a);
+		loadMessagesFixedSize(&file, 0x2585, 14, 20);
+		load8bitBinary(&file, 0x7bb0, 4);
+		loadGlobalObjects(&file, 0x1fa2);
+		_border = load8bitBinImage(&file, 0x210);
+	} else
+		error("Unsupported video mode for DOS");
+}
+
+void DrillerEngine::loadAssetsDOSDemo() {
+	Common::File file;
+	_renderMode = Common::kRenderCGA; // DOS demos is CGA only
+	_viewArea = Common::Rect(36, 16, 284, 117); // correct view area
+	_gfx->_renderMode = _renderMode;
+	loadBundledImages();
+	file.open("d2");
+	if (!file.isOpen())
+		error("Failed to open 'd2' file");
+
+	loadFonts(&file, 0x4eb0);
+	loadMessagesFixedSize(&file, 0x636, 14, 20);
+	load8bitBinary(&file, 0x55b0, 4);
+	loadGlobalObjects(&file, 0x8c);
+
+	// Fixed for a corrupted area names in the demo data
+	_areaMap[2]->_name = "LAPIS LAZULI";
+	_areaMap[3]->_name = "EMERALD";
+	_areaMap[8]->_name = "TOPAZ";
+	file.close();
+}
 
 void DrillerEngine::drawDOSUI(Graphics::Surface *surface) {
 	uint32 color = _renderMode == Common::kRenderCGA ? 1 : 14;
diff --git a/engines/freescape/games/driller/driller.cpp b/engines/freescape/games/driller/driller.cpp
index 73179d250e4..f1ea313ea11 100644
--- a/engines/freescape/games/driller/driller.cpp
+++ b/engines/freescape/games/driller/driller.cpp
@@ -22,7 +22,6 @@
 #include "common/config-manager.h"
 #include "common/events.h"
 #include "common/file.h"
-#include "common/memstream.h"
 #include "common/random.h"
 
 #include "freescape/freescape.h"
@@ -279,49 +278,7 @@ void DrillerEngine::loadAssets() {
 void DrillerEngine::loadAssetsDemo() {
 	Common::File file;
 	if (isAmiga()) {
-		file.open("lift.neo");
-		if (!file.isOpen())
-			error("Failed to open 'lift.neo' file");
-
-		_title = loadAndConvertNeoImage(&file, 0);
-
-		file.close();
-		file.open("console.neo");
-		if (!file.isOpen())
-			error("Failed to open 'console.neo' file");
-
-		_border = loadAndConvertNeoImage(&file, 0);
-
-		file.close();
-		file.open("demo.cmd");
-		if (!file.isOpen())
-			error("Failed to open 'demo.cmd' file");
-
-		loadDemoData(&file, 0, 0x1000);
-
-		file.close();
-		file.open("data");
-		if (!file.isOpen())
-			error("Failed to open 'data' file");
-
-		load8bitBinary(&file, 0x442, 16);
-		loadPalettes(&file, 0x0);
-
-		file.close();
-		file.open("driller");
-		if (!file.isOpen())
-			error("Failed to open 'driller' file");
-
-		loadFonts(&file, 0xa30);
-		loadMessagesFixedSize(&file, 0x3960, 14, 20);
-		loadGlobalObjects(&file, 0x3716);
-
-		file.close();
-		file.open("soundfx");
-		if (!file.isOpen())
-			error("Failed to open 'soundfx' executable for Amiga");
-
-		loadSoundsFx(&file, 0, 25);
+		loadAssetsAmigaDemo();
 	} else if (isAtariST()) {
 		file.open("lift.neo");
 		if (!file.isOpen())
@@ -368,24 +325,7 @@ void DrillerEngine::loadAssetsDemo() {
 
 		loadSoundsFx(&file, 0, 25);
 	} else if (isDOS()) {
-		_renderMode = Common::kRenderCGA; // DOS demos is CGA only
-		_viewArea = Common::Rect(36, 16, 284, 117); // correct view area
-		_gfx->_renderMode = _renderMode;
-		loadBundledImages();
-		file.open("d2");
-		if (!file.isOpen())
-			error("Failed to open 'd2' file");
-
-		loadFonts(&file, 0x4eb0);
-		loadMessagesFixedSize(&file, 0x636, 14, 20);
-		load8bitBinary(&file, 0x55b0, 4);
-		loadGlobalObjects(&file, 0x8c);
-
-		// Fixed for a corrupted area names in the demo data
-		_areaMap[2]->_name = "LAPIS LAZULI";
-		_areaMap[3]->_name = "EMERALD";
-		_areaMap[8]->_name = "TOPAZ";
-		file.close();
+		loadAssetsDOSDemo();
 	} else
 		error("Unsupported demo for Driller");
 
@@ -393,67 +333,10 @@ void DrillerEngine::loadAssetsDemo() {
 	_angleRotationIndex = 0;
 }
 
-extern byte *parseEDSK(const Common::String filename, int &size);
-extern void deobfuscateDrillerCPCVirtualWorlds(byte *memBuffer);
-
 void DrillerEngine::loadAssetsFullGame() {
 	Common::File file;
 	if (isAmiga()) {
-		if (_variant & GF_AMIGA_RETAIL) {
-			file.open("driller");
-
-			if (!file.isOpen())
-				error("Failed to open 'driller' executable for Amiga");
-
-			_border = loadAndConvertNeoImage(&file, 0x137f4);
-			byte *palette = (byte *)malloc(16 * 3);
-			for (int i = 0; i < 16; i++) { // gray scale palette
-				palette[i * 3 + 0] = i * (255 / 16);
-				palette[i * 3 + 1] = i * (255 / 16);
-				palette[i * 3 + 2] = i * (255 / 16);
-			}
-			_title = loadAndConvertNeoImage(&file, 0x10, palette);
-
-			loadFonts(&file, 0x8940);
-			loadMessagesFixedSize(&file, 0xc66e, 14, 20);
-			loadGlobalObjects(&file, 0xbd62);
-			load8bitBinary(&file, 0x29c16, 16);
-			loadPalettes(&file, 0x297d4);
-			loadSoundsFx(&file, 0x30e80, 25);
-		} else if (_variant & GF_AMIGA_BUDGET) {
-			file.open("lift.neo");
-			if (!file.isOpen())
-				error("Failed to open 'lift.neo' file");
-
-			_title = loadAndConvertNeoImage(&file, 0);
-
-			file.close();
-			file.open("console.neo");
-			if (!file.isOpen())
-				error("Failed to open 'console.neo' file");
-
-			_border = loadAndConvertNeoImage(&file, 0);
-
-			file.close();
-			file.open("driller");
-			if (!file.isOpen())
-				error("Failed to open 'driller' executable for Amiga");
-
-			loadFonts(&file, 0xa62);
-			loadMessagesFixedSize(&file, 0x499a, 14, 20);
-			loadGlobalObjects(&file, 0x4098);
-			load8bitBinary(&file, 0x21a3e, 16);
-			loadPalettes(&file, 0x215fc);
-
-			file.close();
-			file.open("soundfx");
-			if (!file.isOpen())
-				error("Failed to open 'soundfx' executable for Amiga");
-
-			loadSoundsFx(&file, 0, 25);
-		}
-		else
-			error("Invalid or unknown Amiga release");
+		loadAssetsAmigaFullGame();
 	} else if (isAtariST()) {
 		file.open("x.prg");
 
@@ -476,83 +359,9 @@ void DrillerEngine::loadAssetsFullGame() {
 		loadPalettes(&file, 0x296fa);
 		loadSoundsFx(&file, 0x30da6, 25);
 	} else if (isSpectrum()) {
-		file.open("driller.zx.title");
-		if (file.isOpen()) {
-			_title = loadAndCenterScrImage(&file);
-		} else
-			error("Unable to find driller.zx.title");
-
-		file.close();
-
-		file.open("driller.zx.border");
-		if (file.isOpen()) {
-			_border = loadAndCenterScrImage(&file);
-		} else
-			error("Unable to find driller.zx.border");
-		file.close();
-
-		file.open("driller.zx.data");
-
-		if (!file.isOpen())
-			error("Failed to open driller.zx.data");
-
-		if (_variant & GF_ZX_DISC)
-			loadMessagesFixedSize(&file, 0x2164, 14, 20);
-		else
-			loadMessagesFixedSize(&file, 0x20e4, 14, 20);
-
-		if (_variant & GF_ZX_RETAIL)
-			loadFonts(&file, 0x62ca);
-		else if (_variant & GF_ZX_BUDGET)
-			loadFonts(&file, 0x5aa8);
-		else if (_variant & GF_ZX_DISC)
-			loadFonts(&file, 0x63f0);
-
-		if (_variant & GF_ZX_DISC)
-			loadGlobalObjects(&file, 0x1d13);
-		else
-			loadGlobalObjects(&file, 0x1c93);
-
-		if (_variant & GF_ZX_RETAIL)
-			load8bitBinary(&file, 0x642c, 4);
-		else if (_variant & GF_ZX_BUDGET)
-			load8bitBinary(&file, 0x5c0a, 4);
-		else if (_variant & GF_ZX_DISC)
-			load8bitBinary(&file, 0x6552, 4);
-
-		else
-			error("Unknown ZX spectrum variant");
+		loadAssetsZXFullGame();
 	} else if (isCPC()) {
-		loadBundledImages();
-		byte *memBuffer;
-		int memSize = 0;
-		if (_variant & GF_CPC_VIRTUALWORLDS) {
-			memBuffer = parseEDSK("virtualworlds.A.cpc.edsk", memSize);
-			deobfuscateDrillerCPCVirtualWorlds(memBuffer);
-		} else
-			memBuffer = parseEDSK("driller.cpc.edsk", memSize);
-		assert(memSize > 0);
-		Common::SeekableReadStream *stream = new Common::MemoryReadStream((const byte*)memBuffer, memSize);
-
-		if (_variant & GF_CPC_RETAIL) {
-			loadMessagesFixedSize(stream, 0xb0f7, 14, 20);
-			loadFonts(stream, 0xeb14);
-			load8bitBinary(stream, 0xec76, 4);
-			loadGlobalObjects(stream, 0xacb2);
-		} else if (_variant & GF_CPC_RETAIL2) {
-			loadMessagesFixedSize(stream, 0xb0f7 - 0x3fab, 14, 20);
-			loadFonts(stream, 0xeb14 - 0x3fab);
-			load8bitBinary(stream, 0xaccb, 4);
-			loadGlobalObjects(stream, 0xacb2 - 0x3fab);
-		} else if (_variant & _variant & GF_CPC_VIRTUALWORLDS) {
-			load8bitBinary(stream, 0x11acb, 4);
-		} else if (_variant & GF_CPC_BUDGET) {
-			loadMessagesFixedSize(stream, 0x9ef7, 14, 20);
-			loadFonts(stream, 0xd914);
-			load8bitBinary(stream, 0xda76, 4);
-			loadGlobalObjects(stream, 0x9ab2);
-		} else
-			error("Unknown Amstrad CPC variant");
+		loadAssetsCPCFullGame();
 	} else if (isC64()) {
 		if (_targetName.hasPrefix("spacestationoblivion")) {
 			loadBundledImages();
@@ -568,49 +377,8 @@ void DrillerEngine::loadAssetsFullGame() {
 			load8bitBinary(&file, 0x8e02 - 0x400, 4);
 			loadGlobalObjects(&file, 0x1855 - 0x400);
 		}
-	} else if (_renderMode == Common::kRenderEGA) {
-		file.open("SCN1E.DAT");
-		if (file.isOpen()) {
-			_title = load8bitBinImage(&file, 0x0);
-		}
-		file.close();
-		file.open("EGATITLE.RL");
-		if (file.isOpen()) {
-			_title = load8bitTitleImage(&file, 0x1b3);
-		}
-		file.close();
-
-		file.open("DRILLE.EXE");
-
-		if (!file.isOpen())
-			error("Failed to open DRILLE.EXE");
-
-		loadMessagesFixedSize(&file, 0x4135, 14, 20);
-		loadFonts(&file, 0x99dd);
-		loadGlobalObjects(&file, 0x3b42);
-		load8bitBinary(&file, 0x9b40, 16);
-		_border = load8bitBinImage(&file, 0x210);
-	} else if (_renderMode == Common::kRenderCGA) {
-		file.open("SCN1C.DAT");
-		if (file.isOpen()) {
-			_title = load8bitBinImage(&file, 0x0);
-		}
-		file.close();
-		file.open("CGATITLE.RL");
-		if (file.isOpen()) {
-			_title = load8bitTitleImage(&file, 0x1b3);
-		}
-		file.close();
-		file.open("DRILLC.EXE");
-
-		if (!file.isOpen())
-			error("Failed to open DRILLC.EXE");
-
-		loadFonts(&file, 0x07a4a);
-		loadMessagesFixedSize(&file, 0x2585, 14, 20);
-		load8bitBinary(&file, 0x7bb0, 4);
-		loadGlobalObjects(&file, 0x1fa2);
-		_border = load8bitBinImage(&file, 0x210);
+	} else if (isDOS()) {
+		loadAssetsDOSFullGame();
 	} else
 		error("Invalid or unsupported render mode %s for Driller", Common::getRenderModeDescription(_renderMode));
 
diff --git a/engines/freescape/games/driller/zx.cpp b/engines/freescape/games/driller/zx.cpp
index 482bde642bc..a8f1a4658e3 100644
--- a/engines/freescape/games/driller/zx.cpp
+++ b/engines/freescape/games/driller/zx.cpp
@@ -18,12 +18,63 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  *
  */
+#include "common/file.h"
 
 #include "freescape/freescape.h"
 #include "freescape/language/8bitDetokeniser.h"
 
 namespace Freescape {
 
+void DrillerEngine::loadAssetsZXFullGame() {
+	Common::File file;
+	file.open("driller.zx.title");
+	if (file.isOpen()) {
+		_title = loadAndCenterScrImage(&file);
+	} else
+		error("Unable to find driller.zx.title");
+
+	file.close();
+
+	file.open("driller.zx.border");
+	if (file.isOpen()) {
+		_border = loadAndCenterScrImage(&file);
+	} else
+		error("Unable to find driller.zx.border");
+	file.close();
+
+	file.open("driller.zx.data");
+
+	if (!file.isOpen())
+		error("Failed to open driller.zx.data");
+
+	if (_variant & GF_ZX_DISC)
+		loadMessagesFixedSize(&file, 0x2164, 14, 20);
+	else
+		loadMessagesFixedSize(&file, 0x20e4, 14, 20);
+
+	if (_variant & GF_ZX_RETAIL)
+		loadFonts(&file, 0x62ca);
+	else if (_variant & GF_ZX_BUDGET)
+		loadFonts(&file, 0x5aa8);
+	else if (_variant & GF_ZX_DISC)
+		loadFonts(&file, 0x63f0);
+
+	if (_variant & GF_ZX_DISC)
+		loadGlobalObjects(&file, 0x1d13);
+	else
+		loadGlobalObjects(&file, 0x1c93);
+
+	if (_variant & GF_ZX_RETAIL)
+		load8bitBinary(&file, 0x642c, 4);
+	else if (_variant & GF_ZX_BUDGET)
+		load8bitBinary(&file, 0x5c0a, 4);
+	else if (_variant & GF_ZX_DISC)
+		load8bitBinary(&file, 0x6552, 4);
+
+	else
+		error("Unknown ZX spectrum variant");
+}
+
 void DrillerEngine::drawZXUI(Graphics::Surface *surface) {
 	uint32 color = 5;
 	uint8 r, g, b;


Commit: edc1322b0b15e9160f24c02beaf832ca0d691969
    https://github.com/scummvm/scummvm/commit/edc1322b0b15e9160f24c02beaf832ca0d691969
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-03-20T09:17:21+01:00

Commit Message:
FREESCAPE: refactored/moved driller code specific for the atari release

Changed paths:
  A engines/freescape/games/driller/atari.cpp
    engines/freescape/freescape.h
    engines/freescape/games/driller/driller.cpp
    engines/freescape/module.mk


diff --git a/engines/freescape/freescape.h b/engines/freescape/freescape.h
index 8b05dd4291b..94521c68e43 100644
--- a/engines/freescape/freescape.h
+++ b/engines/freescape/freescape.h
@@ -439,6 +439,9 @@ private:
 	void loadAssetsDemo();
 	void loadAssetsFullGame();
 
+	void loadAssetsAtariFullGame();
+	void loadAssetsAtariDemo();
+
 	void loadAssetsAmigaFullGame();
 	void loadAssetsAmigaDemo();
 
diff --git a/engines/freescape/games/driller/atari.cpp b/engines/freescape/games/driller/atari.cpp
new file mode 100644
index 00000000000..6c2fe74a4ff
--- /dev/null
+++ b/engines/freescape/games/driller/atari.cpp
@@ -0,0 +1,100 @@
+/* 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 3 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, see <http://www.gnu.org/licenses/>.
+ *
+ */
+#include "common/file.h"
+
+#include "freescape/freescape.h"
+#include "freescape/language/8bitDetokeniser.h"
+
+namespace Freescape {
+
+void DrillerEngine::loadAssetsAtariFullGame() {
+	Common::File file;
+	file.open("x.prg");
+
+	if (!file.isOpen())
+		error("Failed to open 'x.prg' executable for AtariST");
+
+	_border = loadAndConvertNeoImage(&file, 0x1371a);
+	byte *palette = (byte *)malloc(16 * 3);
+	for (int i = 0; i < 16; i++) { // gray scale palette
+		palette[i * 3 + 0] = i * (255 / 16);
+		palette[i * 3 + 1] = i * (255 / 16);
+		palette[i * 3 + 2] = i * (255 / 16);
+	}
+	_title = loadAndConvertNeoImage(&file, 0x10, palette);
+
+	loadFonts(&file, 0x8a32);
+	loadMessagesFixedSize(&file, 0xc5d8, 14, 20);
+	loadGlobalObjects(&file, 0xbccc);
+	load8bitBinary(&file, 0x29b3c, 16);
+	loadPalettes(&file, 0x296fa);
+	loadSoundsFx(&file, 0x30da6, 25);
+}
+
+void DrillerEngine::loadAssetsAtariDemo() {
+	Common::File file;
+	file.open("lift.neo");
+	if (!file.isOpen())
+		error("Failed to open 'lift.neo' file");
+
+	_title = loadAndConvertNeoImage(&file, 0);
+
+	file.close();
+	file.open("console.neo");
+	if (!file.isOpen())
+		error("Failed to open 'console.neo' file");
+
+	_border = loadAndConvertNeoImage(&file, 0);
+
+	file.close();
+	file.open("demo.cmd");
+	if (!file.isOpen())
+		error("Failed to open 'demo.cmd' file");
+
+	loadDemoData(&file, 0, 0x1000);
+
+	file.close();
+	file.open("data");
+
+	if (!file.isOpen())
+		error("Failed to open 'data' file");
+
+	load8bitBinary(&file, 0x442, 16);
+	loadPalettes(&file, 0x0);
+
+	file.close();
+	file.open("x.prg");
+	if (!file.isOpen())
+		error("Failed to open 'x.prg' file");
+
+	loadFonts(&file, 0x7bc);
+	loadMessagesFixedSize(&file, 0x3b90, 14, 20);
+	loadGlobalObjects(&file, 0x3946);
+
+	file.close();
+	file.open("soundfx");
+	if (!file.isOpen())
+		error("Failed to open 'soundfx' executable for AtariST demo");
+
+	loadSoundsFx(&file, 0, 25);
+}
+
+} // End of namespace Freescape
\ No newline at end of file
diff --git a/engines/freescape/games/driller/driller.cpp b/engines/freescape/games/driller/driller.cpp
index f1ea313ea11..752eeed6d96 100644
--- a/engines/freescape/games/driller/driller.cpp
+++ b/engines/freescape/games/driller/driller.cpp
@@ -280,50 +280,7 @@ void DrillerEngine::loadAssetsDemo() {
 	if (isAmiga()) {
 		loadAssetsAmigaDemo();
 	} else if (isAtariST()) {
-		file.open("lift.neo");
-		if (!file.isOpen())
-			error("Failed to open 'lift.neo' file");
-
-		_title = loadAndConvertNeoImage(&file, 0);
-
-		file.close();
-		file.open("console.neo");
-		if (!file.isOpen())
-			error("Failed to open 'console.neo' file");
-
-		_border = loadAndConvertNeoImage(&file, 0);
-
-		file.close();
-		file.open("demo.cmd");
-		if (!file.isOpen())
-			error("Failed to open 'demo.cmd' file");
-
-		loadDemoData(&file, 0, 0x1000);
-
-		file.close();
-		file.open("data");
-
-		if (!file.isOpen())
-			error("Failed to open 'data' file");
-
-		load8bitBinary(&file, 0x442, 16);
-		loadPalettes(&file, 0x0);
-
-		file.close();
-		file.open("x.prg");
-		if (!file.isOpen())
-			error("Failed to open 'x.prg' file");
-
-		loadFonts(&file, 0x7bc);
-		loadMessagesFixedSize(&file, 0x3b90, 14, 20);
-		loadGlobalObjects(&file, 0x3946);
-
-		file.close();
-		file.open("soundfx");
-		if (!file.isOpen())
-			error("Failed to open 'soundfx' executable for AtariST demo");
-
-		loadSoundsFx(&file, 0, 25);
+		loadAssetsAtariDemo();
 	} else if (isDOS()) {
 		loadAssetsDOSDemo();
 	} else
@@ -338,26 +295,7 @@ void DrillerEngine::loadAssetsFullGame() {
 	if (isAmiga()) {
 		loadAssetsAmigaFullGame();
 	} else if (isAtariST()) {
-		file.open("x.prg");
-
-		if (!file.isOpen())
-			error("Failed to open 'x.prg' executable for AtariST");
-
-		_border = loadAndConvertNeoImage(&file, 0x1371a);
-		byte *palette = (byte *)malloc(16 * 3);
-		for (int i = 0; i < 16; i++) { // gray scale palette
-			palette[i * 3 + 0] = i * (255 / 16);
-			palette[i * 3 + 1] = i * (255 / 16);
-			palette[i * 3 + 2] = i * (255 / 16);
-		}
-		_title = loadAndConvertNeoImage(&file, 0x10, palette);
-
-		loadFonts(&file, 0x8a32);
-		loadMessagesFixedSize(&file, 0xc5d8, 14, 20);
-		loadGlobalObjects(&file, 0xbccc);
-		load8bitBinary(&file, 0x29b3c, 16);
-		loadPalettes(&file, 0x296fa);
-		loadSoundsFx(&file, 0x30da6, 25);
+		loadAssetsAtariFullGame();
 	} else if (isSpectrum()) {
 		loadAssetsZXFullGame();
 	} else if (isCPC()) {
diff --git a/engines/freescape/module.mk b/engines/freescape/module.mk
index b3baab38526..0d3c8b7d085 100644
--- a/engines/freescape/module.mk
+++ b/engines/freescape/module.mk
@@ -7,6 +7,7 @@ MODULE_OBJS := \
 	games/castle.o \
 	games/dark.o \
 	games/driller/amiga.o \
+	games/driller/atari.o \
 	games/driller/cpc.o \
 	games/driller/dos.o \
 	games/driller/driller.o \


Commit: c22636621e5f431afad4c057ef0381054271dde9
    https://github.com/scummvm/scummvm/commit/c22636621e5f431afad4c057ef0381054271dde9
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-03-20T09:17:31+01:00

Commit Message:
FREESCAPE: fixed artifacts when using stipple effect in opengl

Changed paths:
    engines/freescape/gfx_opengl.cpp


diff --git a/engines/freescape/gfx_opengl.cpp b/engines/freescape/gfx_opengl.cpp
index db8c9ba1a8b..e504625b1c4 100644
--- a/engines/freescape/gfx_opengl.cpp
+++ b/engines/freescape/gfx_opengl.cpp
@@ -283,7 +283,7 @@ void OpenGLRenderer::setStippleData(byte *data) {
 void OpenGLRenderer::useStipple(bool enabled) {
 	if (enabled) {
 		glEnable(GL_POLYGON_OFFSET_FILL);
-		glPolygonOffset(-5.0f, 1.0f);
+		glPolygonOffset(0.0f, -1.0f);
 		glEnable(GL_POLYGON_STIPPLE);
 		glPolygonStipple(_renderMode == Common::kRenderZX ? _variableStippleArray : _defaultStippleArray);
 	} else {


Commit: 366c5c6bbacf64d6d14fc7376ccf7ec57e547821
    https://github.com/scummvm/scummvm/commit/366c5c6bbacf64d6d14fc7376ccf7ec57e547821
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-03-20T09:17:40+01:00

Commit Message:
FREESCAPE: fixed _lastMinute initialization for driller amiga/atari

Changed paths:
    engines/freescape/games/driller/driller.cpp


diff --git a/engines/freescape/games/driller/driller.cpp b/engines/freescape/games/driller/driller.cpp
index 752eeed6d96..97ce479a819 100644
--- a/engines/freescape/games/driller/driller.cpp
+++ b/engines/freescape/games/driller/driller.cpp
@@ -1002,8 +1002,11 @@ void DrillerEngine::initGameState() {
 	_playerHeightNumber = 1;
 	_playerHeight = _playerHeights[_playerHeightNumber];
 	removeTimers();
-	startCountdown(_initialCountdown);
-	_lastMinute = 0;
+	startCountdown(_initialCountdown - 1);
+
+	int seconds, minutes, hours;
+	getTimeFromCountdown(seconds, minutes, hours);
+	_lastMinute = minutes;
 	_demoIndex = 0;
 	_demoEvents.clear();
 }


Commit: e539c321670e26e950a2e50daf9a180037875c7f
    https://github.com/scummvm/scummvm/commit/e539c321670e26e950a2e50daf9a180037875c7f
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-03-20T09:17:55+01:00

Commit Message:
FREESCAPE: simplified loading of data files in driller cpc

Changed paths:
    engines/freescape/detection.cpp
    engines/freescape/games/driller/cpc.cpp


diff --git a/engines/freescape/detection.cpp b/engines/freescape/detection.cpp
index f3faa281ae6..758267f1f88 100644
--- a/engines/freescape/detection.cpp
+++ b/engines/freescape/detection.cpp
@@ -75,7 +75,7 @@ static const ADGameDescription gameDescriptions[] = {
 		"driller",
 		"",
 		{
-			{"DRILLER.CPC.EDSK", 0, "05df84207b5373e145ef90a3e4b98ae0", 215073},
+			{"DRILL.BIN", 0, "719f5157391e88b2c391c30576340637", 35320},
 			AD_LISTEND
 		},
 		Common::EN_ANY,
@@ -83,30 +83,6 @@ static const ADGameDescription gameDescriptions[] = {
 		GF_CPC_RETAIL,
 		GUIO2(GUIO_NOMIDI, GAMEOPTION_AUTOMATIC_DRILLING)
 	},
-	{
-		"driller",
-		"",
-		{
-			{"DRILLER.CPC.EDSK", 0, "ccca1fb22252f43403f75a546ebb5a57", 194816},
-			AD_LISTEND
-		},
-		Common::EN_ANY,
-		Common::kPlatformAmstradCPC,
-		GF_CPC_RETAIL2,
-		GUIO2(GUIO_NOMIDI, GAMEOPTION_AUTOMATIC_DRILLING)
-	},
-	{
-		"driller",
-		"",
-		{
-			{"DRILLER.CPC.EDSK", 0, "252f90756eaee25f2231e8d3bfaab68f", 125952},
-			AD_LISTEND
-		},
-		Common::EN_ANY,
-		Common::kPlatformAmstradCPC,
-		GF_CPC_BUDGET,
-		GUIO2(GUIO_NOMIDI, GAMEOPTION_AUTOMATIC_DRILLING)
-	},
 	{
 		"driller",
 		"VirtualWorlds-A",
diff --git a/engines/freescape/games/driller/cpc.cpp b/engines/freescape/games/driller/cpc.cpp
index 8bf22b5df99..c42df9fbd49 100644
--- a/engines/freescape/games/driller/cpc.cpp
+++ b/engines/freescape/games/driller/cpc.cpp
@@ -125,37 +125,16 @@ void deobfuscateDrillerCPCVirtualWorlds(byte *memBuffer) {
 
 void DrillerEngine::loadAssetsCPCFullGame() {
 	Common::File file;
-
 	loadBundledImages();
-	byte *memBuffer;
-	int memSize = 0;
-	if (_variant & GF_CPC_VIRTUALWORLDS) {
-		memBuffer = parseEDSK("virtualworlds.A.cpc.edsk", memSize);
-		deobfuscateDrillerCPCVirtualWorlds(memBuffer);
-	} else
-		memBuffer = parseEDSK("driller.cpc.edsk", memSize);
-	assert(memSize > 0);
-	Common::SeekableReadStream *stream = new Common::MemoryReadStream((const byte*)memBuffer, memSize);
-
-	if (_variant & GF_CPC_RETAIL) {
-		loadMessagesFixedSize(stream, 0xb0f7, 14, 20);
-		loadFonts(stream, 0xeb14);
-		load8bitBinary(stream, 0xec76, 4);
-		loadGlobalObjects(stream, 0xacb2);
-	} else if (_variant & GF_CPC_RETAIL2) {
-		loadMessagesFixedSize(stream, 0xb0f7 - 0x3fab, 14, 20);
-		loadFonts(stream, 0xeb14 - 0x3fab);
-		load8bitBinary(stream, 0xaccb, 4);
-		loadGlobalObjects(stream, 0xacb2 - 0x3fab);
-	} else if (_variant & _variant & GF_CPC_VIRTUALWORLDS) {
-		load8bitBinary(stream, 0x11acb, 4);
-	} else if (_variant & GF_CPC_BUDGET) {
-		loadMessagesFixedSize(stream, 0x9ef7, 14, 20);
-		loadFonts(stream, 0xd914);
-		load8bitBinary(stream, 0xda76, 4);
-		loadGlobalObjects(stream, 0x9ab2);
-	} else
-		error("Unknown Amstrad CPC variant");
+	file.open("DRILL.BIN");
+
+	if (!file.isOpen())
+		error("Failed to open DRILL.BIN");
+
+	loadMessagesFixedSize(&file, 0x214c, 14, 20);
+	loadFonts(&file, 0x5b69);
+	loadGlobalObjects(&file, 0x1d07);
+	load8bitBinary(&file, 0x5ccb, 16);
 }
 
 void DrillerEngine::drawCPCUI(Graphics::Surface *surface) {


Commit: 8a0acc14409958c6010771d899fa22819fb92b09
    https://github.com/scummvm/scummvm/commit/8a0acc14409958c6010771d899fa22819fb92b09
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-03-20T09:18:05+01:00

Commit Message:
FREESCAPE: enable some spfx effects for different platforms (zx, cpc)

Changed paths:
    engines/freescape/language/instruction.cpp


diff --git a/engines/freescape/language/instruction.cpp b/engines/freescape/language/instruction.cpp
index 3389ca99493..2f68554d9cb 100644
--- a/engines/freescape/language/instruction.cpp
+++ b/engines/freescape/language/instruction.cpp
@@ -249,7 +249,7 @@ void FreescapeEngine::executeSPFX(FCLInstruction &instruction) {
 		debugC(1, kFreescapeDebugCode, "Switching complete palette to color %d", dst);
 		for (int i = 1; i < 16; i++)
 			_currentArea->remapColor(i, color);
-	} else if (isDOS()) {
+	} else {
 		debugC(1, kFreescapeDebugCode, "Switching palette from position %d to %d", src, dst);
 		if (src == 0 && dst == 1)
 			_currentArea->remapColor(_currentArea->_usualBackgroundColor, _renderMode == Common::kRenderCGA ? 1 : _currentArea->_underFireBackgroundColor);


Commit: 8227c50b44e154047109df299d46aa5e07967b16
    https://github.com/scummvm/scummvm/commit/8227c50b44e154047109df299d46aa5e07967b16
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-03-20T10:05:59+01:00

Commit Message:
FREESCAPE: use managed surfaces for border and title images

Changed paths:
    engines/freescape/freescape.cpp
    engines/freescape/freescape.h
    engines/freescape/games/driller/dos.cpp
    engines/freescape/gfx.cpp
    engines/freescape/gfx.h
    engines/freescape/loaders/8bitBinaryLoader.cpp


diff --git a/engines/freescape/freescape.cpp b/engines/freescape/freescape.cpp
index 2c5b96da6aa..975605018ae 100644
--- a/engines/freescape/freescape.cpp
+++ b/engines/freescape/freescape.cpp
@@ -194,7 +194,7 @@ void FreescapeEngine::drawBorder() {
 void FreescapeEngine::drawTitle() {
 	_gfx->setViewport(_fullscreenViewArea);
 	if (isSpectrum()) {
-		Graphics::Surface *title = new Graphics::Surface();
+		Graphics::ManagedSurface *title = new Graphics::ManagedSurface();
 		title->create(320, 200, _title->format);
 		title->copyRectToSurface(*_title, (320 - _title->w) / 2, (200 - _title->h) / 2, Common::Rect(_title->w, _title->h));
 		_title->free();
@@ -202,7 +202,7 @@ void FreescapeEngine::drawTitle() {
 		_title = title;
 	}
 	if (!_titleTexture)
-		_titleTexture = _gfx->createTexture(_title);
+		_titleTexture = _gfx->createTexture(&_title->rawSurface());
 	_gfx->drawTexturedRect2D(_fullscreenViewArea, _fullscreenViewArea, _titleTexture);
 	_gfx->setViewport(_viewArea);
 }
@@ -617,7 +617,7 @@ void FreescapeEngine::borderScreen() {}
 
 void FreescapeEngine::loadBorder() {
 	if (_border)
-		_borderTexture = _gfx->createTexture(_border);
+		_borderTexture = _gfx->createTexture(&_border->rawSurface());
 }
 
 void FreescapeEngine::processBorder() {
@@ -637,7 +637,7 @@ void FreescapeEngine::processBorder() {
 					_border->setPixel(i, j, transparent);
 			}
 		}
-		_borderTexture = _gfx->createTexture(_border);
+		_borderTexture = _gfx->createTexture(&_border->rawSurface());
 	}
 }
 
@@ -869,20 +869,20 @@ byte *FreescapeEngine::getPaletteFromNeoImage(Common::SeekableReadStream *stream
 	return palette;
 }
 
-Graphics::Surface *FreescapeEngine::loadAndConvertNeoImage(Common::SeekableReadStream *stream, int offset, byte *palette) {
+Graphics::ManagedSurface *FreescapeEngine::loadAndConvertNeoImage(Common::SeekableReadStream *stream, int offset, byte *palette) {
 	stream->seek(offset);
 	NeoDecoder decoder(palette);
 	decoder.loadStream(*stream);
-	Graphics::Surface *surface = new Graphics::Surface();
+	Graphics::ManagedSurface *surface = new Graphics::ManagedSurface();
 	surface->copyFrom(*decoder.getSurface());
 	surface->convertToInPlace(_gfx->_currentPixelFormat, decoder.getPalette());
 	return surface;
 }
 
-Graphics::Surface *FreescapeEngine::loadAndCenterScrImage(Common::SeekableReadStream *stream) {
+Graphics::ManagedSurface *FreescapeEngine::loadAndCenterScrImage(Common::SeekableReadStream *stream) {
 	ScrDecoder decoder;
 	decoder.loadStream(*stream);
-	Graphics::Surface *surface = new Graphics::Surface();
+	Graphics::ManagedSurface *surface = new Graphics::ManagedSurface();
 	const Graphics::Surface *decoded = decoder.getSurface();
 	surface->create(320, 200, decoded->format);
 	surface->copyRectToSurface(*decoded, (320 - decoded->w) / 2, (200 - decoded->h) / 2, Common::Rect(decoded->w, decoded->h));
diff --git a/engines/freescape/freescape.h b/engines/freescape/freescape.h
index 94521c68e43..1b21c8edcc4 100644
--- a/engines/freescape/freescape.h
+++ b/engines/freescape/freescape.h
@@ -25,6 +25,7 @@
 #include "common/bitarray.h"
 #include "common/events.h"
 #include "engines/advancedDetector.h"
+#include "graphics/managed_surface.h"
 #include "graphics/surface.h"
 
 #include "audio/decoders/wave.h"
@@ -124,8 +125,8 @@ public:
 	virtual void drawInfoMenu();
 
 	virtual void drawCrossair(Graphics::Surface *surface);
-	Graphics::Surface *_border;
-	Graphics::Surface *_title;
+	Graphics::ManagedSurface *_border;
+	Graphics::ManagedSurface *_title;
 	Texture *_borderTexture;
 	Texture *_titleTexture;
 	Texture *_uiTexture;
@@ -139,8 +140,8 @@ public:
 	void loadDataBundle();
 	void loadBundledImages();
 	byte *getPaletteFromNeoImage(Common::SeekableReadStream *stream, int offset);
-	Graphics::Surface *loadAndConvertNeoImage(Common::SeekableReadStream *stream, int offset, byte *palette = nullptr);
-	Graphics::Surface *loadAndCenterScrImage(Common::SeekableReadStream *stream);
+	Graphics::ManagedSurface *loadAndConvertNeoImage(Common::SeekableReadStream *stream, int offset, byte *palette = nullptr);
+	Graphics::ManagedSurface *loadAndCenterScrImage(Common::SeekableReadStream *stream);
 	void loadPalettes(Common::SeekableReadStream *file, int offset);
 	void swapPalette(uint16 areaID);
 	Common::HashMap<uint16, byte *> _paletteByArea;
@@ -165,12 +166,12 @@ public:
 	void load8bitBinary(Common::SeekableReadStream *file, int offset, int ncolors);
 	Area *load8bitArea(Common::SeekableReadStream *file, uint16 ncolors);
 	Object *load8bitObject(Common::SeekableReadStream *file);
-	void renderPixels8bitBinImage(Graphics::Surface *surface, int &i, int &j, uint8 pixels, int color);
+	void renderPixels8bitBinImage(Graphics::ManagedSurface *surface, int &i, int &j, uint8 pixels, int color);
 
-	void renderPixels8bitBinCGAImage(Graphics::Surface *surface, int &i, int &j, uint8 pixels, int color);
-	void renderPixels8bitBinEGAImage(Graphics::Surface *surface, int &i, int &j, uint8 pixels, int color);
+	void renderPixels8bitBinCGAImage(Graphics::ManagedSurface *surface, int &i, int &j, uint8 pixels, int color);
+	void renderPixels8bitBinEGAImage(Graphics::ManagedSurface *surface, int &i, int &j, uint8 pixels, int color);
 
-	Graphics::Surface *load8bitBinImage(Common::SeekableReadStream *file, int offset);
+	Graphics::ManagedSurface *load8bitBinImage(Common::SeekableReadStream *file, int offset);
 
 	// Areas
 	uint16 _startArea;
@@ -460,9 +461,9 @@ private:
 	void drawC64UI(Graphics::Surface *surface);
 	void drawAmigaAtariSTUI(Graphics::Surface *surface);
 
-	Graphics::Surface *load8bitTitleImage(Common::SeekableReadStream *file, int offset);
+	Graphics::ManagedSurface *load8bitTitleImage(Common::SeekableReadStream *file, int offset);
 	uint32 getPixel8bitTitleImage(int index);
-	void renderPixels8bitTitleImage(Graphics::Surface *surface, int &i, int &j, int pixels);
+	void renderPixels8bitTitleImage(Graphics::ManagedSurface *surface, int &i, int &j, int pixels);
 };
 
 class DarkEngine : public FreescapeEngine {
diff --git a/engines/freescape/games/driller/dos.cpp b/engines/freescape/games/driller/dos.cpp
index bb3f0b52d32..ee38b0a6b13 100644
--- a/engines/freescape/games/driller/dos.cpp
+++ b/engines/freescape/games/driller/dos.cpp
@@ -35,16 +35,13 @@ extern byte kEGADefaultPaletteData[16][3];
 */
 
 uint32 DrillerEngine::getPixel8bitTitleImage(int index) {
-	uint8 r, g, b;
 	if (index < 4 || _renderMode == Common::kRenderEGA) {
-		_gfx->readFromPalette(index, r, g, b);
-		return _gfx->_currentPixelFormat.ARGBToColor(0xFF, r, g, b);
+		return index;
 	}
-	_gfx->readFromPalette(index / 4, r, g, b);
-	return _gfx->_currentPixelFormat.ARGBToColor(0xFF, r, g, b);
+	return index / 4;
 }
 
-void DrillerEngine::renderPixels8bitTitleImage(Graphics::Surface *surface, int &i, int &j, int pixels) {
+void DrillerEngine::renderPixels8bitTitleImage(Graphics::ManagedSurface *surface, int &i, int &j, int pixels) {
 	int c1 = pixels >> 4;
 	int c2 = pixels & 0xf;
 
@@ -80,17 +77,10 @@ void DrillerEngine::renderPixels8bitTitleImage(Graphics::Surface *surface, int &
 	i++;
 }
 
-Graphics::Surface *DrillerEngine::load8bitTitleImage(Common::SeekableReadStream *file, int offset) {
-	Graphics::Surface *surface = new Graphics::Surface();
-	if (_renderMode == Common::kRenderCGA)
-		_gfx->_palette = (byte *)kCGAPalettePinkBlueWhiteData;
-	else if (_renderMode == Common::kRenderEGA)
-		_gfx->_palette = (byte *)kEGADefaultPaletteData;
-	else
-		error("Invalid render mode: %d", _renderMode);
-	surface->create(_screenW, _screenH, _gfx->_currentPixelFormat);
-	uint32 black = _gfx->_currentPixelFormat.ARGBToColor(0xFF, 0, 0, 0);
-	surface->fillRect(Common::Rect(0, 0, 320, 200), black);
+Graphics::ManagedSurface *DrillerEngine::load8bitTitleImage(Common::SeekableReadStream *file, int offset) {
+	Graphics::ManagedSurface *surface = new Graphics::ManagedSurface();
+	surface->create(_screenW, _screenH, Graphics::PixelFormat::createFormatCLUT8());
+	surface->fillRect(Common::Rect(0, 0, 320, 200), 0);
 
 	int i = 0;
 	int j = 0;
@@ -180,17 +170,45 @@ Graphics::Surface *DrillerEngine::load8bitTitleImage(Common::SeekableReadStream
 	}
 	return surface;
 }
+
+byte kCGAPalettePinkBlueWhiteData[4][3] = {
+	{0x00, 0x00, 0x00},
+	{0x55, 0xff, 0xff},
+	{0xff, 0x55, 0xff},
+	{0xff, 0xff, 0xff},
+};
+
+byte kEGADefaultPaletteData[16][3] = {
+	{0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xaa},
+	{0x00, 0xaa, 0x00},
+	{0xaa, 0x00, 0x00},
+	{0xaa, 0x00, 0xaa},
+	{0xaa, 0x55, 0x00},
+	{0x55, 0xff, 0x55},
+	{0xff, 0x55, 0x55},
+	{0x12, 0x34, 0x56},
+	{0xff, 0xff, 0x55},
+	{0xff, 0xff, 0xff},
+	{0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00}
+};
+
 void DrillerEngine::loadAssetsDOSFullGame() {
 	Common::File file;
 	if (_renderMode == Common::kRenderEGA) {
 		file.open("SCN1E.DAT");
 		if (file.isOpen()) {
 			_title = load8bitBinImage(&file, 0x0);
+			_title->setPalette((byte*)&kEGADefaultPaletteData, 0, 16);
 		}
 		file.close();
 		file.open("EGATITLE.RL");
 		if (file.isOpen()) {
 			_title = load8bitTitleImage(&file, 0x1b3);
+			_title->setPalette((byte*)&kEGADefaultPaletteData, 0, 16);
 		}
 		file.close();
 
@@ -204,15 +222,18 @@ void DrillerEngine::loadAssetsDOSFullGame() {
 		loadGlobalObjects(&file, 0x3b42);
 		load8bitBinary(&file, 0x9b40, 16);
 		_border = load8bitBinImage(&file, 0x210);
+		_border->setPalette((byte*)&kEGADefaultPaletteData, 0, 16);
 	} else if (_renderMode == Common::kRenderCGA) {
 		file.open("SCN1C.DAT");
 		if (file.isOpen()) {
 			_title = load8bitBinImage(&file, 0x0);
+			_title->setPalette((byte*)&kCGAPalettePinkBlueWhiteData, 0, 4);
 		}
 		file.close();
 		file.open("CGATITLE.RL");
 		if (file.isOpen()) {
 			_title = load8bitTitleImage(&file, 0x1b3);
+			_title->setPalette((byte*)&kCGAPalettePinkBlueWhiteData, 0, 4);
 		}
 		file.close();
 		file.open("DRILLC.EXE");
@@ -225,6 +246,7 @@ void DrillerEngine::loadAssetsDOSFullGame() {
 		load8bitBinary(&file, 0x7bb0, 4);
 		loadGlobalObjects(&file, 0x1fa2);
 		_border = load8bitBinImage(&file, 0x210);
+		_border->setPalette((byte*)&kCGAPalettePinkBlueWhiteData, 0, 4);
 	} else
 		error("Unsupported video mode for DOS");
 }
diff --git a/engines/freescape/gfx.cpp b/engines/freescape/gfx.cpp
index 3fab0026779..ac35f24ee4f 100644
--- a/engines/freescape/gfx.cpp
+++ b/engines/freescape/gfx.cpp
@@ -76,7 +76,7 @@ bool Renderer::getRGBAtCGA(uint8 index, uint8 &r1, uint8 &g1, uint8 &b1, uint8 &
 		return false;
 
 	assert (_renderMode == Common::kRenderCGA);
-	if (index <= 4) { // Solid colors 
+	if (index <= 4) { // Solid colors
 		readFromPalette(index - 1, r1, g1, b1);
 		r2 = r1;
 		g2 = g1;
@@ -164,7 +164,7 @@ bool Renderer::getRGBAtZX(uint8 index, uint8 &r1, uint8 &g1, uint8 &b1, uint8 &r
 		return false;
 
 	byte *entry = (*_colorMap)[index - 1];
-	if (entry[0] == 0 && entry[1] == 0 && entry[2] == 0 && entry[3] == 0) { 
+	if (entry[0] == 0 && entry[1] == 0 && entry[2] == 0 && entry[3] == 0) {
 		readFromPalette(_paperColor, r1, g1, b1);
 		readFromPalette(_paperColor, r2, g2, b2);
 		return true;
@@ -342,12 +342,23 @@ void Renderer::flipVertical(Graphics::Surface *s) {
 	}
 }
 
-void Renderer::convertImageFormatIfNecessary(Graphics::Surface *surface) {
+void Renderer::convertImageFormatIfNecessary(Graphics::ManagedSurface *surface) {
 	if (!surface)
 		return;
 
-	if (surface->format != _texturePixelFormat)
-		surface->convertToInPlace(_texturePixelFormat);
+	if (surface->format != _texturePixelFormat) {
+		const uint32 *src = surface->getPalette();
+		byte *palette = (byte *)malloc(sizeof(byte) * 16 * 3);
+		for (int num = 16; num > 0; --num, palette += 3) { // Maximum should be 16 colours
+			uint32 p = *src++;
+			palette[0] =  p        & 0xff;
+			palette[1] = (p >> 8)  & 0xff;
+			palette[2] = (p >> 16) & 0xff;
+		}
+		palette = palette - 16 * 3;
+		surface->convertToInPlace(_texturePixelFormat, palette);
+		free(palette);
+	}
 }
 
 Common::Rect Renderer::viewport() const {
diff --git a/engines/freescape/gfx.h b/engines/freescape/gfx.h
index a8b08b5cd66..074ce8be090 100644
--- a/engines/freescape/gfx.h
+++ b/engines/freescape/gfx.h
@@ -26,6 +26,7 @@
 #include "common/rect.h"
 
 #include "graphics/pixelformat.h"
+#include "graphics/managed_surface.h"
 #include "graphics/renderer.h"
 #include "math/frustum.h"
 #include "math/vector3d.h"
@@ -76,7 +77,7 @@ public:
 	virtual void polygonOffset(bool enabled) = 0;
 
 	virtual Texture *createTexture(const Graphics::Surface *surface) = 0;
-	void convertImageFormatIfNecessary(Graphics::Surface *surface);
+	void convertImageFormatIfNecessary(Graphics::ManagedSurface *surface);
 
 	virtual void freeTexture(Texture *texture) = 0;
 	virtual void drawTexturedRect2D(const Common::Rect &screenRect, const Common::Rect &textureRect, Texture *texture) = 0;
diff --git a/engines/freescape/loaders/8bitBinaryLoader.cpp b/engines/freescape/loaders/8bitBinaryLoader.cpp
index b39cd64c2e3..b62a5e6d28f 100644
--- a/engines/freescape/loaders/8bitBinaryLoader.cpp
+++ b/engines/freescape/loaders/8bitBinaryLoader.cpp
@@ -298,32 +298,7 @@ static const char *eclipseRoomName[] = {
 	"ILLUSION",
 	"????????"};
 
-byte kCGAPalettePinkBlueWhiteData[4][3] = {
-	{0x00, 0x00, 0x00},
-	{0x55, 0xff, 0xff},
-	{0xff, 0x55, 0xff},
-	{0xff, 0xff, 0xff},
-};
-
-byte kEGADefaultPaletteData[16][3] = {
-	{0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xaa},
-	{0x00, 0xaa, 0x00},
-	{0xaa, 0x00, 0x00},
-	{0xaa, 0x00, 0xaa},
-	{0xaa, 0x55, 0x00},
-	{0x55, 0xff, 0x55},
-	{0xff, 0x55, 0x55},
-	{0x12, 0x34, 0x56},
-	{0xff, 0xff, 0x55},
-	{0xff, 0xff, 0xff},
-	{0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00}
-};
-
-void FreescapeEngine::renderPixels8bitBinImage(Graphics::Surface *surface, int &i, int &j, uint8 pixels, int color) {
+void FreescapeEngine::renderPixels8bitBinImage(Graphics::ManagedSurface *surface, int &i, int &j, uint8 pixels, int color) {
 	if (i >= 320) {
 		//debug("cannot continue, stopping here at row %d!", j);
 		return;
@@ -333,13 +308,8 @@ void FreescapeEngine::renderPixels8bitBinImage(Graphics::Surface *surface, int &
 	while (acc > 0) {
 		assert(i < 320);
 		if (acc & pixels) {
-			uint8 r, g, b;
-			uint32 previousPixel = surface->getPixel(i, j);
-			_gfx->_currentPixelFormat.colorToRGB(previousPixel, r, g, b);
-			int previousColor = _gfx->indexFromColor(r, g, b);
-			//debug("index: %d", previousColor + color);
-			_gfx->readFromPalette(previousColor + color, r, g, b);
-			surface->setPixel(i, j, _gfx->_currentPixelFormat.ARGBToColor(0xFF, r, g, b));
+			int previousColor = surface->getPixel(i, j);
+			surface->setPixel(i, j, previousColor + color);
 		}
 		i++;
 		acc = acc >> 1;
@@ -347,18 +317,10 @@ void FreescapeEngine::renderPixels8bitBinImage(Graphics::Surface *surface, int &
 
 }
 
-Graphics::Surface *FreescapeEngine::load8bitBinImage(Common::SeekableReadStream *file, int offset) {
-	Graphics::Surface *surface = new Graphics::Surface();
-	if (_renderMode == Common::kRenderCGA)
-		_gfx->_palette = (byte *)kCGAPalettePinkBlueWhiteData;
-	else if (_renderMode == Common::kRenderEGA)
-		_gfx->_palette = (byte *)kEGADefaultPaletteData;
-	else
-		error("Invalid render mode: %d", _renderMode);
-
-	surface->create(_screenW, _screenH, _gfx->_currentPixelFormat);
-	uint32 black = _gfx->_currentPixelFormat.ARGBToColor(0xFF, 0, 0, 0);
-	surface->fillRect(Common::Rect(0, 0, 320, 200), black);
+Graphics::ManagedSurface *FreescapeEngine::load8bitBinImage(Common::SeekableReadStream *file, int offset) {
+	Graphics::ManagedSurface *surface = new Graphics::ManagedSurface();
+	surface->create(_screenW, _screenH, Graphics::PixelFormat::createFormatCLUT8());
+	surface->fillRect(Common::Rect(0, 0, 320, 200), 0);
 
 	file->seek(offset);
 	int imageSize = file->readUint16BE();
@@ -735,7 +697,7 @@ void FreescapeEngine::load8bitBinary(Common::SeekableReadStream *file, int offse
 }
 
 void FreescapeEngine::loadBundledImages() {
-	Image::BitmapDecoder decoder;
+	/*Image::BitmapDecoder decoder;
 	Common::String targetName = Common::String(_gameDescription->gameId);
 	if (isDOS() && isDemo())
 		Common::replace(targetName, "-demo", "");
@@ -757,7 +719,7 @@ void FreescapeEngine::loadBundledImages() {
 		_title = new Graphics::Surface();
 		_title->copyFrom(*decoder.getSurface());
 		decoder.destroy();
-	}
+	}*/
 }
 
 void FreescapeEngine::loadFonts(Common::SeekableReadStream *file, int offset) {


Commit: 9b0f5b3de324fe5d2b9d1a259c6cb3d9854faf02
    https://github.com/scummvm/scummvm/commit/9b0f5b3de324fe5d2b9d1a259c6cb3d9854faf02
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-03-20T10:10:56+01:00

Commit Message:
FREESCAPE: allow to change the palette of title and border per level using managed surfaces

Changed paths:
    engines/freescape/freescape.cpp
    engines/freescape/games/driller/driller.cpp
    engines/freescape/games/palettes.cpp
    engines/freescape/gfx.cpp
    engines/freescape/gfx.h
    engines/freescape/loaders/8bitBinaryLoader.cpp


diff --git a/engines/freescape/freescape.cpp b/engines/freescape/freescape.cpp
index 975605018ae..52aa76309dd 100644
--- a/engines/freescape/freescape.cpp
+++ b/engines/freescape/freescape.cpp
@@ -193,16 +193,12 @@ void FreescapeEngine::drawBorder() {
 
 void FreescapeEngine::drawTitle() {
 	_gfx->setViewport(_fullscreenViewArea);
-	if (isSpectrum()) {
-		Graphics::ManagedSurface *title = new Graphics::ManagedSurface();
-		title->create(320, 200, _title->format);
-		title->copyRectToSurface(*_title, (320 - _title->w) / 2, (200 - _title->h) / 2, Common::Rect(_title->w, _title->h));
-		_title->free();
-		delete _title;
-		_title = title;
+	if (!_titleTexture) {
+		Graphics::Surface *title = _gfx->convertImageFormatIfNecessary(_title);
+		_titleTexture = _gfx->createTexture(title);
+		title->free();
+		delete title;
 	}
-	if (!_titleTexture)
-		_titleTexture = _gfx->createTexture(&_title->rawSurface());
 	_gfx->drawTexturedRect2D(_fullscreenViewArea, _fullscreenViewArea, _titleTexture);
 	_gfx->setViewport(_viewArea);
 }
@@ -559,8 +555,6 @@ Common::Error FreescapeEngine::run() {
 	initGameState();
 	loadColorPalette();
 
-	_gfx->convertImageFormatIfNecessary(_title);
-	_gfx->convertImageFormatIfNecessary(_border);
 	g_system->lockMouse(true);
 
 	// Simple main event loop
@@ -616,28 +610,37 @@ void FreescapeEngine::titleScreen() {}
 void FreescapeEngine::borderScreen() {}
 
 void FreescapeEngine::loadBorder() {
-	if (_border)
-		_borderTexture = _gfx->createTexture(&_border->rawSurface());
+	if (_border) {
+		Graphics::Surface *border = _gfx->convertImageFormatIfNecessary(_border);
+		_borderTexture = _gfx->createTexture(border);
+		border->free();
+		delete border;
+	}
 }
 
 void FreescapeEngine::processBorder() {
 	if (_border) {
 		if (_borderTexture)
 			delete _borderTexture;
+		Graphics::Surface *border = _gfx->convertImageFormatIfNecessary(_border);
+
 		uint32 gray = _gfx->_texturePixelFormat.ARGBToColor(0x00, 0xA0, 0xA0, 0xA0);
-		_border->fillRect(_viewArea, gray);
+		border->fillRect(_viewArea, gray);
 
 		// Replace black pixel for transparent ones
-		uint32 black = _border->format.ARGBToColor(0xFF, 0x00, 0x00, 0x00);
-		uint32 transparent = _border->format.ARGBToColor(0x00, 0x00, 0x00, 0x00);
+		uint32 black = border->format.ARGBToColor(0xFF, 0x00, 0x00, 0x00);
+		uint32 transparent = border->format.ARGBToColor(0x00, 0x00, 0x00, 0x00);
 
-		for (int i = 0; i < _border->w; i++) {
-			for (int j = 0; j < _border->h; j++) {
-				if (_border->getPixel(i, j) == black)
-					_border->setPixel(i, j, transparent);
+		for (int i = 0; i < border->w; i++) {
+			for (int j = 0; j < border->h; j++) {
+				if (border->getPixel(i, j) == black)
+					border->setPixel(i, j, transparent);
 			}
 		}
-		_borderTexture = _gfx->createTexture(&_border->rawSurface());
+
+		_borderTexture = _gfx->createTexture(border);
+		border->free();
+		delete border;
 	}
 }
 
diff --git a/engines/freescape/games/driller/driller.cpp b/engines/freescape/games/driller/driller.cpp
index 97ce479a819..c1e33edd9e2 100644
--- a/engines/freescape/games/driller/driller.cpp
+++ b/engines/freescape/games/driller/driller.cpp
@@ -29,59 +29,6 @@
 
 namespace Freescape {
 
-enum {
-	kDrillerCGAPalettePinkBlue = 0,
-	kDrillerCGAPaletteRedGreen = 1,
-};
-
-static const struct CGAPalettteEntry {
-	int areaId;
-	int palette;
-} rawCGAPaletteTable[] {
-	{1, kDrillerCGAPaletteRedGreen},
-	{2, kDrillerCGAPalettePinkBlue},
-	{3, kDrillerCGAPaletteRedGreen},
-	{4, kDrillerCGAPalettePinkBlue},
-	{5, kDrillerCGAPaletteRedGreen},
-	{6, kDrillerCGAPalettePinkBlue},
-	{7, kDrillerCGAPaletteRedGreen},
-	{8, kDrillerCGAPalettePinkBlue},
-	{9, kDrillerCGAPaletteRedGreen},
-	{10, kDrillerCGAPalettePinkBlue},
-	{11, kDrillerCGAPaletteRedGreen},
-	{12, kDrillerCGAPalettePinkBlue},
-
-	{14, kDrillerCGAPalettePinkBlue},
-
-	{16, kDrillerCGAPalettePinkBlue},
-
-	{19, kDrillerCGAPaletteRedGreen},
-	{20, kDrillerCGAPalettePinkBlue},
-	{21, kDrillerCGAPaletteRedGreen},
-	{22, kDrillerCGAPalettePinkBlue},
-	{23, kDrillerCGAPaletteRedGreen},
-
-	{28, kDrillerCGAPalettePinkBlue},
-
-	{32, kDrillerCGAPalettePinkBlue},
-	{127, kDrillerCGAPaletteRedGreen},
-	{0, 0}   // This marks the end
-};
-
-byte kDrillerCGAPalettePinkBlueData[4][3] = {
-	{0x00, 0x00, 0x00},
-	{0x00, 0xaa, 0xaa},
-	{0xaa, 0x00, 0xaa},
-	{0xaa, 0xaa, 0xaa},
-};
-
-byte kDrillerCGAPaletteRedGreenData[4][3] = {
-	{0x00, 0x00, 0x00},
-	{0x00, 0xaa, 0x00},
-	{0xaa, 0x00, 0x00},
-	{0xaa, 0x55, 0x00},
-};
-
 enum {
 	kDrillerNoRig = 0,
 	kDrillerRigInPlace = 1,
@@ -147,7 +94,7 @@ void DrillerEngine::titleScreen() {
 	if (isDOS() && isDemo()) // Demo will not show any title screen
 		return;
 
-	if (isAmiga() || isAtariST()) // These releases has their own screens
+	if (isAmiga() || isAtariST()) // TODO: implement these with their own animations
 		return;
 
 	if (_title) {
@@ -161,7 +108,7 @@ void DrillerEngine::borderScreen() {
 	if (isDOS() && isDemo()) // Demo will not show the border
 		return;
 
-	if (isAmiga() || isAtariST()) // These releases has their own screens
+	if (isAmiga() || isAtariST()) // TODO: implement these with their own animations
 		return;
 
 	if (_border) {
@@ -346,47 +293,6 @@ void DrillerEngine::loadAssetsFullGame() {
 
 void DrillerEngine::processBorder() {
 	FreescapeEngine::processBorder();
-	if (isDOS() && _renderMode == Common::kRenderCGA) { // Replace some colors for the CGA borders
-		uint32 color1 = _border->format.ARGBToColor(0xFF, 0xAA, 0x00, 0xAA);
-		uint32 color2 = _border->format.ARGBToColor(0xFF, 0xAA, 0x55, 0x00);
-
-		uint32 colorA = _border->format.ARGBToColor(0xFF, 0x00, 0xAA, 0xAA);
-		uint32 colorB = _border->format.ARGBToColor(0xFF, 0x00, 0xAA, 0x00);
-
-		uint32 colorX = _border->format.ARGBToColor(0xFF, 0xAA, 0xAA, 0xAA);
-		uint32 colorY = _border->format.ARGBToColor(0xFF, 0xAA, 0x00, 0x00);
-
-		Graphics::Surface *borderRedGreen = new Graphics::Surface();
-		borderRedGreen->create(1, 1, _border->format);
-		borderRedGreen->copyFrom(*_border);
-
-		for (int i = 0; i < _border->w; i++) {
-			for (int j = 0; j < _border->h; j++) {
-				if (borderRedGreen->getPixel(i, j) == color1)
-					borderRedGreen->setPixel(i, j, color2);
-				else if (borderRedGreen->getPixel(i, j) == colorA)
-					borderRedGreen->setPixel(i, j, colorB);
-				else if (borderRedGreen->getPixel(i, j) == colorX)
-					borderRedGreen->setPixel(i, j, colorY);
-
-			}
-		}
-		Texture *borderTextureRedGreen = _gfx->createTexture(borderRedGreen);
-
-		const CGAPalettteEntry *entry = rawCGAPaletteTable;
-		while (entry->areaId) {
-
-			if (entry->palette == kDrillerCGAPaletteRedGreen) {
-				_borderCGAByArea[entry->areaId] = borderTextureRedGreen;
-				_paletteCGAByArea[entry->areaId] = (byte *)kDrillerCGAPaletteRedGreenData;
-			} else if (entry->palette == kDrillerCGAPalettePinkBlue) {
-				_borderCGAByArea[entry->areaId] = _borderTexture;
-				_paletteCGAByArea[entry->areaId] = (byte *)kDrillerCGAPalettePinkBlueData;
-			} else
-				error("Invalid CGA palette to use");
-			entry++;
-		}
-	}
 }
 
 void DrillerEngine::drawUI() {
diff --git a/engines/freescape/games/palettes.cpp b/engines/freescape/games/palettes.cpp
index 1f4c8766fe6..97d4cfbf94c 100644
--- a/engines/freescape/games/palettes.cpp
+++ b/engines/freescape/games/palettes.cpp
@@ -155,6 +155,59 @@ void FreescapeEngine::loadPalettes(Common::SeekableReadStream *file, int offset)
 	}
 }
 
+enum {
+	kDrillerCGAPalettePinkBlue = 0,
+	kDrillerCGAPaletteRedGreen = 1,
+};
+
+static const struct CGAPalettteEntry {
+	int areaId;
+	int palette;
+} rawCGAPaletteTable[] {
+	{1, kDrillerCGAPaletteRedGreen},
+	{2, kDrillerCGAPalettePinkBlue},
+	{3, kDrillerCGAPaletteRedGreen},
+	{4, kDrillerCGAPalettePinkBlue},
+	{5, kDrillerCGAPaletteRedGreen},
+	{6, kDrillerCGAPalettePinkBlue},
+	{7, kDrillerCGAPaletteRedGreen},
+	{8, kDrillerCGAPalettePinkBlue},
+	{9, kDrillerCGAPaletteRedGreen},
+	{10, kDrillerCGAPalettePinkBlue},
+	{11, kDrillerCGAPaletteRedGreen},
+	{12, kDrillerCGAPalettePinkBlue},
+
+	{14, kDrillerCGAPalettePinkBlue},
+
+	{16, kDrillerCGAPalettePinkBlue},
+
+	{19, kDrillerCGAPaletteRedGreen},
+	{20, kDrillerCGAPalettePinkBlue},
+	{21, kDrillerCGAPaletteRedGreen},
+	{22, kDrillerCGAPalettePinkBlue},
+	{23, kDrillerCGAPaletteRedGreen},
+
+	{28, kDrillerCGAPalettePinkBlue},
+
+	{32, kDrillerCGAPalettePinkBlue},
+	{127, kDrillerCGAPaletteRedGreen},
+	{0, 0}   // This marks the end
+};
+
+byte kDrillerCGAPalettePinkBlueData[4][3] = {
+	{0x00, 0x00, 0x00},
+	{0x00, 0xaa, 0xaa},
+	{0xaa, 0x00, 0xaa},
+	{0xaa, 0xaa, 0xaa},
+};
+
+byte kDrillerCGAPaletteRedGreenData[4][3] = {
+	{0x00, 0x00, 0x00},
+	{0x00, 0xaa, 0x00},
+	{0xaa, 0x00, 0x00},
+	{0xaa, 0x55, 0x00},
+};
+
 void FreescapeEngine::swapPalette(uint16 levelID) {
 	if (isAmiga() || isAtariST())
 		_gfx->_palette = _paletteByArea[levelID];
@@ -163,11 +216,28 @@ void FreescapeEngine::swapPalette(uint16 levelID) {
 		_gfx->_paperColor = _areaMap[levelID]->_paperColor;
 		_gfx->_underFireBackgroundColor = _areaMap[levelID]->_underFireBackgroundColor;
 	} else if (isDOS() && _renderMode == Common::kRenderCGA) {
-		assert(_borderCGAByArea.contains(levelID));
-		assert(_paletteCGAByArea.contains(levelID));
-		_borderTexture = _borderCGAByArea.getVal(levelID);
-		_gfx->_palette = _paletteCGAByArea.getVal(levelID);
+		const CGAPalettteEntry *entry = rawCGAPaletteTable;
+		while (entry->areaId) {
+			if (entry->areaId == levelID) {
+				if (entry->palette == kDrillerCGAPaletteRedGreen) {
+					_gfx->_palette = (byte *)kDrillerCGAPaletteRedGreenData;
+				} else if (entry->palette == kDrillerCGAPalettePinkBlue) {
+					_gfx->_palette = (byte *)kDrillerCGAPalettePinkBlueData;
+				} else
+					error("Invalid CGA palette to use");
+				break;
+			}
+			entry++;
+		}
+
+		assert(entry->areaId == levelID);
+		_border->setPalette(_gfx->_palette, 0, 4);
+		processBorder();
+	} else if (isDOS() && _renderMode == Common::kRenderEGA) {
+		_border->setPalette(_gfx->_palette, 0, 4);
+		processBorder();
 	}
+
 }
 
 } // End of namespace Freescape
diff --git a/engines/freescape/gfx.cpp b/engines/freescape/gfx.cpp
index ac35f24ee4f..d93e937dab8 100644
--- a/engines/freescape/gfx.cpp
+++ b/engines/freescape/gfx.cpp
@@ -342,23 +342,25 @@ void Renderer::flipVertical(Graphics::Surface *s) {
 	}
 }
 
-void Renderer::convertImageFormatIfNecessary(Graphics::ManagedSurface *surface) {
-	if (!surface)
-		return;
-
-	if (surface->format != _texturePixelFormat) {
-		const uint32 *src = surface->getPalette();
-		byte *palette = (byte *)malloc(sizeof(byte) * 16 * 3);
-		for (int num = 16; num > 0; --num, palette += 3) { // Maximum should be 16 colours
-			uint32 p = *src++;
-			palette[0] =  p        & 0xff;
-			palette[1] = (p >> 8)  & 0xff;
-			palette[2] = (p >> 16) & 0xff;
-		}
-		palette = palette - 16 * 3;
-		surface->convertToInPlace(_texturePixelFormat, palette);
-		free(palette);
-	}
+Graphics::Surface *Renderer::convertImageFormatIfNecessary(Graphics::ManagedSurface *msurface) {
+	if (!msurface)
+		return nullptr;
+
+	assert(msurface->format != _texturePixelFormat);
+	Graphics::Surface *surface = new Graphics::Surface();
+	surface->copyFrom(msurface->rawSurface());
+	const uint32 *src = msurface->getPalette();
+	byte *palette = (byte *)malloc(sizeof(byte) * 16 * 3);
+	for (int num = 16; num > 0; --num, palette += 3) { // Maximum should be 16 colours
+		uint32 p = *src++;
+		palette[0] =  p        & 0xff;
+		palette[1] = (p >> 8)  & 0xff;
+		palette[2] = (p >> 16) & 0xff;
+	}
+	palette = palette - 16 * 3;
+	surface->convertToInPlace(_texturePixelFormat, palette);
+	free(palette);
+	return surface;
 }
 
 Common::Rect Renderer::viewport() const {
diff --git a/engines/freescape/gfx.h b/engines/freescape/gfx.h
index 074ce8be090..867da87b0f0 100644
--- a/engines/freescape/gfx.h
+++ b/engines/freescape/gfx.h
@@ -77,7 +77,7 @@ public:
 	virtual void polygonOffset(bool enabled) = 0;
 
 	virtual Texture *createTexture(const Graphics::Surface *surface) = 0;
-	void convertImageFormatIfNecessary(Graphics::ManagedSurface *surface);
+	Graphics::Surface *convertImageFormatIfNecessary(Graphics::ManagedSurface *surface);
 
 	virtual void freeTexture(Texture *texture) = 0;
 	virtual void drawTexturedRect2D(const Common::Rect &screenRect, const Common::Rect &textureRect, Texture *texture) = 0;
diff --git a/engines/freescape/loaders/8bitBinaryLoader.cpp b/engines/freescape/loaders/8bitBinaryLoader.cpp
index b62a5e6d28f..d9e1157be65 100644
--- a/engines/freescape/loaders/8bitBinaryLoader.cpp
+++ b/engines/freescape/loaders/8bitBinaryLoader.cpp
@@ -310,6 +310,7 @@ void FreescapeEngine::renderPixels8bitBinImage(Graphics::ManagedSurface *surface
 		if (acc & pixels) {
 			int previousColor = surface->getPixel(i, j);
 			surface->setPixel(i, j, previousColor + color);
+			assert(previousColor + color < 16);
 		}
 		i++;
 		acc = acc >> 1;


Commit: d909a548e4f4ba32ece7bdf92209485ed0c26ce9
    https://github.com/scummvm/scummvm/commit/d909a548e4f4ba32ece7bdf92209485ed0c26ce9
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-03-20T10:11:54+01:00

Commit Message:
FREESCAPE: load original images and adjust ui for driller cpc

Changed paths:
    engines/freescape/games/driller/cpc.cpp


diff --git a/engines/freescape/games/driller/cpc.cpp b/engines/freescape/games/driller/cpc.cpp
index c42df9fbd49..25750cfb6b1 100644
--- a/engines/freescape/games/driller/cpc.cpp
+++ b/engines/freescape/games/driller/cpc.cpp
@@ -123,9 +123,75 @@ void deobfuscateDrillerCPCVirtualWorlds(byte *memBuffer) {
 	}
 }
 
+byte kCPCPalettePinkBlueWhiteData[4][3] = {
+	{0x00, 0x00, 0x00},
+	{0x55, 0xff, 0xff},
+	{0xff, 0x55, 0xff},
+	{0xff, 0xff, 0xff},
+};
+
+Graphics::ManagedSurface *readCPCImage(Common::SeekableReadStream *file) {
+	Graphics::ManagedSurface *surface = new Graphics::ManagedSurface();
+	surface->create(320, 200, Graphics::PixelFormat::createFormatCLUT8());
+	surface->fillRect(Common::Rect(0, 0, 320, 200), 0);
+
+	int x, y;
+	file->seek(0x80);
+	for (int block = 0; block < 8; block++) {
+		for (int line = 0; line < 25; line++) {
+			for (int offset = 0; offset < 320 / 4; offset++) {
+				byte cpc_byte = file->readByte(); // Get CPC byte
+
+				// Process first pixel
+				int pixel_0 = ((cpc_byte & 0x08) >> 2) | ((cpc_byte & 0x80) >> 7); // %Aa
+				y = line * 8 + block ; // Coord Y for the pixel
+				x = 4 * offset + 0; // Coord X for the pixel
+				surface->setPixel(x, y, pixel_0);
+
+				// Process second pixel
+				int pixel_1 = ((cpc_byte & 0x04) >> 1) | ((cpc_byte & 0x40) >> 6); // %Bb
+				y = line * 8 + block ; // Coord Y for the pixel
+				x = 4 * offset + 1; // Coord X for the pixel
+				surface->setPixel(x, y, pixel_1);
+
+				// Process third pixel
+				int pixel_2 = (cpc_byte & 0x02)        | ((cpc_byte & 0x20) >> 5); // %Cc
+				y = line * 8 + block ; // Coord Y for the pixel
+				x = 4 * offset + 2; // Coord X for the pixel
+				surface->setPixel(x, y, pixel_2);
+
+				// Process fourth pixel
+				int pixel_3 = ((cpc_byte & 0x01) << 1) | ((cpc_byte & 0x10) >> 4); // %Dd
+				y = line * 8 + block ; // Coord Y for the pixel
+				x = 4 * offset + 3; // Coord X for the pixel
+				surface->setPixel(x, y, pixel_3);
+			}
+		}
+		// We should skip the next 48 bytes, because they are padding the block to be 2048 bytes
+		file->seek(48, SEEK_CUR);
+	}
+	return surface;
+}
+
 void DrillerEngine::loadAssetsCPCFullGame() {
 	Common::File file;
-	loadBundledImages();
+
+	file.open("DSCN1.BIN");
+	if (!file.isOpen())
+		error("Failed to open DSCN1.BIN");
+
+	_title = readCPCImage(&file);
+	_title->setPalette((byte*)&kCPCPalettePinkBlueWhiteData, 0, 4);
+
+	file.close();
+	file.open("DSCN2.BIN");
+	if (!file.isOpen())
+		error("Failed to open DSCN2.BIN");
+
+	_border = readCPCImage(&file);
+	_border->setPalette((byte*)&kCPCPalettePinkBlueWhiteData, 0, 4);
+
+	file.close();
 	file.open("DRILL.BIN");
 
 	if (!file.isOpen())
@@ -153,30 +219,30 @@ void DrillerEngine::drawCPCUI(Graphics::Surface *surface) {
 	uint32 back = _gfx->_texturePixelFormat.ARGBToColor(0xFF, r, g, b);
 
 	int score = _gameStateVars[k8bitVariableScore];
-	drawStringInSurface(_currentArea->_name, 200, 188, front, back, surface);
-	drawStringInSurface(Common::String::format("%04d", int(2 * _position.x())), 149, 148, front, back, surface);
-	drawStringInSurface(Common::String::format("%04d", int(2 * _position.z())), 149, 156, front, back, surface);
-	drawStringInSurface(Common::String::format("%04d", int(2 * _position.y())), 149, 164, front, back, surface);
+	drawStringInSurface(_currentArea->_name, 200, 185, front, back, surface);
+	drawStringInSurface(Common::String::format("%04d", int(2 * _position.x())), 149, 145, front, back, surface);
+	drawStringInSurface(Common::String::format("%04d", int(2 * _position.z())), 149, 153, front, back, surface);
+	drawStringInSurface(Common::String::format("%04d", int(2 * _position.y())), 149, 161, front, back, surface);
 	if (_playerHeightNumber >= 0)
-		drawStringInSurface(Common::String::format("%d", _playerHeightNumber), 54, 164, front, back, surface);
+		drawStringInSurface(Common::String::format("%d", _playerHeightNumber), 54, 161, front, back, surface);
 	else
-		drawStringInSurface(Common::String::format("%s", "J"), 54, 164, front, back, surface);
+		drawStringInSurface(Common::String::format("%s", "J"), 54, 161, front, back, surface);
 
-	drawStringInSurface(Common::String::format("%02d", int(_angleRotations[_angleRotationIndex])), 46, 148, front, back, surface);
-	drawStringInSurface(Common::String::format("%3d", _playerSteps[_playerStepIndex]), 44, 156, front, back, surface);
-	drawStringInSurface(Common::String::format("%07d", score), 239, 132, front, back, surface);
+	drawStringInSurface(Common::String::format("%02d", int(_angleRotations[_angleRotationIndex])), 46, 145, front, back, surface);
+	drawStringInSurface(Common::String::format("%3d", _playerSteps[_playerStepIndex]), 44, 153, front, back, surface);
+	drawStringInSurface(Common::String::format("%07d", score), 239, 129, front, back, surface);
 
 	int seconds, minutes, hours;
 	getTimeFromCountdown(seconds, minutes, hours);
-	drawStringInSurface(Common::String::format("%02d", hours), 209, 11, front, back, surface);
-	drawStringInSurface(Common::String::format("%02d", minutes), 232, 11, front, back, surface);
-	drawStringInSurface(Common::String::format("%02d", seconds), 254, 11, front, back, surface);
+	drawStringInSurface(Common::String::format("%02d", hours), 209, 8, front, back, surface);
+	drawStringInSurface(Common::String::format("%02d", minutes), 232, 8, front, back, surface);
+	drawStringInSurface(Common::String::format("%02d", seconds), 254, 8, front, back, surface);
 
 	Common::String message;
 	int deadline;
 	getLatestMessages(message, deadline);
 	if (deadline <= _countdown) {
-		drawStringInSurface(message, 191, 180, back, front, surface);
+		drawStringInSurface(message, 191, 177, back, front, surface);
 		_temporaryMessages.push_back(message);
 		_temporaryMessageDeadlines.push_back(deadline);
 	} else if (_messagesList.size() > 0) {
@@ -187,24 +253,24 @@ void DrillerEngine::drawCPCUI(Graphics::Surface *surface) {
 		else
 			message = _messagesList[1];
 
-		drawStringInSurface(message, 191, 180, front, back, surface);
+		drawStringInSurface(message, 191, 177, front, back, surface);
 	}
 
 	int energy = _gameStateVars[k8bitVariableEnergy];
 	int shield = _gameStateVars[k8bitVariableShield];
 
 	if (energy >= 0) {
-		Common::Rect backBar(25, 187, 89 - energy, 194);
+		Common::Rect backBar(25, 184, 89 - energy, 191);
 		surface->fillRect(backBar, back);
-		Common::Rect energyBar(88 - energy, 187, 88, 194);
+		Common::Rect energyBar(88 - energy, 184, 88, 191);
 		surface->fillRect(energyBar, front);
 	}
 
 	if (shield >= 0) {
-		Common::Rect backBar(25, 180, 89 - shield, 186);
+		Common::Rect backBar(25, 177, 89 - shield, 183);
 		surface->fillRect(backBar, back);
 
-		Common::Rect shieldBar(88 - shield, 180, 88, 186);
+		Common::Rect shieldBar(88 - shield, 177, 88, 183);
 		surface->fillRect(shieldBar, front);
 	}
 }


Commit: 4633fd48749ac9ec2b93ca5db3fa6fb0306f146a
    https://github.com/scummvm/scummvm/commit/4633fd48749ac9ec2b93ca5db3fa6fb0306f146a
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-03-20T10:12:04+01:00

Commit Message:
FREESCAPE: load correct border palette for certain driller releases

Changed paths:
    engines/freescape/games/driller/driller.cpp
    engines/freescape/games/palettes.cpp


diff --git a/engines/freescape/games/driller/driller.cpp b/engines/freescape/games/driller/driller.cpp
index c1e33edd9e2..76bef52466b 100644
--- a/engines/freescape/games/driller/driller.cpp
+++ b/engines/freescape/games/driller/driller.cpp
@@ -54,7 +54,7 @@ DrillerEngine::DrillerEngine(OSystem *syst, const ADGameDescription *gd) : Frees
 	else if (isSpectrum())
 		_viewArea = Common::Rect(56, 20, 264, 124);
 	else if (isCPC())
-		_viewArea = Common::Rect(36, 19, 284, 120);
+		_viewArea = Common::Rect(36, 16, 284, 117);
 	else if (isC64())
 		_viewArea = Common::Rect(32, 16, 288, 119);
 
diff --git a/engines/freescape/games/palettes.cpp b/engines/freescape/games/palettes.cpp
index 97d4cfbf94c..6baef6c443f 100644
--- a/engines/freescape/games/palettes.cpp
+++ b/engines/freescape/games/palettes.cpp
@@ -215,6 +215,18 @@ void FreescapeEngine::swapPalette(uint16 levelID) {
 		_gfx->_inkColor = _areaMap[levelID]->_inkColor;
 		_gfx->_paperColor = _areaMap[levelID]->_paperColor;
 		_gfx->_underFireBackgroundColor = _areaMap[levelID]->_underFireBackgroundColor;
+
+		byte *palette = (byte *)malloc(sizeof(byte) * 4 * 3);
+		for (int c = 0; c < 4; c++) {
+			byte r, g, b;
+			_gfx->selectColorFromFourColorPalette(c, r, g, b);
+			palette[3 * c + 0] = r;
+			palette[3 * c + 1] = g;
+			palette[3 * c + 2] = b;
+		}
+		_border->setPalette(palette, 0, 4);
+		free(palette);
+		processBorder();
 	} else if (isDOS() && _renderMode == Common::kRenderCGA) {
 		const CGAPalettteEntry *entry = rawCGAPaletteTable;
 		while (entry->areaId) {


Commit: 6dc129dc3488fcd665356b323c037e9a862a04ca
    https://github.com/scummvm/scummvm/commit/6dc129dc3488fcd665356b323c037e9a862a04ca
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-03-20T10:12:14+01:00

Commit Message:
FREESCAPE: color and ui fixes for driller cpc

Changed paths:
    engines/freescape/games/driller/cpc.cpp
    engines/freescape/games/driller/driller.cpp


diff --git a/engines/freescape/games/driller/cpc.cpp b/engines/freescape/games/driller/cpc.cpp
index 25750cfb6b1..68c33eba2e4 100644
--- a/engines/freescape/games/driller/cpc.cpp
+++ b/engines/freescape/games/driller/cpc.cpp
@@ -123,11 +123,18 @@ void deobfuscateDrillerCPCVirtualWorlds(byte *memBuffer) {
 	}
 }
 
-byte kCPCPalettePinkBlueWhiteData[4][3] = {
+byte kCPCPaletteTitleData[4][3] = {
 	{0x00, 0x00, 0x00},
-	{0x55, 0xff, 0xff},
-	{0xff, 0x55, 0xff},
-	{0xff, 0xff, 0xff},
+	{0x00, 0x80, 0xff},
+	{0xff, 0x00, 0x00},
+	{0xff, 0xff, 0x00},
+};
+
+byte kCPCPaletteBorderData[4][3] = {
+	{0x00, 0x00, 0x00},
+	{0xff, 0x80, 0x00},
+	{0x80, 0xff, 0xff},
+	{0x00, 0x80, 0x00},
 };
 
 Graphics::ManagedSurface *readCPCImage(Common::SeekableReadStream *file) {
@@ -181,7 +188,7 @@ void DrillerEngine::loadAssetsCPCFullGame() {
 		error("Failed to open DSCN1.BIN");
 
 	_title = readCPCImage(&file);
-	_title->setPalette((byte*)&kCPCPalettePinkBlueWhiteData, 0, 4);
+	_title->setPalette((byte*)&kCPCPaletteTitleData, 0, 4);
 
 	file.close();
 	file.open("DSCN2.BIN");
@@ -189,7 +196,7 @@ void DrillerEngine::loadAssetsCPCFullGame() {
 		error("Failed to open DSCN2.BIN");
 
 	_border = readCPCImage(&file);
-	_border->setPalette((byte*)&kCPCPalettePinkBlueWhiteData, 0, 4);
+	_border->setPalette((byte*)&kCPCPaletteBorderData, 0, 4);
 
 	file.close();
 	file.open("DRILL.BIN");
@@ -220,9 +227,9 @@ void DrillerEngine::drawCPCUI(Graphics::Surface *surface) {
 
 	int score = _gameStateVars[k8bitVariableScore];
 	drawStringInSurface(_currentArea->_name, 200, 185, front, back, surface);
-	drawStringInSurface(Common::String::format("%04d", int(2 * _position.x())), 149, 145, front, back, surface);
-	drawStringInSurface(Common::String::format("%04d", int(2 * _position.z())), 149, 153, front, back, surface);
-	drawStringInSurface(Common::String::format("%04d", int(2 * _position.y())), 149, 161, front, back, surface);
+	drawStringInSurface(Common::String::format("%04d", int(2 * _position.x())), 150, 145, front, back, surface);
+	drawStringInSurface(Common::String::format("%04d", int(2 * _position.z())), 150, 153, front, back, surface);
+	drawStringInSurface(Common::String::format("%04d", int(2 * _position.y())), 150, 161, front, back, surface);
 	if (_playerHeightNumber >= 0)
 		drawStringInSurface(Common::String::format("%d", _playerHeightNumber), 54, 161, front, back, surface);
 	else
diff --git a/engines/freescape/games/driller/driller.cpp b/engines/freescape/games/driller/driller.cpp
index 76bef52466b..62ff6f7d970 100644
--- a/engines/freescape/games/driller/driller.cpp
+++ b/engines/freescape/games/driller/driller.cpp
@@ -420,6 +420,9 @@ void DrillerEngine::drawInfoMenu() {
 		case Common::kRenderZX:
 			color = 6;
 			break;
+		case Common::kRenderCPC:
+			color = _gfx->_underFireBackgroundColor;
+			break;
 		default:
 			color = 14;
 	}


Commit: c77e28050002a023caeaf6577af6eed38551b11f
    https://github.com/scummvm/scummvm/commit/c77e28050002a023caeaf6577af6eed38551b11f
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-03-20T10:12:23+01:00

Commit Message:
FREESCAPE: correctly parse images in dos driller demo and removed extra files from freescape.dat

Changed paths:
  R devtools/create_freescape/driller_cga.bmp
  R devtools/create_freescape/driller_cpc.bmp
    dists/engine-data/freescape.dat
    engines/freescape/freescape.h
    engines/freescape/games/driller/dos.cpp
    engines/freescape/games/driller/driller.cpp


diff --git a/devtools/create_freescape/driller_cga.bmp b/devtools/create_freescape/driller_cga.bmp
deleted file mode 100644
index 4234daf00ac..00000000000
Binary files a/devtools/create_freescape/driller_cga.bmp and /dev/null differ
diff --git a/devtools/create_freescape/driller_cpc.bmp b/devtools/create_freescape/driller_cpc.bmp
deleted file mode 100644
index 2b834a76adc..00000000000
Binary files a/devtools/create_freescape/driller_cpc.bmp and /dev/null differ
diff --git a/dists/engine-data/freescape.dat b/dists/engine-data/freescape.dat
index 322725f9b14..4bae5edd3a7 100644
Binary files a/dists/engine-data/freescape.dat and b/dists/engine-data/freescape.dat differ
diff --git a/engines/freescape/freescape.h b/engines/freescape/freescape.h
index 1b21c8edcc4..d2f8405437a 100644
--- a/engines/freescape/freescape.h
+++ b/engines/freescape/freescape.h
@@ -462,6 +462,8 @@ private:
 	void drawAmigaAtariSTUI(Graphics::Surface *surface);
 
 	Graphics::ManagedSurface *load8bitTitleImage(Common::SeekableReadStream *file, int offset);
+	Graphics::ManagedSurface *load8bitDemoImage(Common::SeekableReadStream *file, int offset);
+
 	uint32 getPixel8bitTitleImage(int index);
 	void renderPixels8bitTitleImage(Graphics::ManagedSurface *surface, int &i, int &j, int pixels);
 };
diff --git a/engines/freescape/games/driller/dos.cpp b/engines/freescape/games/driller/dos.cpp
index ee38b0a6b13..4998673f6a7 100644
--- a/engines/freescape/games/driller/dos.cpp
+++ b/engines/freescape/games/driller/dos.cpp
@@ -196,6 +196,50 @@ byte kEGADefaultPaletteData[16][3] = {
 	{0x00, 0x00, 0x00}
 };
 
+Graphics::ManagedSurface *DrillerEngine::load8bitDemoImage(Common::SeekableReadStream *file, int offset) {
+	Graphics::ManagedSurface *surface = new Graphics::ManagedSurface();
+	surface->create(320, 200, Graphics::PixelFormat::createFormatCLUT8());
+	surface->fillRect(Common::Rect(0, 0, 320, 200), 0);
+	file->seek(offset);
+	int i = 0;
+	int j = 0;
+	while (true) {
+		byte pixels = file->readByte();
+		for (int b = 0; b < 4; b++) {
+			int color = pixels & 3;
+			pixels = pixels >> 2;
+			surface->setPixel(i + (3 - b), 2 * j, color);
+		}
+		i = i + 4;
+		if (i == 320) {
+			i = 0;
+			j++;
+		}
+		if (j == 100)
+			break;
+	}
+	file->seek(0xc0, SEEK_CUR);
+
+	i = 0;
+	j = 0;
+	while (true) {
+		byte pixels = file->readByte();
+		for (int b = 0; b < 4; b++) {
+			int color = pixels & 3;
+			pixels = pixels >> 2;
+			surface->setPixel(i + (3 - b), 2 * j + 1, color);
+		}
+		i = i + 4;
+		if (i == 320) {
+			i = 0;
+			j++;
+		}
+		if (j == 100)
+			break;
+	}
+	return surface;
+}
+
 void DrillerEngine::loadAssetsDOSFullGame() {
 	Common::File file;
 	if (_renderMode == Common::kRenderEGA) {
@@ -256,7 +300,6 @@ void DrillerEngine::loadAssetsDOSDemo() {
 	_renderMode = Common::kRenderCGA; // DOS demos is CGA only
 	_viewArea = Common::Rect(36, 16, 284, 117); // correct view area
 	_gfx->_renderMode = _renderMode;
-	loadBundledImages();
 	file.open("d2");
 	if (!file.isOpen())
 		error("Failed to open 'd2' file");
@@ -265,6 +308,8 @@ void DrillerEngine::loadAssetsDOSDemo() {
 	loadMessagesFixedSize(&file, 0x636, 14, 20);
 	load8bitBinary(&file, 0x55b0, 4);
 	loadGlobalObjects(&file, 0x8c);
+	_border = load8bitDemoImage(&file, 0x6220);
+	_border->setPalette((byte*)&kCGAPalettePinkBlueWhiteData, 0, 4);
 
 	// Fixed for a corrupted area names in the demo data
 	_areaMap[2]->_name = "LAPIS LAZULI";
diff --git a/engines/freescape/games/driller/driller.cpp b/engines/freescape/games/driller/driller.cpp
index 62ff6f7d970..782506c5ea8 100644
--- a/engines/freescape/games/driller/driller.cpp
+++ b/engines/freescape/games/driller/driller.cpp
@@ -105,9 +105,6 @@ void DrillerEngine::titleScreen() {
 	}
 }
 void DrillerEngine::borderScreen() {
-	if (isDOS() && isDemo()) // Demo will not show the border
-		return;
-
 	if (isAmiga() || isAtariST()) // TODO: implement these with their own animations
 		return;
 


Commit: ef1a07d8f5ce731bfa08a0140339738cdf340452
    https://github.com/scummvm/scummvm/commit/ef1a07d8f5ce731bfa08a0140339738cdf340452
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-03-20T10:12:44+01:00

Commit Message:
FREESCAPE: removed edsk related code to parse cpc releases of driller

Changed paths:
    engines/freescape/detection.cpp
    engines/freescape/games/driller/cpc.cpp


diff --git a/engines/freescape/detection.cpp b/engines/freescape/detection.cpp
index 758267f1f88..cdfcccba49d 100644
--- a/engines/freescape/detection.cpp
+++ b/engines/freescape/detection.cpp
@@ -83,18 +83,6 @@ static const ADGameDescription gameDescriptions[] = {
 		GF_CPC_RETAIL,
 		GUIO2(GUIO_NOMIDI, GAMEOPTION_AUTOMATIC_DRILLING)
 	},
-	{
-		"driller",
-		"VirtualWorlds-A",
-		{
-			{"VIRTUALWORLDS.A.CPC.EDSK", 0, "421d369636984fc209a0969007daa35b", 195635},
-			AD_LISTEND
-		},
-		Common::EN_ANY,
-		Common::kPlatformAmstradCPC,
-		GF_CPC_VIRTUALWORLDS,
-		GUIO2(GUIO_NOMIDI, GAMEOPTION_AUTOMATIC_DRILLING)
-	},
 	{
 		"spacestationoblivion",
 		"",
diff --git a/engines/freescape/games/driller/cpc.cpp b/engines/freescape/games/driller/cpc.cpp
index 68c33eba2e4..bd43a0a1d01 100644
--- a/engines/freescape/games/driller/cpc.cpp
+++ b/engines/freescape/games/driller/cpc.cpp
@@ -27,102 +27,6 @@
 
 namespace Freescape {
 
-byte *parseEDSK(const Common::String filename, int &size) {
-	debugC(1, kFreescapeDebugParser, "Trying to parse edsk file: %s", filename.c_str());
-	Common::File file;
-	file.open(filename);
-	if (!file.isOpen())
-		error("Failed to open %s", filename.c_str());
-
-	int totalSize = file.size();
-	byte *edskBuffer = (byte *)malloc(totalSize);
-	file.read(edskBuffer, totalSize);
-	file.close();
-
-	// We don't know the final size, but we allocate enough
-	byte *memBuffer = (byte *)malloc(totalSize);
-
-	byte nsides = edskBuffer[49];
-	assert(nsides == 1);
-	int ntracks = 0;
-	int i = 256;
-	int j = 0;
-	while (i + 1 < totalSize) {
-		byte ssize = edskBuffer[i + 0x14];
-		debugC(1, kFreescapeDebugParser, "i: %x ssize: %d, number: %d", i, ssize, edskBuffer[i + 0x10]);
-		assert(ssize == 3 || edskBuffer[i + 0x0] == 'T');
-		assert(ssize == 3 || edskBuffer[i + 0x1] == 'r');
-		assert(ssize == 3 || edskBuffer[i + 0x2] == 'a');
-		//assert(ssize == 3 || ntracks == edskBuffer[i + 0x10]);
-		int start = i + 0x100;
-		debugC(1, kFreescapeDebugParser, "sector size: %d", ssize);
-		if (ssize == 2) {
-			i = i + 9 * 512 + 256;
-		} else if (ssize == 5) {
-			i = i + 8 * 512 + 256;
-		} else if (ssize == 0) {
-			i = totalSize - 1;
-		} else if (ssize == 3) {
-			break; // Not sure
-		} else {
-			error("ssize: %d", ssize);
-		}
-		int osize = i - start;
-		debugC(1, kFreescapeDebugParser, "copying track %d start: %x size: %x, dest: %x", ntracks, start, osize, j);
-		memcpy(memBuffer + j, edskBuffer + start, osize);
-		j = j + osize;
-		ntracks++;
-	}
-	size = j;
-
-	if (0) { // Useful to debug where exactly each object is located in memory once it is parsed
-		i = 0;
-		while(i < j) {
-			debugN("%05x: ", i);
-			for (int k = 0; k <= 16; k++) {
-				debugN("%02x ", memBuffer[i]);
-				i++;
-			}
-			debugN("\n");
-		}
-	}
-	free(edskBuffer);
-	return memBuffer;
-}
-
-void deobfuscateDrillerCPCVirtualWorlds(byte *memBuffer) {
-	// Deofuscation / loader code
-	for (int j = 0; j < 0x200; j++) {
-		memBuffer[0x14000 + j] = memBuffer[0x14200 + j];
-		memBuffer[0x14200 + j] = memBuffer[0x13400 + j];
-		memBuffer[0x14400 + j] = memBuffer[0x13800 + j];
-		memBuffer[0x14600 + j] = memBuffer[0x13c00 + j];
-	}
-
-	for (int j = 0; j < 0x200; j++) {
-		memBuffer[0x13c00 + j] = memBuffer[0x13a00 + j];
-		memBuffer[0x13a00 + j] = memBuffer[0x13600 + j];
-		memBuffer[0x13800 + j] = memBuffer[0x13200 + j];
-		memBuffer[0x13600 + j] = memBuffer[0x12e00 + j];
-		memBuffer[0x12e00 + j] = memBuffer[0x13000 + j];
-		memBuffer[0x13000 + j] = memBuffer[0x12200 + j];
-		memBuffer[0x13200 + j] = memBuffer[0x12600 + j];
-		memBuffer[0x13400 + j] = memBuffer[0x12a00 + j];
-	}
-
-	for (int i = 6; i >= 0; i--) {
-		//debug("copying 0x200 bytes to %x from %x", 0x12000 + 0x200*i, 0x11400 + 0x400*i);
-		for (int j = 0; j < 0x200; j++) {
-			memBuffer[0x12000 + 0x200*i + j] = memBuffer[0x11400 + 0x400*i + j];
-		}
-	}
-
-	for (int j = 0; j < 0x200; j++) {
-		memBuffer[0x11c00 + j] = memBuffer[0x11e00 + j];
-		memBuffer[0x11e00 + j] = memBuffer[0x11000 + j];
-	}
-}
-
 byte kCPCPaletteTitleData[4][3] = {
 	{0x00, 0x00, 0x00},
 	{0x00, 0x80, 0xff},


Commit: cc7bb7d6601540f78a6e9bc832c06c7f6f65294b
    https://github.com/scummvm/scummvm/commit/cc7bb7d6601540f78a6e9bc832c06c7f6f65294b
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-03-20T11:00:52+01:00

Commit Message:
FREESCAPE: load and show driller dos demo title image

Changed paths:
    engines/freescape/games/driller/dos.cpp
    engines/freescape/games/driller/driller.cpp


diff --git a/engines/freescape/games/driller/dos.cpp b/engines/freescape/games/driller/dos.cpp
index 4998673f6a7..fa948e5c330 100644
--- a/engines/freescape/games/driller/dos.cpp
+++ b/engines/freescape/games/driller/dos.cpp
@@ -196,6 +196,11 @@ byte kEGADefaultPaletteData[16][3] = {
 	{0x00, 0x00, 0x00}
 };
 
+/*
+ The following function is only used for decoding images for
+ the Driller DOS demo
+*/
+
 Graphics::ManagedSurface *DrillerEngine::load8bitDemoImage(Common::SeekableReadStream *file, int offset) {
 	Graphics::ManagedSurface *surface = new Graphics::ManagedSurface();
 	surface->create(320, 200, Graphics::PixelFormat::createFormatCLUT8());
@@ -300,6 +305,14 @@ void DrillerEngine::loadAssetsDOSDemo() {
 	_renderMode = Common::kRenderCGA; // DOS demos is CGA only
 	_viewArea = Common::Rect(36, 16, 284, 117); // correct view area
 	_gfx->_renderMode = _renderMode;
+	file.open("d1");
+	if (!file.isOpen())
+		error("Failed to open 'd1' file");
+
+	_title = load8bitDemoImage(&file, 0x0);
+	_title->setPalette((byte*)&kCGAPalettePinkBlueWhiteData, 0, 4);
+
+	file.close();
 	file.open("d2");
 	if (!file.isOpen())
 		error("Failed to open 'd2' file");
diff --git a/engines/freescape/games/driller/driller.cpp b/engines/freescape/games/driller/driller.cpp
index 782506c5ea8..a9fb1974581 100644
--- a/engines/freescape/games/driller/driller.cpp
+++ b/engines/freescape/games/driller/driller.cpp
@@ -91,9 +91,6 @@ DrillerEngine::~DrillerEngine() {
 }
 
 void DrillerEngine::titleScreen() {
-	if (isDOS() && isDemo()) // Demo will not show any title screen
-		return;
-
 	if (isAmiga() || isAtariST()) // TODO: implement these with their own animations
 		return;
 


Commit: b4f7bc818d2f7507102f85e4f733952e79ead4da
    https://github.com/scummvm/scummvm/commit/b4f7bc818d2f7507102f85e4f733952e79ead4da
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-03-20T11:01:01+01:00

Commit Message:
FREESCAPE: moved dark side related code to its own directory

Changed paths:
  A engines/freescape/games/dark/dark.cpp
  A engines/freescape/games/dark/dos.cpp
  R engines/freescape/games/dark.cpp
    engines/freescape/module.mk


diff --git a/engines/freescape/games/dark.cpp b/engines/freescape/games/dark/dark.cpp
similarity index 82%
rename from engines/freescape/games/dark.cpp
rename to engines/freescape/games/dark/dark.cpp
index 1a10368adb1..29414dbbbc9 100644
--- a/engines/freescape/games/dark.cpp
+++ b/engines/freescape/games/dark/dark.cpp
@@ -298,69 +298,6 @@ void DarkEngine::updateTimeVariables() {
 	}
 }
 
-void DarkEngine::drawDOSUI(Graphics::Surface *surface) {
-	uint32 color = _renderMode == Common::kRenderCGA ? 1 : 14;
-	uint8 r, g, b;
-
-	_gfx->readFromPalette(color, r, g, b);
-	uint32 front = _gfx->_texturePixelFormat.ARGBToColor(0xFF, r, g, b);
-
-	color = _currentArea->_usualBackgroundColor;
-	if (_gfx->_colorRemaps && _gfx->_colorRemaps->contains(color)) {
-		color = (*_gfx->_colorRemaps)[color];
-	}
-
-	_gfx->readFromPalette(color, r, g, b);
-	uint32 back = _gfx->_texturePixelFormat.ARGBToColor(0xFF, r, g, b);
-
-	int score = _gameStateVars[k8bitVariableScore];
-	drawStringInSurface(Common::String::format("%04d", int(2 * _position.x())), 199, 137, front, back, surface);
-	drawStringInSurface(Common::String::format("%04d", int(2 * _position.z())), 199, 145, front, back, surface);
-	drawStringInSurface(Common::String::format("%04d", int(2 * _position.y())), 199, 153, front, back, surface);
-
-	drawStringInSurface(Common::String::format("%02d", int(_angleRotations[_angleRotationIndex])), 71, 168, front, back, surface);
-	drawStringInSurface(Common::String::format("%3d", _playerSteps[_playerStepIndex]), 71, 177, front, back, surface);
-	drawStringInSurface(Common::String::format("%07d", score), 95, 8, front, back, surface);
-
-	int seconds, minutes, hours;
-	getTimeFromCountdown(seconds, minutes, hours);
-	// TODO: implement binary clock
-
-	Common::String message;
-	int deadline;
-	getLatestMessages(message, deadline);
-	if (deadline <= _countdown) {
-		drawStringInSurface(message, 112, 177, back, front, surface);
-		_temporaryMessages.push_back(message);
-		_temporaryMessageDeadlines.push_back(deadline);
-	} else
-		drawStringInSurface(_currentArea->_name, 112, 177, front, back, surface);
-
-	int energy = _gameStateVars[k8bitVariableEnergy]; // called fuel in this game
-	int shield = _gameStateVars[k8bitVariableShield];
-
-	_gfx->readFromPalette(9, r, g, b);
-	uint32 blue = _gfx->_texturePixelFormat.ARGBToColor(0xFF, r, g, b);
-
-	if (shield >= 0) {
-		Common::Rect shieldBar;
-		shieldBar = Common::Rect(72, 139, 151 - (k8bitMaxShield - shield), 146);
-		surface->fillRect(shieldBar, front);
-
-		shieldBar = Common::Rect(72, 140, 151 - (k8bitMaxShield - shield), 145);
-		surface->fillRect(shieldBar, blue);
-	}
-
-	if (energy >= 0) {
-		Common::Rect energyBar;
-		energyBar = Common::Rect(72, 147, 151 - (k8bitMaxEnergy - energy), 154);
-		surface->fillRect(energyBar, front);
-
-		energyBar = Common::Rect(72, 148, 151 - (k8bitMaxEnergy - energy), 153);
-		surface->fillRect(energyBar, blue);
-	}
-}
-
 void DarkEngine::drawUI() {
 	Graphics::Surface *surface = nullptr;
 	if (_border) { // This can be removed when all the borders are loaded
diff --git a/engines/freescape/games/dark/dos.cpp b/engines/freescape/games/dark/dos.cpp
new file mode 100644
index 00000000000..6a3c5aff2ae
--- /dev/null
+++ b/engines/freescape/games/dark/dos.cpp
@@ -0,0 +1,92 @@
+/* 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 3 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, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "common/file.h"
+
+#include "freescape/freescape.h"
+#include "freescape/language/8bitDetokeniser.h"
+
+namespace Freescape {
+
+void DarkEngine::drawDOSUI(Graphics::Surface *surface) {
+	uint32 color = _renderMode == Common::kRenderCGA ? 1 : 14;
+	uint8 r, g, b;
+
+	_gfx->readFromPalette(color, r, g, b);
+	uint32 front = _gfx->_texturePixelFormat.ARGBToColor(0xFF, r, g, b);
+
+	color = _currentArea->_usualBackgroundColor;
+	if (_gfx->_colorRemaps && _gfx->_colorRemaps->contains(color)) {
+		color = (*_gfx->_colorRemaps)[color];
+	}
+
+	_gfx->readFromPalette(color, r, g, b);
+	uint32 back = _gfx->_texturePixelFormat.ARGBToColor(0xFF, r, g, b);
+
+	int score = _gameStateVars[k8bitVariableScore];
+	drawStringInSurface(Common::String::format("%04d", int(2 * _position.x())), 199, 137, front, back, surface);
+	drawStringInSurface(Common::String::format("%04d", int(2 * _position.z())), 199, 145, front, back, surface);
+	drawStringInSurface(Common::String::format("%04d", int(2 * _position.y())), 199, 153, front, back, surface);
+
+	drawStringInSurface(Common::String::format("%02d", int(_angleRotations[_angleRotationIndex])), 71, 168, front, back, surface);
+	drawStringInSurface(Common::String::format("%3d", _playerSteps[_playerStepIndex]), 71, 177, front, back, surface);
+	drawStringInSurface(Common::String::format("%07d", score), 95, 8, front, back, surface);
+
+	int seconds, minutes, hours;
+	getTimeFromCountdown(seconds, minutes, hours);
+	// TODO: implement binary clock
+
+	Common::String message;
+	int deadline;
+	getLatestMessages(message, deadline);
+	if (deadline <= _countdown) {
+		drawStringInSurface(message, 112, 177, back, front, surface);
+		_temporaryMessages.push_back(message);
+		_temporaryMessageDeadlines.push_back(deadline);
+	} else
+		drawStringInSurface(_currentArea->_name, 112, 177, front, back, surface);
+
+	int energy = _gameStateVars[k8bitVariableEnergy]; // called fuel in this game
+	int shield = _gameStateVars[k8bitVariableShield];
+
+	_gfx->readFromPalette(9, r, g, b);
+	uint32 blue = _gfx->_texturePixelFormat.ARGBToColor(0xFF, r, g, b);
+
+	if (shield >= 0) {
+		Common::Rect shieldBar;
+		shieldBar = Common::Rect(72, 139, 151 - (k8bitMaxShield - shield), 146);
+		surface->fillRect(shieldBar, front);
+
+		shieldBar = Common::Rect(72, 140, 151 - (k8bitMaxShield - shield), 145);
+		surface->fillRect(shieldBar, blue);
+	}
+
+	if (energy >= 0) {
+		Common::Rect energyBar;
+		energyBar = Common::Rect(72, 147, 151 - (k8bitMaxEnergy - energy), 154);
+		surface->fillRect(energyBar, front);
+
+		energyBar = Common::Rect(72, 148, 151 - (k8bitMaxEnergy - energy), 153);
+		surface->fillRect(energyBar, blue);
+	}
+}
+
+} // End of namespace Freescape
\ No newline at end of file
diff --git a/engines/freescape/module.mk b/engines/freescape/module.mk
index 0d3c8b7d085..771c5b78e7f 100644
--- a/engines/freescape/module.mk
+++ b/engines/freescape/module.mk
@@ -5,7 +5,8 @@ MODULE_OBJS := \
 	demo.o \
 	freescape.o \
 	games/castle.o \
-	games/dark.o \
+	games/dark/dark.o \
+	games/dark/dos.o \
 	games/driller/amiga.o \
 	games/driller/atari.o \
 	games/driller/cpc.o \


Commit: 82813e11d638072799ca9d8c7b85e7e3da437535
    https://github.com/scummvm/scummvm/commit/82813e11d638072799ca9d8c7b85e7e3da437535
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-03-20T11:01:09+01:00

Commit Message:
FREESCAPE: moved some functions to the main freescape class and reorganized game code

Changed paths:
  A engines/freescape/assets.cpp
  A engines/freescape/ui.cpp
    engines/freescape/freescape.cpp
    engines/freescape/freescape.h
    engines/freescape/games/castle.cpp
    engines/freescape/games/dark/dark.cpp
    engines/freescape/games/driller/driller.cpp
    engines/freescape/games/eclipse.cpp
    engines/freescape/module.mk


diff --git a/engines/freescape/assets.cpp b/engines/freescape/assets.cpp
new file mode 100644
index 00000000000..a43b59d02c1
--- /dev/null
+++ b/engines/freescape/assets.cpp
@@ -0,0 +1,72 @@
+/* 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 3 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, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+// Based on Phantasma code by Thomas Harte (2013),
+// available at https://github.com/TomHarte/Phantasma/ (MIT)
+
+#include "freescape/freescape.h"
+
+namespace Freescape {
+
+void FreescapeEngine::loadAssets() {
+	if (isDemo())
+		loadAssetsDemo();
+	else
+		loadAssetsFullGame();
+}
+
+void FreescapeEngine::loadAssetsDemo() {
+}
+
+void FreescapeEngine::loadAssetsAtariDemo() {
+}
+
+void FreescapeEngine::loadAssetsAmigaDemo() {
+}
+
+void FreescapeEngine::loadAssetsDOSDemo() {
+}
+
+void FreescapeEngine::loadAssetsZXDemo() {
+}
+
+void FreescapeEngine::loadAssetsCPCDemo() {
+}
+
+void FreescapeEngine::loadAssetsFullGame() {
+}
+
+void FreescapeEngine::loadAssetsAtariFullGame() {
+}
+
+void FreescapeEngine::loadAssetsAmigaFullGame() {
+}
+
+void FreescapeEngine::loadAssetsDOSFullGame() {
+}
+
+void FreescapeEngine::loadAssetsZXFullGame() {
+}
+
+void FreescapeEngine::loadAssetsCPCFullGame() {
+}
+
+} // End of namespace Freescape
diff --git a/engines/freescape/freescape.cpp b/engines/freescape/freescape.cpp
index 52aa76309dd..c39ed86ade4 100644
--- a/engines/freescape/freescape.cpp
+++ b/engines/freescape/freescape.cpp
@@ -203,10 +203,6 @@ void FreescapeEngine::drawTitle() {
 	_gfx->setViewport(_viewArea);
 }
 
-void FreescapeEngine::loadAssets() {
-	error("Function \"%s\" not implemented", __FUNCTION__);
-}
-
 // Taken from the Myst 3 codebase, it should be abstracted
 Math::Vector3d FreescapeEngine::directionToVector(float pitch, float heading) {
 	Math::Vector3d v;
@@ -222,25 +218,6 @@ Math::Vector3d FreescapeEngine::directionToVector(float pitch, float heading) {
 	return v;
 }
 
-void FreescapeEngine::drawUI() {
-	// TODO: crossair
-	_gfx->setViewport(_viewArea);
-}
-
-void FreescapeEngine::drawInfoMenu() {
-	warning("Function \"%s\" not implemented", __FUNCTION__);
-}
-
-void FreescapeEngine::drawCrossair(Graphics::Surface *surface) {
-	uint32 white = _gfx->_texturePixelFormat.ARGBToColor(0xFF, 0x00, 0x00, 0x00);
-
-	surface->drawLine(_crossairPosition.x - 3, _crossairPosition.y, _crossairPosition.x - 2, _crossairPosition.y, white);
-	surface->drawLine(_crossairPosition.x + 2, _crossairPosition.y, _crossairPosition.x + 3, _crossairPosition.y, white);
-
-	surface->drawLine(_crossairPosition.x, _crossairPosition.y - 3, _crossairPosition.x, _crossairPosition.y - 2, white);
-	surface->drawLine(_crossairPosition.x, _crossairPosition.y + 2, _crossairPosition.x, _crossairPosition.y + 3, white);
-}
-
 void FreescapeEngine::centerCrossair() {
 	_crossairPosition.x = _viewArea.left + _viewArea.width() / 2;
 	_crossairPosition.y = _viewArea.top + _viewArea.height() / 2;
@@ -295,7 +272,6 @@ void FreescapeEngine::drawBackground() {
 	_gfx->clear(_currentArea->_skyColor);
 }
 
-
 void FreescapeEngine::drawFrame() {
 	_gfx->updateProjectionMatrix(70.0, _nearClipPlane, _farClipPlane);
 	_gfx->positionCamera(_position, _position + _cameraFront);
diff --git a/engines/freescape/freescape.h b/engines/freescape/freescape.h
index d2f8405437a..f0418c893f8 100644
--- a/engines/freescape/freescape.h
+++ b/engines/freescape/freescape.h
@@ -135,7 +135,31 @@ public:
 
 	// Parsing assets
 	uint8 _binaryBits;
-	virtual void loadAssets();
+	void loadAssets();
+	virtual void loadAssetsDemo();
+	virtual void loadAssetsFullGame();
+
+	virtual void loadAssetsAtariFullGame();
+	virtual void loadAssetsAtariDemo();
+
+	virtual void loadAssetsAmigaFullGame();
+	virtual void loadAssetsAmigaDemo();
+
+	virtual void loadAssetsDOSFullGame();
+	virtual void loadAssetsDOSDemo();
+
+	virtual void loadAssetsZXFullGame();
+	virtual void loadAssetsZXDemo();
+
+	virtual void loadAssetsCPCFullGame();
+	virtual void loadAssetsCPCDemo();
+
+	virtual void drawDOSUI(Graphics::Surface *surface);
+	virtual void drawZXUI(Graphics::Surface *surface);
+	virtual void drawCPCUI(Graphics::Surface *surface);
+	virtual void drawC64UI(Graphics::Surface *surface);
+	virtual void drawAmigaAtariSTUI(Graphics::Surface *surface);
+
 	Common::Archive *_dataBundle;
 	void loadDataBundle();
 	void loadBundledImages();
@@ -419,8 +443,6 @@ public:
 	void titleScreen() override;
 
 	void processBorder() override;
-	void loadAssets() override;
-	void drawUI() override;
 	void drawInfoMenu() override;
 
 	void pressedKey(const int keycode) override;
@@ -437,29 +459,27 @@ private:
 	void removeDrill(Area *area);
 	void addSkanner(Area *area);
 
-	void loadAssetsDemo();
-	void loadAssetsFullGame();
+	void loadAssetsDemo() override;
+	void loadAssetsFullGame() override;
 
-	void loadAssetsAtariFullGame();
-	void loadAssetsAtariDemo();
+	void loadAssetsAtariFullGame() override;
+	void loadAssetsAtariDemo() override;
 
-	void loadAssetsAmigaFullGame();
-	void loadAssetsAmigaDemo();
+	void loadAssetsAmigaFullGame() override;
+	void loadAssetsAmigaDemo() override;
 
-	void loadAssetsDOSFullGame();
-	void loadAssetsDOSDemo();
+	void loadAssetsDOSFullGame() override;
+	void loadAssetsDOSDemo() override;
 
-	void loadAssetsZXFullGame();
-	void loadAssetsZXDemo();
+	void loadAssetsZXFullGame() override;
 
-	void loadAssetsCPCFullGame();
-	void loadAssetsCPCDemo();
+	void loadAssetsCPCFullGame() override;
 
-	void drawDOSUI(Graphics::Surface *surface);
-	void drawZXUI(Graphics::Surface *surface);
-	void drawCPCUI(Graphics::Surface *surface);
-	void drawC64UI(Graphics::Surface *surface);
-	void drawAmigaAtariSTUI(Graphics::Surface *surface);
+	void drawDOSUI(Graphics::Surface *surface) override;
+	void drawZXUI(Graphics::Surface *surface) override;
+	void drawCPCUI(Graphics::Surface *surface) override;
+	void drawC64UI(Graphics::Surface *surface) override;
+	void drawAmigaAtariSTUI(Graphics::Surface *surface) override;
 
 	Graphics::ManagedSurface *load8bitTitleImage(Common::SeekableReadStream *file, int offset);
 	Graphics::ManagedSurface *load8bitDemoImage(Common::SeekableReadStream *file, int offset);
@@ -475,7 +495,6 @@ public:
 	uint32 _initialFuel;
 	uint32 _initialShield;
 
-	void loadAssets() override;
 	void initGameState() override;
 	void borderScreen() override;
 	void titleScreen() override;
@@ -505,7 +524,7 @@ class EclipseEngine : public FreescapeEngine {
 public:
 	EclipseEngine(OSystem *syst, const ADGameDescription *gd);
 
-	void loadAssets() override;
+	void loadAssetsFullGame() override;
 	void titleScreen() override;
 
 	void gotoArea(uint16 areaID, int entranceID) override;
@@ -519,7 +538,7 @@ class CastleEngine : public FreescapeEngine {
 public:
 	CastleEngine(OSystem *syst, const ADGameDescription *gd);
 
-	void loadAssets() override;
+	void loadAssetsFullGame() override;
 
 	void gotoArea(uint16 areaID, int entranceID) override;
 	Common::Error saveGameStreamExtended(Common::WriteStream *stream, bool isAutosave = false) override;
diff --git a/engines/freescape/games/castle.cpp b/engines/freescape/games/castle.cpp
index 249c3b32064..1830891b8ed 100644
--- a/engines/freescape/games/castle.cpp
+++ b/engines/freescape/games/castle.cpp
@@ -56,7 +56,7 @@ Common::SeekableReadStream *CastleEngine::decryptFile(const Common::String filen
 	return (new Common::MemoryReadStream(encryptedBuffer, size));
 }
 
-void CastleEngine::loadAssets() {
+void CastleEngine::loadAssetsFullGame() {
 	Common::SeekableReadStream *stream = nullptr;
 
 	stream = decryptFile("CMLE");
diff --git a/engines/freescape/games/dark/dark.cpp b/engines/freescape/games/dark/dark.cpp
index 29414dbbbc9..eadc74d1c12 100644
--- a/engines/freescape/games/dark/dark.cpp
+++ b/engines/freescape/games/dark/dark.cpp
@@ -61,13 +61,6 @@ void DarkEngine::titleScreen() {
 	}
 }
 
-void DarkEngine::loadAssets() {
-	if (isDemo())
-		loadAssetsDemo();
-	else
-		loadAssetsFullGame();
-}
-
 void DarkEngine::loadAssetsDemo() {
 	Common::File file;
 	if (isDOS() && _renderMode == Common::kRenderEGA) {
diff --git a/engines/freescape/games/driller/driller.cpp b/engines/freescape/games/driller/driller.cpp
index a9fb1974581..d132721d0ae 100644
--- a/engines/freescape/games/driller/driller.cpp
+++ b/engines/freescape/games/driller/driller.cpp
@@ -206,16 +206,6 @@ void DrillerEngine::loadGlobalObjects(Common::SeekableReadStream *file, int offs
 	_areaMap[255] = new Area(255, 0, globalObjectsByID, nullptr);
 }
 
-void DrillerEngine::loadAssets() {
-	if (isDemo())
-		loadAssetsDemo();
-	else
-		loadAssetsFullGame();
-
-	// Start playing music, if any, in any supported format
-	playMusic("Matt Gray - The Best Of Reformation - 07 Driller Theme");
-}
-
 void DrillerEngine::loadAssetsDemo() {
 	Common::File file;
 	if (isAmiga()) {
@@ -242,20 +232,7 @@ void DrillerEngine::loadAssetsFullGame() {
 	} else if (isCPC()) {
 		loadAssetsCPCFullGame();
 	} else if (isC64()) {
-		if (_targetName.hasPrefix("spacestationoblivion")) {
-			loadBundledImages();
-			file.open("spacestationoblivion.c64.data");
-			loadMessagesFixedSize(&file, 0x167a, 14, 20);
-			//loadFonts(&file, 0xae54);
-			load8bitBinary(&file, 0x8e02, 4);
-			loadGlobalObjects(&file, 0x1855);
-		} else if (_targetName.hasPrefix("driller")) {
-			file.open("driller.c64.data");
-			loadMessagesFixedSize(&file, 0x167a - 0x400, 14, 20);
-			//loadFonts(&file, 0xae54);
-			load8bitBinary(&file, 0x8e02 - 0x400, 4);
-			loadGlobalObjects(&file, 0x1855 - 0x400);
-		}
+		//loadAssetsC64FullGame();
 	} else if (isDOS()) {
 		loadAssetsDOSFullGame();
 	} else
@@ -289,41 +266,6 @@ void DrillerEngine::processBorder() {
 	FreescapeEngine::processBorder();
 }
 
-void DrillerEngine::drawUI() {
-	Graphics::Surface *surface = nullptr;
-	if (_border) { // This can be removed when all the borders are loaded
-		uint32 gray = _gfx->_texturePixelFormat.ARGBToColor(0x00, 0xA0, 0xA0, 0xA0);
-		surface = new Graphics::Surface();
-		surface->create(_screenW, _screenH, _gfx->_texturePixelFormat);
-		surface->fillRect(_fullscreenViewArea, gray);
-		drawCrossair(surface);
-	} else
-		return;
-
-	if (isDOS())
-		drawDOSUI(surface);
-	else if (isC64())
-		drawC64UI(surface);
-	else if (isSpectrum())
-		drawZXUI(surface);
-	else if (isCPC())
-		drawCPCUI(surface);
-	else if (isAmiga() || isAtariST())
-		drawAmigaAtariSTUI(surface);
-
-	if (!_uiTexture)
-		_uiTexture = _gfx->createTexture(surface);
-	else
-		_uiTexture->update(surface);
-
-	_gfx->setViewport(_fullscreenViewArea);
-	_gfx->drawTexturedRect2D(_fullscreenViewArea, _fullscreenViewArea, _uiTexture);
-	_gfx->setViewport(_viewArea);
-
-	surface->free();
-	delete surface;
-}
-
 void DrillerEngine::drawC64UI(Graphics::Surface *surface) {
 	uint32 color = 1;
 	uint8 r, g, b;
@@ -912,6 +854,9 @@ void DrillerEngine::initGameState() {
 	_lastMinute = minutes;
 	_demoIndex = 0;
 	_demoEvents.clear();
+
+	// Start playing music, if any, in any supported format
+	playMusic("Matt Gray - The Best Of Reformation - 07 Driller Theme");
 }
 
 bool DrillerEngine::checkIfGameEnded() {
diff --git a/engines/freescape/games/eclipse.cpp b/engines/freescape/games/eclipse.cpp
index 56baa42f46b..e8d67acbfb4 100644
--- a/engines/freescape/games/eclipse.cpp
+++ b/engines/freescape/games/eclipse.cpp
@@ -111,7 +111,7 @@ void EclipseEngine::titleScreen() {
 	}
 }
 
-void EclipseEngine::loadAssets() {
+void EclipseEngine::loadAssetsFullGame() {
 	Common::File file;
 	if (_renderMode == Common::kRenderEGA) {
 		file.open("SCN1E.DAT");
diff --git a/engines/freescape/module.mk b/engines/freescape/module.mk
index 771c5b78e7f..f157394ca05 100644
--- a/engines/freescape/module.mk
+++ b/engines/freescape/module.mk
@@ -2,6 +2,7 @@ MODULE := engines/freescape
 
 MODULE_OBJS := \
 	area.o \
+	assets.o \
 	demo.o \
 	freescape.o \
 	games/castle.o \
@@ -25,7 +26,8 @@ MODULE_OBJS := \
 	objects/geometricobject.o \
 	objects/sensor.o \
 	scr.o \
-	sound.o
+	sound.o \
+	ui.o
 
 ifdef USE_TINYGL
 MODULE_OBJS += \
diff --git a/engines/freescape/ui.cpp b/engines/freescape/ui.cpp
new file mode 100644
index 00000000000..9bc829e4b93
--- /dev/null
+++ b/engines/freescape/ui.cpp
@@ -0,0 +1,90 @@
+/* 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 3 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, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "freescape/freescape.h"
+
+namespace Freescape {
+
+void FreescapeEngine::drawUI() {
+	Graphics::Surface *surface = nullptr;
+	if (_border) { // This can be removed when all the borders are loaded
+		uint32 gray = _gfx->_texturePixelFormat.ARGBToColor(0x00, 0xA0, 0xA0, 0xA0);
+		surface = new Graphics::Surface();
+		surface->create(_screenW, _screenH, _gfx->_texturePixelFormat);
+		surface->fillRect(_fullscreenViewArea, gray);
+		drawCrossair(surface);
+	} else
+		return;
+
+	if (isDOS())
+		drawDOSUI(surface);
+	else if (isC64())
+		drawC64UI(surface);
+	else if (isSpectrum())
+		drawZXUI(surface);
+	else if (isCPC())
+		drawCPCUI(surface);
+	else if (isAmiga() || isAtariST())
+		drawAmigaAtariSTUI(surface);
+
+	if (!_uiTexture)
+		_uiTexture = _gfx->createTexture(surface);
+	else
+		_uiTexture->update(surface);
+
+	_gfx->setViewport(_fullscreenViewArea);
+	_gfx->drawTexturedRect2D(_fullscreenViewArea, _fullscreenViewArea, _uiTexture);
+	_gfx->setViewport(_viewArea);
+
+	surface->free();
+	delete surface;
+}
+
+void FreescapeEngine::drawInfoMenu() {
+	warning("Function \"%s\" not implemented", __FUNCTION__);
+}
+
+void FreescapeEngine::drawCrossair(Graphics::Surface *surface) {
+	uint32 white = _gfx->_texturePixelFormat.ARGBToColor(0xFF, 0x00, 0x00, 0x00);
+
+	surface->drawLine(_crossairPosition.x - 3, _crossairPosition.y, _crossairPosition.x - 2, _crossairPosition.y, white);
+	surface->drawLine(_crossairPosition.x + 2, _crossairPosition.y, _crossairPosition.x + 3, _crossairPosition.y, white);
+
+	surface->drawLine(_crossairPosition.x, _crossairPosition.y - 3, _crossairPosition.x, _crossairPosition.y - 2, white);
+	surface->drawLine(_crossairPosition.x, _crossairPosition.y + 2, _crossairPosition.x, _crossairPosition.y + 3, white);
+}
+
+void FreescapeEngine::drawAmigaAtariSTUI(Graphics::Surface *surface) {
+}
+
+void FreescapeEngine::drawDOSUI(Graphics::Surface *surface) {
+}
+
+void FreescapeEngine::drawZXUI(Graphics::Surface *surface) {
+}
+
+void FreescapeEngine::drawCPCUI(Graphics::Surface *surface) {
+}
+
+void FreescapeEngine::drawC64UI(Graphics::Surface *surface) {
+}
+
+} // End of namespace Freescape


Commit: 98a2bbb4f012f840bf481c4e40aaf7b6995197ef
    https://github.com/scummvm/scummvm/commit/98a2bbb4f012f840bf481c4e40aaf7b6995197ef
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-03-20T11:01:17+01:00

Commit Message:
FREESCAPE: moved more functions to the main freescape class and reorganized game code

Changed paths:
    engines/freescape/assets.cpp
    engines/freescape/freescape.h
    engines/freescape/games/castle.cpp
    engines/freescape/games/dark/dark.cpp
    engines/freescape/games/driller/driller.cpp
    engines/freescape/games/eclipse.cpp


diff --git a/engines/freescape/assets.cpp b/engines/freescape/assets.cpp
index a43b59d02c1..813dfb45683 100644
--- a/engines/freescape/assets.cpp
+++ b/engines/freescape/assets.cpp
@@ -22,6 +22,8 @@
 // Based on Phantasma code by Thomas Harte (2013),
 // available at https://github.com/TomHarte/Phantasma/ (MIT)
 
+#include "common/file.h"
+
 #include "freescape/freescape.h"
 
 namespace Freescape {
@@ -33,7 +35,37 @@ void FreescapeEngine::loadAssets() {
 		loadAssetsFullGame();
 }
 
+void FreescapeEngine::loadAssetsFullGame() {
+	Common::File file;
+	if (isAmiga()) {
+		loadAssetsAmigaFullGame();
+	} else if (isAtariST()) {
+		loadAssetsAtariFullGame();
+	} else if (isSpectrum()) {
+		loadAssetsZXFullGame();
+	} else if (isCPC()) {
+		loadAssetsCPCFullGame();
+	} else if (isC64()) {
+		//loadAssetsC64FullGame();
+	} else if (isDOS()) {
+		loadAssetsDOSFullGame();
+	} else
+		error("Invalid or unsupported render mode %s for Driller", Common::getRenderModeDescription(_renderMode));
+}
+
 void FreescapeEngine::loadAssetsDemo() {
+	Common::File file;
+	if (isAmiga()) {
+		loadAssetsAmigaDemo();
+	} else if (isAtariST()) {
+		loadAssetsAtariDemo();
+	} else if (isDOS()) {
+		loadAssetsDOSDemo();
+	} else
+		error("Unsupported demo for Driller");
+
+	_demoMode = !_disableDemoMode;
+	_angleRotationIndex = 0;
 }
 
 void FreescapeEngine::loadAssetsAtariDemo() {
@@ -51,9 +83,6 @@ void FreescapeEngine::loadAssetsZXDemo() {
 void FreescapeEngine::loadAssetsCPCDemo() {
 }
 
-void FreescapeEngine::loadAssetsFullGame() {
-}
-
 void FreescapeEngine::loadAssetsAtariFullGame() {
 }
 
diff --git a/engines/freescape/freescape.h b/engines/freescape/freescape.h
index f0418c893f8..46d817799cb 100644
--- a/engines/freescape/freescape.h
+++ b/engines/freescape/freescape.h
@@ -459,7 +459,6 @@ private:
 	void removeDrill(Area *area);
 	void addSkanner(Area *area);
 
-	void loadAssetsDemo() override;
 	void loadAssetsFullGame() override;
 
 	void loadAssetsAtariFullGame() override;
@@ -504,14 +503,14 @@ public:
 	void pressedKey(const int keycode) override;
 	void executePrint(FCLInstruction &instruction) override;
 
-	void loadAssetsDemo();
-	void loadAssetsFullGame();
+	void loadAssetsDOSFullGame() override;
+	void loadAssetsDOSDemo() override;
+
 	int _lastTenSeconds;
 	void updateTimeVariables() override;
 	void executeMovementConditions() override;
 
-	void drawUI() override;
-	void drawDOSUI(Graphics::Surface *surface);
+	void drawDOSUI(Graphics::Surface *surface) override;
 	void drawFullscreenMessage(Common::String message);
 	Common::Error saveGameStreamExtended(Common::WriteStream *stream, bool isAutosave = false) override;
 	Common::Error loadGameStreamExtended(Common::SeekableReadStream *stream) override;
@@ -524,12 +523,12 @@ class EclipseEngine : public FreescapeEngine {
 public:
 	EclipseEngine(OSystem *syst, const ADGameDescription *gd);
 
-	void loadAssetsFullGame() override;
 	void titleScreen() override;
-
 	void gotoArea(uint16 areaID, int entranceID) override;
 
+	void loadAssetsDOSFullGame() override;
 	void drawUI() override;
+
 	Common::Error saveGameStreamExtended(Common::WriteStream *stream, bool isAutosave = false) override;
 	Common::Error loadGameStreamExtended(Common::SeekableReadStream *stream) override;
 };
@@ -538,7 +537,7 @@ class CastleEngine : public FreescapeEngine {
 public:
 	CastleEngine(OSystem *syst, const ADGameDescription *gd);
 
-	void loadAssetsFullGame() override;
+	void loadAssetsDOSFullGame() override;
 
 	void gotoArea(uint16 areaID, int entranceID) override;
 	Common::Error saveGameStreamExtended(Common::WriteStream *stream, bool isAutosave = false) override;
diff --git a/engines/freescape/games/castle.cpp b/engines/freescape/games/castle.cpp
index 1830891b8ed..e81afcff921 100644
--- a/engines/freescape/games/castle.cpp
+++ b/engines/freescape/games/castle.cpp
@@ -56,7 +56,7 @@ Common::SeekableReadStream *CastleEngine::decryptFile(const Common::String filen
 	return (new Common::MemoryReadStream(encryptedBuffer, size));
 }
 
-void CastleEngine::loadAssetsFullGame() {
+void CastleEngine::loadAssetsDOSFullGame() {
 	Common::SeekableReadStream *stream = nullptr;
 
 	stream = decryptFile("CMLE");
diff --git a/engines/freescape/games/dark/dark.cpp b/engines/freescape/games/dark/dark.cpp
index eadc74d1c12..0cb8e2d2a9a 100644
--- a/engines/freescape/games/dark/dark.cpp
+++ b/engines/freescape/games/dark/dark.cpp
@@ -61,36 +61,6 @@ void DarkEngine::titleScreen() {
 	}
 }
 
-void DarkEngine::loadAssetsDemo() {
-	Common::File file;
-	if (isDOS() && _renderMode == Common::kRenderEGA) {
-		file.open("SCN1E.DAT");
-		if (file.isOpen())
-			_title = load8bitBinImage(&file, 0x0);
-		file.close();
-		file.open("DSIDEE.EXE");
-
-		if (!file.isOpen())
-			error("Failed to open DSIDEE.EXE");
-		loadMessagesFixedSize(&file, 0x4525, 16, 27);
-		loadMessagesFixedSize(&file, 0x9959, 307, 5);
-		loadFonts(&file, 0xa598);
-		loadGlobalObjects(&file, 0x3d04);
-		load8bitBinary(&file, 0xa700, 16);
-		_border = load8bitBinImage(&file, 0x210);
-	} else if (isDOS() && _renderMode == Common::kRenderCGA) {
-		//loadBundledImages();
-		file.open("DSIDEC.EXE");
-
-		if (!file.isOpen())
-			error("Failed to open DSIDEC.EXE");
-		loadFonts(&file, 0xa598);
-		load8bitBinary(&file, 0x8a70, 4); // TODO
-	} else
-		error("Invalid or unsupported render mode %s for Dark Side", Common::getRenderModeDescription(_renderMode));
-}
-
-
 void DarkEngine::loadGlobalObjects(Common::SeekableReadStream *file, int offset) {
 	assert(!_areaMap.contains(255));
 	ObjectMap *globalObjectsByID = new ObjectMap;
@@ -106,7 +76,6 @@ void DarkEngine::loadGlobalObjects(Common::SeekableReadStream *file, int offset)
 	_areaMap[255] = new Area(255, 0, globalObjectsByID, nullptr);
 }
 
-
 void DarkEngine::initGameState() {
 	_flyMode = false;
 	_noClipMode = false;
@@ -135,12 +104,48 @@ void DarkEngine::initGameState() {
 	_demoEvents.clear();
 }
 
-void DarkEngine::loadAssetsFullGame() {
+extern byte kEGADefaultPaletteData[16][3];
+
+void DarkEngine::loadAssetsDOSDemo() {
 	Common::File file;
 	if (_renderMode == Common::kRenderEGA) {
 		file.open("SCN1E.DAT");
-		if (file.isOpen())
+		if (file.isOpen()) {
 			_title = load8bitBinImage(&file, 0x0);
+			_title->setPalette((byte *)&kEGADefaultPaletteData, 0, 16);
+		}
+		file.close();
+		file.open("DSIDEE.EXE");
+
+		if (!file.isOpen())
+			error("Failed to open DSIDEE.EXE");
+		loadMessagesFixedSize(&file, 0x4525, 16, 27);
+		loadMessagesFixedSize(&file, 0x9959, 307, 5);
+		loadFonts(&file, 0xa598);
+		loadGlobalObjects(&file, 0x3d04);
+		load8bitBinary(&file, 0xa700, 16);
+		_border = load8bitBinImage(&file, 0x210);
+		_border->setPalette((byte *)&kEGADefaultPaletteData, 0, 16);
+	} else if (_renderMode == Common::kRenderCGA) {
+		//loadBundledImages();
+		file.open("DSIDEC.EXE");
+
+		if (!file.isOpen())
+			error("Failed to open DSIDEC.EXE");
+		loadFonts(&file, 0xa598);
+		load8bitBinary(&file, 0x8a70, 4); // TODO
+	} else
+		error("Invalid or unsupported render mode %s for Dark Side", Common::getRenderModeDescription(_renderMode));
+}
+
+void DarkEngine::loadAssetsDOSFullGame() {
+	Common::File file;
+	if (_renderMode == Common::kRenderEGA) {
+		file.open("SCN1E.DAT");
+		if (file.isOpen()) {
+			_title = load8bitBinImage(&file, 0x0);
+			_title->setPalette((byte *)&kEGADefaultPaletteData, 0, 16);
+		}
 		file.close();
 		file.open("DSIDEE.EXE");
 
@@ -152,6 +157,7 @@ void DarkEngine::loadAssetsFullGame() {
 		loadGlobalObjects(&file, 0x3d04);
 		load8bitBinary(&file, 0xa280, 16);
 		_border = load8bitBinImage(&file, 0x210);
+		_border->setPalette((byte *)&kEGADefaultPaletteData, 0, 16);
 
 		// TODO: load objects
 		/*for (auto &it : _areaMap) {
@@ -291,35 +297,6 @@ void DarkEngine::updateTimeVariables() {
 	}
 }
 
-void DarkEngine::drawUI() {
-	Graphics::Surface *surface = nullptr;
-	if (_border) { // This can be removed when all the borders are loaded
-		uint32 gray = _gfx->_texturePixelFormat.ARGBToColor(0x00, 0xA0, 0xA0, 0xA0);
-		surface = new Graphics::Surface();
-		surface->create(_screenW, _screenH, _gfx->_texturePixelFormat);
-		surface->fillRect(_fullscreenViewArea, gray);
-		drawCrossair(surface);
-	} else
-		return;
-
-	if (isDOS())
-		drawDOSUI(surface);
-	else
-		error("UI not implemented yet");
-
-	if (!_uiTexture)
-		_uiTexture = _gfx->createTexture(surface);
-	else
-		_uiTexture->update(surface);
-
-	_gfx->setViewport(_fullscreenViewArea);
-	_gfx->drawTexturedRect2D(_fullscreenViewArea, _fullscreenViewArea, _uiTexture);
-	_gfx->setViewport(_viewArea);
-
-	surface->free();
-	delete surface;
-}
-
 void DarkEngine::borderScreen() {
 	if (_border) {
 		drawBorder();
diff --git a/engines/freescape/games/driller/driller.cpp b/engines/freescape/games/driller/driller.cpp
index d132721d0ae..72e7f9e05a6 100644
--- a/engines/freescape/games/driller/driller.cpp
+++ b/engines/freescape/games/driller/driller.cpp
@@ -206,38 +206,8 @@ void DrillerEngine::loadGlobalObjects(Common::SeekableReadStream *file, int offs
 	_areaMap[255] = new Area(255, 0, globalObjectsByID, nullptr);
 }
 
-void DrillerEngine::loadAssetsDemo() {
-	Common::File file;
-	if (isAmiga()) {
-		loadAssetsAmigaDemo();
-	} else if (isAtariST()) {
-		loadAssetsAtariDemo();
-	} else if (isDOS()) {
-		loadAssetsDOSDemo();
-	} else
-		error("Unsupported demo for Driller");
-
-	_demoMode = !_disableDemoMode;
-	_angleRotationIndex = 0;
-}
-
 void DrillerEngine::loadAssetsFullGame() {
-	Common::File file;
-	if (isAmiga()) {
-		loadAssetsAmigaFullGame();
-	} else if (isAtariST()) {
-		loadAssetsAtariFullGame();
-	} else if (isSpectrum()) {
-		loadAssetsZXFullGame();
-	} else if (isCPC()) {
-		loadAssetsCPCFullGame();
-	} else if (isC64()) {
-		//loadAssetsC64FullGame();
-	} else if (isDOS()) {
-		loadAssetsDOSFullGame();
-	} else
-		error("Invalid or unsupported render mode %s for Driller", Common::getRenderModeDescription(_renderMode));
-
+	FreescapeEngine::loadAssetsFullGame();
 	/*
 	We are going to inject a small script in the
 	last area to force the game to end:
diff --git a/engines/freescape/games/eclipse.cpp b/engines/freescape/games/eclipse.cpp
index e8d67acbfb4..7f970e86209 100644
--- a/engines/freescape/games/eclipse.cpp
+++ b/engines/freescape/games/eclipse.cpp
@@ -111,12 +111,15 @@ void EclipseEngine::titleScreen() {
 	}
 }
 
-void EclipseEngine::loadAssetsFullGame() {
+extern byte kEGADefaultPaletteData[16][3];
+
+void EclipseEngine::loadAssetsDOSFullGame() {
 	Common::File file;
 	if (_renderMode == Common::kRenderEGA) {
 		file.open("SCN1E.DAT");
 		if (file.isOpen()) {
 			_title = load8bitBinImage(&file, 0x0);
+			_title->setPalette((byte *)&kEGADefaultPaletteData, 0, 16);
 		}
 		file.close();
 		file.open("TOTEE.EXE");
@@ -129,6 +132,7 @@ void EclipseEngine::loadAssetsFullGame() {
 		for (auto &it : _areaMap)
 			it._value->addStructure(_areaMap[255]);
 		_border = load8bitBinImage(&file, 0x210);
+		_border->setPalette((byte *)&kEGADefaultPaletteData, 0, 16);
 	} else if (_renderMode == Common::kRenderCGA) {
 		loadBundledImages();
 		file.open("TOTEC.EXE");


Commit: 3b135c9ed82efdfe9a0514bba124f1b6c53c271a
    https://github.com/scummvm/scummvm/commit/3b135c9ed82efdfe9a0514bba124f1b6c53c271a
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-03-20T11:01:34+01:00

Commit Message:
FREESCAPE: moved code from dark dos release into its dedicated file

Changed paths:
    engines/freescape/games/dark/dark.cpp
    engines/freescape/games/dark/dos.cpp


diff --git a/engines/freescape/games/dark/dark.cpp b/engines/freescape/games/dark/dark.cpp
index 0cb8e2d2a9a..d628c4d4ef5 100644
--- a/engines/freescape/games/dark/dark.cpp
+++ b/engines/freescape/games/dark/dark.cpp
@@ -104,78 +104,6 @@ void DarkEngine::initGameState() {
 	_demoEvents.clear();
 }
 
-extern byte kEGADefaultPaletteData[16][3];
-
-void DarkEngine::loadAssetsDOSDemo() {
-	Common::File file;
-	if (_renderMode == Common::kRenderEGA) {
-		file.open("SCN1E.DAT");
-		if (file.isOpen()) {
-			_title = load8bitBinImage(&file, 0x0);
-			_title->setPalette((byte *)&kEGADefaultPaletteData, 0, 16);
-		}
-		file.close();
-		file.open("DSIDEE.EXE");
-
-		if (!file.isOpen())
-			error("Failed to open DSIDEE.EXE");
-		loadMessagesFixedSize(&file, 0x4525, 16, 27);
-		loadMessagesFixedSize(&file, 0x9959, 307, 5);
-		loadFonts(&file, 0xa598);
-		loadGlobalObjects(&file, 0x3d04);
-		load8bitBinary(&file, 0xa700, 16);
-		_border = load8bitBinImage(&file, 0x210);
-		_border->setPalette((byte *)&kEGADefaultPaletteData, 0, 16);
-	} else if (_renderMode == Common::kRenderCGA) {
-		//loadBundledImages();
-		file.open("DSIDEC.EXE");
-
-		if (!file.isOpen())
-			error("Failed to open DSIDEC.EXE");
-		loadFonts(&file, 0xa598);
-		load8bitBinary(&file, 0x8a70, 4); // TODO
-	} else
-		error("Invalid or unsupported render mode %s for Dark Side", Common::getRenderModeDescription(_renderMode));
-}
-
-void DarkEngine::loadAssetsDOSFullGame() {
-	Common::File file;
-	if (_renderMode == Common::kRenderEGA) {
-		file.open("SCN1E.DAT");
-		if (file.isOpen()) {
-			_title = load8bitBinImage(&file, 0x0);
-			_title->setPalette((byte *)&kEGADefaultPaletteData, 0, 16);
-		}
-		file.close();
-		file.open("DSIDEE.EXE");
-
-		if (!file.isOpen())
-			error("Failed to open DSIDEE.EXE");
-
-		loadFonts(&file, 0xa113);
-		loadMessagesFixedSize(&file, 0x4525, 16, 27);
-		loadGlobalObjects(&file, 0x3d04);
-		load8bitBinary(&file, 0xa280, 16);
-		_border = load8bitBinImage(&file, 0x210);
-		_border->setPalette((byte *)&kEGADefaultPaletteData, 0, 16);
-
-		// TODO: load objects
-		/*for (auto &it : _areaMap) {
-			if (!it._value->entranceWithID(255))
-				continue;
-			it._value->addStructure(_areaMap[255]);
-		}*/
-	} else if (_renderMode == Common::kRenderCGA) {
-		loadBundledImages();
-		file.open("DSIDEC.EXE");
-
-		if (!file.isOpen())
-			error("Failed to open DSIDEC.EXE");
-		load8bitBinary(&file, 0x7bb0, 4); // TODO
-	} else
-		error("Invalid or unsupported render mode %s for Dark Side", Common::getRenderModeDescription(_renderMode));
-}
-
 void DarkEngine::gotoArea(uint16 areaID, int entranceID) {
 	debugC(1, kFreescapeDebugMove, "Jumping to area: %d, entrance: %d", areaID, entranceID);
 	if (!_gameStateBits.contains(areaID))
diff --git a/engines/freescape/games/dark/dos.cpp b/engines/freescape/games/dark/dos.cpp
index 6a3c5aff2ae..24c4396d079 100644
--- a/engines/freescape/games/dark/dos.cpp
+++ b/engines/freescape/games/dark/dos.cpp
@@ -26,6 +26,78 @@
 
 namespace Freescape {
 
+extern byte kEGADefaultPaletteData[16][3];
+
+void DarkEngine::loadAssetsDOSDemo() {
+	Common::File file;
+	if (_renderMode == Common::kRenderEGA) {
+		file.open("SCN1E.DAT");
+		if (file.isOpen()) {
+			_title = load8bitBinImage(&file, 0x0);
+			_title->setPalette((byte *)&kEGADefaultPaletteData, 0, 16);
+		}
+		file.close();
+		file.open("DSIDEE.EXE");
+
+		if (!file.isOpen())
+			error("Failed to open DSIDEE.EXE");
+		loadMessagesFixedSize(&file, 0x4525, 16, 27);
+		loadMessagesFixedSize(&file, 0x9959, 307, 5);
+		loadFonts(&file, 0xa598);
+		loadGlobalObjects(&file, 0x3d04);
+		load8bitBinary(&file, 0xa700, 16);
+		_border = load8bitBinImage(&file, 0x210);
+		_border->setPalette((byte *)&kEGADefaultPaletteData, 0, 16);
+	} else if (_renderMode == Common::kRenderCGA) {
+		//loadBundledImages();
+		file.open("DSIDEC.EXE");
+
+		if (!file.isOpen())
+			error("Failed to open DSIDEC.EXE");
+		loadFonts(&file, 0xa598);
+		load8bitBinary(&file, 0x8a70, 4); // TODO
+	} else
+		error("Invalid or unsupported render mode %s for Dark Side", Common::getRenderModeDescription(_renderMode));
+}
+
+void DarkEngine::loadAssetsDOSFullGame() {
+	Common::File file;
+	if (_renderMode == Common::kRenderEGA) {
+		file.open("SCN1E.DAT");
+		if (file.isOpen()) {
+			_title = load8bitBinImage(&file, 0x0);
+			_title->setPalette((byte *)&kEGADefaultPaletteData, 0, 16);
+		}
+		file.close();
+		file.open("DSIDEE.EXE");
+
+		if (!file.isOpen())
+			error("Failed to open DSIDEE.EXE");
+
+		loadFonts(&file, 0xa113);
+		loadMessagesFixedSize(&file, 0x4525, 16, 27);
+		loadGlobalObjects(&file, 0x3d04);
+		load8bitBinary(&file, 0xa280, 16);
+		_border = load8bitBinImage(&file, 0x210);
+		_border->setPalette((byte *)&kEGADefaultPaletteData, 0, 16);
+
+		// TODO: load objects
+		/*for (auto &it : _areaMap) {
+			if (!it._value->entranceWithID(255))
+				continue;
+			it._value->addStructure(_areaMap[255]);
+		}*/
+	} else if (_renderMode == Common::kRenderCGA) {
+		loadBundledImages();
+		file.open("DSIDEC.EXE");
+
+		if (!file.isOpen())
+			error("Failed to open DSIDEC.EXE");
+		load8bitBinary(&file, 0x7bb0, 4); // TODO
+	} else
+		error("Invalid or unsupported render mode %s for Dark Side", Common::getRenderModeDescription(_renderMode));
+}
+
 void DarkEngine::drawDOSUI(Graphics::Surface *surface) {
 	uint32 color = _renderMode == Common::kRenderCGA ? 1 : 14;
 	uint8 r, g, b;


Commit: 0154df5c8bd619f8c5b86573fd615cf67085f880
    https://github.com/scummvm/scummvm/commit/0154df5c8bd619f8c5b86573fd615cf67085f880
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-03-20T11:01:42+01:00

Commit Message:
FREESCAPE: simplified driller cpc color handling code

Changed paths:
    engines/freescape/games/driller/cpc.cpp
    engines/freescape/gfx.cpp


diff --git a/engines/freescape/games/driller/cpc.cpp b/engines/freescape/games/driller/cpc.cpp
index bd43a0a1d01..ced3e80c64e 100644
--- a/engines/freescape/games/driller/cpc.cpp
+++ b/engines/freescape/games/driller/cpc.cpp
@@ -41,6 +41,19 @@ byte kCPCPaletteBorderData[4][3] = {
 	{0x00, 0x80, 0x00},
 };
 
+byte getCPCPixel(byte cpc_byte, int index) {
+	if (index == 0)
+		return ((cpc_byte & 0x08) >> 2) | ((cpc_byte & 0x80) >> 7);
+	else if (index == 1)
+		return ((cpc_byte & 0x04) >> 1) | ((cpc_byte & 0x40) >> 6);
+	else if (index == 2)
+		return (cpc_byte & 0x02)        | ((cpc_byte & 0x20) >> 5);
+	else if (index == 3)
+		return ((cpc_byte & 0x01) << 1) | ((cpc_byte & 0x10) >> 4);
+	else
+		error("Invalid index %d requested", index);
+}
+
 Graphics::ManagedSurface *readCPCImage(Common::SeekableReadStream *file) {
 	Graphics::ManagedSurface *surface = new Graphics::ManagedSurface();
 	surface->create(320, 200, Graphics::PixelFormat::createFormatCLUT8());
@@ -54,25 +67,25 @@ Graphics::ManagedSurface *readCPCImage(Common::SeekableReadStream *file) {
 				byte cpc_byte = file->readByte(); // Get CPC byte
 
 				// Process first pixel
-				int pixel_0 = ((cpc_byte & 0x08) >> 2) | ((cpc_byte & 0x80) >> 7); // %Aa
+				int pixel_0 = getCPCPixel(cpc_byte, 0); // %Aa
 				y = line * 8 + block ; // Coord Y for the pixel
 				x = 4 * offset + 0; // Coord X for the pixel
 				surface->setPixel(x, y, pixel_0);
 
 				// Process second pixel
-				int pixel_1 = ((cpc_byte & 0x04) >> 1) | ((cpc_byte & 0x40) >> 6); // %Bb
+				int pixel_1 = getCPCPixel(cpc_byte, 1); // %Bb
 				y = line * 8 + block ; // Coord Y for the pixel
 				x = 4 * offset + 1; // Coord X for the pixel
 				surface->setPixel(x, y, pixel_1);
 
 				// Process third pixel
-				int pixel_2 = (cpc_byte & 0x02)        | ((cpc_byte & 0x20) >> 5); // %Cc
+				int pixel_2 = getCPCPixel(cpc_byte, 2); // %Cc
 				y = line * 8 + block ; // Coord Y for the pixel
 				x = 4 * offset + 2; // Coord X for the pixel
 				surface->setPixel(x, y, pixel_2);
 
 				// Process fourth pixel
-				int pixel_3 = ((cpc_byte & 0x01) << 1) | ((cpc_byte & 0x10) >> 4); // %Dd
+				int pixel_3 = getCPCPixel(cpc_byte, 3); // %Dd
 				y = line * 8 + block ; // Coord Y for the pixel
 				x = 4 * offset + 3; // Coord X for the pixel
 				surface->setPixel(x, y, pixel_3);
diff --git a/engines/freescape/gfx.cpp b/engines/freescape/gfx.cpp
index d93e937dab8..55fbc4d7624 100644
--- a/engines/freescape/gfx.cpp
+++ b/engines/freescape/gfx.cpp
@@ -188,44 +188,6 @@ bool Renderer::getRGBAtZX(uint8 index, uint8 &r1, uint8 &g1, uint8 &b1, uint8 &r
 	return true;
 }
 
-void Renderer::extractCPCIndexes(uint8 cm1, uint8 cm2, uint8 &i1, uint8 &i2) {
-	if (cm1 == 0xb4 && cm2 == 0xe1) {
-		i1 = 1;
-		i2 = 2;
-	} else if (cm1 == 0xb0 && cm2 == 0xe0) {
-		i1 = 1;
-		i2 = 0;
-	} else if (cm1 == 0x05 && cm2 == 0x0a) {
-		i1 = 2;
-		i2 = 0;
-	} else if (cm1 == 0x50 && cm2 == 0xa0) {
-		i1 = 1;
-		i2 = 0;
-	} else if (cm1 == 0x55 && cm2 == 0xaa) {
-		i1 = 3;
-		i2 = 0;
-	} else if (cm1 == 0xf5 && cm2 == 0xfa) {
-		i1 = 3;
-		i2 = 1;
-	} else if (cm1 == 0x5a && cm2 == 0xa5) {
-		i1 = 1;
-		i2 = 2;
-	} else if (cm1 == 0xbb && cm2 == 0xee) {
-		i1 = 3;
-		i2 = 0;
-	} else if (cm1 == 0x5f && cm2 == 0xaf) {
-		i1 = 3;
-		i2 = 2;
-	} else if (cm1 == 0xfb && cm2 == 0xfe) { // TODO
-		i1 = 0;
-		i2 = 0;
-	} else if (cm1 == 0x40 && cm2 == 0x20) { // This one has a special stapple pattern
-		i1 = 1;
-		i2 = 0;
-	} else
-		error("%x %x", cm1, cm2);
-}
-
 void Renderer::selectColorFromFourColorPalette(uint8 index, uint8 &r1, uint8 &g1, uint8 &b1) {
 	if (index == 0) {
 		r1 = 0;
@@ -241,6 +203,8 @@ void Renderer::selectColorFromFourColorPalette(uint8 index, uint8 &r1, uint8 &g1
 		error("Invalid color");
 }
 
+extern byte getCPCPixel(byte cpc_byte, int index);
+
 bool Renderer::getRGBAtCPC(uint8 index, uint8 &r1, uint8 &g1, uint8 &b1, uint8 &r2, uint8 &g2, uint8 &b2) {
 	if (index == _keyColor)
 		return false;
@@ -260,7 +224,8 @@ bool Renderer::getRGBAtCPC(uint8 index, uint8 &r1, uint8 &g1, uint8 &b1, uint8 &
 	entry++;
 	uint8 cm2 = *(entry);
 
-	extractCPCIndexes(cm1, cm2, i1, i2);
+	i1 = getCPCPixel(cm1, 0);
+	i2 = getCPCPixel(cm1, 1);
 	selectColorFromFourColorPalette(i1, r1, g1, b1);
 	selectColorFromFourColorPalette(i2, r2, g2, b2);
 	return true;


Commit: 35492b4673ec67cdc2eeff09837011aff026378d
    https://github.com/scummvm/scummvm/commit/35492b4673ec67cdc2eeff09837011aff026378d
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-03-20T11:02:03+01:00

Commit Message:
FREESCAPE: commented unused variable

Changed paths:
    engines/freescape/gfx.cpp


diff --git a/engines/freescape/gfx.cpp b/engines/freescape/gfx.cpp
index 55fbc4d7624..c0e1ef5716c 100644
--- a/engines/freescape/gfx.cpp
+++ b/engines/freescape/gfx.cpp
@@ -222,7 +222,7 @@ bool Renderer::getRGBAtCPC(uint8 index, uint8 &r1, uint8 &g1, uint8 &b1, uint8 &
 	byte *entry = (*_colorMap)[index - 1];
 	uint8 cm1 = *(entry);
 	entry++;
-	uint8 cm2 = *(entry);
+	//uint8 cm2 = *(entry);
 
 	i1 = getCPCPixel(cm1, 0);
 	i2 = getCPCPixel(cm1, 1);


Commit: 55ae8e40967d0f43180abd61a2b6331a12fc4df4
    https://github.com/scummvm/scummvm/commit/55ae8e40967d0f43180abd61a2b6331a12fc4df4
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-03-20T11:02:14+01:00

Commit Message:
FREESCAPE: pregenerate and show stipple patterns for driller in zx, cpc and cga

Changed paths:
    engines/freescape/games/palettes.cpp
    engines/freescape/gfx.cpp
    engines/freescape/gfx.h
    engines/freescape/gfx_opengl.cpp


diff --git a/engines/freescape/games/palettes.cpp b/engines/freescape/games/palettes.cpp
index 6baef6c443f..00e626fb653 100644
--- a/engines/freescape/games/palettes.cpp
+++ b/engines/freescape/games/palettes.cpp
@@ -124,7 +124,7 @@ void FreescapeEngine::loadColorPalette() {
 	} else
 		error("Invalid render mode, no palette selected");
 
-	_gfx->_colorMap = &_colorMap;
+	_gfx->setColorMap(&_colorMap);
 }
 
 void FreescapeEngine::loadPalettes(Common::SeekableReadStream *file, int offset) {
diff --git a/engines/freescape/gfx.cpp b/engines/freescape/gfx.cpp
index c0e1ef5716c..ccf83daa9b2 100644
--- a/engines/freescape/gfx.cpp
+++ b/engines/freescape/gfx.cpp
@@ -48,10 +48,117 @@ Renderer::Renderer(int screenW, int screenH, Common::RenderMode renderMode) {
 	_colorRemaps = nullptr;
 	_renderMode = renderMode;
 	_isAccelerated = false;
+
+	for (int i = 0; i < 16; i++) {
+		_stipples[0][i] = 0;
+		_stipples[1][i] = 0;
+		_stipples[2][i] = 0;
+		_stipples[3][i] = 0;
+	}
 }
 
 Renderer::~Renderer() {}
 
+extern byte getCPCPixel(byte cpc_byte, int index);
+
+byte getCPCStipple(byte cpc_byte, int back, int fore) {
+	int c0 = getCPCPixel(cpc_byte, 0);
+	assert(c0 == back || c0 == fore);
+	int c1 = getCPCPixel(cpc_byte, 1);
+	assert(c1 == back || c1 == fore);
+	int c2 = getCPCPixel(cpc_byte, 2);
+	assert(c2 == back || c2 == fore);
+	int c3 = getCPCPixel(cpc_byte, 3);
+	assert(c3 == back || c3 == fore);
+
+	byte st = 0;
+	if (c0 == fore)
+		st = st | 0x3;
+
+	if (c1 == fore)
+		st = st | (2 << 0x3);
+
+	if (c2 == fore)
+		st = st | (4 << 0x3);
+
+	if (c3 == fore)
+		st = st |  (6 << 0x3);
+
+	return st;
+}
+
+byte getCGAPixel(byte x, int index) {
+	if (index == 0)
+		return (x >> 0) & 0x3;
+	else if (index == 1)
+		return (x >> 2) & 0x3;
+	else if (index == 2)
+		return (x >> 4) & 0x3;
+	else if (index == 3)
+		return (x >> 6) & 0x3;
+	else
+		error("Invalid index %d requested", index);
+}
+
+byte getCGAStipple(byte x, int back, int fore) {
+	int c0 = getCGAPixel(x, 0);
+	assert(c0 == back || c0 == fore || back == fore);
+	int c1 = getCGAPixel(x, 1);
+	assert(c1 == back || c1 == fore || back == fore);
+	int c2 = getCGAPixel(x, 2);
+	assert(c2 == back || c2 == fore || back == fore);
+	int c3 = getCGAPixel(x, 3);
+	assert(c3 == back || c3 == fore || back == fore);
+
+	byte st = 0;
+	if (c0 == fore)
+		st = st | 0x3;
+
+	if (c1 == fore)
+		st = st | (2 << 0x3);
+
+	if (c2 == fore)
+		st = st | (4 << 0x3);
+
+	if (c3 == fore)
+		st = st |  (6 << 0x3);
+
+	return st;
+}
+
+void Renderer::setColorMap(ColorMap *colorMap_) {
+	_colorMap = colorMap_;
+	if (_renderMode == Common::kRenderZX) {
+		for (int i = 0; i < 15; i++) {
+			byte *entry = (*_colorMap)[i];
+			_stipples[0][i] = entry[0];
+			_stipples[1][i] = entry[1];
+			_stipples[2][i] = entry[2];
+			_stipples[3][i] = entry[3];
+		}
+	} else if (_renderMode == Common::kRenderCPC) {
+		for (int i = 0; i < 15; i++) {
+			byte *entry = (*_colorMap)[i];
+			int i1 = getCPCPixel(entry[0], 0);
+			int i2 = getCPCPixel(entry[0], 1);
+			_stipples[0][i] = getCPCStipple(entry[0], i1, i2);
+			_stipples[1][i] = getCPCStipple(entry[1], i1, i2);
+			_stipples[2][i] = getCPCStipple(entry[2], i1, i2);
+			_stipples[3][i] = getCPCStipple(entry[3], i1, i2);
+		}
+	} else if (_renderMode == Common::kRenderCGA) {
+		for (int i = 0; i < 15; i++) {
+			byte *entry = (*_colorMap)[i];
+			int i1 = getCGAPixel(entry[0], 0);
+			int i2 = getCGAPixel(entry[0], 1);
+			_stipples[0][i] = getCGAStipple(entry[0], i1, i2);
+			_stipples[1][i] = getCGAStipple(entry[1], i1, i2);
+			_stipples[2][i] = getCGAStipple(entry[2], i1, i2);
+			_stipples[3][i] = getCGAStipple(entry[3], i1, i2);
+		}
+	}
+}
+
 void Renderer::readFromPalette(uint8 index, uint8 &r, uint8 &g, uint8 &b) {
 	r = _palette[3 * index + 0];
 	g = _palette[3 * index + 1];
@@ -71,7 +178,7 @@ void Renderer::setColorRemaps(ColorReMap *colorRemaps) {
 	_colorRemaps = colorRemaps;
 }
 
-bool Renderer::getRGBAtCGA(uint8 index, uint8 &r1, uint8 &g1, uint8 &b1, uint8 &r2, uint8 &g2, uint8 &b2) {
+bool Renderer::getRGBAtCGA(uint8 index, uint8 &r1, uint8 &g1, uint8 &b1, uint8 &r2, uint8 &g2, uint8 &b2, byte *stipple) {
 	if (index == _keyColor)
 		return false;
 
@@ -84,12 +191,18 @@ bool Renderer::getRGBAtCGA(uint8 index, uint8 &r1, uint8 &g1, uint8 &b1, uint8 &
 		return true;
 	}
 
+	if (stipple) {
+		stipple[0] = _stipples[0][index - 1];
+		stipple[1] = _stipples[1][index - 1];
+		stipple[2] = _stipples[2][index - 1];
+		stipple[3] = _stipples[3][index - 1];
+	}
+
 	byte *entry = (*_colorMap)[index - 1];
-	byte be = *(entry);
-	readFromPalette((be >> 4) % 4, r1, g1, b1);
-	entry++;
-	be = *(entry);
-	readFromPalette((be >> 4) % 4, r2, g2, b2);
+	uint8 c1 = getCGAPixel(entry[0], 0);
+	uint8 c2 = getCGAPixel(entry[0], 1);
+	readFromPalette(c1, r1, g1, b1);
+	readFromPalette(c2, r2, g2, b2);
 	return true;
 }
 
@@ -177,10 +290,10 @@ bool Renderer::getRGBAtZX(uint8 index, uint8 &r1, uint8 &g1, uint8 &b1, uint8 &r
 	}
 
 	if (stipple) {
-		stipple[0] = entry[0];
-		stipple[1] = entry[1];
-		stipple[2] = entry[2];
-		stipple[3] = entry[3];
+		stipple[0] = _stipples[0][index - 1];
+		stipple[1] = _stipples[1][index - 1];
+		stipple[2] = _stipples[2][index - 1];
+		stipple[3] = _stipples[3][index - 1];
 	}
 
 	readFromPalette(_paperColor, r1, g1, b1);
@@ -203,9 +316,7 @@ void Renderer::selectColorFromFourColorPalette(uint8 index, uint8 &r1, uint8 &g1
 		error("Invalid color");
 }
 
-extern byte getCPCPixel(byte cpc_byte, int index);
-
-bool Renderer::getRGBAtCPC(uint8 index, uint8 &r1, uint8 &g1, uint8 &b1, uint8 &r2, uint8 &g2, uint8 &b2) {
+bool Renderer::getRGBAtCPC(uint8 index, uint8 &r1, uint8 &g1, uint8 &b1, uint8 &r2, uint8 &g2, uint8 &b2, byte *stipple) {
 	if (index == _keyColor)
 		return false;
 
@@ -218,14 +329,16 @@ bool Renderer::getRGBAtCPC(uint8 index, uint8 &r1, uint8 &g1, uint8 &b1, uint8 &
 		return true;
 	}
 
-	uint8 i1, i2;
-	byte *entry = (*_colorMap)[index - 1];
-	uint8 cm1 = *(entry);
-	entry++;
-	//uint8 cm2 = *(entry);
+	if (stipple) {
+		stipple[0] = _stipples[0][index - 1];
+		stipple[1] = _stipples[1][index - 1];
+		stipple[2] = _stipples[2][index - 1];
+		stipple[3] = _stipples[3][index - 1];
+	}
 
-	i1 = getCPCPixel(cm1, 0);
-	i2 = getCPCPixel(cm1, 1);
+	byte *entry = (*_colorMap)[index - 1];
+	uint8 i1 = getCPCPixel(entry[0], 0);
+	uint8 i2 = getCPCPixel(entry[0], 1);
 	selectColorFromFourColorPalette(i1, r1, g1, b1);
 	selectColorFromFourColorPalette(i2, r2, g2, b2);
 	return true;
@@ -286,9 +399,9 @@ bool Renderer::getRGBAt(uint8 index, uint8 &r1, uint8 &g1, uint8 &b1, uint8 &r2,
 	else if (_renderMode == Common::kRenderC64)
 		return getRGBAtC64(index, r1, g1, b1, r2, g2, b2);
 	else if (_renderMode == Common::kRenderCGA)
-		return getRGBAtCGA(index, r1, g1, b1, r2, g2, b2);
+		return getRGBAtCGA(index, r1, g1, b1, r2, g2, b2, stipple);
 	else if (_renderMode == Common::kRenderCPC)
-		return getRGBAtCPC(index, r1, g1, b1, r2, g2, b2);
+		return getRGBAtCPC(index, r1, g1, b1, r2, g2, b2, stipple);
 	else if (_renderMode == Common::kRenderZX)
 		return getRGBAtZX(index, r1, g1, b1, r2, g2, b2, stipple);
 
diff --git a/engines/freescape/gfx.h b/engines/freescape/gfx.h
index 867da87b0f0..ff6612ee011 100644
--- a/engines/freescape/gfx.h
+++ b/engines/freescape/gfx.h
@@ -101,8 +101,8 @@ public:
 	uint8 indexFromColor(uint8 r, uint8 g, uint8 b);
 	bool getRGBAt(uint8 index, uint8 &r1, uint8 &g1, uint8 &b1, uint8 &r2, uint8 &g2, uint8 &b2, byte *stipple);
 	bool getRGBAtC64(uint8 index, uint8 &r1, uint8 &g1, uint8 &b1, uint8 &r2, uint8 &g2, uint8 &b2);
-	bool getRGBAtCGA(uint8 index, uint8 &r1, uint8 &g1, uint8 &b1, uint8 &r2, uint8 &g2, uint8 &b2);
-	bool getRGBAtCPC(uint8 index, uint8 &r1, uint8 &g1, uint8 &b1, uint8 &r2, uint8 &g2, uint8 &b2);
+	bool getRGBAtCGA(uint8 index, uint8 &r1, uint8 &g1, uint8 &b1, uint8 &r2, uint8 &g2, uint8 &b2, byte *stipple);
+	bool getRGBAtCPC(uint8 index, uint8 &r1, uint8 &g1, uint8 &b1, uint8 &r2, uint8 &g2, uint8 &b2, byte *stipple);
 	bool getRGBAtEGA(uint8 index, uint8 &r1, uint8 &g1, uint8 &b1, uint8 &r2, uint8 &g2, uint8 &b2);
 	bool getRGBAtZX(uint8 index, uint8 &r1, uint8 &g1, uint8 &b1, uint8 &r2, uint8 &g2, uint8 &b2, byte *stipple);
 	void extractCPCIndexes(uint8 cm1, uint8 cm2, uint8 &i1, uint8 &i2);
@@ -113,12 +113,14 @@ public:
 	virtual void setStippleData(byte *data) {};
 	virtual void useStipple(bool enabled) {};
 	byte *_palette;
+	void setColorMap(ColorMap *colorMap_);
 	ColorMap *_colorMap;
 	ColorReMap *_colorRemaps;
 	int _keyColor;
 	int _inkColor;
 	int _paperColor;
 	int _underFireBackgroundColor;
+	byte _stipples[4][16];
 
 	/**
 	 * Select the window where to render
diff --git a/engines/freescape/gfx_opengl.cpp b/engines/freescape/gfx_opengl.cpp
index e504625b1c4..13f08e5db49 100644
--- a/engines/freescape/gfx_opengl.cpp
+++ b/engines/freescape/gfx_opengl.cpp
@@ -285,7 +285,12 @@ void OpenGLRenderer::useStipple(bool enabled) {
 		glEnable(GL_POLYGON_OFFSET_FILL);
 		glPolygonOffset(0.0f, -1.0f);
 		glEnable(GL_POLYGON_STIPPLE);
-		glPolygonStipple(_renderMode == Common::kRenderZX ? _variableStippleArray : _defaultStippleArray);
+		if (_renderMode == Common::kRenderZX  ||
+			_renderMode == Common::kRenderCPC ||
+			_renderMode == Common::kRenderCGA)
+			glPolygonStipple(_variableStippleArray);
+		else
+			glPolygonStipple(_defaultStippleArray);
 	} else {
 		glPolygonOffset(0, 0);
 		glDisable(GL_POLYGON_OFFSET_FILL);


Commit: 3dfd360667ee16a81fe2dcfb9db4431c4d00dda7
    https://github.com/scummvm/scummvm/commit/3dfd360667ee16a81fe2dcfb9db4431c4d00dda7
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-03-20T11:03:06+01:00

Commit Message:
FREESCAPE: improved stipple generation

Changed paths:
    engines/freescape/gfx.cpp
    engines/freescape/gfx.h


diff --git a/engines/freescape/gfx.cpp b/engines/freescape/gfx.cpp
index ccf83daa9b2..9b9df6ecb5e 100644
--- a/engines/freescape/gfx.cpp
+++ b/engines/freescape/gfx.cpp
@@ -54,6 +54,7 @@ Renderer::Renderer(int screenW, int screenH, Common::RenderMode renderMode) {
 		_stipples[1][i] = 0;
 		_stipples[2][i] = 0;
 		_stipples[3][i] = 0;
+		_colorPair[i] = 0;
 	}
 }
 
@@ -126,6 +127,45 @@ byte getCGAStipple(byte x, int back, int fore) {
 	return st;
 }
 
+void Renderer::fillColorPairArray() {
+	for (int i = 4; i < 15; i++) {
+		byte *entry = (*_colorMap)[i];
+		int c1;
+		if (_renderMode == Common::kRenderCGA)
+			c1 = getCGAPixel(entry[0], 0);
+		else if (_renderMode == Common::kRenderCPC)
+			c1 = getCPCPixel(entry[0], 0);
+		else
+			error("Not implemented");
+
+		//debug("c1 = %d", c1);
+		int c2 = -1;
+
+		for (int j = 0; j < 4; j++) {
+			int k, c;
+			for (k = 0; k < 4; k++) {
+				if (_renderMode == Common::kRenderCGA)
+					c = getCGAPixel(entry[j], k);
+				else if (_renderMode == Common::kRenderCPC)
+					c = getCPCPixel(entry[j], k);
+				else
+					error("Not implemented");
+				//debug("c = %d", c);
+				if (c1 != c) {
+					c2 = c;
+					break;
+				}
+			}
+			if (k != 4)
+				break;
+		}
+		assert(c2 >= 0);
+		assert((c1 < 16) & (c2 < 16));
+		_colorPair[i] = byte(c1) | (byte(c2) << 4);
+		//debug("pair: %x", _colorPair[i]);
+	}
+}
+
 void Renderer::setColorMap(ColorMap *colorMap_) {
 	_colorMap = colorMap_;
 	if (_renderMode == Common::kRenderZX) {
@@ -137,6 +177,7 @@ void Renderer::setColorMap(ColorMap *colorMap_) {
 			_stipples[3][i] = entry[3];
 		}
 	} else if (_renderMode == Common::kRenderCPC) {
+		fillColorPairArray();
 		for (int i = 0; i < 15; i++) {
 			byte *entry = (*_colorMap)[i];
 			int i1 = getCPCPixel(entry[0], 0);
@@ -147,14 +188,16 @@ void Renderer::setColorMap(ColorMap *colorMap_) {
 			_stipples[3][i] = getCPCStipple(entry[3], i1, i2);
 		}
 	} else if (_renderMode == Common::kRenderCGA) {
-		for (int i = 0; i < 15; i++) {
+		fillColorPairArray();
+		for (int i = 4; i < 15; i++) {
 			byte *entry = (*_colorMap)[i];
-			int i1 = getCGAPixel(entry[0], 0);
-			int i2 = getCGAPixel(entry[0], 1);
-			_stipples[0][i] = getCGAStipple(entry[0], i1, i2);
-			_stipples[1][i] = getCGAStipple(entry[1], i1, i2);
-			_stipples[2][i] = getCGAStipple(entry[2], i1, i2);
-			_stipples[3][i] = getCGAStipple(entry[3], i1, i2);
+			byte pair = _colorPair[i];
+			byte c1 = pair & 0xf;
+			byte c2 = (pair >> 4) & 0xf;
+			_stipples[0][i] = getCGAStipple(entry[0], c1, c2);
+			_stipples[1][i] = getCGAStipple(entry[1], c1, c2);
+			_stipples[2][i] = getCGAStipple(entry[2], c1, c2);
+			_stipples[3][i] = getCGAStipple(entry[3], c1, c2);
 		}
 	}
 }
@@ -198,9 +241,9 @@ bool Renderer::getRGBAtCGA(uint8 index, uint8 &r1, uint8 &g1, uint8 &b1, uint8 &
 		stipple[3] = _stipples[3][index - 1];
 	}
 
-	byte *entry = (*_colorMap)[index - 1];
-	uint8 c1 = getCGAPixel(entry[0], 0);
-	uint8 c2 = getCGAPixel(entry[0], 1);
+	byte pair = _colorPair[index - 1];
+	byte c1 = pair & 0xf;
+	byte c2 = (pair >> 4) & 0xf;
 	readFromPalette(c1, r1, g1, b1);
 	readFromPalette(c2, r2, g2, b2);
 	return true;
diff --git a/engines/freescape/gfx.h b/engines/freescape/gfx.h
index ff6612ee011..8c948e05068 100644
--- a/engines/freescape/gfx.h
+++ b/engines/freescape/gfx.h
@@ -116,6 +116,8 @@ public:
 	void setColorMap(ColorMap *colorMap_);
 	ColorMap *_colorMap;
 	ColorReMap *_colorRemaps;
+	void fillColorPairArray();
+	byte _colorPair[16];
 	int _keyColor;
 	int _inkColor;
 	int _paperColor;


Commit: e6b033b40963182b9dd0b37364c38be98c5d228f
    https://github.com/scummvm/scummvm/commit/e6b033b40963182b9dd0b37364c38be98c5d228f
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-03-20T11:03:12+01:00

Commit Message:
FREESCAPE: improved and optimized stipple pattern usage

Changed paths:
    engines/freescape/gfx.cpp
    engines/freescape/gfx.h
    engines/freescape/gfx_opengl.cpp
    engines/freescape/gfx_opengl.h
    engines/freescape/gfx_tinygl.cpp


diff --git a/engines/freescape/gfx.cpp b/engines/freescape/gfx.cpp
index 9b9df6ecb5e..8d5e2721cfd 100644
--- a/engines/freescape/gfx.cpp
+++ b/engines/freescape/gfx.cpp
@@ -50,10 +50,9 @@ Renderer::Renderer(int screenW, int screenH, Common::RenderMode renderMode) {
 	_isAccelerated = false;
 
 	for (int i = 0; i < 16; i++) {
-		_stipples[0][i] = 0;
-		_stipples[1][i] = 0;
-		_stipples[2][i] = 0;
-		_stipples[3][i] = 0;
+		for (int j = 0; j < 128; j++) {
+			_stipples[i][j] = 0;
+		}
 		_colorPair[i] = 0;
 	}
 }
@@ -77,13 +76,13 @@ byte getCPCStipple(byte cpc_byte, int back, int fore) {
 		st = st | 0x3;
 
 	if (c1 == fore)
-		st = st | (2 << 0x3);
+		st = st | (0x3 << 2);
 
 	if (c2 == fore)
-		st = st | (4 << 0x3);
+		st = st | (0x3 << 4);
 
 	if (c3 == fore)
-		st = st |  (6 << 0x3);
+		st = st | (0x3 << 6);
 
 	return st;
 }
@@ -116,13 +115,13 @@ byte getCGAStipple(byte x, int back, int fore) {
 		st = st | 0x3;
 
 	if (c1 == fore)
-		st = st | (2 << 0x3);
+		st = st | (0x3 << 2);
 
 	if (c2 == fore)
-		st = st | (4 << 0x3);
+		st = st | (0x3 << 4);
 
 	if (c3 == fore)
-		st = st |  (6 << 0x3);
+		st = st |  (0x3 << 6);
 
 	return st;
 }
@@ -138,7 +137,6 @@ void Renderer::fillColorPairArray() {
 		else
 			error("Not implemented");
 
-		//debug("c1 = %d", c1);
 		int c2 = -1;
 
 		for (int j = 0; j < 4; j++) {
@@ -150,7 +148,6 @@ void Renderer::fillColorPairArray() {
 					c = getCPCPixel(entry[j], k);
 				else
 					error("Not implemented");
-				//debug("c = %d", c);
 				if (c1 != c) {
 					c2 = c;
 					break;
@@ -162,7 +159,6 @@ void Renderer::fillColorPairArray() {
 		assert(c2 >= 0);
 		assert((c1 < 16) & (c2 < 16));
 		_colorPair[i] = byte(c1) | (byte(c2) << 4);
-		//debug("pair: %x", _colorPair[i]);
 	}
 }
 
@@ -171,33 +167,28 @@ void Renderer::setColorMap(ColorMap *colorMap_) {
 	if (_renderMode == Common::kRenderZX) {
 		for (int i = 0; i < 15; i++) {
 			byte *entry = (*_colorMap)[i];
-			_stipples[0][i] = entry[0];
-			_stipples[1][i] = entry[1];
-			_stipples[2][i] = entry[2];
-			_stipples[3][i] = entry[3];
+			for (int j = 0; j < 128; j++)
+				_stipples[i][j] = entry[(j / 16) % 4];
 		}
 	} else if (_renderMode == Common::kRenderCPC) {
 		fillColorPairArray();
-		for (int i = 0; i < 15; i++) {
+		for (int i = 4; i < 15; i++) {
+			byte pair = _colorPair[i];
+			byte c1 = pair & 0xf;
+			byte c2 = (pair >> 4) & 0xf;
 			byte *entry = (*_colorMap)[i];
-			int i1 = getCPCPixel(entry[0], 0);
-			int i2 = getCPCPixel(entry[0], 1);
-			_stipples[0][i] = getCPCStipple(entry[0], i1, i2);
-			_stipples[1][i] = getCPCStipple(entry[1], i1, i2);
-			_stipples[2][i] = getCPCStipple(entry[2], i1, i2);
-			_stipples[3][i] = getCPCStipple(entry[3], i1, i2);
+			for (int j = 0; j < 128; j++)
+				_stipples[i][j] = getCPCStipple(entry[(j / 8) % 4], c1, c2) ;
 		}
 	} else if (_renderMode == Common::kRenderCGA) {
 		fillColorPairArray();
 		for (int i = 4; i < 15; i++) {
-			byte *entry = (*_colorMap)[i];
 			byte pair = _colorPair[i];
 			byte c1 = pair & 0xf;
 			byte c2 = (pair >> 4) & 0xf;
-			_stipples[0][i] = getCGAStipple(entry[0], c1, c2);
-			_stipples[1][i] = getCGAStipple(entry[1], c1, c2);
-			_stipples[2][i] = getCGAStipple(entry[2], c1, c2);
-			_stipples[3][i] = getCGAStipple(entry[3], c1, c2);
+			byte *entry = (*_colorMap)[i];
+			for (int j = 0; j < 128; j++)
+				_stipples[i][j] = getCGAStipple(entry[(j / 8) % 4], c1, c2) ;
 		}
 	}
 }
@@ -221,7 +212,7 @@ void Renderer::setColorRemaps(ColorReMap *colorRemaps) {
 	_colorRemaps = colorRemaps;
 }
 
-bool Renderer::getRGBAtCGA(uint8 index, uint8 &r1, uint8 &g1, uint8 &b1, uint8 &r2, uint8 &g2, uint8 &b2, byte *stipple) {
+bool Renderer::getRGBAtCGA(uint8 index, uint8 &r1, uint8 &g1, uint8 &b1, uint8 &r2, uint8 &g2, uint8 &b2, byte *&stipple) {
 	if (index == _keyColor)
 		return false;
 
@@ -234,13 +225,7 @@ bool Renderer::getRGBAtCGA(uint8 index, uint8 &r1, uint8 &g1, uint8 &b1, uint8 &
 		return true;
 	}
 
-	if (stipple) {
-		stipple[0] = _stipples[0][index - 1];
-		stipple[1] = _stipples[1][index - 1];
-		stipple[2] = _stipples[2][index - 1];
-		stipple[3] = _stipples[3][index - 1];
-	}
-
+	stipple = (byte *)_stipples[index - 1];
 	byte pair = _colorPair[index - 1];
 	byte c1 = pair & 0xf;
 	byte c2 = (pair >> 4) & 0xf;
@@ -315,7 +300,7 @@ bool Renderer::getRGBAtC64(uint8 index, uint8 &r1, uint8 &g1, uint8 &b1, uint8 &
 	return true;
 }
 
-bool Renderer::getRGBAtZX(uint8 index, uint8 &r1, uint8 &g1, uint8 &b1, uint8 &r2, uint8 &g2, uint8 &b2, byte *stipple) {
+bool Renderer::getRGBAtZX(uint8 index, uint8 &r1, uint8 &g1, uint8 &b1, uint8 &r2, uint8 &g2, uint8 &b2, byte *&stipple) {
 	if (index == _keyColor)
 		return false;
 
@@ -332,12 +317,7 @@ bool Renderer::getRGBAtZX(uint8 index, uint8 &r1, uint8 &g1, uint8 &b1, uint8 &r
 		return true;
 	}
 
-	if (stipple) {
-		stipple[0] = _stipples[0][index - 1];
-		stipple[1] = _stipples[1][index - 1];
-		stipple[2] = _stipples[2][index - 1];
-		stipple[3] = _stipples[3][index - 1];
-	}
+	stipple = (byte *)_stipples[index - 1];
 
 	readFromPalette(_paperColor, r1, g1, b1);
 	readFromPalette(_inkColor, r2, g2, b2);
@@ -359,7 +339,7 @@ void Renderer::selectColorFromFourColorPalette(uint8 index, uint8 &r1, uint8 &g1
 		error("Invalid color");
 }
 
-bool Renderer::getRGBAtCPC(uint8 index, uint8 &r1, uint8 &g1, uint8 &b1, uint8 &r2, uint8 &g2, uint8 &b2, byte *stipple) {
+bool Renderer::getRGBAtCPC(uint8 index, uint8 &r1, uint8 &g1, uint8 &b1, uint8 &r2, uint8 &g2, uint8 &b2, byte *&stipple) {
 	if (index == _keyColor)
 		return false;
 
@@ -372,13 +352,7 @@ bool Renderer::getRGBAtCPC(uint8 index, uint8 &r1, uint8 &g1, uint8 &b1, uint8 &
 		return true;
 	}
 
-	if (stipple) {
-		stipple[0] = _stipples[0][index - 1];
-		stipple[1] = _stipples[1][index - 1];
-		stipple[2] = _stipples[2][index - 1];
-		stipple[3] = _stipples[3][index - 1];
-	}
-
+	stipple = (byte *)_stipples[index - 1];
 	byte *entry = (*_colorMap)[index - 1];
 	uint8 i1 = getCPCPixel(entry[0], 0);
 	uint8 i2 = getCPCPixel(entry[0], 1);
@@ -409,7 +383,7 @@ bool Renderer::getRGBAtEGA(uint8 index, uint8 &r1, uint8 &g1, uint8 &b1, uint8 &
 	return true;
 }
 
-bool Renderer::getRGBAt(uint8 index, uint8 &r1, uint8 &g1, uint8 &b1, uint8 &r2, uint8 &g2, uint8 &b2, byte *stipple) {
+bool Renderer::getRGBAt(uint8 index, uint8 &r1, uint8 &g1, uint8 &b1, uint8 &r2, uint8 &g2, uint8 &b2, byte *&stipple) {
 
 	if (_colorRemaps && _colorRemaps->contains(index)) {
 		index = (*_colorRemaps)[index];
@@ -591,10 +565,10 @@ void Renderer::renderPyramid(const Math::Vector3d &origin, const Math::Vector3d
 	}
 
 	Common::Array<Math::Vector3d> face;
-	uint32 stipple = 0;
+	byte *stipple = nullptr;
 	uint8 r1, g1, b1, r2, g2, b2;
-	if (getRGBAt((*colours)[0], r1, g1, b1, r2, g2, b2, (byte *)&stipple)) {
-		setStippleData((byte *)&stipple);
+	if (getRGBAt((*colours)[0], r1, g1, b1, r2, g2, b2, stipple)) {
+		setStippleData(stipple);
 		useColor(r1, g1, b1);
 
 		face.push_back(vertices[4]);
@@ -614,8 +588,8 @@ void Renderer::renderPyramid(const Math::Vector3d &origin, const Math::Vector3d
 		face.clear();
 	}
 
-	if (getRGBAt((*colours)[1], r1, g1, b1, r2, g2, b2, (byte *)&stipple)) {
-		setStippleData((byte *)&stipple);
+	if (getRGBAt((*colours)[1], r1, g1, b1, r2, g2, b2, stipple)) {
+		setStippleData(stipple);
 		useColor(r1, g1, b1);
 
 		face.push_back(vertices[5]);
@@ -634,8 +608,8 @@ void Renderer::renderPyramid(const Math::Vector3d &origin, const Math::Vector3d
 		face.clear();
 	}
 
-	if (getRGBAt((*colours)[2], r1, g1, b1, r2, g2, b2, (byte *)&stipple)) {
-		setStippleData((byte *)&stipple);
+	if (getRGBAt((*colours)[2], r1, g1, b1, r2, g2, b2, stipple)) {
+		setStippleData(stipple);
 		useColor(r1, g1, b1);
 
 		face.push_back(vertices[6]);
@@ -653,8 +627,8 @@ void Renderer::renderPyramid(const Math::Vector3d &origin, const Math::Vector3d
 		face.clear();
 	}
 
-	if (getRGBAt((*colours)[3], r1, g1, b1, r2, g2, b2, (byte *)&stipple)) {
-		setStippleData((byte *)&stipple);
+	if (getRGBAt((*colours)[3], r1, g1, b1, r2, g2, b2, stipple)) {
+		setStippleData(stipple);
 		useColor(r1, g1, b1);
 
 		face.push_back(vertices[7]);
@@ -673,8 +647,8 @@ void Renderer::renderPyramid(const Math::Vector3d &origin, const Math::Vector3d
 		face.clear();
 	}
 
-	if (getRGBAt((*colours)[4], r1, g1, b1, r2, g2, b2, (byte *)&stipple)) {
-		setStippleData((byte *)&stipple);
+	if (getRGBAt((*colours)[4], r1, g1, b1, r2, g2, b2, stipple)) {
+		setStippleData(stipple);
 		useColor(r1, g1, b1);
 
 		face.push_back(vertices[0]);
@@ -692,8 +666,8 @@ void Renderer::renderPyramid(const Math::Vector3d &origin, const Math::Vector3d
 		face.clear();
 	}
 
-	if (getRGBAt((*colours)[5], r1, g1, b1, r2, g2, b2, (byte *)&stipple)) {
-		setStippleData((byte *)&stipple);
+	if (getRGBAt((*colours)[5], r1, g1, b1, r2, g2, b2, stipple)) {
+		setStippleData(stipple);
 		useColor(r1, g1, b1);
 
 		face.push_back(vertices[7]);
@@ -711,12 +685,12 @@ void Renderer::renderPyramid(const Math::Vector3d &origin, const Math::Vector3d
 }
 
 void Renderer::renderCube(const Math::Vector3d &origin, const Math::Vector3d &size, Common::Array<uint8> *colours) {
-	uint32 stipple = 0;
+	byte *stipple = nullptr;
 	uint8 r1, g1, b1, r2, g2, b2;
 	Common::Array<Math::Vector3d> face;
 
-	if (getRGBAt((*colours)[0], r1, g1, b1, r2, g2, b2, (byte *)&stipple)) {
-		setStippleData((byte *)&stipple);
+	if (getRGBAt((*colours)[0], r1, g1, b1, r2, g2, b2, stipple)) {
+		setStippleData(stipple);
 		useColor(r1, g1, b1);
 		face.push_back(origin);
 		face.push_back(Math::Vector3d(origin.x(), origin.y(), origin.z() + size.z()));
@@ -731,8 +705,8 @@ void Renderer::renderCube(const Math::Vector3d &origin, const Math::Vector3d &si
 		}
 	}
 
-	if (getRGBAt((*colours)[1], r1, g1, b1, r2, g2, b2, (byte *)&stipple)) {
-		setStippleData((byte *)&stipple);
+	if (getRGBAt((*colours)[1], r1, g1, b1, r2, g2, b2, stipple)) {
+		setStippleData(stipple);
 		useColor(r1, g1, b1);
 		face.clear();
 		face.push_back(Math::Vector3d(origin.x() + size.x(), origin.y() + size.y(), origin.z()));
@@ -748,8 +722,8 @@ void Renderer::renderCube(const Math::Vector3d &origin, const Math::Vector3d &si
 		}
 	}
 
-	if (getRGBAt((*colours)[2], r1, g1, b1, r2, g2, b2, (byte *)&stipple)) {
-		setStippleData((byte *)&stipple);
+	if (getRGBAt((*colours)[2], r1, g1, b1, r2, g2, b2, stipple)) {
+		setStippleData(stipple);
 		useColor(r1, g1, b1);
 		face.clear();
 		face.push_back(Math::Vector3d(origin.x() + size.x(), origin.y(), origin.z()));
@@ -765,8 +739,8 @@ void Renderer::renderCube(const Math::Vector3d &origin, const Math::Vector3d &si
 		}
 	}
 
-	if (getRGBAt((*colours)[3], r1, g1, b1, r2, g2, b2, (byte *)&stipple)) {
-		setStippleData((byte *)&stipple);
+	if (getRGBAt((*colours)[3], r1, g1, b1, r2, g2, b2, stipple)) {
+		setStippleData(stipple);
 		useColor(r1, g1, b1);
 		face.clear();
 		face.push_back(Math::Vector3d(origin.x(), origin.y() + size.y(), origin.z()));
@@ -782,8 +756,8 @@ void Renderer::renderCube(const Math::Vector3d &origin, const Math::Vector3d &si
 		}
 	}
 
-	if (getRGBAt((*colours)[4], r1, g1, b1, r2, g2, b2, (byte *)&stipple)) {
-		setStippleData((byte *)&stipple);
+	if (getRGBAt((*colours)[4], r1, g1, b1, r2, g2, b2, stipple)) {
+		setStippleData(stipple);
 		useColor(r1, g1, b1);
 		face.clear();
 		face.push_back(Math::Vector3d(origin.x(), origin.y() + size.y(), origin.z()));
@@ -799,8 +773,8 @@ void Renderer::renderCube(const Math::Vector3d &origin, const Math::Vector3d &si
 		}
 	}
 
-	if (getRGBAt((*colours)[5], r1, g1, b1, r2, g2, b2, (byte *)&stipple)) {
-		setStippleData((byte *)&stipple);
+	if (getRGBAt((*colours)[5], r1, g1, b1, r2, g2, b2, stipple)) {
+		setStippleData(stipple);
 		useColor(r1, g1, b1);
 		face.clear();
 		face.push_back(Math::Vector3d(origin.x(), origin.y(), origin.z() + size.z()));
@@ -824,13 +798,13 @@ void Renderer::renderRectangle(const Math::Vector3d &origin, const Math::Vector3
 
 	float dx, dy, dz;
 	uint8 r1, g1, b1, r2, g2, b2;
-	uint32 stipple = 0;
+	byte *stipple = nullptr;
 	Common::Array<Math::Vector3d> vertices;
 	for (int i = 0; i < 2; i++) {
 
 		// debug("rec color: %d", (*colours)[i]);
-		if (getRGBAt((*colours)[i], r1, g1, b1, r2, g2, b2, (byte *)&stipple)) {
-			setStippleData((byte *)&stipple);
+		if (getRGBAt((*colours)[i], r1, g1, b1, r2, g2, b2, stipple)) {
+			setStippleData(stipple);
 			useColor(r1, g1, b1);
 			vertices.clear();
 			vertices.push_back(Math::Vector3d(origin.x(), origin.y(), origin.z()));
@@ -882,7 +856,7 @@ void Renderer::renderRectangle(const Math::Vector3d &origin, const Math::Vector3
 
 void Renderer::renderPolygon(const Math::Vector3d &origin, const Math::Vector3d &size, const Common::Array<uint16> *ordinates, Common::Array<uint8> *colours) {
 	uint8 r1, g1, b1, r2, g2, b2;
-	uint32 stipple = 0;
+	byte *stipple = nullptr;
 	if (ordinates->size() % 3 > 0 && ordinates->size() > 0)
 		error("Invalid polygon with size %f %f %f and ordinates %d", size.x(), size.y(), size.z(), ordinates->size());
 
@@ -890,8 +864,8 @@ void Renderer::renderPolygon(const Math::Vector3d &origin, const Math::Vector3d
 	polygonOffset(true);
 
 	if (ordinates->size() == 6) {                 // Line
-		assert(getRGBAt((*colours)[0], r1, g1, b1, r2, g2, b2, (byte *)&stipple)); // It will never return false?
-		setStippleData((byte *)&stipple);
+		assert(getRGBAt((*colours)[0], r1, g1, b1, r2, g2, b2, stipple)); // It will never return false?
+		setStippleData(stipple);
 		useColor(r1, g1, b1);
 		for (uint i = 0; i < ordinates->size(); i = i + 3)
 			vertices.push_back(Math::Vector3d((*ordinates)[i], (*ordinates)[i + 1], (*ordinates)[i + 2]));
@@ -904,8 +878,8 @@ void Renderer::renderPolygon(const Math::Vector3d &origin, const Math::Vector3d
 		}
 
 		vertices.clear();
-		assert(getRGBAt((*colours)[1], r1, g1, b1, r2, g2, b2, (byte *)&stipple)); // It will never return false?
-		setStippleData((byte *)&stipple);
+		assert(getRGBAt((*colours)[1], r1, g1, b1, r2, g2, b2, stipple)); // It will never return false?
+		setStippleData(stipple);
 		useColor(r1, g1, b1);
 		for (int i = ordinates->size(); i > 0; i = i - 3)
 			vertices.push_back(Math::Vector3d((*ordinates)[i - 3], (*ordinates)[i - 2], (*ordinates)[i - 1]));
@@ -918,8 +892,8 @@ void Renderer::renderPolygon(const Math::Vector3d &origin, const Math::Vector3d
 		}
 
 	} else {
-		if (getRGBAt((*colours)[0], r1, g1, b1, r2, g2, b2, (byte *)&stipple)) {
-			setStippleData((byte *)&stipple);
+		if (getRGBAt((*colours)[0], r1, g1, b1, r2, g2, b2, stipple)) {
+			setStippleData(stipple);
 			useColor(r1, g1, b1);
 			for (uint i = 0; i < ordinates->size(); i = i + 3) {
 				vertices.push_back(Math::Vector3d((*ordinates)[i], (*ordinates)[i + 1], (*ordinates)[i + 2]));
@@ -933,8 +907,8 @@ void Renderer::renderPolygon(const Math::Vector3d &origin, const Math::Vector3d
 			}
 		}
 		vertices.clear();
-		if (getRGBAt((*colours)[1], r1, g1, b1, r2, g2, b2, (byte *)&stipple)) {
-			setStippleData((byte *)&stipple);
+		if (getRGBAt((*colours)[1], r1, g1, b1, r2, g2, b2, stipple)) {
+			setStippleData(stipple);
 			useColor(r1, g1, b1);
 			for (int i = ordinates->size(); i > 0; i = i - 3) {
 				vertices.push_back(Math::Vector3d((*ordinates)[i - 3], (*ordinates)[i - 2], (*ordinates)[i - 1]));
diff --git a/engines/freescape/gfx.h b/engines/freescape/gfx.h
index 8c948e05068..6bae31840c9 100644
--- a/engines/freescape/gfx.h
+++ b/engines/freescape/gfx.h
@@ -99,12 +99,12 @@ public:
 	// palette
 	void readFromPalette(uint8 index, uint8 &r, uint8 &g, uint8 &b);
 	uint8 indexFromColor(uint8 r, uint8 g, uint8 b);
-	bool getRGBAt(uint8 index, uint8 &r1, uint8 &g1, uint8 &b1, uint8 &r2, uint8 &g2, uint8 &b2, byte *stipple);
+	bool getRGBAt(uint8 index, uint8 &r1, uint8 &g1, uint8 &b1, uint8 &r2, uint8 &g2, uint8 &b2, byte *&stipple);
 	bool getRGBAtC64(uint8 index, uint8 &r1, uint8 &g1, uint8 &b1, uint8 &r2, uint8 &g2, uint8 &b2);
-	bool getRGBAtCGA(uint8 index, uint8 &r1, uint8 &g1, uint8 &b1, uint8 &r2, uint8 &g2, uint8 &b2, byte *stipple);
-	bool getRGBAtCPC(uint8 index, uint8 &r1, uint8 &g1, uint8 &b1, uint8 &r2, uint8 &g2, uint8 &b2, byte *stipple);
+	bool getRGBAtCGA(uint8 index, uint8 &r1, uint8 &g1, uint8 &b1, uint8 &r2, uint8 &g2, uint8 &b2, byte *&stipple);
+	bool getRGBAtCPC(uint8 index, uint8 &r1, uint8 &g1, uint8 &b1, uint8 &r2, uint8 &g2, uint8 &b2, byte *&stipple);
 	bool getRGBAtEGA(uint8 index, uint8 &r1, uint8 &g1, uint8 &b1, uint8 &r2, uint8 &g2, uint8 &b2);
-	bool getRGBAtZX(uint8 index, uint8 &r1, uint8 &g1, uint8 &b1, uint8 &r2, uint8 &g2, uint8 &b2, byte *stipple);
+	bool getRGBAtZX(uint8 index, uint8 &r1, uint8 &g1, uint8 &b1, uint8 &r2, uint8 &g2, uint8 &b2, byte *&stipple);
 	void extractCPCIndexes(uint8 cm1, uint8 cm2, uint8 &i1, uint8 &i2);
 	void extractC64Indexes(uint8 cm1, uint8 cm2, uint8 &i1, uint8 &i2);
 
@@ -122,7 +122,7 @@ public:
 	int _inkColor;
 	int _paperColor;
 	int _underFireBackgroundColor;
-	byte _stipples[4][16];
+	byte _stipples[16][128];
 
 	/**
 	 * Select the window where to render
diff --git a/engines/freescape/gfx_opengl.cpp b/engines/freescape/gfx_opengl.cpp
index 13f08e5db49..2848f48e9fb 100644
--- a/engines/freescape/gfx_opengl.cpp
+++ b/engines/freescape/gfx_opengl.cpp
@@ -42,6 +42,7 @@ OpenGLRenderer::OpenGLRenderer(int screenW, int screenH, Common::RenderMode rend
 	_coords = (Coord *)malloc(sizeof(Coord) * kCoordsArraySize);
 	_texturePixelFormat = OpenGLTexture::getRGBAPixelFormat();
 	_isAccelerated = true;
+	_variableStippleArray = nullptr;
 }
 
 OpenGLRenderer::~OpenGLRenderer() {
@@ -276,8 +277,9 @@ void OpenGLRenderer::setStippleData(byte *data) {
 	if (!data)
 		return;
 
-	for (int i = 0; i < 128; i++)
-		_variableStippleArray[i] = data[(i / 16) % 4];
+	_variableStippleArray = data;
+	//for (int i = 0; i < 128; i++)
+	//	_variableStippleArray[i] = data[(i / 16) % 4];
 }
 
 void OpenGLRenderer::useStipple(bool enabled) {
@@ -316,8 +318,8 @@ void OpenGLRenderer::clear(uint8 color) {
 
 void OpenGLRenderer::drawFloor(uint8 color) {
 	uint8 r1, g1, b1, r2, g2, b2;
-	uint32 stipple = 0;
-	assert(getRGBAt(color, r1, g1, b1, r2, g2, b2, (byte *)&stipple)); // TODO: move check inside this function
+	byte *stipple;
+	assert(getRGBAt(color, r1, g1, b1, r2, g2, b2, stipple)); // TODO: move check inside this function
 	glColor3ub(r1, g1, b1);
 
 	glEnableClientState(GL_VERTEX_ARRAY);
diff --git a/engines/freescape/gfx_opengl.h b/engines/freescape/gfx_opengl.h
index cc9536eac79..a3925a8d4ba 100644
--- a/engines/freescape/gfx_opengl.h
+++ b/engines/freescape/gfx_opengl.h
@@ -79,24 +79,7 @@ public:
 		0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33,
 	};
 
-	GLubyte _variableStippleArray[128] = {
-		0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
-		0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
-		0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
-		0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
-		0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
-		0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
-		0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
-		0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
-		0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
-		0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
-		0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
-		0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
-		0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
-		0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
-		0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
-		0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
-	};
+	GLubyte *_variableStippleArray;
 
 	virtual void init() override;
 	virtual void clear(uint8 color) override;
diff --git a/engines/freescape/gfx_tinygl.cpp b/engines/freescape/gfx_tinygl.cpp
index 15456f24118..ad1c0f62195 100644
--- a/engines/freescape/gfx_tinygl.cpp
+++ b/engines/freescape/gfx_tinygl.cpp
@@ -227,7 +227,8 @@ void TinyGLRenderer::clear(uint8 color) {
 
 void TinyGLRenderer::drawFloor(uint8 color) {
 	uint8 r1, g1, b1, r2, g2, b2;
-	assert(getRGBAt(color, r1, g1, b1, r2, g2, b2, nullptr)); // TODO: move check inside this function
+	byte *stipple = nullptr;
+	assert(getRGBAt(color, r1, g1, b1, r2, g2, b2, stipple)); // TODO: move check inside this function
 	tglColor3ub(r1, g1, b1);
 
 	tglEnableClientState(TGL_VERTEX_ARRAY);


Commit: 59cae6551a7174d06905fcfc68e0412d53effcfa
    https://github.com/scummvm/scummvm/commit/59cae6551a7174d06905fcfc68e0412d53effcfa
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-03-20T11:04:57+01:00

Commit Message:
FREESCAPE: avoid crash selecting a missing palette in driller demo for amiga/atari

Changed paths:
    engines/freescape/games/palettes.cpp


diff --git a/engines/freescape/games/palettes.cpp b/engines/freescape/games/palettes.cpp
index 00e626fb653..2947a6c6268 100644
--- a/engines/freescape/games/palettes.cpp
+++ b/engines/freescape/games/palettes.cpp
@@ -209,9 +209,13 @@ byte kDrillerCGAPaletteRedGreenData[4][3] = {
 };
 
 void FreescapeEngine::swapPalette(uint16 levelID) {
-	if (isAmiga() || isAtariST())
+	if (isAmiga() || isAtariST()) {
+		// The following palette was not available in the demo, so we select another one
+		if (isDemo() && levelID == 32)
+			levelID = 31;
+
 		_gfx->_palette = _paletteByArea[levelID];
-	else if (isSpectrum() || isCPC() || isC64()) {
+	} else if (isSpectrum() || isCPC() || isC64()) {
 		_gfx->_inkColor = _areaMap[levelID]->_inkColor;
 		_gfx->_paperColor = _areaMap[levelID]->_paperColor;
 		_gfx->_underFireBackgroundColor = _areaMap[levelID]->_underFireBackgroundColor;


Commit: 8b1448d70dc765eb2d2370f17ff16752b2fc5f3e
    https://github.com/scummvm/scummvm/commit/8b1448d70dc765eb2d2370f17ff16752b2fc5f3e
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-03-20T11:05:07+01:00

Commit Message:
FREESCAPE: disallow crossair to be outside the view area

Changed paths:
    engines/freescape/freescape.cpp


diff --git a/engines/freescape/freescape.cpp b/engines/freescape/freescape.cpp
index c39ed86ade4..50df8756748 100644
--- a/engines/freescape/freescape.cpp
+++ b/engines/freescape/freescape.cpp
@@ -433,6 +433,8 @@ void FreescapeEngine::processInput() {
 				} else {
 					g_system->lockMouse(false);
 					g_system->warpMouse(_crossairPosition.x, _crossairPosition.y);
+					g_system->getEventManager()->purgeMouseEvents();
+					g_system->getEventManager()->purgeKeyboardEvents();
 				}
 				break;
 			case Common::KEYCODE_i:
@@ -462,15 +464,34 @@ void FreescapeEngine::processInput() {
 				g_system->warpMouse(mousePos.x, mousePos.y);
 
 			if (_shootMode) {
-				_crossairPosition = mousePos;
-				if (mousePos.x < _viewArea.left)
-					g_system->warpMouse(_viewArea.left + 1, _crossairPosition.y);
-				else if  (mousePos.x > _viewArea.right)
-					g_system->warpMouse(_viewArea.right - 1, _crossairPosition.y);
-				else if (mousePos.y < _viewArea.top)
-					g_system->warpMouse(_crossairPosition.x, _viewArea.top + 1);
-				else if  (mousePos.y > _viewArea.bottom)
-					g_system->warpMouse(_crossairPosition.x, _viewArea.bottom - 1);
+				{
+					bool shouldWarp = false;
+					_crossairPosition = mousePos;
+					if (mousePos.x < _viewArea.left) {
+						_crossairPosition.x = _viewArea.left + 1;
+						shouldWarp = true;
+					}
+
+					if  (mousePos.x > _viewArea.right) {
+						_crossairPosition.x = _viewArea.right - 1;
+						shouldWarp = true;
+					}
+					if (mousePos.y < _viewArea.top) {
+						_crossairPosition.y =  _viewArea.top + 1;
+						shouldWarp = true;
+					}
+
+					if  (mousePos.y > _viewArea.bottom) {
+						_crossairPosition.y = _viewArea.bottom - 1;
+						shouldWarp = true;
+					}
+
+					if (shouldWarp) {
+						g_system->warpMouse(_crossairPosition.x, _crossairPosition.y);
+						g_system->getEventManager()->purgeMouseEvents();
+						g_system->getEventManager()->purgeKeyboardEvents();
+					}
+				}
 				break;
 			}
 




More information about the Scummvm-git-logs mailing list