[Scummvm-git-logs] scummvm master -> 650a9dc492010bfdcdead40502b06ea4c3c2f8ed
neuromancer
noreply at scummvm.org
Tue Mar 31 09:18:08 UTC 2026
This automated email contains information about 4 new commits which have been
pushed to the 'scummvm' repo located at https://api.github.com/repos/scummvm/scummvm .
Summary:
6f8aa6d186 FREESCAPE: cannot rest in the desert
e27a0be75d FREESCAPE: eclipse ending fixes and commands to easily reach it
43c9390cd3 FREESCAPE: avoid UB in Renderer::getRGBAtCPC
650a9dc492 FREESCAPE: show indicators in the correct color in eclipse cpc
Commit: 6f8aa6d18613ed116be617a5e4d6bd1ec7cacdcd
https://github.com/scummvm/scummvm/commit/6f8aa6d18613ed116be617a5e4d6bd1ec7cacdcd
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2026-03-31T11:17:32+02:00
Commit Message:
FREESCAPE: cannot rest in the desert
Changed paths:
engines/freescape/games/eclipse/eclipse.cpp
diff --git a/engines/freescape/games/eclipse/eclipse.cpp b/engines/freescape/games/eclipse/eclipse.cpp
index dc74dcebb30..feba68ffb94 100644
--- a/engines/freescape/games/eclipse/eclipse.cpp
+++ b/engines/freescape/games/eclipse/eclipse.cpp
@@ -555,7 +555,7 @@ void EclipseEngine::pressedKey(const int keycode) {
else
error("Invalid player height index: %d", _playerHeightNumber);
} else if (keycode == kActionRest) {
- if (_currentArea->getAreaID() == 1) {
+ if (_currentArea->getAreaID() == 1 || _currentArea->getAreaID() == 51) {
playSoundFx(3, false);
if (_temporaryMessages.empty())
insertTemporaryMessage(_messagesList[6], _countdown - 2);
Commit: e27a0be75ddae7ebf1eda026d9b0231ff262aa56
https://github.com/scummvm/scummvm/commit/e27a0be75ddae7ebf1eda026d9b0231ff262aa56
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2026-03-31T11:17:32+02:00
Commit Message:
FREESCAPE: eclipse ending fixes and commands to easily reach it
Changed paths:
engines/freescape/debugger.cpp
engines/freescape/debugger.h
engines/freescape/language/instruction.cpp
engines/freescape/movement.cpp
diff --git a/engines/freescape/debugger.cpp b/engines/freescape/debugger.cpp
index 47b58d3199f..d9cac80416c 100644
--- a/engines/freescape/debugger.cpp
+++ b/engines/freescape/debugger.cpp
@@ -21,6 +21,7 @@
#include "freescape/debugger.h"
#include "freescape/freescape.h"
+#include "freescape/games/eclipse/eclipse.h"
#include "freescape/gfx.h"
#include "freescape/objects/object.h"
#include "freescape/area.h"
@@ -39,12 +40,13 @@ Debugger::Debugger(FreescapeEngine *vm) : GUI::Debugger(), _vm(vm) {
registerCmd("iso", WRAP_METHOD(Debugger, cmdHighlightID)); // isolate object
registerCmd("obj_pos", WRAP_METHOD(Debugger, cmdObjPos)); // get object pos
registerCmd("obj_mov", WRAP_METHOD(Debugger, cmdSetObjPos)); // move object
- registerCmd("goto", WRAP_METHOD(Debugger, cmdGoto)); // teleport to a position
+ registerCmd("goto", WRAP_METHOD(Debugger, cmdGoto)); // teleport to area/entrance or position
registerCmd("sort_order", WRAP_METHOD(Debugger, cmdSortOrder)); // print current draw order of objects
registerCmd("occ", WRAP_METHOD(Debugger, cmdShowOcclusion)); // toggle occlussion boxes
registerCmd("area", WRAP_METHOD(Debugger, cmdArea)); // show current area info
registerCmd("pos", WRAP_METHOD(Debugger, cmdPos)); // show camera position and direction
registerCmd("win", WRAP_METHOD(Debugger, cmdWin)); // trigger the current game's win condition
+ registerCmd("ankh", WRAP_METHOD(Debugger, cmdAnkh)); // set ankh count (Total Eclipse only)
}
Debugger::~Debugger() {}
@@ -167,15 +169,25 @@ bool Debugger::cmdSetObjPos(int argc, const char **argv) {
}
bool Debugger::cmdGoto(int argc, const char **argv) {
- if (argc < 4) {
- debugPrintf("Usage: goto <x> <y> <z>\n");
+ if (argc == 3) {
+ uint16 areaID = atoi(argv[1]);
+ int entranceID = atoi(argv[2]);
+ _vm->gotoArea(areaID, entranceID);
+ debugPrintf("Jumped to area %d, entrance %d\n", areaID, entranceID);
return true;
}
- float x = atof(argv[1]);
- float y = atof(argv[2]);
- float z = atof(argv[3]);
- _vm->_position = Math::Vector3d(x, y, z);
- debugPrintf("Teleported to %f %f %f\n", x, y, z);
+
+ if (argc >= 4) {
+ float x = atof(argv[1]);
+ float y = atof(argv[2]);
+ float z = atof(argv[3]);
+ _vm->_position = Math::Vector3d(x, y, z);
+ debugPrintf("Teleported to %f %f %f\n", x, y, z);
+ return true;
+ }
+
+ debugPrintf("Usage: goto <area> <entrance>\n");
+ debugPrintf(" goto <x> <y> <z>\n");
return true;
}
@@ -303,4 +315,22 @@ bool Debugger::cmdWin(int argc, const char **argv) {
return true;
}
+bool Debugger::cmdAnkh(int argc, const char **argv) {
+ if (!_vm->isEclipse()) {
+ debugPrintf("This command is only available in Total Eclipse.\n");
+ return true;
+ }
+
+ if (argc < 2) {
+ debugPrintf("Current ankhs: %d\n", _vm->_gameStateVars[kVariableEclipseAnkhs]);
+ debugPrintf("Usage: ankh <count>\n");
+ return true;
+ }
+
+ int count = atoi(argv[1]);
+ _vm->_gameStateVars[kVariableEclipseAnkhs] = count;
+ debugPrintf("Ankhs set to %d\n", count);
+ return true;
+}
+
}
diff --git a/engines/freescape/debugger.h b/engines/freescape/debugger.h
index 579a0e57649..8d66f3be8cd 100644
--- a/engines/freescape/debugger.h
+++ b/engines/freescape/debugger.h
@@ -49,6 +49,7 @@ private:
bool cmdArea(int argc, const char **argv);
bool cmdPos(int argc, const char **argv);
bool cmdWin(int argc, const char **argv);
+ bool cmdAnkh(int argc, const char **argv);
};
}
diff --git a/engines/freescape/language/instruction.cpp b/engines/freescape/language/instruction.cpp
index 6b2763dc616..a0457b18707 100644
--- a/engines/freescape/language/instruction.cpp
+++ b/engines/freescape/language/instruction.cpp
@@ -361,6 +361,9 @@ void FreescapeEngine::executeRedraw(FCLInstruction &instruction) {
if (isDriller() && (isSpectrum() || isCPC() || isC64()) && _gameStateVars[32] == 18)
delay = delay * 15; // Slow down redraws when the final cutscene is playing
+ if (isEclipse() && _currentArea->getAreaID() == 37 && getGameBit(6))
+ delay = delay * 10; // Slow down redraws in the final area of Eclipse
+
waitInLoop(delay);
}
diff --git a/engines/freescape/movement.cpp b/engines/freescape/movement.cpp
index 49b65359ab2..a6fe607b099 100644
--- a/engines/freescape/movement.cpp
+++ b/engines/freescape/movement.cpp
@@ -347,6 +347,14 @@ bool FreescapeEngine::rise() {
changePlayerHeight(_playerHeightNumber);
if (!isCastle())
setGameBit(31);
+
+ Math::Ray ray(_position, _upVector);
+ Object *collidedUp = _currentArea->checkCollisionRay(ray, _playerHeight + 3);
+ if (collidedUp) {
+ GeometricObject *gobj = (GeometricObject *)collidedUp;
+ debugC(1, kFreescapeDebugMove, "Collided up with object id %d", gobj->getObjectID());
+ executeObjectConditions(gobj, false, true, false);
+ }
}
} else
result = true;
Commit: 43c9390cd3e1c3e068d0e0deef50819f5e56d8e0
https://github.com/scummvm/scummvm/commit/43c9390cd3e1c3e068d0e0deef50819f5e56d8e0
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2026-03-31T11:17:32+02:00
Commit Message:
FREESCAPE: avoid UB in Renderer::getRGBAtCPC
Changed paths:
engines/freescape/gfx.cpp
diff --git a/engines/freescape/gfx.cpp b/engines/freescape/gfx.cpp
index 0d8742d134b..d8172b7ad87 100644
--- a/engines/freescape/gfx.cpp
+++ b/engines/freescape/gfx.cpp
@@ -511,6 +511,18 @@ bool Renderer::getRGBAtCPC(uint8 index, uint8 &r1, uint8 &g1, uint8 &b1, uint8 &
return true;
}
+ if (index == 0 || index > 15) {
+ // Color indices outside the 1-15 stipple range are raw CPC ink
+ // values used for backgrounds. Read directly from the hardware
+ // palette instead of the stipple tables.
+ readFromPalette(index, r1, g1, b1);
+ r2 = r1;
+ g2 = g1;
+ b2 = b1;
+ stipple = nullptr;
+ return true;
+ }
+
stipple = (byte *)_stipples[index - 1];
byte pair = _colorPair[index - 1];
uint8 i1 = pair & 0xf;
Commit: 650a9dc492010bfdcdead40502b06ea4c3c2f8ed
https://github.com/scummvm/scummvm/commit/650a9dc492010bfdcdead40502b06ea4c3c2f8ed
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2026-03-31T11:17:32+02:00
Commit Message:
FREESCAPE: show indicators in the correct color in eclipse cpc
Changed paths:
engines/freescape/games/eclipse/cpc.cpp
engines/freescape/games/eclipse/eclipse.cpp
engines/freescape/games/eclipse/eclipse.h
diff --git a/engines/freescape/games/eclipse/cpc.cpp b/engines/freescape/games/eclipse/cpc.cpp
index 628a43e10aa..f7809096510 100644
--- a/engines/freescape/games/eclipse/cpc.cpp
+++ b/engines/freescape/games/eclipse/cpc.cpp
@@ -64,38 +64,20 @@ byte kCPCPaletteEclipseBorderData[4][3] = {
void EclipseEngine::loadHeartFramesCPC(Common::SeekableReadStream *file, int restOffset, int beatOffset) {
- // Decode into _eclipseSprites[0] (beat) and _eclipseSprites[1] (rest),
- // matching the Atari ST convention for future unification.
- // Uses loadFrameCPCIndexed (shared with Castle) for pixel decoding,
- // then converts CLUT8âARGB via convertImageFormatIfNecessary.
+ // Decode heart frames as indexed (CLUT8) pixel data.
+ // The actual palette is applied at draw time from the current area's
+ // ink/paper colors, since CPC pen assignments change per area.
int offsets[2] = { beatOffset, restOffset };
- byte palette[4 * 3];
- for (int c = 0; c < 4; c++) {
- uint8 r, g, b;
- _gfx->selectColorFromFourColorPalette(c, r, g, b);
- palette[c * 3 + 0] = r;
- palette[c * 3 + 1] = g;
- palette[c * 3 + 2] = b;
- }
-
for (int f = 0; f < 2; f++) {
file->seek(offsets[f]);
int height = file->readByte();
int widthBytes = file->readByte();
- Graphics::ManagedSurface clut8;
- clut8.create(widthBytes * 4, height, Graphics::PixelFormat::createFormatCLUT8());
- loadFrameCPCIndexed(file, &clut8, widthBytes, height);
- clut8.setPalette(palette, 0, 4);
-
- Graphics::Surface *converted = _gfx->convertImageFormatIfNecessary(&clut8);
- auto *surf = new Graphics::ManagedSurface();
- surf->copyFrom(*converted);
- converted->free();
- delete converted;
-
- _eclipseSprites.push_back(surf);
+ auto *indexed = new Graphics::ManagedSurface();
+ indexed->create(widthBytes * 4, height, Graphics::PixelFormat::createFormatCLUT8());
+ loadFrameCPCIndexed(file, indexed, widthBytes, height);
+ _heartFramesCPCIndexed.push_back(indexed);
}
}
@@ -149,8 +131,10 @@ void EclipseEngine::loadAssetsCPCFullGame() {
loadColorPalette();
swapPalette(1);
- if (!isEclipse2())
+ if (!isEclipse2()) {
loadHeartFramesCPC(&file, 0x0CDB, 0x0D0D);
+ updateHeartFramesCPC();
+ }
_indicators.push_back(loadBundledImage("eclipse_ankh_indicator"));
@@ -182,6 +166,7 @@ void EclipseEngine::loadAssetsCPCDemo() {
loadColorPalette();
swapPalette(1);
loadHeartFramesCPC(&file, 0x0D17, 0x0D49);
+ updateHeartFramesCPC();
// This patch forces a solid color to the bottom of the chest in the area 5
// It was transparent in the original game
@@ -195,6 +180,40 @@ void EclipseEngine::loadAssetsCPCDemo() {
it->convertToInPlace(_gfx->_texturePixelFormat);
}
+void EclipseEngine::updateHeartFramesCPC() {
+ if (_heartFramesCPCIndexed.empty())
+ return;
+
+ uint8 r, g, b;
+ byte palette[4 * 3];
+ for (int c = 0; c < 4; c++) {
+ _gfx->selectColorFromFourColorPalette(c, r, g, b);
+ palette[c * 3 + 0] = r;
+ palette[c * 3 + 1] = g;
+ palette[c * 3 + 2] = b;
+ }
+
+ for (auto &sprite : _eclipseSprites) {
+ sprite->free();
+ delete sprite;
+ }
+ _eclipseSprites.clear();
+
+ for (uint i = 0; i < _heartFramesCPCIndexed.size(); i++) {
+ Graphics::ManagedSurface clut8;
+ clut8.copyFrom(*_heartFramesCPCIndexed[i]);
+ clut8.setPalette(palette, 0, 4);
+
+ Graphics::Surface *converted = _gfx->convertImageFormatIfNecessary(&clut8);
+ auto *surf = new Graphics::ManagedSurface();
+ surf->copyFrom(*converted);
+ converted->free();
+ delete converted;
+
+ _eclipseSprites.push_back(surf);
+ }
+}
+
void EclipseEngine::drawCPCUI(Graphics::Surface *surface) {
uint32 color = _currentArea->_underFireBackgroundColor;
uint8 r, g, b;
@@ -256,14 +275,14 @@ void EclipseEngine::drawCPCUI(Graphics::Surface *surface) {
if (energy < 0)
energy = 0;
- _gfx->readFromPalette(19, r, g, b);
- uint32 blue = _gfx->_texturePixelFormat.ARGBToColor(0xFF, r, g, b);
+ _gfx->readFromPalette(_currentArea->_paperColor, r, g, b);
+ uint32 waterColor = _gfx->_texturePixelFormat.ARGBToColor(0xFF, r, g, b);
Common::Rect jarBackground(124, 165, 148, 192);
surface->fillRect(jarBackground, back);
Common::Rect jarWater(124, 192 - energy, 148, 192);
- surface->fillRect(jarWater, blue);
+ surface->fillRect(jarWater, waterColor);
drawHeartIndicator(surface, 176, 168);
diff --git a/engines/freescape/games/eclipse/eclipse.cpp b/engines/freescape/games/eclipse/eclipse.cpp
index feba68ffb94..97b417cb188 100644
--- a/engines/freescape/games/eclipse/eclipse.cpp
+++ b/engines/freescape/games/eclipse/eclipse.cpp
@@ -372,6 +372,8 @@ void EclipseEngine::gotoArea(uint16 areaID, int entranceID) {
_gfx->_keyColor = 0;
swapPalette(areaID);
+ if (isCPC())
+ updateHeartFramesCPC();
if (isAmiga() || isAtariST())
_currentArea->_skyColor = 15;
diff --git a/engines/freescape/games/eclipse/eclipse.h b/engines/freescape/games/eclipse/eclipse.h
index 88eadf1862d..508bd07d7db 100644
--- a/engines/freescape/games/eclipse/eclipse.h
+++ b/engines/freescape/games/eclipse/eclipse.h
@@ -107,6 +107,10 @@ public:
void loadHeartFramesDOS(Common::SeekableReadStream *file, int restOffset, int beatOffset);
void drawHeartIndicator(Graphics::Surface *surface, int x, int y);
+ // CPC heart frames stored as indexed (CLUT8) for per-area re-paletting
+ Common::Array<Graphics::ManagedSurface *> _heartFramesCPCIndexed;
+ void updateHeartFramesCPC();
+
Common::Array<byte> _musicData; // TEMUSIC.ST TEXT segment (Atari ST)
Common::Array<byte> _c64MusicData;
EclipseC64MusicPlayer *_playerC64Music;
More information about the Scummvm-git-logs
mailing list