[Scummvm-git-logs] scummvm master -> 0befed2f78418f3d30d171d00cabd9ba3b3f656f
neuromancer
noreply at scummvm.org
Fri Jun 5 11:24:56 UTC 2026
This automated email contains information about 7 new commits which have been
pushed to the 'scummvm' repo located at https://api.github.com/repos/scummvm/scummvm .
Summary:
4031c5786f COLONY: mouse is less sensitive when turning
efe59024d9 COLONY: do not crash when calling glDepthRangef in desktop
a731f96b70 COLONY: added missing sounds
e3981b3175 COLONY: refined mac b&w interface and refactored some related code
9b0fb92042 COLONY: fixed xor mode in shader rendering
d541fc5d0e COLONY: complete rendering of mountain parallax
0befed2f78 COLONY: make sure the battle coordinates are normalized before starting
Commit: 4031c5786f456add3413cc8071ed1fc9ac6ce718
https://github.com/scummvm/scummvm/commit/4031c5786f456add3413cc8071ed1fc9ac6ce718
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2026-06-05T13:24:41+02:00
Commit Message:
COLONY: mouse is less sensitive when turning
Changed paths:
engines/colony/colony.cpp
engines/colony/colony.h
diff --git a/engines/colony/colony.cpp b/engines/colony/colony.cpp
index 2b736f884ab..3748d3d8dda 100644
--- a/engines/colony/colony.cpp
+++ b/engines/colony/colony.cpp
@@ -53,6 +53,9 @@ namespace Colony {
namespace {
+const float kMouseLookSensitivity = 0.25f;
+const float kKeyboardTurnSpeed = 30.0f; // angle units per second
+
class OwnedCursor final : public Graphics::Cursor {
public:
OwnedCursor(uint16 width, uint16 height, uint16 hotspotX, uint16 hotspotY, byte keyColor,
@@ -139,7 +142,7 @@ ColonyEngine::ColonyEngine(OSystem *syst, const ADGameDescription *gd) : Engine(
_height = 350;
_centerX = _width / 2;
_centerY = _height / 2;
- _mouseSensitivity = 1;
+ _mouseSensitivity = kMouseLookSensitivity;
_mouseLocked = false;
_mousePos = Common::Point(_centerX, _centerY);
_showDashBoard = true;
@@ -841,6 +844,7 @@ Common::Error ColonyEngine::run() {
updateMouseCapture(true);
int mouseDX = 0, mouseDY = 0;
+ float mouseLookAccumX = 0.0f, mouseLookAccumY = 0.0f;
bool mouseMoved = false;
uint32 lastMoveTick = _system->getMillis();
uint32 lastColonyTick = lastMoveTick;
@@ -930,6 +934,7 @@ Common::Error ColonyEngine::run() {
updateMouseCapture(true);
if (_mouseLocked) {
mouseDX = mouseDY = 0;
+ mouseLookAccumX = mouseLookAccumY = 0.0f;
mouseMoved = false;
}
}
@@ -995,6 +1000,7 @@ Common::Error ColonyEngine::run() {
updateMouseCapture(true);
if (_mouseLocked) {
mouseDX = mouseDY = 0;
+ mouseLookAccumX = mouseLookAccumY = 0.0f;
mouseMoved = false;
}
}
@@ -1009,6 +1015,9 @@ Common::Error ColonyEngine::run() {
openMainMenuDialog();
_gfx->computeScreenViewport();
updateMouseCapture(true);
+ mouseDX = mouseDY = 0;
+ mouseLookAccumX = mouseLookAccumY = 0.0f;
+ mouseMoved = false;
break;
default:
break;
@@ -1073,13 +1082,27 @@ Common::Error ColonyEngine::run() {
if (mouseMoved && _mouseLocked) {
if (mouseDX != 0) {
- _me.look = (uint8)((int)_me.look - (mouseDX * _mouseSensitivity));
- // In battle mode, body always faces look direction
- if (_gameMode == kModeBattle)
- _me.ang = _me.look;
+ mouseLookAccumX -= mouseDX * _mouseSensitivity;
+ const int lookDelta = (int)mouseLookAccumX;
+ if (lookDelta != 0) {
+ mouseLookAccumX -= lookDelta;
+ _me.look = (uint8)((int)_me.look + lookDelta);
+ // In battle mode, body always faces look direction
+ if (_gameMode == kModeBattle)
+ _me.ang = _me.look;
+ }
}
- if (mouseDY != 0 && !_fl) {
- _me.lookY = (int8)CLIP<int>((int)_me.lookY - (mouseDY * _mouseSensitivity), -64, 64);
+ if (mouseDY != 0) {
+ if (!_fl) {
+ mouseLookAccumY -= mouseDY * _mouseSensitivity;
+ const int lookYDelta = (int)mouseLookAccumY;
+ if (lookYDelta != 0) {
+ mouseLookAccumY -= lookYDelta;
+ _me.lookY = (int8)CLIP<int>((int)_me.lookY + lookYDelta, -64, 64);
+ }
+ } else {
+ mouseLookAccumY = 0.0f;
+ }
}
// Warp back to center and purge remaining mouse events
// to prevent the warp from generating phantom deltas (Freescape pattern)
@@ -1145,7 +1168,7 @@ Common::Error ColonyEngine::run() {
}
if (_rotateLeft || _rotateRight) {
- const float rotSpeed = (float)(1 << (_speedShift - 1)) * 15.0f;
+ const float rotSpeed = kKeyboardTurnSpeed;
_rotAccum += (_rotateLeft ? rotSpeed : -rotSpeed) * dt;
const int rint = (int)_rotAccum;
_rotAccum -= rint;
diff --git a/engines/colony/colony.h b/engines/colony/colony.h
index 5e41698308a..c933b6ec992 100644
--- a/engines/colony/colony.h
+++ b/engines/colony/colony.h
@@ -507,7 +507,7 @@ private:
int _cost[256];
int _centerX, _centerY;
int _width, _height;
- int _mouseSensitivity;
+ float _mouseSensitivity;
bool _mouseLocked;
bool _soundOn = true;
bool _showDashBoard;
Commit: efe59024d91aa031c0d1369530498dc86e03a968
https://github.com/scummvm/scummvm/commit/efe59024d91aa031c0d1369530498dc86e03a968
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2026-06-05T13:24:41+02:00
Commit Message:
COLONY: do not crash when calling glDepthRangef in desktop
Changed paths:
engines/colony/renderer_opengl_shaders.cpp
diff --git a/engines/colony/renderer_opengl_shaders.cpp b/engines/colony/renderer_opengl_shaders.cpp
index eab77613daa..0639d28f5da 100644
--- a/engines/colony/renderer_opengl_shaders.cpp
+++ b/engines/colony/renderer_opengl_shaders.cpp
@@ -106,6 +106,7 @@ private:
void applyLineWidth(GLenum mode);
void uploadSolid3D(const float *positions, int vertCount);
+ void setGLDepthRange(float nearVal, float farVal);
// allowStipple=true on the fill pass picks up _stippleActive; lines
// must always render unstippled (matches the fixed-function path,
// which only stipples GL_QUADS / GL_POLYGON, never lines).
@@ -692,8 +693,18 @@ void OpenGLShaderRenderer::setDepthState(bool testEnabled, bool writeEnabled) {
glDepthMask(writeEnabled ? GL_TRUE : GL_FALSE);
}
-void OpenGLShaderRenderer::setDepthRange(float nearVal, float farVal) {
+void OpenGLShaderRenderer::setGLDepthRange(float nearVal, float farVal) {
+#if USE_FORCED_GLES || USE_FORCED_GLES2
glDepthRangef(nearVal, farVal);
+#else
+ // glDepthRangef is only core in desktop OpenGL 4.1+. The double-precision
+ // entry point is core since OpenGL 1.0, so use it for desktop GL contexts.
+ glDepthRange(nearVal, farVal);
+#endif
+}
+
+void OpenGLShaderRenderer::setDepthRange(float nearVal, float farVal) {
+ setGLDepthRange(nearVal, farVal);
}
void OpenGLShaderRenderer::begin3D(int camX, int camY, int camZ, int angle, int angleY,
@@ -767,7 +778,7 @@ void OpenGLShaderRenderer::begin3D(int camX, int camY, int camZ, int angle, int
void OpenGLShaderRenderer::end3D() {
glDisable(GL_DEPTH_TEST);
glDepthMask(GL_TRUE);
- glDepthRangef(0.0f, 1.0f);
+ setGLDepthRange(0.0f, 1.0f);
glDisable(GL_SCISSOR_TEST);
// Restore the 2D viewport so subsequent overlay draws (dashboard, menu,
Commit: a731f96b706d0dd933c9d0d811ce86bd858294b5
https://github.com/scummvm/scummvm/commit/a731f96b706d0dd933c9d0d811ce86bd858294b5
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2026-06-05T13:24:41+02:00
Commit Message:
COLONY: added missing sounds
Changed paths:
engines/colony/animation.cpp
engines/colony/colony.cpp
engines/colony/colony.h
engines/colony/movement.cpp
diff --git a/engines/colony/animation.cpp b/engines/colony/animation.cpp
index 43efac8971c..180ae0df359 100644
--- a/engines/colony/animation.cpp
+++ b/engines/colony/animation.cpp
@@ -657,10 +657,9 @@ void ColonyEngine::playAnimation() {
_system->getEventManager()->purgeMouseEvents();
_system->getEventManager()->purgeKeyboardEvents();
- // Suppress collision sound on the first few wall hits after animation exit.
+ // Suppress collision sound on the first wall hit after animation exit.
// The player is at a door/wall boundary and held movement keys will
- // immediately trigger checkwall collisions that play kBang â which sounds
- // like a spurious gunshot. The flag auto-clears on the first successful move.
+ // immediately trigger a collision sound. The flag auto-clears in cCommand().
_suppressCollisionSound = true;
deleteAnimation();
@@ -1254,6 +1253,9 @@ void ColonyEngine::handleTeleshowClick(int item) {
}
void ColonyEngine::handleKeypadClick(int item) {
+ if (item > 0 && item <= 12)
+ _sound->play(Sound::kDit);
+
if (item >= 1 && item <= 10) {
for (int i = 5; i >= 1; i--)
_animDisplay[i] = _animDisplay[i - 1];
diff --git a/engines/colony/colony.cpp b/engines/colony/colony.cpp
index 3748d3d8dda..c6b5c121211 100644
--- a/engines/colony/colony.cpp
+++ b/engines/colony/colony.cpp
@@ -690,6 +690,7 @@ void ColonyEngine::startNewGame() {
_orbit = 0;
_allGrow = false;
_suppressCollisionSound = false;
+ _lastCollisionSoundTime = 0;
_action0 = 0;
_action1 = 0;
_creature = 0;
@@ -977,14 +978,17 @@ Common::Error ColonyEngine::run() {
_me.lookY = 0;
break;
case kActionToggleDashboard:
+ _sound->play(Sound::kDit);
_showDashBoard = !_showDashBoard;
break;
case kActionToggleWireframe:
+ _sound->play(Sound::kDit);
_wireframe = !_wireframe;
debugC(1, kColonyDebugRender, "Polyfill: %s", _wireframe ? "off (wireframe)" : "on (filled)");
break;
case kActionToggleFullscreen:
if (_macMenu) {
+ _sound->play(Sound::kDit);
_fullscreen = !_fullscreen;
_menuBarHeight = _fullscreen ? 0 : 20;
updateViewportLayout();
diff --git a/engines/colony/colony.h b/engines/colony/colony.h
index c933b6ec992..84a8d14ad0e 100644
--- a/engines/colony/colony.h
+++ b/engines/colony/colony.h
@@ -558,6 +558,7 @@ private:
uint32 _lastHotfootTime = 0; // Time-gate for HOTFOOT damage (~8fps)
uint32 _lastAnimUpdate = 0;
uint32 _lastWarningChimeTime = 0;
+ uint32 _lastCollisionSoundTime = 0;
int _action0 = 0, _action1 = 0;
int _creature = 0;
bool _allGrow = false;
@@ -815,6 +816,7 @@ private:
Common::Rect readRect(Common::SeekableReadStreamEndian &file);
int whichSprite(const Common::Point &p);
void handleAnimationClick(int item);
+ void playCollisionSound();
void handleDeskClick(int item);
void handleVanityClick(int item);
void handleSlidesClick(int item);
diff --git a/engines/colony/movement.cpp b/engines/colony/movement.cpp
index 9e7cfcbd87f..84c40706357 100644
--- a/engines/colony/movement.cpp
+++ b/engines/colony/movement.cpp
@@ -411,8 +411,6 @@ int ColonyEngine::checkwall(int xnew, int ynew, Locate *pobject) {
return r;
}
debugC(1, kColonyDebugMove, "Collision South at x=%d y=%d", pobject->xindex, yind2);
- if (!_suppressCollisionSound)
- _sound->play(Sound::kBang);
return -1;
}
@@ -427,8 +425,6 @@ int ColonyEngine::checkwall(int xnew, int ynew, Locate *pobject) {
return r;
}
debugC(1, kColonyDebugMove, "Collision North at x=%d y=%d", pobject->xindex, pobject->yindex);
- if (!_suppressCollisionSound)
- _sound->play(Sound::kBang);
return -1;
}
@@ -445,8 +441,6 @@ int ColonyEngine::checkwall(int xnew, int ynew, Locate *pobject) {
return r;
}
debugC(1, kColonyDebugMove, "Collision East at x=%d y=%d", xind2, pobject->yindex);
- if (!_suppressCollisionSound)
- _sound->play(Sound::kBang);
return -1;
}
@@ -461,8 +455,6 @@ int ColonyEngine::checkwall(int xnew, int ynew, Locate *pobject) {
return r;
}
debugC(1, kColonyDebugMove, "Collision West at x=%d y=%d", pobject->xindex, pobject->yindex);
- if (!_suppressCollisionSound)
- _sound->play(Sound::kBang);
return -1;
}
@@ -1128,13 +1120,33 @@ void ColonyEngine::checkCenter() {
}
}
+void ColonyEngine::playCollisionSound() {
+ if (_suppressCollisionSound)
+ return;
+
+ const uint32 now = _system->getMillis();
+ if (_lastCollisionSoundTime != 0 && now - _lastCollisionSoundTime < 175)
+ return;
+
+ _lastCollisionSoundTime = now;
+ _sound->play(Sound::kBonk);
+}
+
void ColonyEngine::cCommand(int xnew, int ynew, bool allowInteraction) {
if (_me.xindex >= 0 && _me.xindex < 32 && _me.yindex >= 0 && _me.yindex < 32)
_robotArray[_me.xindex][_me.yindex] = 0;
+ const int oldXIndex = _me.xindex;
+ const int oldYIndex = _me.yindex;
+ const bool sameCellAttempt = ((xnew >> 8) == oldXIndex && (ynew >> 8) == oldYIndex);
const int robot = checkwall(xnew, ynew, &_me);
if (robot > 0 && allowInteraction)
interactWithObject(robot);
+ else if (robot)
+ playCollisionSound();
+ else if (sameCellAttempt && _me.xindex == oldXIndex && _me.yindex == oldYIndex &&
+ (_me.xloc != xnew || _me.yloc != ynew))
+ playCollisionSound();
if (_me.xindex >= 0 && _me.xindex < 32 && _me.yindex >= 0 && _me.yindex < 32)
_robotArray[_me.xindex][_me.yindex] = kMeNum;
Commit: e3981b3175121858b0b3fdac1ae674ae61eb9dd8
https://github.com/scummvm/scummvm/commit/e3981b3175121858b0b3fdac1ae674ae61eb9dd8
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2026-06-05T13:24:41+02:00
Commit Message:
COLONY: refined mac b&w interface and refactored some related code
Changed paths:
engines/colony/animation.cpp
engines/colony/colony.cpp
engines/colony/colony.h
engines/colony/interaction.cpp
engines/colony/intro.cpp
engines/colony/movement.cpp
engines/colony/render.cpp
engines/colony/render_features.cpp
engines/colony/render_objects.cpp
engines/colony/ui.cpp
diff --git a/engines/colony/animation.cpp b/engines/colony/animation.cpp
index 180ae0df359..e04f5c6629b 100644
--- a/engines/colony/animation.cpp
+++ b/engines/colony/animation.cpp
@@ -398,7 +398,7 @@ void ColonyEngine::playAnimation() {
_system->lockMouse(false);
warpMouseLogical(_centerX, _centerY);
const char *cursorName = "default arrow cursor";
- if (_renderMode == Common::kRenderMacintosh && _macArrowCursor) {
+ if (isMacRenderMode() && _macArrowCursor) {
cursorName = "Mac arrow cursor";
CursorMan.replaceCursor(_macArrowCursor);
} else {
@@ -713,7 +713,7 @@ void ColonyEngine::drawAnimation() {
ox = (ox / 8) * 8;
int oy = _screenR.top + (_screenR.height() - 264) / 2;
- const bool useColor = (_hasMacColors && _renderMode == Common::kRenderMacintosh
+ const bool useColor = (isMacColorMode()
&& !_animBMColors.empty());
// Fill background patterns (416x264 area).
@@ -728,7 +728,7 @@ void ColonyEngine::drawAnimation() {
// did 416*264 = 109,824 individual setPixel calls per drawAnimation, each
// issuing its own glBegin/glEnd; on the OpenGL backend that took tens of
// milliseconds per frame and starved the cursor of refreshes.
- const int patternMode = useColor ? 2 : (_renderMode == Common::kRenderMacintosh ? 1 : 0);
+ const int patternMode = useColor ? 2 : (isMacRenderMode() ? 1 : 0);
uint32 topColor = 0, botColor = 0;
if (useColor) {
const bool powered = (_corePower[_coreIndex] > 0);
@@ -833,7 +833,7 @@ void ColonyEngine::drawComplexSprite(int index, int ox, int oy) {
// Resolve fill color from BMColor[index+2] (ganimate.c DrawlSprite).
uint32 fillColor = 0xFFFFFFFF; // B&W default: white
- const bool useColor = (_hasMacColors && _renderMode == Common::kRenderMacintosh
+ const bool useColor = (isMacColorMode()
&& !_animBMColors.empty());
if (useColor) {
int bmIdx = index + 2;
@@ -857,8 +857,8 @@ void ColonyEngine::drawAnimationImage(Image *img, Image *mask, int x, int y, uin
// fg bit=0 -> BackColor (fillColor from BMColor)
// Mac B&W: same â fg bit=1 is black (0), fg bit=0 is white (15).
// DOS MetaWINDOW: OPPOSITE â fg bit=1 is white (15), fg bit=0 is black (0).
- const bool useColor = (_hasMacColors && _renderMode == Common::kRenderMacintosh);
- const bool isMacMode = (_renderMode == Common::kRenderMacintosh);
+ const bool useColor = isMacColorMode();
+ const bool isMacMode = isMacRenderMode();
// Pixels written into the alpha-keyed RGBA cache. mask=0 â alpha 0
// (transparent), so drawSurface's alpha-blend skips them naturally.
diff --git a/engines/colony/colony.cpp b/engines/colony/colony.cpp
index c6b5c121211..abdeed7de21 100644
--- a/engines/colony/colony.cpp
+++ b/engines/colony/colony.cpp
@@ -166,7 +166,7 @@ ColonyEngine::ColonyEngine(OSystem *syst, const ADGameDescription *gd) : Engine(
_renderMode = Common::kRenderEGA;
}
- _wireframe = (_renderMode != Common::kRenderMacintosh);
+ _wireframe = !isMacRenderMode();
_fullscreen = false;
_speedShift = 2; // DOS default: speedshift=1, but 2 feels better with our frame rate
_moveForward = false;
@@ -487,7 +487,7 @@ void ColonyEngine::updateMouseCapture(bool recenter) {
int cursorMode = 0;
- if (!_mouseLocked && _renderMode == Common::kRenderMacintosh && _wm) {
+ if (!_mouseLocked && isMacRenderMode() && _wm) {
if (_macCrossCursor) {
cursorMode = 1;
_wm->replaceCursor(Graphics::kMacCursorCustom, _macCrossCursor);
@@ -585,7 +585,7 @@ void ColonyEngine::handleMenuAction(int action) {
}
void ColonyEngine::initMacMenus() {
- if (_renderMode != Common::kRenderMacintosh) {
+ if (!isMacRenderMode()) {
_menuBarHeight = 0;
return;
}
@@ -775,7 +775,7 @@ Common::Error ColonyEngine::run() {
// Original Mac Colony: rScreen capped at 640x480 (inits.c lines 111-112).
// DOS EGA: 640x350 with non-square pixels displayed at 4:3.
// Mac uses square pixels at native 640x480.
- if (_renderMode == Common::kRenderMacintosh) {
+ if (isMacRenderMode()) {
_width = 640;
_height = 480;
} else {
@@ -791,6 +791,7 @@ Common::Error ColonyEngine::run() {
if (!_gfx)
return Common::kUserCanceled;
+ loadMacColors();
updateViewportLayout();
const Graphics::PixelFormat format = _system->getScreenFormat();
debugC(1, kColonyDebugRender, "Screen format: %d bytesPerPixel. Actual size: %dx%d", format.bytesPerPixel, _width, _height);
@@ -814,8 +815,7 @@ Common::Error ColonyEngine::run() {
pal[i * 3 + 2] = i;
}
- loadMacColors();
- if (_hasMacColors) {
+ if (isMacColorMode()) {
for (int i = 0; i < 145; i++) {
pal[(100 + i) * 3 + 0] = _macColors[i].fg[0] >> 8;
pal[(100 + i) * 3 + 1] = _macColors[i].fg[1] >> 8;
diff --git a/engines/colony/colony.h b/engines/colony/colony.h
index 84a8d14ad0e..b4be8d94fb9 100644
--- a/engines/colony/colony.h
+++ b/engines/colony/colony.h
@@ -451,6 +451,8 @@ public:
Common::Platform getPlatform() const { return _gameDescription->platform; }
bool isSoundEnabled() const { return _soundOn; }
const Graphics::Surface *getSavedScreen() const { return _savedScreen; }
+ bool isMacRenderMode() const { return _renderMode == Common::kRenderMacintosh || _renderMode == Common::kRenderMacintoshBW; }
+ bool isMacColorMode() const { return _renderMode == Common::kRenderMacintosh && _hasMacColors; }
void initTrig();
void loadMacColors();
diff --git a/engines/colony/interaction.cpp b/engines/colony/interaction.cpp
index ca543bca7e0..3f791c564d4 100644
--- a/engines/colony/interaction.cpp
+++ b/engines/colony/interaction.cpp
@@ -475,7 +475,7 @@ void ColonyEngine::destroyRobot(int num) {
// bottom-left and bottom-right corners of the viewport converging at the aim
// point, plus a small filled oval at center. Simulates a rifle-barrel perspective.
void ColonyEngine::doShootCircles(int cx, int cy) {
- const bool isMac = (_renderMode == Common::kRenderMacintosh);
+ const bool isMac = isMacRenderMode();
if (isMac) {
// Mac shoot.c CShoot(): patXor diagonal lines radiating from aim point
@@ -541,7 +541,7 @@ void ColonyEngine::doShootCircles(int cx, int cy) {
// SHOOT.C doBurnHole(): expanding concentric random rays in blue/yellow/white
// when a robot is hit. Creates an "explosion" effect at the hit location.
void ColonyEngine::doBurnHole(int cx, int cy, int radius) {
- const bool isMac = (_renderMode == Common::kRenderMacintosh);
+ const bool isMac = isMacRenderMode();
if (isMac) {
// Mac: InvertOval at robot bounds
@@ -605,7 +605,7 @@ void ColonyEngine::meGetShot() {
if (vw <= 0 || vh <= 0)
return;
- const bool isMac = (_renderMode == Common::kRenderMacintosh);
+ const bool isMac = isMacRenderMode();
if (isMac) {
// Mac shoot.c: InvertRect(&Clip) â full viewport flash
diff --git a/engines/colony/intro.cpp b/engines/colony/intro.cpp
index 78a93b8b985..e345cf30a5f 100644
--- a/engines/colony/intro.cpp
+++ b/engines/colony/intro.cpp
@@ -140,7 +140,7 @@ public:
};
int ColonyEngine::runMacEndgameDialog(const Common::String &message) {
- if (_renderMode != Common::kRenderMacintosh || !_wm || !_menuSurface || !_gfx)
+ if (!isMacRenderMode() || !_wm || !_menuSurface || !_gfx)
return Graphics::kMacDialogQuitRequested;
if (_macMenu && _wm->isMenuActive())
@@ -502,7 +502,7 @@ bool ColonyEngine::scrollInfo(const Graphics::Font *macFont) {
// Set up gradient palette entries (200-213) for story text
// Mac original: tColor.blue starts at 0xFFFF and decreases by 4096 per visible line
// B&W Mac: white gradient instead of blue
- const bool bwMac = (macFont && !_hasMacColors);
+ const bool bwMac = (macFont && !isMacColorMode());
byte pal[14 * 3]; // storyLength entries
memset(pal, 0, sizeof(pal));
for (int i = 0; i < storyLength; i++) {
@@ -968,7 +968,7 @@ bool ColonyEngine::timeSquare(const Common::String &str, const Graphics::Font *m
int centery = _height / 2 - 10;
- const bool bwMac = (macFont && !_hasMacColors);
+ const bool bwMac = (macFont && !isMacColorMode());
const bool macStyle = (macFont != nullptr);
const uint32 grayIndex = 160;
const uint32 textIndex = 176;
@@ -1214,7 +1214,7 @@ void ColonyEngine::terminateGame(bool blowup) {
_centerX = savedCenterX;
_centerY = savedCenterY;
- if (_renderMode == Common::kRenderMacintosh) {
+ if (isMacRenderMode()) {
while (!shouldQuit()) {
switch (runMacEndgameDialog(_("You have been terminated."))) {
case 0:
diff --git a/engines/colony/movement.cpp b/engines/colony/movement.cpp
index 84c40706357..08649bf0b99 100644
--- a/engines/colony/movement.cpp
+++ b/engines/colony/movement.cpp
@@ -786,7 +786,7 @@ int ColonyEngine::tryPassThroughFeature(int fromX, int fromY, int direction, Loc
void ColonyEngine::playTunnelAirlockEffect() {
const Common::Rect effectRect(0, _menuBarHeight, _width, _height);
- const bool macColor = (_renderMode == Common::kRenderMacintosh && _hasMacColors);
+ const bool macColor = isMacColorMode();
const int tunnelColor = 24; // c_tunnel
const uint32 fillFg = macColor ? packMacColor(_macColors[tunnelColor].fg) : 0;
const uint32 fillBg = macColor ? packMacColor(_macColors[tunnelColor].bg) : 0;
@@ -883,7 +883,7 @@ void ColonyEngine::playTunnelEffect(bool falling) {
// Original TUNNEL.C: falling into the reactor reuses the tunnel renderer
// with the falling flag set, which removes the tracks and shortens the run.
const Common::Rect effectRect(0, _menuBarHeight, _width, _height);
- const bool macColor = (_renderMode == Common::kRenderMacintosh && _hasMacColors);
+ const bool macColor = isMacColorMode();
const int tunnelColor = 24; // c_tunnel
const int tunnelFrames = falling ? 10 : 49;
const uint32 fillFg = macColor ? packMacColor(_macColors[tunnelColor].fg) : 0;
diff --git a/engines/colony/render.cpp b/engines/colony/render.cpp
index d40a6de5edf..32cf7e59df8 100644
--- a/engines/colony/render.cpp
+++ b/engines/colony/render.cpp
@@ -522,7 +522,7 @@ void ColonyEngine::draw3DPrism(Thing &obj, const PrismPartDef &def, bool useLook
continue;
}
- if (_renderMode == Common::kRenderMacintosh && _hasMacColors) {
+ if (isMacColorMode()) {
// Mac color rendering: follows SuperPoly() from calcrobo.c:429-505.
int pattern;
uint32 fg;
@@ -574,7 +574,7 @@ void ColonyEngine::draw3DPrism(Thing &obj, const PrismPartDef &def, bool useLook
_gfx->setStippleData(nullptr);
}
} else if (lit) {
- if (_renderMode == Common::kRenderMacintosh) {
+ if (isMacRenderMode()) {
// Mac B&W: stipple dither pattern fill + black outline
int pattern;
if (colorIdx == kColorCorridorWall) {
@@ -632,10 +632,10 @@ void ColonyEngine::draw3DLeaf(const Thing &obj, const PrismPartDef &def) {
const bool lit = (_corePower[_coreIndex] > 0);
// Mac color: c_plant bg; Mac B&W: black; EGA: green; unlit: white/black
uint32 color;
- if (_renderMode == Common::kRenderMacintosh && _hasMacColors) {
+ if (isMacColorMode()) {
color = lit ? packMacColor(_macColors[63].bg) : 0xFF000000; // c_plant
} else {
- color = lit ? (_renderMode == Common::kRenderMacintosh ? 0 : 2) : 15;
+ color = lit ? (isMacRenderMode() ? 0 : 2) : 15;
}
for (int i = 0; i < def.surfaceCount; i++) {
@@ -740,7 +740,7 @@ void ColonyEngine::draw3DSphere(Thing &obj, int pt0x, int pt0y, int pt0z,
}
}
- if (_renderMode == Common::kRenderMacintosh && _hasMacColors) {
+ if (isMacColorMode()) {
// Mac color: map fillColor to Mac color index and use RGB
// fillColor is an ObjColor enum value passed by the caller
const int fillIdx = mapObjColorToMacColor((int)fillColor, _level);
@@ -760,7 +760,7 @@ void ColonyEngine::draw3DSphere(Thing &obj, int pt0x, int pt0y, int pt0z,
if (stipple)
_gfx->setStippleData(nullptr);
} else if (lit) {
- if (_renderMode == Common::kRenderMacintosh) {
+ if (isMacRenderMode()) {
int pattern = lookupMacPattern((int)fillColor, _level);
if (pattern == kPatternClear)
pattern = kPatternGray;
@@ -872,11 +872,11 @@ void ColonyEngine::renderCorridor3D() {
computeVisibleCells();
bool lit = (_corePower[_coreIndex] > 0);
- bool macMode = (_renderMode == Common::kRenderMacintosh);
+ bool macMode = isMacRenderMode();
uint32 wallFill, wallLine, floorColor, ceilColor;
- if (macMode && _hasMacColors) {
+ if (isMacColorMode()) {
if (lit) {
// Mac Display(): wallColor = cColor[c_char0+level-1].f (level-specific color).
// SuperPoly(c_lwall) uses wallColor as fill, giving all walls the level tint.
@@ -928,7 +928,7 @@ void ColonyEngine::renderCorridor3D() {
// Mac color mode: original corridor renderer only showed ceiling edges at wall
// boundaries (via 2D perspective), not a full-map grid. Wall tops from draw3DWall
// already provide the ceiling lines where walls exist.
- if (!(macMode && _hasMacColors)) {
+ if (!isMacColorMode()) {
for (int i = 0; i <= 32; i++) {
float d = i * 256.0f;
float maxD = 32.0f * 256.0f;
diff --git a/engines/colony/render_features.cpp b/engines/colony/render_features.cpp
index 8534a898db8..ec211480f47 100644
--- a/engines/colony/render_features.cpp
+++ b/engines/colony/render_features.cpp
@@ -252,8 +252,8 @@ void ColonyEngine::wallChar(const float corners[4][3], uint8 cnum) {
if (!data || data[0] == 0)
return;
- const bool macMode = (_renderMode == Common::kRenderMacintosh);
- const bool macColors = (macMode && _hasMacColors);
+ const bool macMode = isMacRenderMode();
+ const bool macColors = isMacColorMode();
const uint32 fillColor = macColors ? packMacColor(_macColors[8 + _level - 1].bg) : 0;
const uint32 lineColor = macColors ? (uint32)0xFF000000 : 0;
@@ -354,7 +354,7 @@ void ColonyEngine::wallChar(const float corners[4][3], uint8 cnum) {
}
if (macMode) {
- const uint32 wallFill = _hasMacColors
+ const uint32 wallFill = macColors
? packMacColor(_macColors[8 + _level - 1].fg)
: (uint32)255;
_gfx->setWireframe(true, wallFill);
@@ -393,8 +393,8 @@ void ColonyEngine::drawCellFeature3D(int cellX, int cellY) {
bool lit = (_corePower[_coreIndex] > 0);
uint32 holeColor = lit ? 0 : 7;
- const bool macMode = (_renderMode == Common::kRenderMacintosh);
- const bool macColors = (macMode && _hasMacColors);
+ const bool macMode = isMacRenderMode();
+ const bool macColors = isMacColorMode();
// Helper lambda: draw a filled hole polygon with Mac color or B&W fallback
auto drawHolePoly = [&](const float *u, const float *v, int cnt, int macIdx) {
@@ -484,8 +484,8 @@ void ColonyEngine::drawWallFeature3D(int cellX, int cellY, int direction) {
float corners[4][3];
getWallFace3D(cellX, cellY, direction, corners);
- const bool macMode = (_renderMode == Common::kRenderMacintosh);
- const bool macColors = (_renderMode == Common::kRenderMacintosh && _hasMacColors);
+ const bool macMode = isMacRenderMode();
+ const bool macColors = isMacColorMode();
const bool lit = (_corePower[_coreIndex] > 0);
const uint32 wallFeatureFill = macColors
? packMacColor(lit ? _macColors[8 + _level - 1].fg : _macColors[6].bg)
@@ -653,7 +653,7 @@ void ColonyEngine::drawWallFeature3D(int cellX, int cellY, int direction) {
const uint32 col = macColors ? (uint32)0xFF000000 : 0; // vBLACK
// Mac: fill entire wall face (c_upstairs)
- if (_renderMode == Common::kRenderMacintosh) {
+ if (isMacRenderMode()) {
float uf[4] = {0.0f, 1.0f, 1.0f, 0.0f};
float vf2[4] = {0.0f, 0.0f, 1.0f, 1.0f};
if (macColors) {
@@ -726,7 +726,7 @@ void ColonyEngine::drawWallFeature3D(int cellX, int cellY, int direction) {
const uint32 col = macColors ? (uint32)0xFF000000 : 0; // vBLACK
// Mac: fill entire wall face (c_dnstairs)
- if (_renderMode == Common::kRenderMacintosh) {
+ if (isMacRenderMode()) {
float uf[4] = {0.0f, 1.0f, 1.0f, 0.0f};
float vf2[4] = {0.0f, 0.0f, 1.0f, 1.0f};
if (macColors) {
@@ -830,7 +830,7 @@ void ColonyEngine::drawWallFeature3D(int cellX, int cellY, int direction) {
// Tunnel: hexagonal opening from Grid (0,0 0,5 1,6 5,6 6,5 6,0)
const float uT[6] = { 0.0f, 0.0f, 1/6.0f, 5/6.0f, 1.0f, 1.0f };
const float vT[6] = { 0.0f, 0.750f, 0.875f, 0.875f, 0.750f, 0.0f };
- if (_renderMode == Common::kRenderMacintosh) {
+ if (isMacRenderMode()) {
if (macColors) {
macFillPoly(uT, vT, 6, 24); // c_tunnel
} else {
@@ -894,7 +894,7 @@ void ColonyEngine::drawWallFeature3D(int cellX, int cellY, int direction) {
// map[1..4] = pattern ID per band (0=WHITE, 1=LTGRAY, 2=GRAY, 3=DKGRAY, 4=BLACK).
// Values >= 5 trigger animation: color = (map[i+1] + _displayCount) % 5.
// Band 0 (top): v=0.75..1.0, Band 1: v=0.5..0.75, Band 2: v=0.25..0.5, Band 3: v=0..0.25.
- if (_renderMode == Common::kRenderMacintosh) {
+ if (isMacRenderMode()) {
if (macColors) {
// Mac drawColor: map[i+1] selects color (0âc_color0..3âc_color3, 4âBLACK).
// Values >= 5: animated = (map[i+1] + _displayCount) % 5.
diff --git a/engines/colony/render_objects.cpp b/engines/colony/render_objects.cpp
index a13f4076449..a93feac780c 100644
--- a/engines/colony/render_objects.cpp
+++ b/engines/colony/render_objects.cpp
@@ -1271,7 +1271,7 @@ void ColonyEngine::drawPrismOval3D(Thing &thing, const PrismPartDef &def, bool u
pz[i] = centerZ + ca * axisHZ + sa * axisVZ;
}
- if (_renderMode == Common::kRenderMacintosh && _hasMacColors) {
+ if (isMacColorMode()) {
const int macColorIdx = mapEyeOverlayColorToMacColor(fillColorIdx, _level);
int pattern = _macColors[macColorIdx].pattern;
uint32 fg = packEyeOverlayMacColor(_macColors[macColorIdx].fg);
@@ -1288,7 +1288,7 @@ void ColonyEngine::drawPrismOval3D(Thing &thing, const PrismPartDef &def, bool u
if (stipple)
_gfx->setStippleData(nullptr);
} else if (lit) {
- if (_renderMode == Common::kRenderMacintosh) {
+ if (isMacRenderMode()) {
int pattern = mapEyeOverlayColorToMacPattern(fillColorIdx);
if (pattern == kPatternClear)
return;
@@ -1375,13 +1375,13 @@ bool ColonyEngine::drawStaticObjectPrisms3D(Thing &obj) {
_gfx->setDepthRange(0.0f, 1.0f);
break;
case kObjFWall:
- if (_renderMode == Common::kRenderMacintosh)
+ if (isMacRenderMode())
draw3DPrism(obj, kFWallPart, false, kColorCorridorWall, true, true);
else
draw3DPrism(obj, kFWallPart, false, -1, true, true);
break;
case kObjCWall:
- if (_renderMode == Common::kRenderMacintosh)
+ if (isMacRenderMode())
draw3DPrism(obj, kCWallPart, false, kColorCorridorWall, true, true);
else
draw3DPrism(obj, kCWallPart, false, -1, true, true);
@@ -1715,7 +1715,7 @@ bool ColonyEngine::drawStaticObjectPrisms3D(Thing &obj) {
Thing &nearEye = leftFirst ? rightEye : leftEye;
const PrismPartDef &farWing = leftFirst ? kQLWingDef : kQRWingDef;
const PrismPartDef &nearWing = leftFirst ? kQRWingDef : kQLWingDef;
- const int wingColor = (_renderMode != Common::kRenderMacintosh && _level == 7) ? kColorQueenWingRed : kColorClear;
+ const int wingColor = (!isMacRenderMode() && _level == 7) ? kColorQueenWingRed : kColorClear;
// DOS draweyes(): queen eyeball is RED fill + WHITE outline
// (hardcoded, not from color table). Iris is GREEN.
diff --git a/engines/colony/ui.cpp b/engines/colony/ui.cpp
index e73ce82bc1c..5b0cf0516d2 100644
--- a/engines/colony/ui.cpp
+++ b/engines/colony/ui.cpp
@@ -161,18 +161,16 @@ bool drawMacTextPopup(Graphics::MacWindowManager *wm, Renderer *gfx,
return true;
}
-// Load a PICT resource from the Mac resource fork, returning a new RGB surface.
-// Try Color Colony first (has color dashboard PICTs), then fall back to B&W Colony.
+// Load a dashboard PICT resource from the Mac resource fork, returning a new
+// RGB surface. The companion Color Colony resource fork contains the complete
+// dashboard PICT set, so prefer it when available and fall back to the base app.
// Caller owns the returned surface. Returns nullptr on failure.
Graphics::Surface *ColonyEngine::loadPictSurface(int resID) {
Common::SeekableReadStream *pictStream = nullptr;
- // Try Color Colony resource fork first
- if (_colorResMan && _colorResMan->hasResFork()) {
+ if (_colorResMan && _colorResMan->hasResFork())
pictStream = _colorResMan->getResource(MKTAG('P', 'I', 'C', 'T'), (int16)resID);
- }
- // Fall back to B&W Colony resource fork
if (!pictStream && _resMan && (_resMan->isMacFile() || _resMan->hasResFork())) {
pictStream = _resMan->getResource(MKTAG('P', 'I', 'C', 'T'), (int16)resID);
}
@@ -235,8 +233,7 @@ Graphics::Surface *ColonyEngine::loadPictSurface(int resID) {
// Draw a PICT surface at a specific destination position. The surface was
// created by loadPictSurface() in the exact ARGB layout the renderer's
-// drawSurface() consumes, so this is a single textured-quad blit â no need
-// to walk pixels.
+// drawSurface() consumes, so this is a single textured-quad blit.
void ColonyEngine::drawPictAt(Graphics::Surface *surf, int destX, int destY) {
if (!surf)
return;
@@ -252,7 +249,7 @@ void ColonyEngine::updateViewportLayout() {
return Common::Rect(left, top, right, bottom);
};
- const bool isMac = (_renderMode == Common::kRenderMacintosh);
+ const bool isMac = isMacRenderMode();
// Original IBM_INIT.C: pix_per_Qinch = pixResX/4, pixResY/4
// MetaWINDOW EGA 640x350: pixResX=96, pixResY=72 â pQx=24, pQy=18
@@ -293,12 +290,35 @@ void ColonyEngine::updateViewportLayout() {
if (isMac) {
// Original Mac layout from inits.c/compass.c/power.c:
// screenR.left = 96 sidebar is 96px wide.
- // Two floating windows centered in sidebar over gray desktop.
+ // Two floating windows over gray desktop.
// moveWindow: compRect = (0,0, 2*CCENTER, 3*CCENTER) = (0,0, 70, 105)
// floorRect (minimap) = (8,8)-(62,62) 54x54 inside moveWindow
// compass dish below at (19,66)-(51,98), needle center at (35,82)
- // infoWindow: sized from PICT resource, positioned above moveWindow
+ // infoWindow: original WIND 10930 rect (9,26)-(79,189).
const int CCENTER = 35;
+ auto loadWindowRect = [this, &makeSafeRect](int resID, const Common::Rect &fallback) {
+ Common::SeekableReadStream *windStream = nullptr;
+ if (_resMan && (_resMan->isMacFile() || _resMan->hasResFork()))
+ windStream = _resMan->getResource(MKTAG('W', 'I', 'N', 'D'), (int16)resID);
+ if (!windStream && _colorResMan && _colorResMan->hasResFork())
+ windStream = _colorResMan->getResource(MKTAG('W', 'I', 'N', 'D'), (int16)resID);
+
+ if (!windStream)
+ return fallback;
+
+ Common::Rect r = fallback;
+ if (windStream->size() >= 8) {
+ const int top = windStream->readSint16BE();
+ const int left = windStream->readSint16BE();
+ const int bottom = windStream->readSint16BE();
+ const int right = windStream->readSint16BE();
+ r = makeSafeRect(left, top, right, bottom);
+ }
+ delete windStream;
+ return r;
+ };
+
+ const Common::Rect infoWindow = loadWindowRect(10930, Common::Rect(9, 26, 79, 189));
// Load PICT surfaces (cached after first load)
if (!_pictCompass)
@@ -312,23 +332,24 @@ void ColonyEngine::updateViewportLayout() {
if (_armor > 0)
wantID = -32755;
else
- wantID = _hasMacColors ? -32761 : -32752;
+ wantID = isMacColorMode() ? -32761 : -32752;
_pictPower = loadPictSurface(wantID);
if (!_pictPower && _armor > 0 && wantID != -32755)
_pictPower = loadPictSurface(-32755);
_pictPowerID = _pictPower ? wantID : 0;
}
- // moveWindow dimensions from original constants
+ // Keep the ScummVM dashboard's bottom moveWindow placement. The original
+ // Mac window resource is for a compact 512x342 desktop and should not
+ // move this panel upward on our larger Mac render surface.
const int moveW = 2 * CCENTER; // 70
const int moveH = 3 * CCENTER; // 105
- const int infoW = _pictPower ? _pictPower->w : moveW;
- const int infoH = _pictPower ? _pictPower->h : moveH;
+ const int infoW = infoWindow.width();
+ const int infoH = infoWindow.height();
- // Center panels horizontally in sidebar
const int centerX = dashWidth / 2;
- // Position moveWindow at the bottom of the sidebar
+ // Position moveWindow at the bottom of the sidebar.
const int moveLeft = MAX(0, centerX - moveW / 2);
const int moveTop = _height - pad - moveH;
@@ -340,11 +361,12 @@ void ColonyEngine::updateViewportLayout() {
// _compassRect = entire moveWindow (used for compass dish drawing)
_compassRect = makeSafeRect(moveLeft, moveTop, moveLeft + moveW, moveTop + moveH);
- // Position infoWindow below the Mac menu bar.
- // Original PICT is drawn at (-2,-2) in window-local coords, so offset
- // the panel by 2px to prevent the PICT from overlapping the menu bar.
- const int infoLeft = MAX(0, centerX - infoW / 2);
- const int infoTop = menuTop + pad;
+ int infoLeft = infoWindow.left;
+ int infoTop = infoWindow.top;
+ if (infoLeft + infoW > dashWidth)
+ infoLeft = MAX(0, dashWidth - infoW);
+ if (infoTop + infoH > _height)
+ infoTop = MAX(menuTop, _height - pad - infoH);
_powerRect = makeSafeRect(infoLeft, infoTop, infoLeft + infoW, infoTop + infoH);
} else {
// DASHBOAR.C RCompass(): compOval before shrink
@@ -428,7 +450,7 @@ void ColonyEngine::drawDashboardStep1() {
if (_dashBoardRect.width() <= 0 || _dashBoardRect.height() <= 0)
return;
- const bool isMac = (_renderMode == Common::kRenderMacintosh);
+ const bool isMac = isMacRenderMode();
if (isMac) {
drawDashboardMac();
@@ -521,7 +543,7 @@ void ColonyEngine::drawDashboardStep1() {
// Original Mac had two floating windows (infoWindow + moveWindow) over gray desktop.
void ColonyEngine::drawDashboardMac() {
- const bool macColor = _hasMacColors;
+ const bool macColor = isMacColorMode();
const uint32 colBlack = packRGB(0, 0, 0);
const uint32 colWhite = packRGB(255, 255, 255);
const uint32 colWinBg = macColor ? packMacColor(_macColors[7].bg) : colWhite;
@@ -580,27 +602,44 @@ void ColonyEngine::drawDashboardMac() {
// In the original B&W game, GetPicture(-32752) returns null when !armor,
// so DrawPicture is a no-op â the window just shows white fill.
if (_pictPower)
- drawPictAt(_pictPower, _powerRect.left - 2, _powerRect.top - 2);
+ drawPictAt(_pictPower, _powerRect.left + 1, _powerRect.top + 1);
+
+ if (!macColor) {
+ // Match the B&W Window Manager shadow as pixels. The shadow is
+ // staggered over the checkerboard desktop; a solid rect is too wide.
+ _gfx->fillRect(Common::Rect(_powerRect.right, _powerRect.top - 1,
+ _powerRect.right + 1, _powerRect.bottom + 3), colBlack);
+ _gfx->fillRect(Common::Rect(_powerRect.right + 1, _powerRect.top,
+ _powerRect.right + 2, _powerRect.bottom + 4), colBlack);
+ _gfx->fillRect(Common::Rect(_powerRect.right + 2, _powerRect.top - 1,
+ _powerRect.right + 3, _powerRect.top), colBlack);
+ _gfx->fillRect(Common::Rect(_powerRect.right + 2, _powerRect.top + 1,
+ _powerRect.right + 3, _powerRect.bottom + 3), colBlack);
+ _gfx->fillRect(Common::Rect(_powerRect.left - 2, _powerRect.bottom,
+ _powerRect.right + 3, _powerRect.bottom + 1), colBlack);
+ _gfx->fillRect(Common::Rect(_powerRect.left + 1, _powerRect.bottom + 1,
+ _powerRect.right + 4, _powerRect.bottom + 2), colBlack);
+ _gfx->fillRect(Common::Rect(_powerRect.left, _powerRect.bottom + 2,
+ _powerRect.right + 3, _powerRect.bottom + 3), colBlack);
+ }
// Blue bars only when armored (power.c: if(armor) { ... ForeColor(blueColor) ... })
if (_armor > 0 && _pictPower) {
- // power.c info rect adjustments: left+=3,right+=3,top-=3,bottom-=3, then ++/--
- // Net effect: info is adjusted relative to PICT position
- const int infoLeft = _powerRect.left - 2 + 2; // -2 (PICT offset) +3-1 = 0, +2 net
- const int infoBottom = _powerRect.top - 2 + _pictPower->h - 2; // PICT bottom adjusted
- const int bot = infoBottom - 27; // power.c: bot = info.bottom - 27
+ // power.c draws the bars with QuickDraw MoveTo/LineTo after shifting
+ // the PICT rect. GL line rasterization does not cover the same pixels,
+ // so draw the observed 18x2 bar strips explicitly.
+ const int infoLeft = _powerRect.left - 1;
+ const int bot = _powerRect.bottom - 27; // power.c: bot = info.bottom - 27
for (int i = 0; i < 3; i++) {
- // power.c: lft = 3 + info.left + i*23
+ // Reference B&W frame: columns start at x 10, 33, 56; bars are
+ // inset by 2 pixels on each side: x 12..29, 35..52, 58..75.
const int lft = 3 + infoLeft + i * 23;
for (int j = 0; j < ePower[i] && j < 20; j++) {
const int ln = bot - 3 * j;
if (ln <= _powerRect.top)
break;
- // power.c: MoveTo(lft+1,ln); LineTo(lft+16,ln); 16px wide, 2 lines
- _gfx->drawLine(lft + 1, ln, lft + 16, ln, colBlue);
- if (ln - 1 > _powerRect.top)
- _gfx->drawLine(lft + 1, ln - 1, lft + 16, ln - 1, colBlue);
+ _gfx->fillRect(Common::Rect(lft + 1, ln - 1, lft + 19, ln + 1), colBlue);
}
}
}
@@ -694,7 +733,7 @@ void ColonyEngine::drawMiniMap(uint32 lineColor) {
_gfx->drawLine(x1, y1, x2, y2, color);
};
- const bool isMac = (_renderMode == Common::kRenderMacintosh);
+ const bool isMac = isMacRenderMode();
int lExt, sExt, xloc, yloc, ccenterx, ccentery;
if (isMac) {
@@ -921,8 +960,8 @@ void ColonyEngine::drawAutomap() {
return;
const int lv = _level - 1;
- const bool isMac = (_renderMode == Common::kRenderMacintosh);
- const bool macColor = isMac && _hasMacColors;
+ const bool isMac = isMacRenderMode();
+ const bool macColor = isMacColorMode();
const Common::Rect vp(0, _menuBarHeight, _width, _height);
const int vpW = vp.width();
@@ -1014,7 +1053,7 @@ void ColonyEngine::drawForkliftOverlay() {
const int w = _screenR.width();
const int h = _screenR.height();
const int cx = w / 2;
- const uint32 color = (_renderMode == Common::kRenderMacintosh) ? packRGB(0, 0, 0) : 0;
+ const uint32 color = isMacRenderMode() ? packRGB(0, 0, 0) : 0;
const int tx2 = cx >> 2; // centerX/4
const int tx1 = cx >> 1; // centerX/2
@@ -1031,7 +1070,7 @@ void ColonyEngine::drawCrosshair() {
if (!_crosshair || _screenR.width() <= 0 || _screenR.height() <= 0)
return;
- const bool isMac = (_renderMode == Common::kRenderMacintosh);
+ const bool isMac = isMacRenderMode();
if (isMac && _cursorShoot && !_mouseLocked && _weapons > 0)
return;
@@ -1039,7 +1078,7 @@ void ColonyEngine::drawCrosshair() {
if (isMac) {
// Mac: black when powered, gray when no weapons, white when armed but no power
// B&W: no gray, so powered=black, else white
- if (_hasMacColors)
+ if (isMacColorMode())
color = (_corePower[_coreIndex] > 0) ? packRGB(0, 0, 0)
: (_weapons > 0) ? packRGB(255, 255, 255) : packRGB(128, 128, 128);
else
@@ -1109,8 +1148,8 @@ void ColonyEngine::printMessage(const char *text[], bool hold) {
numLines++;
}
- if (_renderMode == Common::kRenderMacintosh && drawMacTextPopup(_wm, _gfx,
- _width, _height, _centerX, _centerY, lines, Graphics::kTextAlignCenter, _hasMacColors)) {
+ if (isMacRenderMode() && drawMacTextPopup(_wm, _gfx,
+ _width, _height, _centerX, _centerY, lines, Graphics::kTextAlignCenter, isMacColorMode())) {
if (hold)
waitForInput();
return;
@@ -1226,13 +1265,13 @@ void ColonyEngine::doText(int entry, int center) {
if (maxlines > (int)lineArray.size())
maxlines = lineArray.size();
- if (_renderMode == Common::kRenderMacintosh) {
+ if (isMacRenderMode()) {
Common::Array<Common::String> popupLines;
for (int i = 0; i < maxlines; ++i)
popupLines.push_back(lineArray[i]);
popupLines.push_back((int)lineArray.size() > maxlines ? kmore : kpress);
if (drawMacTextPopup(_wm, _gfx, _width, _height, _centerX, _centerY, popupLines,
- center == 1 ? Graphics::kTextAlignCenter : Graphics::kTextAlignLeft, _hasMacColors)) {
+ center == 1 ? Graphics::kTextAlignCenter : Graphics::kTextAlignLeft, isMacColorMode())) {
waitForInput();
delete[] page;
return;
Commit: 9b0fb9204204cb43b003148c5f8740c682c8519a
https://github.com/scummvm/scummvm/commit/9b0fb9204204cb43b003148c5f8740c682c8519a
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2026-06-05T13:24:41+02:00
Commit Message:
COLONY: fixed xor mode in shader rendering
Changed paths:
engines/colony/renderer_opengl_shaders.cpp
diff --git a/engines/colony/renderer_opengl_shaders.cpp b/engines/colony/renderer_opengl_shaders.cpp
index 0639d28f5da..9315a5c8f9b 100644
--- a/engines/colony/renderer_opengl_shaders.cpp
+++ b/engines/colony/renderer_opengl_shaders.cpp
@@ -45,8 +45,6 @@
namespace Colony {
// Phase 3: 2D primitives + the 3D corridor draw path are programmable.
-// XOR mode and polygon stipple are intentionally left stubbed â see the
-// renderer audit for why those are deferred.
class OpenGLShaderRenderer : public Renderer {
public:
OpenGLShaderRenderer(OSystem *system, int width, int height);
@@ -77,7 +75,7 @@ public:
void copyToScreen() override;
void setWireframe(bool enable, int64_t fillColor) override;
- void setXorMode(bool enable) override {}
+ void setXorMode(bool enable) override;
void setStippleData(const byte *data) override;
void setMacColors(uint32 fg, uint32 bg) override;
void setDepthState(bool testEnabled, bool writeEnabled) override;
@@ -147,6 +145,7 @@ private:
bool _wireframe = true;
int64_t _wireframeFillColor = 0; // -1 = no fill, else color (palette idx or ARGB)
+ bool _xorMode = false;
// Stipple state. The shader emulates glPolygonStipple via a 128-int
// uniform array (Freescape pattern, GLES2-safe). _stippleActive is
@@ -348,6 +347,17 @@ void OpenGLShaderRenderer::drawSolid(GLenum mode, const float *positions, int ve
const float rgba[4]) {
if (vertCount <= 0)
return;
+ if (_xorMode) {
+ // QuickDraw's patXor effects are drawn with white mask pixels in the
+ // reimplementation. This blend state turns those pixels into
+ // 1 - destination, which matches the visible Mac B&W shoot/invert flash
+ // behavior and works on shader renderers without GL logic ops.
+ glEnable(GL_BLEND);
+ glBlendEquation(GL_FUNC_ADD);
+ glBlendFuncSeparate(GL_ONE_MINUS_DST_COLOR, GL_ZERO, GL_ZERO, GL_ONE);
+ } else {
+ glDisable(GL_BLEND);
+ }
uploadSolid(positions, vertCount);
// "projection" is set once by uploadProjectionUniform() â it persists in
// the program object across draws. Shader stays bound between draws so
@@ -665,6 +675,12 @@ void OpenGLShaderRenderer::setWireframe(bool enable, int64_t fillColor) {
_wireframeFillColor = fillColor;
}
+void OpenGLShaderRenderer::setXorMode(bool enable) {
+ _xorMode = enable;
+ if (!enable)
+ glDisable(GL_BLEND);
+}
+
void OpenGLShaderRenderer::setStippleData(const byte *data) {
const bool nowActive = (data != nullptr);
if (nowActive) {
Commit: d541fc5d0e6d2d7385cd4a036d8229de5d948840
https://github.com/scummvm/scummvm/commit/d541fc5d0e6d2d7385cd4a036d8229de5d948840
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2026-06-05T13:24:41+02:00
Commit Message:
COLONY: complete rendering of mountain parallax
Changed paths:
engines/colony/battle.cpp
diff --git a/engines/colony/battle.cpp b/engines/colony/battle.cpp
index 5ec5031274b..6dd4f82cf06 100644
--- a/engines/colony/battle.cpp
+++ b/engines/colony/battle.cpp
@@ -458,8 +458,9 @@ void ColonyEngine::battleInit() {
_projon = false;
_pcount = 0;
- // Mountain parallax
- _battledx = _width / 59;
+ // Mountain parallax. battleBackdrop() recomputes this once the viewport
+ // layout is final; keep a sane initial value for freshly initialized state.
+ _battledx = MAX<int>(1, _screenR.width() / 59);
// Generate mountain height profile (smoothed random)
int temp[257];
@@ -548,7 +549,13 @@ void ColonyEngine::battleBackdrop() {
// Mountain silhouette
uint32 mtColor = 0xFF606060;
uint8 ang = _me.look;
- int xloc = -_battledx;
+ // Original battle.c draws the mountain profile under ClipRect(&Clip).
+ // Align the first sample to the active viewport, not to logical x=0
+ // where the Mac dashboard/sidebar lives in ScummVM.
+ _battledx = MAX<int>(1, _screenR.width() / 59);
+ if (!isMacRenderMode())
+ _battledx++;
+ int xloc = _screenR.left - _battledx;
if (ang & 0x01) {
xloc += _battledx;
ang--;
@@ -569,7 +576,12 @@ void ColonyEngine::battleBackdrop() {
sunon = true;
}
int curY = horizonY - _mountains[ang];
- _gfx->drawLine(prevX, prevY, xloc, curY, mtColor);
+ int x1 = prevX;
+ int y1 = prevY;
+ int x2 = xloc;
+ int y2 = curY;
+ if (clipLineToRect(x1, y1, x2, y2, _screenR))
+ _gfx->drawLine(x1, y1, x2, y2, mtColor);
prevX = xloc;
prevY = curY;
}
Commit: 0befed2f78418f3d30d171d00cabd9ba3b3f656f
https://github.com/scummvm/scummvm/commit/0befed2f78418f3d30d171d00cabd9ba3b3f656f
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2026-06-05T13:24:41+02:00
Commit Message:
COLONY: make sure the battle coordinates are normalized before starting
Changed paths:
engines/colony/battle.cpp
engines/colony/colony.h
engines/colony/movement.cpp
engines/colony/savegame.cpp
diff --git a/engines/colony/battle.cpp b/engines/colony/battle.cpp
index 6dd4f82cf06..cc870b5d272 100644
--- a/engines/colony/battle.cpp
+++ b/engines/colony/battle.cpp
@@ -515,6 +515,16 @@ void ColonyEngine::battleSet() {
}
}
+void ColonyEngine::normalizeBattlePlayerPosition() {
+ // The original stored battle coordinates in 16-bit ints. Airlock map
+ // targets such as 253<<8 wrap to negative world coordinates there; keep
+ // the same representation before battle culling and camera math run.
+ _me.xloc = battleNormalizeCoord(_me.xloc);
+ _me.yloc = battleNormalizeCoord(_me.yloc);
+ _me.xindex = wrapBattleCoord(_me.xloc) >> 8;
+ _me.yindex = wrapBattleCoord(_me.yloc) >> 8;
+}
+
// =====================================================================
// battleBackdrop: Draw 2D sky gradient and ground fill.
// Called before 3D rendering begins.
@@ -1187,6 +1197,7 @@ void ColonyEngine::battleProjCommand(int xcheck, int ycheck) {
// Called from the main loop when _gameMode == kModeBattle.
// =====================================================================
void ColonyEngine::renderBattle() {
+ normalizeBattlePlayerPosition();
_battleMaxP = 0;
// Phase 1: 2D backdrop (sky gradient, mountains, sun) follows camera pitch
diff --git a/engines/colony/colony.h b/engines/colony/colony.h
index b4be8d94fb9..f3de2a2e2df 100644
--- a/engines/colony/colony.h
+++ b/engines/colony/colony.h
@@ -693,6 +693,7 @@ private:
void battleInit();
void battleSet();
void battleThink();
+ void normalizeBattlePlayerPosition();
void enterColonyFromBattle(int mapNum, int xloc, int yloc);
void battleCommand(int xnew, int ynew);
void battleShoot();
diff --git a/engines/colony/movement.cpp b/engines/colony/movement.cpp
index 08649bf0b99..fd550ab45ed 100644
--- a/engines/colony/movement.cpp
+++ b/engines/colony/movement.cpp
@@ -599,6 +599,7 @@ int ColonyEngine::goToDestination(const uint8 *map, Locate *pobject) {
_me.yloc = targetY << 8;
_me.xindex = targetX;
_me.yindex = targetY;
+ normalizeBattlePlayerPosition();
return 2;
}
diff --git a/engines/colony/savegame.cpp b/engines/colony/savegame.cpp
index 8d7df774b93..1f423247887 100644
--- a/engines/colony/savegame.cpp
+++ b/engines/colony/savegame.cpp
@@ -581,6 +581,8 @@ Common::Error ColonyEngine::loadGameStream(Common::SeekableReadStream *stream) {
_lastWarningChimeTime = 0;
_battledx = _width / 59;
updateViewportLayout();
+ if (_gameMode == kModeBattle)
+ normalizeBattlePlayerPosition();
return Common::kNoError;
}
More information about the Scummvm-git-logs
mailing list