[Scummvm-git-logs] scummvm master -> e8cfe46d2156238f170f10fbc68c39d53db7adb2
mgerhardy
noreply at scummvm.org
Sun Jul 5 08:58:41 UTC 2026
This automated email contains information about 3 new commits which have been
pushed to the 'scummvm' repo located at https://api.github.com/repos/scummvm/scummvm .
Summary:
ee699988c6 MACS2: fixed wrong main menu conditions and switching scenes when actor x coordinate is negative
d65c1fbe08 MACS2: revert "fixed center of mouse cursor sprite"
e8cfe46d21 MACS2: convert imgui debugger into a window to ensure that the top can get clicked to trigger scene switches
Commit: ee699988c61586703d37419ddb095160fbcfdc3f
https://github.com/scummvm/scummvm/commit/ee699988c61586703d37419ddb095160fbcfdc3f
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2026-07-05T10:54:47+02:00
Commit Message:
MACS2: fixed wrong main menu conditions and switching scenes when actor x coordinate is negative
Changed paths:
engines/macs2/scriptexecutor.cpp
engines/macs2/view1.cpp
diff --git a/engines/macs2/scriptexecutor.cpp b/engines/macs2/scriptexecutor.cpp
index da5990d9ea5..bedff69742b 100644
--- a/engines/macs2/scriptexecutor.cpp
+++ b/engines/macs2/scriptexecutor.cpp
@@ -1042,6 +1042,21 @@ void Script::ScriptExecutor::scriptMoveObject() {
_stream->seek(0, SEEK_END);
}
+ // Binary (1008:aa83): when runtime data exists, sync target/finalDest to the new
+ // object position so a subsequent waitForWalk completes immediately.
+ if (object->_dataOffset != 0) {
+ GameObject::StoredWalkRuntime &s = object->_storedWalkRuntime;
+ s.valid = true;
+ s.targetPosition = object->_position;
+ s.pathFinalDestination = object->_position;
+ s.currentPathIndex = 0;
+ s.path.clear();
+ s.stepDeltaX = 0;
+ s.stepDeltaY = 0;
+ s.stepError = 0;
+ s.stepDirectionSet = false;
+ }
+
currentView->rebuildCharacterLookupTable();
}
@@ -1314,16 +1329,15 @@ ExecutionResult Script::ScriptExecutor::scriptWaitForWalk() {
endBuffering(_lastOpcodeTriggeredSkip);
return ExecutionResult::ScriptFinished;
}
- // Original checks runtime+0x231 (frozen/attached flag) -> error 0x1F
- if (walkObject->_hasBoundsAttachment) {
- setScriptError(0x1F);
+ // Binary (1008:db56 opcode 0x11): object+0x0A runtime must exist; no on-screen Character required.
+ if (walkObject->_dataOffset == 0) {
+ setScriptError(2);
endBuffering(_lastOpcodeTriggeredSkip);
return ExecutionResult::ScriptFinished;
}
- View1 *currentView = (View1 *)_engine->findView("View1");
- Character *c = currentView->getCharacterByIndex(objectID);
- if (c == nullptr) {
- setScriptError(2);
+ // Original checks runtime+0x231 (frozen/attached flag) -> error 0x1F
+ if (walkObject->_hasBoundsAttachment) {
+ setScriptError(0x1F);
endBuffering(_lastOpcodeTriggeredSkip);
return ExecutionResult::ScriptFinished;
}
diff --git a/engines/macs2/view1.cpp b/engines/macs2/view1.cpp
index 5abf0a7c2b3..65b3371cc81 100644
--- a/engines/macs2/view1.cpp
+++ b/engines/macs2/view1.cpp
@@ -1663,14 +1663,21 @@ bool View1::handleInput(const MouseDownMessage &msg) {
_savedCursorMode = g_engine->_scriptExecutor->_cursorMode;
openOriginalSaveLoadPanel();
} else {
+ // Binary save/load path saves cursor then sets PanelCursor (0x19).
+ _savedCursorMode = g_engine->_scriptExecutor->_cursorMode;
+ g_engine->setCursorMode(Script::MouseMode::PanelCursor);
g_engine->openMainMenuDialog();
+ updateCursor();
}
}
return true;
}
- // From handleInput (1008:e8bf): right-click when not executing
+ // From handleInput (1008:e8bf): right-click when not executing and cursor != Disabled
// opens the action bar at the mouse position.
+ if (g_engine->_scriptExecutor->_cursorMode == Script::MouseMode::Disabled) {
+ return true;
+ }
if (_uiPanelState != kUiPanelActionBar) {
openMainMenu(msg._pos);
} else {
@@ -1712,6 +1719,14 @@ bool View1::handlePanelRelease(const MouseUpMessage &msg) {
return false;
}
+ // Binary handleInput (1008:e8bf): action bar/inventory panel release is only handled
+ // when g_wScriptIsExecuting==0 and g_wCursorMode!=0x1A. Save/load (state 4) still
+ // closes during script execution.
+ if (g_engine->_scriptExecutor->isExecuting() &&
+ _uiPanelState != kUiPanelSaveLoad) {
+ return true;
+ }
+
const UiPanelState previousState = _uiPanelState;
bool shouldClose = false;
@@ -1823,6 +1838,15 @@ bool View1::msgAction(const ActionMessage &msg) {
debug("Game speed mode: %u", g_engine->_gameSpeedMode);
return true;
case Macs2::kMacs2ActionOpenGMM:
+ // Binary has no GMM; mirror save/load panel cursor handling when a script wait is active.
+ if (g_engine->_scriptExecutor->isExecuting()) {
+ if (g_engine->_scriptExecutor->_cursorMode == Script::MouseMode::Disabled) {
+ _savedCursorMode = g_engine->_scriptExecutor->_cursorMode;
+ g_engine->setCursorMode(Script::MouseMode::PanelCursor);
+ }
+ } else if (g_engine->_scriptExecutor->_cursorMode == Script::MouseMode::Disabled) {
+ return true;
+ }
g_engine->openMainMenuDialog();
updateCursor();
return true;
@@ -2158,6 +2182,7 @@ bool View1::tick() {
executor->_walkTargetObjectIndex = 0;
} else {
Character *c = getCharacterByIndex(walkTarget);
+ bool walkComplete = false;
if (c != nullptr) {
Common::Point pos = c->getPosition();
// Binary: walkAlongPath guarantees pos == finalDest on arrival.
@@ -2169,20 +2194,31 @@ bool View1::tick() {
c->_motionProgress == 0) {
c->_motionTargetVerticalOffset = walkObject->_verticalOffsetScale;
}
- bool verticalOk = !c->hasPendingVerticalMotion();
- if (verticalOk) {
- if (!executor->_pickupInProgress) {
- executor->_walkTargetObjectIndex = 0;
- g_engine->runScriptExecutor();
- } else if (c->_gameObject->_orientation != 0x11) {
- // Binary: pickup in progress, trigger pickup animation.
- // Save current orientation so it can be restored after pickup.
- c->_previousOrientation = c->_gameObject->_orientation;
- c->_gameObject->_orientation = 0x11;
- }
+ walkComplete = !c->hasPendingVerticalMotion();
+ }
+ } else if (walkObject->_storedWalkRuntime.valid) {
+ // Binary gameTick (1008:e752): polls object table pos vs runtime finalDest;
+ // no on-screen Character is required (e.g. after moveObject to another scene).
+ const GameObject::StoredWalkRuntime &rt = walkObject->_storedWalkRuntime;
+ if (walkObject->_position.x == rt.pathFinalDestination.x &&
+ walkObject->_position.y == rt.pathFinalDestination.y) {
+ if ((int16)rt.motionTargetVerticalOffset < 0 ||
+ rt.motionTargetVerticalOffset == walkObject->_verticalOffsetScale) {
+ walkComplete = true;
}
}
}
+ if (walkComplete) {
+ if (!executor->_pickupInProgress) {
+ executor->_walkTargetObjectIndex = 0;
+ g_engine->runScriptExecutor();
+ } else if (c != nullptr && c->_gameObject->_orientation != 0x11) {
+ // Binary: pickup in progress, trigger pickup animation.
+ // Save current orientation so it can be restored after pickup.
+ c->_previousOrientation = c->_gameObject->_orientation;
+ c->_gameObject->_orientation = 0x11;
+ }
+ }
}
} else if (executor->_waitForPcmSound) {
drawSceneUpdate();
Commit: d65c1fbe086e65a378bfc51939e13119a4d7d09c
https://github.com/scummvm/scummvm/commit/d65c1fbe086e65a378bfc51939e13119a4d7d09c
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2026-07-05T10:57:42+02:00
Commit Message:
MACS2: revert "fixed center of mouse cursor sprite"
This reverts commit ddb9646d8c505331034ed627688e8e39f1cc8e0d.
This was in fact an error elsewhere: see 641e3d987e70009cb6b3d02fbb431ad00fc9ef0f
Changed paths:
engines/macs2/macs2.cpp
engines/macs2/view1.cpp
diff --git a/engines/macs2/macs2.cpp b/engines/macs2/macs2.cpp
index 56cf79321f5..1904014ce66 100644
--- a/engines/macs2/macs2.cpp
+++ b/engines/macs2/macs2.cpp
@@ -1120,10 +1120,38 @@ int Macs2Engine::computeMinCostToReachable(int nodeIndex, int prevNode, uint16 a
}
void Macs2Engine::setCursorMode(Script::MouseMode newMode) {
- // setCursorMode (1008:3ea5): binary adjusts top-left by old/new half-extents.
+ // setCursorMode (1008:3ea5): when the cursor image changes, keep the hotspot
+ // fixed on screen by compensating for the old/new image half-extents, clamp,
+ // refresh the cursor graphic, and flag the clip rect dirty.
+ const Script::MouseMode oldMode = _scriptExecutor->_cursorMode;
const bool cursorVisible = CursorMan.isVisible();
+ auto cursorHalfSize = [this](Script::MouseMode mode, uint16 &halfW, uint16 &halfH) {
+ halfW = halfH = 0;
+ const int index = (int)mode - 1;
+ if (index < 0 || index >= (int)_imageResources.size())
+ return;
+ halfW = _imageResources[index]._width / 2;
+ halfH = _imageResources[index]._height / 2;
+ };
+
+ uint16 oldHalfW = 0, oldHalfH = 0, newHalfW = 0, newHalfH = 0;
+ cursorHalfSize(oldMode, oldHalfW, oldHalfH);
+
+ Common::Point mouse = g_system->getEventManager()->getMousePos();
+ mouse.x += oldHalfW;
+ mouse.y += oldHalfH;
+
_scriptExecutor->_cursorMode = newMode;
+
+ cursorHalfSize(newMode, newHalfW, newHalfH);
+ mouse.x -= newHalfW;
+ mouse.y -= newHalfH;
+
+ mouse.x = CLIP<int>(mouse.x, (int)newHalfW, 319 - (int)newHalfW);
+ mouse.y = CLIP<int>(mouse.y, (int)newHalfH, 199 - (int)newHalfH);
+ g_system->warpMouse(mouse.x, mouse.y);
+
_clipRectDirty = true;
if (View1 *view = (View1 *)findView("View1"))
diff --git a/engines/macs2/view1.cpp b/engines/macs2/view1.cpp
index 65b3371cc81..0f509a4aa3f 100644
--- a/engines/macs2/view1.cpp
+++ b/engines/macs2/view1.cpp
@@ -28,7 +28,6 @@
#include "engines/enhancements.h"
#include "graphics/cursorman.h"
#include "graphics/paletteman.h"
-#include "graphics/scaler/aspect.h"
#include "macs2/debugtools.h"
#include "macs2/detection.h"
#include "macs2/gameobjects.h"
@@ -118,28 +117,6 @@ void buildFadedPalette(byte *colors, const byte *sourcePalette, int fadeValue) {
}
}
-static Common::Point cursorReplaceHotspot(uint16 width, uint16 height) {
- const uint scale = MAX(1u, g_system->getScaleFactor());
- const int hotX = (int)width / (2 * (int)scale);
- int hotY = (int)height / (2 * (int)scale);
-
- if (g_system->getFeatureState(OSystem::kFeatureAspectRatioCorrection)) {
- const int target = (int)height / 2;
- int bestHotY = hotY;
- int bestErr = ABS(real2Aspect(bestHotY * (int)scale) - target);
- for (int candidate = 0; candidate <= (int)height; candidate++) {
- const int err = ABS(real2Aspect(candidate * (int)scale) - target);
- if (err < bestErr) {
- bestErr = err;
- bestHotY = candidate;
- }
- }
- hotY = bestHotY;
- }
-
- return Common::Point(hotX, hotY);
-}
-
} // namespace
const View1::BorderStyle View1::kBorderRaised = {0x1010, 0x1012, 0x1011};
@@ -385,10 +362,7 @@ void View1::updateCursor(const byte *palette) {
rgbaCursor[i] = rgbaCursorFormat.RGBToColor(paletteEntry[0], paletteEntry[1], paletteEntry[2]);
}
- // adjustViewportToMouse (1008:3de3): interaction center = mouse; draw at center - half.
- // getMousePos() is the center; compensate hotspot for SurfaceSdl rHot scaling (see above).
- const Common::Point hotspot = cursorReplaceHotspot(width, height);
- CursorMan.replaceCursor(rgbaCursor.data(), width, height, hotspot.x, hotspot.y, 0, &rgbaCursorFormat);
+ CursorMan.replaceCursor(rgbaCursor.data(), width, height, width >> 1, height >> 1, 0, &rgbaCursorFormat);
// Enable a cursor palette so the backend won't re-blit the cursor on
// every screen palette change. The macs2 engine uses RGBA cursors with
// baked-in palette colors, so the cursor palette content is irrelevant -
Commit: e8cfe46d2156238f170f10fbc68c39d53db7adb2
https://github.com/scummvm/scummvm/commit/e8cfe46d2156238f170f10fbc68c39d53db7adb2
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2026-07-05T10:58:28+02:00
Commit Message:
MACS2: convert imgui debugger into a window to ensure that the top can get clicked to trigger scene switches
Changed paths:
engines/macs2/debugtools.cpp
diff --git a/engines/macs2/debugtools.cpp b/engines/macs2/debugtools.cpp
index 387905dbfa0..a1e6c29dc05 100644
--- a/engines/macs2/debugtools.cpp
+++ b/engines/macs2/debugtools.cpp
@@ -1988,6 +1988,7 @@ static void showObjectScriptsWindow() {
}
static void showSoundWindow();
+static void showDebugToolbarWindow();
bool shouldDrawPathfindingOverlay() {
return _showPathfindingOverlay;
@@ -2012,7 +2013,34 @@ void onImGuiRender() {
}
ImGui::GetIO().ConfigFlags &= ~(ImGuiConfigFlags_NoMouseCursorChange | ImGuiConfigFlags_NoMouse);
- if (ImGui::BeginMainMenuBar()) {
+ showDebugToolbarWindow();
+ showScriptWindow();
+ showObjectScriptsWindow();
+ showBreakpointsWindow();
+ showVariablesWindow();
+ showCharactersWindow();
+ drawHoveredObjectOverlay();
+ showAnimViewerWindow();
+ showInventoryWindow();
+ showAnimationsWindow();
+ showSceneMapsWindow();
+ showImageResourcesWindow();
+ showDebugOutputWindow();
+ showTextLogWindow();
+ showSoundWindow();
+}
+
+static void showDebugToolbarWindow() {
+ // Movable toolbar window instead of BeginMainMenuBar(), which reserves the full
+ // viewport width and intercepts clicks along the top edge of the game view.
+ ImGui::SetNextWindowPos(ImVec2(8.0f, 8.0f), ImGuiCond_FirstUseEver);
+ const ImGuiWindowFlags flags = ImGuiWindowFlags_MenuBar | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoCollapse;
+ if (!ImGui::Begin("MACS2 Debug", nullptr, flags)) {
+ ImGui::End();
+ return;
+ }
+
+ if (ImGui::BeginMenuBar()) {
if (ImGui::BeginMenu("Debug")) {
ImGui::MenuItem("Script", NULL, &_showScript);
ImGui::MenuItem("Object Scripts", NULL, &_showObjectScripts);
@@ -2047,21 +2075,25 @@ void onImGuiRender() {
for (const auto &ch : channels) {
bool enabled = debugChannelSet(-1, ch.flag);
if (ImGui::MenuItem(ch.name, NULL, enabled)) {
- if (enabled)
+ if (enabled) {
DebugMan.disableDebugChannel(ch.flag);
- else
+ } else {
DebugMan.enableDebugChannel(ch.flag);
+ }
}
}
ImGui::EndMenu();
}
if (ImGui::BeginMenu("Speed")) {
- if (ImGui::MenuItem("Normal", NULL, g_engine->_gameSpeedMode == 0))
+ if (ImGui::MenuItem("Normal", NULL, g_engine->_gameSpeedMode == 0)) {
g_engine->_gameSpeedMode = 0;
- if (ImGui::MenuItem("Fast", NULL, g_engine->_gameSpeedMode == 1))
+ }
+ if (ImGui::MenuItem("Fast", NULL, g_engine->_gameSpeedMode == 1)) {
g_engine->_gameSpeedMode = 1;
- if (ImGui::MenuItem("Slow", NULL, g_engine->_gameSpeedMode == 2))
+ }
+ if (ImGui::MenuItem("Slow", NULL, g_engine->_gameSpeedMode == 2)) {
g_engine->_gameSpeedMode = 2;
+ }
ImGui::EndMenu();
}
if (ImGui::BeginMenu("Tools")) {
@@ -2070,50 +2102,58 @@ void onImGuiRender() {
ImGui::MenuItem("Auto-click (simulate repeated clicks)", NULL, &toolsView->_autoclickActive);
}
ImGui::Separator();
- if (ImGui::MenuItem("Quick Start (Scene 6)"))
+ if (ImGui::MenuItem("Quick Start (Scene 6)")) {
g_engine->changeScene(0x6);
+ }
ImGui::Separator();
static int sceneInput = 1;
ImGui::SetNextItemWidth(60);
ImGui::InputInt("##scn", &sceneInput, 1, 10);
ImGui::SameLine();
if (ImGui::MenuItem("Change Scene")) {
- if (sceneInput > 0 && sceneInput <= 512)
+ if (sceneInput > 0 && sceneInput <= 512) {
g_engine->changeScene((uint32)sceneInput);
+ }
}
ImGui::Separator();
- if (ImGui::MenuItem("Run Script Executor"))
+ if (ImGui::MenuItem("Run Script Executor")) {
g_engine->runScriptExecutor(true);
+ }
static int dosSaveSlot = 0;
ImGui::SetNextItemWidth(60);
ImGui::InputInt("##dosslot", &dosSaveSlot, 1, 1);
- if (dosSaveSlot < 0)
+ if (dosSaveSlot < 0) {
dosSaveSlot = 0;
- if (dosSaveSlot > 9)
+ }
+ if (dosSaveSlot > 9) {
dosSaveSlot = 9;
+ }
ImGui::SameLine();
if (ImGui::MenuItem("Save to original DOS slot (SAVEGAME.N)")) {
Common::Error err = g_engine->saveOriginalGameState(dosSaveSlot);
- if (err.getCode() != Common::kNoError)
+ if (err.getCode() != Common::kNoError) {
warning("Failed to write original DOS save SAVEGAME.%d", dosSaveSlot);
- else
+ } else {
debug("Wrote original DOS save SAVEGAME.%d", dosSaveSlot);
+ }
}
static int dosLoadSlot = 0;
ImGui::SetNextItemWidth(60);
ImGui::InputInt("##dosloadslot", &dosLoadSlot, 1, 1);
- if (dosLoadSlot < 0)
+ if (dosLoadSlot < 0) {
dosLoadSlot = 0;
- if (dosLoadSlot > 9)
+ }
+ if (dosLoadSlot > 9) {
dosLoadSlot = 9;
+ }
ImGui::SameLine();
if (ImGui::MenuItem("Load original DOS slot (SAVEGAME.N)")) {
- // loadGameState slots 100..109 map to original DOS SAVEGAME.0..9
Common::Error err = g_engine->loadGameState(100 + dosLoadSlot);
- if (err.getCode() != Common::kNoError)
+ if (err.getCode() != Common::kNoError) {
warning("Failed to load original DOS save SAVEGAME.%d", dosLoadSlot);
- else
+ } else {
debug("Loaded original DOS save SAVEGAME.%d", dosLoadSlot);
+ }
}
if (ImGui::MenuItem("Reset Background + Fade")) {
View1 *view = (View1 *)g_engine->findView("View1");
@@ -2129,12 +2169,15 @@ void onImGuiRender() {
if (view->isInventorySourceProtagonist()) {
const uint16 currentScene = Scenes::instance()._currentSceneIndex;
for (GameObject *obj : GameObjects::instance()._objects) {
- if (obj == nullptr)
+ if (obj == nullptr) {
continue;
- if ((int16)obj->_sceneIndex < 0 || obj->_sceneIndex != currentScene)
+ }
+ if ((int16)obj->_sceneIndex < 0 || obj->_sceneIndex != currentScene) {
continue;
- if (0x13 >= obj->_blobs.size() || obj->_blobs[0x13].empty())
+ }
+ if (0x13 >= obj->_blobs.size() || obj->_blobs[0x13].empty()) {
continue;
+ }
view->transferInventoryItem(view->_activeInventoryItem, obj);
view->_activeInventoryItem = nullptr;
view->setInventorySource(view->_inventorySource);
@@ -2149,25 +2192,13 @@ void onImGuiRender() {
}
ImGui::EndMenu();
}
- ImGui::Text("| Scene: %d | Speed: %s", Scenes::instance()._currentSceneIndex,
+ ImGui::Separator();
+ ImGui::Text("Scene: %d | Speed: %s", Scenes::instance()._currentSceneIndex,
g_engine->_gameSpeedMode == 0 ? "Normal" : (g_engine->_gameSpeedMode == 1 ? "Fast" : "Slow"));
- ImGui::EndMainMenuBar();
+ ImGui::EndMenuBar();
}
- showScriptWindow();
- showObjectScriptsWindow();
- showBreakpointsWindow();
- showVariablesWindow();
- showCharactersWindow();
- drawHoveredObjectOverlay();
- showAnimViewerWindow();
- showInventoryWindow();
- showAnimationsWindow();
- showSceneMapsWindow();
- showImageResourcesWindow();
- showDebugOutputWindow();
- showTextLogWindow();
- showSoundWindow();
+ ImGui::End();
}
static void showSoundWindow() {
More information about the Scummvm-git-logs
mailing list