[Scummvm-git-logs] scummvm master -> d4a9b8612595323d997348b8ee341f708e062b85
neuromancer
noreply at scummvm.org
Thu Apr 30 08:16:21 UTC 2026
This automated email contains information about 6 new commits which have been
pushed to the 'scummvm' repo located at https://api.github.com/repos/scummvm/scummvm .
Summary:
60cff2859c COLONY: improved movement and implement face foward key to reduce confusion when looking up/down
2719eff73f COLONY: fixed automap colors in mac b&w release
08281f3ebd COLONY: improve intro audio timing
9055a677e0 COLONY: avoid choppy mouse cursor during animations
a3f835dd6e COLONY: refactor color packing
d4a9b86125 COLONY: use managed surfaces to increase performance
Commit: 60cff2859c01951b3bf57950b0cf86655d2c4cfa
https://github.com/scummvm/scummvm/commit/60cff2859c01951b3bf57950b0cf86655d2c4cfa
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2026-04-30T10:16:05+02:00
Commit Message:
COLONY: improved movement and implement face foward key to reduce confusion when looking up/down
Changed paths:
engines/colony/colony.cpp
engines/colony/colony.h
engines/colony/metaengine.cpp
diff --git a/engines/colony/colony.cpp b/engines/colony/colony.cpp
index bb63dd13df0..7f4cbf5c027 100644
--- a/engines/colony/colony.cpp
+++ b/engines/colony/colony.cpp
@@ -173,6 +173,9 @@ ColonyEngine::ColonyEngine(OSystem *syst, const ADGameDescription *gd) : Engine(
_rotateLeft = false;
_rotateRight = false;
_sprint = false;
+ _moveAccumX = 0.0f;
+ _moveAccumY = 0.0f;
+ _rotAccum = 0.0f;
_wm = nullptr;
_macMenu = nullptr;
_menuSurface = nullptr;
@@ -928,6 +931,9 @@ Common::Error ColonyEngine::run() {
case kActionLookBehind:
_me.look = _me.ang + 128;
break;
+ case kActionFaceForward:
+ _me.lookY = 0;
+ break;
case kActionToggleDashboard:
_showDashBoard = !_showDashBoard;
break;
@@ -1045,57 +1051,72 @@ Common::Error ColonyEngine::run() {
mouseDX = mouseDY = 0;
}
- // Apply continuous movement/rotation from held keys,
- // throttled to ~15 ticks/sec to match original key-repeat feel
- if (now - lastMoveTick >= 66) {
+ // Smooth, deltaTime-based movement (Freescape-style). Top speed
+ // matches the previous 15Hz tick: units/sec = 120 * (1 << spd).
+ // Sprint (shift) bumps the speed level by 1; speed keys 1-5 select
+ // the base level. Diagonals are normalized so combined input is
+ // not faster than single-axis movement.
+ {
+ float dt = (now - lastMoveTick) / 1000.0f;
lastMoveTick = now;
- const int spd = _sprint ? _speedShift + 1 : _speedShift;
- const int moveX = (_cost[_me.look] * (1 << spd)) >> 4;
- const int moveY = (_sint[_me.look] * (1 << spd)) >> 4;
- const int rotSpeed = 1 << (_speedShift - 1);
-
- if (_gameMode == kModeBattle) {
- if (_moveForward)
- battleCommand(_me.xloc + moveX, _me.yloc + moveY);
- if (_moveBackward)
- battleCommand(_me.xloc - moveX, _me.yloc - moveY);
- if (_strafeLeft) {
- uint8 strafeAngle = (uint8)((int)_me.look + 64);
- int sx = (_cost[strafeAngle] * (1 << spd)) >> 4;
- int sy = (_sint[strafeAngle] * (1 << spd)) >> 4;
- battleCommand(_me.xloc + sx, _me.yloc + sy);
- }
- if (_strafeRight) {
- uint8 strafeAngle = (uint8)((int)_me.look - 64);
- int sx = (_cost[strafeAngle] * (1 << spd)) >> 4;
- int sy = (_sint[strafeAngle] * (1 << spd)) >> 4;
- battleCommand(_me.xloc + sx, _me.yloc + sy);
+ if (dt > 0.1f)
+ dt = 0.1f; // clamp for first frame / pause-resume
+
+ const int spd = CLIP(_sprint ? _speedShift + 1 : _speedShift, 1, 6);
+ const float speed = 120.0f * (float)(1 << spd); // world units/sec
+
+ float dirX = 0.0f, dirY = 0.0f;
+ if (_moveForward) {
+ dirX += _cost[_me.look];
+ dirY += _sint[_me.look];
+ }
+ if (_moveBackward) {
+ dirX -= _cost[_me.look];
+ dirY -= _sint[_me.look];
+ }
+ if (_strafeLeft) {
+ uint8 a = (uint8)((int)_me.look + 64);
+ dirX += _cost[a];
+ dirY += _sint[a];
+ }
+ if (_strafeRight) {
+ uint8 a = (uint8)((int)_me.look - 64);
+ dirX += _cost[a];
+ dirY += _sint[a];
+ }
+
+ if (dirX != 0.0f || dirY != 0.0f) {
+ const float len = sqrtf(dirX * dirX + dirY * dirY);
+ const float ux = dirX / len;
+ const float uy = dirY / len;
+ _moveAccumX += ux * speed * dt;
+ _moveAccumY += uy * speed * dt;
+ const int ix = (int)_moveAccumX;
+ const int iy = (int)_moveAccumY;
+ _moveAccumX -= ix;
+ _moveAccumY -= iy;
+ if (ix != 0 || iy != 0) {
+ if (_gameMode == kModeBattle)
+ battleCommand(_me.xloc + ix, _me.yloc + iy);
+ else
+ cCommand(_me.xloc + ix, _me.yloc + iy, true);
}
} else {
- if (_moveForward)
- cCommand(_me.xloc + moveX, _me.yloc + moveY, true);
- if (_moveBackward)
- cCommand(_me.xloc - moveX, _me.yloc - moveY, true);
- if (_strafeLeft) {
- uint8 strafeAngle = (uint8)((int)_me.look + 64);
- int sx = (_cost[strafeAngle] * (1 << spd)) >> 4;
- int sy = (_sint[strafeAngle] * (1 << spd)) >> 4;
- cCommand(_me.xloc + sx, _me.yloc + sy, true);
- }
- if (_strafeRight) {
- uint8 strafeAngle = (uint8)((int)_me.look - 64);
- int sx = (_cost[strafeAngle] * (1 << spd)) >> 4;
- int sy = (_sint[strafeAngle] * (1 << spd)) >> 4;
- cCommand(_me.xloc + sx, _me.yloc + sy, true);
- }
- }
- if (_rotateLeft) {
- _me.ang += rotSpeed;
- _me.look += rotSpeed;
+ _moveAccumX = 0.0f;
+ _moveAccumY = 0.0f;
}
- if (_rotateRight) {
- _me.ang -= rotSpeed;
- _me.look -= rotSpeed;
+
+ if (_rotateLeft || _rotateRight) {
+ const float rotSpeed = (float)(1 << (_speedShift - 1)) * 15.0f;
+ _rotAccum += (_rotateLeft ? rotSpeed : -rotSpeed) * dt;
+ const int rint = (int)_rotAccum;
+ _rotAccum -= rint;
+ if (rint != 0) {
+ _me.ang = (uint8)((int)_me.ang + rint);
+ _me.look = (uint8)((int)_me.look + rint);
+ }
+ } else {
+ _rotAccum = 0.0f;
}
}
diff --git a/engines/colony/colony.h b/engines/colony/colony.h
index 5ba166a3a7c..61a7341e329 100644
--- a/engines/colony/colony.h
+++ b/engines/colony/colony.h
@@ -66,6 +66,7 @@ enum ColonyAction {
kActionLookLeft,
kActionLookRight,
kActionLookBehind,
+ kActionFaceForward,
kActionToggleMouselook,
kActionToggleDashboard,
kActionToggleWireframe,
@@ -498,6 +499,13 @@ private:
bool _rotateRight;
bool _sprint;
+ // Sub-unit accumulators for deltaTime-based smooth movement.
+ // Position uses 256-units-per-cell integers, angles are uint8 â these
+ // retain fractional progress between frames so low speeds aren't lost.
+ float _moveAccumX;
+ float _moveAccumY;
+ float _rotAccum;
+
Common::RandomSource _randomSource;
Common::Point _mousePos;
uint8 _decode1[4];
diff --git a/engines/colony/metaengine.cpp b/engines/colony/metaengine.cpp
index 4b88aca2400..a9af9b4517e 100644
--- a/engines/colony/metaengine.cpp
+++ b/engines/colony/metaengine.cpp
@@ -149,6 +149,11 @@ Common::KeymapArray ColonyMetaEngine::initKeymaps(const char *target) const {
act->addDefaultInputMapping("x");
engineKeyMap->addAction(act);
+ act = new Common::Action("FACEFRWARD", _("Face forward"));
+ act->setCustomEngineActionEvent(kActionFaceForward);
+ act->addDefaultInputMapping("f");
+ engineKeyMap->addAction(act);
+
act = new Common::Action("MOUSE", _("Toggle mouselook"));
act->setCustomEngineActionEvent(kActionToggleMouselook);
act->addDefaultInputMapping("SPACE");
@@ -184,7 +189,7 @@ Common::KeymapArray ColonyMetaEngine::initKeymaps(const char *target) const {
act = new Common::Action("FIRE", _("Fire weapon"));
act->setCustomEngineActionEvent(kActionFire);
- act->addDefaultInputMapping("f");
+ act->addDefaultInputMapping("LCTRL");
act->addDefaultInputMapping("JOY_B");
engineKeyMap->addAction(act);
Commit: 2719eff73fbae65ed76e5c2bc931ef839c8c03c1
https://github.com/scummvm/scummvm/commit/2719eff73fbae65ed76e5c2bc931ef839c8c03c1
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2026-04-30T10:16:05+02:00
Commit Message:
COLONY: fixed automap colors in mac b&w release
Changed paths:
engines/colony/ui.cpp
diff --git a/engines/colony/ui.cpp b/engines/colony/ui.cpp
index a40a589018a..e0141e5cc75 100644
--- a/engines/colony/ui.cpp
+++ b/engines/colony/ui.cpp
@@ -943,6 +943,7 @@ void ColonyEngine::drawAutomap() {
const int lv = _level - 1;
const bool isMac = (_renderMode == Common::kRenderMacintosh);
+ const bool macColor = isMac && _hasMacColors;
const Common::Rect vp(0, _menuBarHeight, _width, _height);
const int vpW = vp.width();
@@ -950,7 +951,9 @@ void ColonyEngine::drawAutomap() {
if (vpW <= 0 || vpH <= 0)
return;
- _gfx->fillRect(vp, isMac ? 0xFFA0D0FF : 15);
+ // Match the minimap: B&W Mac is white background + black lines, like the
+ // compass area; color Mac keeps its tinted background.
+ _gfx->fillRect(vp, macColor ? 0xFFA0D0FF : (isMac ? packRGB(255, 255, 255) : 15));
_gfx->drawRect(vp, 0);
const int lExt = MIN(vpW, vpH) / 12;
Commit: 08281f3ebd0f1c04518b0eba1a3e2eff690992c9
https://github.com/scummvm/scummvm/commit/08281f3ebd0f1c04518b0eba1a3e2eff690992c9
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2026-04-30T10:16:05+02:00
Commit Message:
COLONY: improve intro audio timing
Changed paths:
engines/colony/colony.cpp
engines/colony/colony.h
engines/colony/intro.cpp
engines/colony/metaengine.cpp
engines/colony/sound.cpp
engines/colony/sound.h
diff --git a/engines/colony/colony.cpp b/engines/colony/colony.cpp
index 7f4cbf5c027..4083f778227 100644
--- a/engines/colony/colony.cpp
+++ b/engines/colony/colony.cpp
@@ -1164,7 +1164,7 @@ bool ColonyEngine::checkSkipRequested() {
case Common::EVENT_RETURN_TO_LAUNCHER:
return true;
case Common::EVENT_CUSTOM_ENGINE_ACTION_START:
- if (event.customType == kActionSkipIntro)
+ if (event.customType == kActionEscape)
return true;
break;
case Common::EVENT_SCREEN_CHANGED:
@@ -1196,7 +1196,7 @@ bool ColonyEngine::waitForInput() {
case Common::EVENT_RETURN_TO_LAUNCHER:
return false;
case Common::EVENT_CUSTOM_ENGINE_ACTION_START:
- if (event.customType == kActionSkipIntro)
+ if (event.customType == kActionEscape)
return true;
return false;
case Common::EVENT_KEYDOWN:
diff --git a/engines/colony/colony.h b/engines/colony/colony.h
index 61a7341e329..6c59dcd02e4 100644
--- a/engines/colony/colony.h
+++ b/engines/colony/colony.h
@@ -71,7 +71,6 @@ enum ColonyAction {
kActionToggleDashboard,
kActionToggleWireframe,
kActionToggleFullscreen,
- kActionSkipIntro,
kActionEscape,
kActionFire
};
diff --git a/engines/colony/intro.cpp b/engines/colony/intro.cpp
index be70a7aff33..020b284e740 100644
--- a/engines/colony/intro.cpp
+++ b/engines/colony/intro.cpp
@@ -218,7 +218,10 @@ void ColonyEngine::playIntro() {
_gfx->clear(_gfx->black());
if (!drawPict(-32565)) // Color Colony
drawPict(-32748); // B&W Colony
- _sound->play(Sound::kMars);
+ // Original intro.c: PlayMars() â PlayCSound(mars), looped via VBL
+ // task. Mars stays alive across the next several intro sections
+ // until EndCSound() is called.
+ _sound->play(Sound::kMars, true);
qt = makeStars(_screenR, 0);
if (!qt) {
@@ -1044,8 +1047,9 @@ bool ColonyEngine::timeSquare(const Common::String &str, const Graphics::Font *m
_sound->stop();
// Phase 3: Mac resumes Mars here; DOS scrolls out silently.
+ // Original intro.c TimeSquare line 323: PlayMars() restarts the loop.
if (macStyle)
- _sound->play(Sound::kMars);
+ _sound->play(Sound::kMars, true);
for (int x = targetX; x > endX; x -= stepX) {
_gfx->fillRect(textBand, 0);
_gfx->drawString(font, str, x, centery + 2, textIndex, Graphics::kTextAlignLeft);
diff --git a/engines/colony/metaengine.cpp b/engines/colony/metaengine.cpp
index a9af9b4517e..717450467c6 100644
--- a/engines/colony/metaengine.cpp
+++ b/engines/colony/metaengine.cpp
@@ -175,13 +175,7 @@ Common::KeymapArray ColonyMetaEngine::initKeymaps(const char *target) const {
act->addDefaultInputMapping("F11");
engineKeyMap->addAction(act);
- act = new Common::Action("SKIP", _("Skip intro"));
- act->setCustomEngineActionEvent(kActionSkipIntro);
- act->addDefaultInputMapping("S+s");
- act->addDefaultInputMapping("JOY_X");
- engineKeyMap->addAction(act);
-
- act = new Common::Action("ESCAPE", _("Menu"));
+ act = new Common::Action("ESCAPE", _("Menu / Skip intro"));
act->setCustomEngineActionEvent(kActionEscape);
act->addDefaultInputMapping("ESCAPE");
act->addDefaultInputMapping("JOY_BACK");
diff --git a/engines/colony/sound.cpp b/engines/colony/sound.cpp
index 3dea5fcc281..9ab0459219d 100644
--- a/engines/colony/sound.cpp
+++ b/engines/colony/sound.cpp
@@ -141,14 +141,14 @@ bool Sound::isPlaying() const {
return _vm->_mixer->isSoundHandleActive(_handle) || _speaker->isPlaying();
}
-void Sound::play(int soundID) {
+void Sound::play(int soundID, bool loop) {
stop();
if (!_vm->isSoundEnabled())
return;
if (_vm->getPlatform() == Common::kPlatformMacintosh)
- playMacSound(soundID);
+ playMacSound(soundID, loop);
else
playPCSpeaker(soundID);
}
@@ -345,7 +345,7 @@ void Sound::playPCSpeaker(int soundID) {
}
}
-bool Sound::playMacSound(int soundID) {
+bool Sound::playMacSound(int soundID, bool loop) {
// Primary resource IDs from original sound.c
int resID = -1;
switch (soundID) {
@@ -379,7 +379,7 @@ bool Sound::playMacSound(int soundID) {
default: break;
}
- if (resID != -1 && playResource(resID))
+ if (resID != -1 && playResource(resID, loop))
return true;
// Fallback resource IDs for sounds missing from this binary version.
@@ -392,7 +392,7 @@ bool Sound::playMacSound(int soundID) {
default: break;
}
- if (altResID != -1 && playResource(altResID))
+ if (altResID != -1 && playResource(altResID, loop))
return true;
// Fallback to DOS sounds if Mac resource is missing
@@ -400,7 +400,7 @@ bool Sound::playMacSound(int soundID) {
return false;
}
-bool Sound::playResource(int resID) {
+bool Sound::playResource(int resID, bool loop) {
Common::SeekableReadStream *snd = nullptr;
// Search Zounds first (has most sounds)
@@ -426,7 +426,8 @@ bool Sound::playResource(int resID) {
snd->read(data, dataSize);
delete snd;
- Audio::AudioStream *stream = Audio::makeRawStream(data, dataSize, 11127, Audio::FLAG_UNSIGNED, DisposeAfterUse::YES);
+ Audio::RewindableAudioStream *raw = Audio::makeRawStream(data, dataSize, 11127, Audio::FLAG_UNSIGNED, DisposeAfterUse::YES);
+ Audio::AudioStream *stream = loop ? Audio::makeLoopingAudioStream(raw, 0) : raw;
_vm->_mixer->playStream(Audio::Mixer::kSFXSoundType, &_handle, stream);
return true;
}
diff --git a/engines/colony/sound.h b/engines/colony/sound.h
index 93ddcb601ea..78c8fb936ef 100644
--- a/engines/colony/sound.h
+++ b/engines/colony/sound.h
@@ -43,7 +43,7 @@ public:
~Sound();
void init();
- void play(int soundID);
+ void play(int soundID, bool loop = false);
void stop();
bool isPlaying() const;
@@ -90,8 +90,8 @@ private:
Audio::SoundHandle _handle;
void playPCSpeaker(int soundID);
- bool playMacSound(int soundID);
- bool playResource(int resID);
+ bool playMacSound(int soundID, bool loop);
+ bool playResource(int resID, bool loop);
};
} // End of namespace Colony
Commit: 9055a677e08827083f37b8f04a8e9692e8e80d40
https://github.com/scummvm/scummvm/commit/9055a677e08827083f37b8f04a8e9692e8e80d40
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2026-04-30T10:16:05+02:00
Commit Message:
COLONY: avoid choppy mouse cursor during animations
Changed paths:
engines/colony/animation.cpp
engines/colony/colony.cpp
engines/colony/colony.h
diff --git a/engines/colony/animation.cpp b/engines/colony/animation.cpp
index 694def0a7b1..16dea3e934b 100644
--- a/engines/colony/animation.cpp
+++ b/engines/colony/animation.cpp
@@ -32,6 +32,7 @@
#include "common/stream.h"
#include "common/system.h"
#include "graphics/cursorman.h"
+#include "graphics/surface.h"
#include "colony/colony.h"
#include "colony/renderer.h"
@@ -573,6 +574,12 @@ void ColonyEngine::playAnimation() {
_gfx->copyToScreen();
}
+ // drawAnimation is heavy (per-pixel setPixel calls for the 416x264 pattern)
+ // so cap it to the animation update cadence (50ms = 20fps). Between draws,
+ // only call updateScreen so the OpenGL backend re-composites with the
+ // current cursor position â keeps the pointer smooth without re-rendering.
+ uint32 lastDrawTime = 0;
+ bool needsDraw = true;
while (_animationRunning && !shouldQuit()) {
Common::Event event;
while (_system->getEventManager()->pollEvent(event)) {
@@ -581,10 +588,12 @@ void ColonyEngine::playAnimation() {
return;
} else if (event.type == Common::EVENT_SCREEN_CHANGED) {
_gfx->computeScreenViewport();
+ needsDraw = true;
} else if (event.type == Common::EVENT_LBUTTONDOWN) {
int item = whichSprite(event.mouse);
if (item > 0) {
handleAnimationClick(item);
+ needsDraw = true;
}
} else if (event.type == Common::EVENT_RBUTTONDOWN) {
// DOS: right-click exits animation (AnimControl returns FALSE on button-up)
@@ -596,6 +605,7 @@ void ColonyEngine::playAnimation() {
if (event.customType == kActionEscape) {
openMainMenuDialog();
_gfx->computeScreenViewport();
+ needsDraw = true;
}
} else if (event.type == Common::EVENT_KEYDOWN) {
int item = 0;
@@ -611,14 +621,28 @@ void ColonyEngine::playAnimation() {
if (item > 0) {
handleAnimationClick(item);
+ needsDraw = true;
}
}
}
+ // updateAnimation has its own 50ms throttle; only redraw when we know
+ // the visible state changed (click feedback) or the cadence is due.
+ const uint32 prevAnimUpdate = _lastAnimUpdate;
updateAnimation();
- drawAnimation();
- _gfx->copyToScreen();
- responsiveAnimationDelay(_system, 4);
+ if (_lastAnimUpdate != prevAnimUpdate)
+ needsDraw = true;
+
+ const uint32 now = _system->getMillis();
+ if (needsDraw || now - lastDrawTime >= 50) {
+ drawAnimation();
+ _gfx->copyToScreen();
+ lastDrawTime = now;
+ needsDraw = false;
+ } else {
+ _system->updateScreen();
+ }
+ _system->delayMillis(2);
}
_system->lockMouse(true);
@@ -698,44 +722,76 @@ void ColonyEngine::drawAnimation() {
// Top: BMColor[0]<0 -> system color; ==0 -> powered:c_char0+level-1.f, else:c_dwall.b
// Bottom: powered -> c_lwall.f; unpowered -> inherits top BackColor
// B&W/DOS: preserve existing palette-index behavior (bit 1 -> 15, bit 0 -> 0).
+ //
+ // We render the pattern into a cached RGBA surface and blit it via
+ // drawSurface (one texture upload per change). The previous implementation
+ // 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);
+ uint32 topColor = 0, botColor = 0;
if (useColor) {
const bool powered = (_corePower[_coreIndex] > 0);
- uint32 topBG = resolveAnimColor(_animBMColors[0]);
- // Bottom: only uses c_lwall.f when powered; unpowered inherits top color
- uint32 botBG = powered ? packMacColorBG(_macColors[kMcLwall].fg) : topBG;
- for (int y = 0; y < 264; y++) {
- byte *pat = (y < _divideBG) ? _topBG : _bottomBG;
- byte row = pat[y % 8];
- uint32 bg = (y < _divideBG) ? topBG : botBG;
- for (int x = 0; x < 416; x++) {
- bool set = (row & (0x80 >> (x % 8))) != 0;
- _gfx->setPixel(ox + x, oy + y, set ? (uint32)0xFF000000 : bg);
- }
- }
- } else if (_renderMode == Common::kRenderMacintosh) {
- // Mac QuickDraw FillRect: pattern bit=1 â ForeColor (black=0),
- // bit=0 â BackColor (white=15).
- for (int y = 0; y < 264; y++) {
- byte *pat = (y < _divideBG) ? _topBG : _bottomBG;
- byte row = pat[y % 8];
- for (int x = 0; x < 416; x++) {
- bool set = (row & (0x80 >> (x % 8))) != 0;
- _gfx->setPixel(ox + x, oy + y, set ? 0 : 15);
- }
+ topColor = resolveAnimColor(_animBMColors[0]);
+ botColor = powered ? packMacColorBG(_macColors[kMcLwall].fg) : topColor;
+ }
+
+ const bool keyChanged = !_animPatternValid
+ || _animPatternKeyMode != patternMode
+ || _animPatternKeyDivide != _divideBG
+ || _animPatternKeyTopColor != topColor
+ || _animPatternKeyBotColor != botColor
+ || memcmp(_animPatternKeyTopBG, _topBG, 8) != 0
+ || memcmp(_animPatternKeyBottomBG, _bottomBG, 8) != 0;
+
+ if (!_animPatternSurface) {
+ _animPatternSurface = new Graphics::Surface();
+ _animPatternSurface->create(416, 264, Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0));
+ }
+
+ if (keyChanged) {
+ const Graphics::PixelFormat &fmt = _animPatternSurface->format;
+ uint32 fgPixel, topBgPixel, botBgPixel;
+ switch (patternMode) {
+ case 2: // Mac color: bit=1 â black, bit=0 â topColor/botColor
+ fgPixel = fmt.ARGBToColor(255, 0, 0, 0);
+ topBgPixel = fmt.ARGBToColor(255,
+ (topColor >> 16) & 0xFF, (topColor >> 8) & 0xFF, topColor & 0xFF);
+ botBgPixel = fmt.ARGBToColor(255,
+ (botColor >> 16) & 0xFF, (botColor >> 8) & 0xFF, botColor & 0xFF);
+ break;
+ case 1: // Mac B&W: bit=1 â black, bit=0 â white
+ fgPixel = fmt.ARGBToColor(255, 0, 0, 0);
+ topBgPixel = botBgPixel = fmt.ARGBToColor(255, 255, 255, 255);
+ break;
+ default: // DOS: bit=1 â white, bit=0 â black
+ fgPixel = fmt.ARGBToColor(255, 255, 255, 255);
+ topBgPixel = botBgPixel = fmt.ARGBToColor(255, 0, 0, 0);
+ break;
}
- } else {
- // DOS MetaWINDOW: pattern bit=1 â pen color (white=15),
- // bit=0 â background (black=0). Opposite of Mac QuickDraw.
+
+ uint32 *pixels = (uint32 *)_animPatternSurface->getPixels();
for (int y = 0; y < 264; y++) {
- byte *pat = (y < _divideBG) ? _topBG : _bottomBG;
- byte row = pat[y % 8];
+ const byte row = ((y < _divideBG) ? _topBG : _bottomBG)[y % 8];
+ const uint32 bgPixel = (y < _divideBG) ? topBgPixel : botBgPixel;
+ uint32 *dst = pixels + y * 416;
for (int x = 0; x < 416; x++) {
- bool set = (row & (0x80 >> (x % 8))) != 0;
- _gfx->setPixel(ox + x, oy + y, set ? 15 : 0);
+ const bool set = (row & (0x80 >> (x % 8))) != 0;
+ dst[x] = set ? fgPixel : bgPixel;
}
}
+
+ memcpy(_animPatternKeyTopBG, _topBG, 8);
+ memcpy(_animPatternKeyBottomBG, _bottomBG, 8);
+ _animPatternKeyDivide = _divideBG;
+ _animPatternKeyTopColor = topColor;
+ _animPatternKeyBotColor = botColor;
+ _animPatternKeyMode = patternMode;
+ _animPatternValid = true;
}
+ _gfx->drawSurface(_animPatternSurface, ox, oy);
+
// Draw background image if active.
// Original: BMColor[1] only applied when corepower[coreindex] > 0.
if (_backgroundActive && _backgroundFG) {
diff --git a/engines/colony/colony.cpp b/engines/colony/colony.cpp
index 4083f778227..0996a626682 100644
--- a/engines/colony/colony.cpp
+++ b/engines/colony/colony.cpp
@@ -279,6 +279,10 @@ ColonyEngine::~ColonyEngine() {
_pictCompass->free();
delete _pictCompass;
}
+ if (_animPatternSurface) {
+ _animPatternSurface->free();
+ delete _animPatternSurface;
+ }
delete _frameLimiter;
delete _gfx;
delete _sound;
diff --git a/engines/colony/colony.h b/engines/colony/colony.h
index 6c59dcd02e4..3482d847f85 100644
--- a/engines/colony/colony.h
+++ b/engines/colony/colony.h
@@ -714,6 +714,19 @@ private:
byte _topBG[8] = {};
byte _bottomBG[8] = {};
int16 _divideBG;
+
+ // Cache for the animation background pattern. Regenerated only when
+ // pattern bytes / colors / split point change. Replaces a 110k-pixel
+ // setPixel loop with one texture upload, fixing cursor choppiness
+ // during animations on the OpenGL renderer.
+ Graphics::Surface *_animPatternSurface = nullptr;
+ byte _animPatternKeyTopBG[8] = {};
+ byte _animPatternKeyBottomBG[8] = {};
+ int16 _animPatternKeyDivide = -1;
+ uint32 _animPatternKeyTopColor = 0;
+ uint32 _animPatternKeyBotColor = 0;
+ int _animPatternKeyMode = -1; // 0=DOS, 1=Mac B&W, 2=Mac color
+ bool _animPatternValid = false;
Common::String _animationName;
Common::Array<int16> _animBMColors;
bool _animationRunning;
Commit: a3f835dd6e8969c68f15d4e1b5e7d645baf90ba8
https://github.com/scummvm/scummvm/commit/a3f835dd6e8969c68f15d4e1b5e7d645baf90ba8
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2026-04-30T10:16:05+02:00
Commit Message:
COLONY: refactor color packing
Changed paths:
engines/colony/animation.cpp
engines/colony/colony.h
engines/colony/intro.cpp
engines/colony/movement.cpp
engines/colony/render_internal.h
engines/colony/ui.cpp
diff --git a/engines/colony/animation.cpp b/engines/colony/animation.cpp
index 16dea3e934b..05436e4cbe0 100644
--- a/engines/colony/animation.cpp
+++ b/engines/colony/animation.cpp
@@ -243,11 +243,6 @@ uint32 macSysColorToARGB(int sysColor) {
}
}
-uint32 packMacColorBG(const uint16 rgb[3]) {
- return 0xFF000000 | ((uint32)(rgb[0] >> 8) << 16) |
- ((uint32)(rgb[1] >> 8) << 8) | (uint32)(rgb[2] >> 8);
-}
-
int getAnimationStateCount(const Common::Array<ComplexSprite *> &sprites, int num) {
num--;
if (num >= 0 && num < (int)sprites.size()) {
@@ -692,15 +687,15 @@ uint32 ColonyEngine::resolveAnimColor(int16 bmEntry) const {
return macSysColorToARGB(-bmEntry);
} else if (bmEntry > 0) {
if (bmEntry < 145)
- return packMacColorBG(_macColors[bmEntry].bg);
+ return packMacColor(_macColors[bmEntry].bg);
return 0xFFFFFFFF;
} else {
// Zero = level-based (original gamesprt.c DrawlSprite/DrawBackGround):
// if(corepower[coreindex]) RGBBackColor(&cColor[c_char0+level-1].f);
// else RGBBackColor(&cColor[c_dwall].b);
if (_corePower[_coreIndex] > 0 && _level >= 1 && _level <= 7)
- return packMacColorBG(_macColors[kMcChar0 + _level - 1].fg);
- return packMacColorBG(_macColors[kMcDwall].bg);
+ return packMacColor(_macColors[kMcChar0 + _level - 1].fg);
+ return packMacColor(_macColors[kMcDwall].bg);
}
}
@@ -733,7 +728,7 @@ void ColonyEngine::drawAnimation() {
if (useColor) {
const bool powered = (_corePower[_coreIndex] > 0);
topColor = resolveAnimColor(_animBMColors[0]);
- botColor = powered ? packMacColorBG(_macColors[kMcLwall].fg) : topColor;
+ botColor = powered ? packMacColor(_macColors[kMcLwall].fg) : topColor;
}
const bool keyChanged = !_animPatternValid
diff --git a/engines/colony/colony.h b/engines/colony/colony.h
index 3482d847f85..073cfd73f09 100644
--- a/engines/colony/colony.h
+++ b/engines/colony/colony.h
@@ -34,6 +34,7 @@
#include "common/rendermode.h"
#include "engines/advancedDetector.h"
#include "engines/engine.h"
+#include "graphics/pixelformat.h"
namespace Common {
class MacResManager;
@@ -55,6 +56,24 @@ namespace Colony {
class Renderer;
class Sound;
+// Engine-wide color packing. The OpenGL renderer's useColor() treats values
+// with the high byte == 0xFF as direct ARGB (R=bits 16-23, G=8-15, B=0-7) and
+// values with high byte 0 as palette indices. The PixelFormat below matches
+// that direct-ARGB layout exactly so we can build colors via ARGBToColor.
+inline const Graphics::PixelFormat &renderColorFormat() {
+ static const Graphics::PixelFormat fmt(4, 8, 8, 8, 8, 16, 8, 0, 24);
+ return fmt;
+}
+
+inline uint32 packRGB(byte r, byte g, byte b) {
+ return renderColorFormat().ARGBToColor(255, r, g, b);
+}
+
+// Mac native QuickDraw stores RGB as 16-bit-per-channel; we collapse to 8 bits.
+inline uint32 packMacColor(const uint16 rgb[3]) {
+ return packRGB((byte)(rgb[0] >> 8), (byte)(rgb[1] >> 8), (byte)(rgb[2] >> 8));
+}
+
enum ColonyAction {
kActionNone,
kActionMoveForward,
diff --git a/engines/colony/intro.cpp b/engines/colony/intro.cpp
index 020b284e740..e09190b446e 100644
--- a/engines/colony/intro.cpp
+++ b/engines/colony/intro.cpp
@@ -1125,7 +1125,7 @@ bool ColonyEngine::drawPict(int resID) {
uint32 pixel = surface->getPixel(ix, iy);
surface->format.colorToRGB(pixel, r, g, b);
}
- _gfx->setPixel(sx, sy, 0xFF000000 | ((uint32)r << 16) | ((uint32)g << 8) | b);
+ _gfx->setPixel(sx, sy, packRGB(r, g, b));
}
}
_gfx->copyToScreen();
diff --git a/engines/colony/movement.cpp b/engines/colony/movement.cpp
index 667231e777b..9e7cfcbd87f 100644
--- a/engines/colony/movement.cpp
+++ b/engines/colony/movement.cpp
@@ -63,11 +63,6 @@ const int kTunnelST[] = {
const int kTunnelStraight[60] = {0};
-uint32 packTunnelMacColor(const uint16 rgb[3]) {
- return 0xFF000000 | ((uint32)(rgb[0] >> 8) << 16) |
- ((uint32)(rgb[1] >> 8) << 8) | (uint32)(rgb[2] >> 8);
-}
-
void fillTunnelPattern(Renderer *gfx, const Common::Rect &rect, uint32 fg, uint32 bg, int pattern) {
if (rect.isEmpty())
return;
@@ -801,8 +796,8 @@ void ColonyEngine::playTunnelAirlockEffect() {
const Common::Rect effectRect(0, _menuBarHeight, _width, _height);
const bool macColor = (_renderMode == Common::kRenderMacintosh && _hasMacColors);
const int tunnelColor = 24; // c_tunnel
- const uint32 fillFg = macColor ? packTunnelMacColor(_macColors[tunnelColor].fg) : 0;
- const uint32 fillBg = macColor ? packTunnelMacColor(_macColors[tunnelColor].bg) : 0;
+ const uint32 fillFg = macColor ? packMacColor(_macColors[tunnelColor].fg) : 0;
+ const uint32 fillBg = macColor ? packMacColor(_macColors[tunnelColor].bg) : 0;
const uint32 lineColor = macColor ? 0xFF000000 : 15;
int troy = 180;
int counter = 4;
@@ -899,8 +894,8 @@ void ColonyEngine::playTunnelEffect(bool falling) {
const bool macColor = (_renderMode == Common::kRenderMacintosh && _hasMacColors);
const int tunnelColor = 24; // c_tunnel
const int tunnelFrames = falling ? 10 : 49;
- const uint32 fillFg = macColor ? packTunnelMacColor(_macColors[tunnelColor].fg) : 0;
- const uint32 fillBg = macColor ? packTunnelMacColor(_macColors[tunnelColor].bg) : 0;
+ const uint32 fillFg = macColor ? packMacColor(_macColors[tunnelColor].fg) : 0;
+ const uint32 fillBg = macColor ? packMacColor(_macColors[tunnelColor].bg) : 0;
const uint32 lineColor = macColor ? 0xFF000000 : 15;
int troy = 180;
int cnt = 0;
diff --git a/engines/colony/render_internal.h b/engines/colony/render_internal.h
index b19de4098a4..0af6bb1b877 100644
--- a/engines/colony/render_internal.h
+++ b/engines/colony/render_internal.h
@@ -100,11 +100,6 @@ static const byte *kMacStippleData[] = {
nullptr // kPatternClear - outline only
};
-// Pack Mac 16-bit RGB into 32-bit ARGB with 0xFF000000 marker for direct RGB.
-inline uint32 packMacColor(const uint16 rgb[3]) {
- return 0xFF000000 | ((rgb[0] >> 8) << 16) | ((rgb[1] >> 8) << 8) | (rgb[2] >> 8);
-}
-
// Helper: set up Mac color stipple rendering for a given cColor[] pattern.
// Configures setMacColors/setStippleData/setWireframe for the pattern type.
// Returns the stipple pointer (null for solid patterns) caller must clear with setStippleData(nullptr).
diff --git a/engines/colony/ui.cpp b/engines/colony/ui.cpp
index e0141e5cc75..1ee16d7374f 100644
--- a/engines/colony/ui.cpp
+++ b/engines/colony/ui.cpp
@@ -45,16 +45,6 @@
namespace Colony {
-// Pack RGB into 32-bit ARGB with 0xFF000000 marker for direct RGB rendering.
-uint32 packRGB(byte r, byte g, byte b) {
- return 0xFF000000 | ((uint32)r << 16) | ((uint32)g << 8) | b;
-}
-
-// Pack Mac 16-bit RGB into 32-bit ARGB.
-uint32 packMacColorUI(const uint16 rgb[3]) {
- return 0xFF000000 | ((rgb[0] >> 8) << 16) | ((rgb[1] >> 8) << 8) | (rgb[2] >> 8);
-}
-
bool drawMacTextPopup(Graphics::MacWindowManager *wm, Renderer *gfx,
int screenWidth, int screenHeight, int centerX, int centerY,
const Common::Array<Common::String> &lines, Graphics::TextAlign align, bool macColor) {
@@ -545,7 +535,7 @@ void ColonyEngine::drawDashboardMac() {
const bool macColor = _hasMacColors;
const uint32 colBlack = packRGB(0, 0, 0);
const uint32 colWhite = packRGB(255, 255, 255);
- const uint32 colWinBg = macColor ? packMacColorUI(_macColors[7].bg) : colWhite;
+ const uint32 colWinBg = macColor ? packMacColor(_macColors[7].bg) : colWhite;
// power.c: ForeColor(blueColor) on 1-bit display, blue maps to black
const uint32 colBlue = macColor ? packRGB(0, 0, 255) : colBlack;
Commit: d4a9b8612595323d997348b8ee341f708e062b85
https://github.com/scummvm/scummvm/commit/d4a9b8612595323d997348b8ee341f708e062b85
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2026-04-30T10:16:05+02:00
Commit Message:
COLONY: use managed surfaces to increase performance
Changed paths:
engines/colony/animation.cpp
engines/colony/colony.h
engines/colony/intro.cpp
engines/colony/ui.cpp
diff --git a/engines/colony/animation.cpp b/engines/colony/animation.cpp
index 05436e4cbe0..970fe084230 100644
--- a/engines/colony/animation.cpp
+++ b/engines/colony/animation.cpp
@@ -371,6 +371,12 @@ void ColonyEngine::deleteAnimation() {
_backgroundMask = nullptr;
delete _backgroundFG;
_backgroundFG = nullptr;
+ if (_backgroundBaked) {
+ _backgroundBaked->free();
+ delete _backgroundBaked;
+ _backgroundBaked = nullptr;
+ }
+ _backgroundBakedKey = 0;
for (uint i = 0; i < _cSprites.size(); i++)
delete _cSprites[i];
_cSprites.clear();
@@ -799,7 +805,7 @@ void ColonyEngine::drawAnimation() {
}
drawAnimationImage(_backgroundFG, _backgroundMask,
ox + _backgroundLocate.left, oy + _backgroundLocate.top,
- bgFill);
+ bgFill, _backgroundBaked, _backgroundBakedKey);
}
// Draw complex sprites
@@ -838,54 +844,73 @@ void ColonyEngine::drawComplexSprite(int index, int ox, int oy) {
fillColor = resolveAnimColor(0); // fallback to level-based
}
- drawAnimationImage(s->fg, s->mask, x, y, fillColor);
+ drawAnimationImage(s->fg, s->mask, x, y, fillColor, s->baked, s->bakedKey);
}
-void ColonyEngine::drawAnimationImage(Image *img, Image *mask, int x, int y, uint32 fillColor) {
+void ColonyEngine::drawAnimationImage(Image *img, Image *mask, int x, int y, uint32 fillColor,
+ Graphics::Surface *&bakedCache, uint64 &bakedCacheKey) {
if (!img || !img->data)
return;
- const bool useColor = (_hasMacColors && _renderMode == Common::kRenderMacintosh);
// Mac QuickDraw srcBic+srcOr rendering:
// mask bit=1 -> opaque (part of sprite)
// fg bit=1 -> ForeColor (black)
// 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);
- uint32 fgColor, bgColor;
+
+ // Pixels written into the alpha-keyed RGBA cache. mask=0 â alpha 0
+ // (transparent), so drawSurface's alpha-blend skips them naturally.
+ const Graphics::PixelFormat fmt(4, 8, 8, 8, 8, 24, 16, 8, 0);
+ const uint32 black = fmt.ARGBToColor(255, 0, 0, 0);
+ const uint32 white = fmt.ARGBToColor(255, 255, 255, 255);
+ const uint32 transparent = 0;
+
+ uint32 fgPixel, bgPixel;
if (useColor) {
- fgColor = (uint32)0xFF000000;
- bgColor = fillColor;
+ fgPixel = black;
+ bgPixel = fmt.ARGBToColor(255,
+ (fillColor >> 16) & 0xFF, (fillColor >> 8) & 0xFF, fillColor & 0xFF);
} else if (isMacMode) {
- fgColor = 0;
- bgColor = 15;
+ fgPixel = black;
+ bgPixel = white;
} else {
- fgColor = 15;
- bgColor = 0;
+ fgPixel = white;
+ bgPixel = black;
}
- for (int iy = 0; iy < img->height; iy++) {
- for (int ix = 0; ix < img->width; ix++) {
- int byteIdx = iy * img->rowBytes + (ix / 8);
- int bitIdx = 7 - (ix % 8);
-
- bool maskSet = true;
- if (mask && mask->data) {
- int mByteIdx = iy * mask->rowBytes + (ix / 8);
- int mBitIdx = 7 - (ix % 8);
- maskSet = (mask->data[mByteIdx] & (1 << mBitIdx)) != 0;
+ const uint64 key = ((uint64)fgPixel << 32) | bgPixel;
+ if (!bakedCache || bakedCacheKey != key
+ || bakedCache->w != img->width || bakedCache->h != img->height) {
+ if (bakedCache) {
+ bakedCache->free();
+ delete bakedCache;
+ }
+ bakedCache = new Graphics::Surface();
+ bakedCache->create(img->width, img->height, fmt);
+
+ uint32 *pixels = (uint32 *)bakedCache->getPixels();
+ for (int iy = 0; iy < img->height; iy++) {
+ const byte *fgRow = img->data + iy * img->rowBytes;
+ const byte *maskRow = (mask && mask->data) ? mask->data + iy * mask->rowBytes : nullptr;
+ uint32 *dst = pixels + iy * img->width;
+ for (int ix = 0; ix < img->width; ix++) {
+ const int bitIdx = 7 - (ix & 7);
+ const bool maskSet = !maskRow || ((maskRow[ix >> 3] & (1 << bitIdx)) != 0);
+ if (!maskSet) {
+ dst[ix] = transparent;
+ continue;
+ }
+ const bool fgSet = (fgRow[ix >> 3] & (1 << bitIdx)) != 0;
+ dst[ix] = fgSet ? fgPixel : bgPixel;
}
-
- if (!maskSet)
- continue;
-
- bool fgSet = (img->data[byteIdx] & (1 << bitIdx)) != 0;
- uint32 color = fgSet ? fgColor : bgColor;
-
- _gfx->setPixel(x + ix, y + iy, color);
}
+ bakedCacheKey = key;
}
+
+ _gfx->drawSurface(bakedCache, x, y);
}
Image *ColonyEngine::loadImage(Common::SeekableReadStreamEndian &file) {
diff --git a/engines/colony/colony.h b/engines/colony/colony.h
index 073cfd73f09..a7f70bc0876 100644
--- a/engines/colony/colony.h
+++ b/engines/colony/colony.h
@@ -35,6 +35,7 @@
#include "engines/advancedDetector.h"
#include "engines/engine.h"
#include "graphics/pixelformat.h"
+#include "graphics/surface.h"
namespace Common {
class MacResManager;
@@ -48,7 +49,6 @@ class FrameLimiter;
class MacMenu;
class MacWindowManager;
class ManagedSurface;
-struct Surface;
}
namespace Colony {
@@ -392,8 +392,22 @@ struct Sprite {
Common::Rect locate;
bool used;
- Sprite() : fg(nullptr), mask(nullptr), used(false) {}
- ~Sprite() { delete fg; delete mask; }
+ // Per-sprite render cache: bit-pattern + mask are baked into an
+ // alpha-keyed RGBA surface and uploaded once via drawSurface, instead
+ // of issuing setPixel per pixel each frame. Invalidated when the
+ // (fgColor, bgColor) pair changes (level/palette transition).
+ Graphics::Surface *baked;
+ uint64 bakedKey;
+
+ Sprite() : fg(nullptr), mask(nullptr), used(false), baked(nullptr), bakedKey(0) {}
+ ~Sprite() {
+ delete fg;
+ delete mask;
+ if (baked) {
+ baked->free();
+ delete baked;
+ }
+ }
};
struct ComplexSprite {
@@ -725,6 +739,10 @@ private:
Common::Array<ComplexSprite *> _lSprites;
Image *_backgroundMask = nullptr;
Image *_backgroundFG = nullptr;
+ // Same render cache convention as Sprite::baked, applied to the
+ // per-animation background image (no Sprite owner, so it lives here).
+ Graphics::Surface *_backgroundBaked = nullptr;
+ uint64 _backgroundBakedKey = 0;
Common::Rect _backgroundClip;
Common::Rect _backgroundLocate;
bool _backgroundActive;
@@ -774,7 +792,8 @@ private:
void updateAnimation();
void drawAnimation();
void drawComplexSprite(int index, int ox, int oy);
- void drawAnimationImage(Image *img, Image *mask, int x, int y, uint32 fillColor = 0xFFFFFFFF);
+ void drawAnimationImage(Image *img, Image *mask, int x, int y, uint32 fillColor,
+ Graphics::Surface *&bakedCache, uint64 &bakedCacheKey);
uint32 resolveAnimColor(int16 bmEntry) const;
Image *loadImage(Common::SeekableReadStreamEndian &file);
void unpackBytes(Common::SeekableReadStreamEndian &file, byte *dst, uint32 len);
diff --git a/engines/colony/intro.cpp b/engines/colony/intro.cpp
index e09190b446e..eee3ebe8dc5 100644
--- a/engines/colony/intro.cpp
+++ b/engines/colony/intro.cpp
@@ -971,12 +971,11 @@ bool ColonyEngine::timeSquare(const Common::String &str, const Graphics::Font *m
_gfx->setPalette(pal, textIndex, 1);
}
- // Draw the blue gradient lines above/below the center band.
+ // Draw the blue gradient bands above/below the center band â each
+ // iteration is a 2-pixel-tall stripe in palette index 160+i.
for (int i = 0; i < 16; i++) {
- _gfx->drawLine(0, centery - 2 - i * 2, _width, centery - 2 - i * 2, 160 + i);
- _gfx->drawLine(0, centery - 2 - (i * 2 + 1), _width, centery - 2 - (i * 2 + 1), 160 + i);
- _gfx->drawLine(0, centery + 16 + i * 2, _width, centery + 16 + i * 2, 160 + i);
- _gfx->drawLine(0, centery + 16 + i * 2 + 1, _width, centery + 16 + i * 2 + 1, 160 + i);
+ _gfx->fillRect(Common::Rect(0, centery - 3 - i * 2, _width, centery - 1 - i * 2), 160 + i);
+ _gfx->fillRect(Common::Rect(0, centery + 16 + i * 2, _width, centery + 18 + i * 2), 160 + i);
}
} else {
// DOS warning band: white outer lines, gray inner lines, white text.
diff --git a/engines/colony/ui.cpp b/engines/colony/ui.cpp
index 1ee16d7374f..f82440cd37f 100644
--- a/engines/colony/ui.cpp
+++ b/engines/colony/ui.cpp
@@ -233,25 +233,14 @@ Graphics::Surface *ColonyEngine::loadPictSurface(int resID) {
return result;
}
-// Draw a PICT surface at a specific destination position using packRGB.
-// Matches original DrawPicture(pic, &rect) where rect is positioned at (destX, destY).
+// 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.
void ColonyEngine::drawPictAt(Graphics::Surface *surf, int destX, int destY) {
if (!surf)
return;
- for (int y = 0; y < surf->h; y++) {
- int sy = destY + y;
- if (sy < 0 || sy >= _height)
- continue;
- for (int x = 0; x < surf->w; x++) {
- int sx = destX + x;
- if (sx < 0 || sx >= _width)
- continue;
- uint32 pixel = surf->getPixel(x, y);
- byte a, r, g, b;
- surf->format.colorToARGB(pixel, a, r, g, b);
- _gfx->setPixel(sx, sy, packRGB(r, g, b));
- }
- }
+ _gfx->drawSurface(surf, destX, destY);
}
void ColonyEngine::updateViewportLayout() {
More information about the Scummvm-git-logs
mailing list