[Scummvm-git-logs] scummvm master -> d98cb3af02bf2845de72a13c96d995f84152792c

alexbevi noreply at scummvm.org
Wed Oct 21 10:58:12 UTC 2026


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

Summary:
8fc6788885 HARVESTER: Show help screen when F1 is pressed
d98cb3af02 HARVESTER: Properly handled deferred palette fades after movies


Commit: 8fc67888853e699607dd36505faf3c58d69e07b0
    https://github.com/scummvm/scummvm/commit/8fc67888853e699607dd36505faf3c58d69e07b0
Author: Alex Bevilacqua (alex at alexbevi.com)
Date: 2026-10-21T06:57:51-04:00

Commit Message:
HARVESTER: Show help screen when F1 is pressed

Assisted-by: Codex:gpt-6.1-sol

Changed paths:
    engines/harvester/flow/flow.cpp
    engines/harvester/flow/flow.h
    engines/harvester/menu/menu.h
    engines/harvester/metaengine.cpp
    engines/harvester/scene/input.h
    engines/harvester/scene/input_keyboard.cpp


diff --git a/engines/harvester/flow/flow.cpp b/engines/harvester/flow/flow.cpp
index db68aea317a..8d20e005c61 100644
--- a/engines/harvester/flow/flow.cpp
+++ b/engines/harvester/flow/flow.cpp
@@ -22,9 +22,11 @@
 #include "harvester/flow/flow.h"
 
 #include "common/algorithm.h"
+#include "common/debug.h"
 #include "common/events.h"
 #include "common/memstream.h"
 #include "common/serializer.h"
+#include "harvester/detection.h"
 #include "harvester/harvester.h"
 #include "harvester/scene/input.h"
 #include "harvester/entity.h"
@@ -164,6 +166,17 @@ Common::Error Flow::runMainMenu() {
 	return _menu.runMainMenu(*this);
 }
 
+Common::Error Flow::runHelpScreen(const byte *palette, float paletteBrightness) {
+	EntityManager *entityManager = _engine.getRuntimeEntities();
+	if (entityManager)
+		entityManager->pauseTimerCountdowns();
+	Common::Error result = _menu.runHelpScreen(palette, paletteBrightness, *this);
+	if (entityManager)
+		entityManager->resumeTimerCountdowns();
+	debugC(1, kDebugRoom, "Harvester: help screen close error=%d", result.getCode());
+	return result;
+}
+
 Common::Error Flow::runRoomMenu(const IndexedBitmap &backdrop, const byte *palette,
 		float paletteBrightness, bool canSaveGame) {
 	return _menu.runRoomMenu(backdrop, palette, paletteBrightness, *this, canSaveGame);
diff --git a/engines/harvester/flow/flow.h b/engines/harvester/flow/flow.h
index 2d4a310d734..ff8f00a775a 100644
--- a/engines/harvester/flow/flow.h
+++ b/engines/harvester/flow/flow.h
@@ -71,6 +71,7 @@ public:
 	bool requestDebugRoomChange(const Common::String &roomName);
 
 	Common::Error runDemoEnding();
+	Common::Error runHelpScreen(const byte *palette, float paletteBrightness);
 	Common::Error runRoomMenu(const IndexedBitmap &backdrop, const byte *palette,
 		float paletteBrightness, bool canSaveGame);
 	Common::Error runRoomNpcDialogue(const IndexedBitmap &backdrop, const byte *palette,
diff --git a/engines/harvester/menu/menu.h b/engines/harvester/menu/menu.h
index a1df12c29fb..8e959305c1a 100644
--- a/engines/harvester/menu/menu.h
+++ b/engines/harvester/menu/menu.h
@@ -93,6 +93,7 @@ public:
 		const Common::Array<Common::String> &menuItems);
 
 	Common::Error runMainMenu(Flow &flow);
+	Common::Error runHelpScreen(const byte *palette, float paletteBrightness, Flow &flow);
 	Common::Error runRoomMenu(const IndexedBitmap &backdrop, const byte *palette,
 		float paletteBrightness, Flow &flow, bool canSaveGame);
 	Common::Error validateParentalPassword(Flow &flow);
@@ -155,7 +156,6 @@ private:
 		Flow &flow, bool &loadedGame);
 	Common::Error runOptionsMenu(const IndexedBitmap &backdrop, const byte *palette,
 		float paletteBrightness, Flow &flow);
-	Common::Error runHelpScreen(const byte *palette, float paletteBrightness, Flow &flow);
 	Common::Error runSaveGameMenu(const byte *palette, float paletteBrightness,
 		Flow &flow, bool &savedGame);
 	Common::Error restoreRoomBackdropAfterSave(const IndexedBitmap &backdrop, const byte *palette,
diff --git a/engines/harvester/metaengine.cpp b/engines/harvester/metaengine.cpp
index 08ec130bde0..d8a248ac878 100644
--- a/engines/harvester/metaengine.cpp
+++ b/engines/harvester/metaengine.cpp
@@ -88,14 +88,15 @@ Common::KeymapArray HarvesterMetaEngine::initKeymaps(const char *target) const {
 		{ "RIGHT", _s("Move right"), kActionMoveRight, "RIGHT", "JOY_RIGHT" },
 		{ "UP", _s("Move up"), kActionMoveUp, "UP", "JOY_UP" },
 		{ "DOWN", _s("Move down"), kActionMoveDown, "DOWN", "JOY_DOWN" },
-		{ "ATTACK", _s("Attack modifier"), kActionAttackModifier, "LCTRL", "RCTRL" },
-		{ "EVADE", _s("Evasive movement modifier"), kActionEvasiveModifier, "RSHIFT", nullptr },
 		{ "SPEEDUP", _s("Speed up"), kActionSpeedUp, "LALT", "RALT" },
 		{ "INVENTORY", _s("Inventory"), kActionInventory, "i", nullptr },
 		{ "MENU", _s("Game menu"), kActionMenu, "ESCAPE", "JOY_Y" },
+		{ "HELP", _s("Help menu"), kActionHelp, "F1", nullptr },
+		{ "ATTACK", _s("Attack modifier"), kActionAttackModifier, "LCTRL", "RCTRL" },
 		{ "HIGHATTACK", _s("High attack"), kActionHighAttack, nullptr, nullptr },
 		{ "MEDIUMATTACK", _s("Medium attack"), kActionMediumAttack, nullptr, nullptr },
 		{ "LOWATTACK", _s("Low attack"), kActionLowAttack, nullptr, nullptr },
+		{ "EVADE", _s("Evasive movement modifier"), kActionEvasiveModifier, "RSHIFT", nullptr },
 		{ "DUCK", _s("Duck"), kActionDuck, nullptr, nullptr },
 		{ "JUMP", _s("Jump"), kActionJump, nullptr, nullptr }
 	};
diff --git a/engines/harvester/scene/input.h b/engines/harvester/scene/input.h
index d3f58d24b83..d01c593480e 100644
--- a/engines/harvester/scene/input.h
+++ b/engines/harvester/scene/input.h
@@ -63,6 +63,7 @@ enum GameAction {
 	kActionSpeedUp,
 	kActionInventory,
 	kActionMenu,
+	kActionHelp,
 	kActionHighAttack,
 	kActionMediumAttack,
 	kActionLowAttack,
@@ -149,6 +150,7 @@ private:
 	InputResult applyCheatActivation(InteractionResult &cheatInteraction,
 		const CheatActivation &cheatActivation, bool &needsRedraw);
 	InputResult openRoomMenu(bool &needsRedraw);
+	InputResult openHelpScreen(bool &needsRedraw);
 	void beginInspectText(const ObjectRecord &object, const ResolvedText &text);
 	InputResult finishInspectText(bool &needsRedraw);
 	InputResult applyObjectInteraction(InteractionResult &interaction, bool &needsRedraw);
diff --git a/engines/harvester/scene/input_keyboard.cpp b/engines/harvester/scene/input_keyboard.cpp
index 0c2fb74ccde..ae9c7831e4e 100644
--- a/engines/harvester/scene/input_keyboard.cpp
+++ b/engines/harvester/scene/input_keyboard.cpp
@@ -78,7 +78,7 @@ InputResult Input::handleGameAction(GameAction action, bool pressed, bool &needs
 	static const Common::KeyCode keys[] = {
 		Common::KEYCODE_LEFT, Common::KEYCODE_RIGHT, Common::KEYCODE_UP, Common::KEYCODE_DOWN,
 		Common::KEYCODE_LCTRL, Common::KEYCODE_RSHIFT, Common::KEYCODE_LALT,
-		Common::KEYCODE_i, Common::KEYCODE_ESCAPE
+		Common::KEYCODE_i, Common::KEYCODE_ESCAPE, Common::KEYCODE_F1
 	};
 	if ((uint)action >= ARRAYSIZE(keys))
 		return InputResult();
@@ -161,6 +161,9 @@ InputResult Input::handleGameplayKeyDown(const Common::KeyState &key,
 	else if (gameAction && key.keycode == Common::KEYCODE_DOWN)
 		inputState.moveDown = true;
 
+	if (gameAction && key.keycode == Common::KEYCODE_F1)
+		return openHelpScreen(needsRedraw);
+
 	if (_session.isPlayerCombatLocked())
 		return InputResult();
 
@@ -234,6 +237,19 @@ InputResult Input::applyCheatActivation(InteractionResult &cheatInteraction,
 	return InputResult();
 }
 
+InputResult Input::openHelpScreen(bool &needsRedraw) {
+	Common::Error helpError = _flow.runHelpScreen(_scene.palette, _scene.targetPaletteBrightness);
+	_session.getInputState().clearHeldActions();
+	if (helpError.getCode() != Common::kNoError)
+		return InputResult::leaveRoom(helpError);
+	// Stow the carried item after help returns.
+	if (!_roomItems.stowCarriedRoomItemToInventory())
+		return InputResult::leaveRoom(Common::kReadingFailed);
+	_inventory.clearSelection();
+	needsRedraw = true;
+	return InputResult();
+}
+
 InputResult Input::openRoomMenu(bool &needsRedraw) {
 	Player &player = _session.getPlayer();
 	InputState &inputState = _session.getInputState();


Commit: d98cb3af02bf2845de72a13c96d995f84152792c
    https://github.com/scummvm/scummvm/commit/d98cb3af02bf2845de72a13c96d995f84152792c
Author: Alex Bevilacqua (alex at alexbevi.com)
Date: 2026-10-21T06:57:51-04:00

Commit Message:
HARVESTER: Properly handled deferred palette fades after movies

Assisted-by: Codex:gpt-6.1-sol

Changed paths:
    engines/harvester/fst_player.cpp
    engines/harvester/media/media_manager.cpp
    engines/harvester/media/media_manager.h
    engines/harvester/scene/room_presentation.cpp
    engines/harvester/scene/scene.cpp
    engines/harvester/scene/scene.h


diff --git a/engines/harvester/fst_player.cpp b/engines/harvester/fst_player.cpp
index 22f26d01167..9b570b6769b 100644
--- a/engines/harvester/fst_player.cpp
+++ b/engines/harvester/fst_player.cpp
@@ -34,7 +34,9 @@
 #include "common/textconsole.h"
 #include "graphics/paletteman.h"
 #include "graphics/surface.h"
+#include "harvester/detection.h"
 #include "harvester/harvester.h"
+#include "harvester/media/media_manager.h"
 #include "harvester/resources.h"
 #include "image/pcx.h"
 
@@ -583,6 +585,15 @@ bool FstPlayer::play(const Common::String &path) {
 	if (shouldSwitchToMovieDisplay)
 		_vm.setDisplayMode(previousDisplayWidth, previousDisplayHeight);
 
+	// play_fst_sequence consumes FADE_IN after playback; callers perform the fade.
+	MediaManager *media = _vm.getMedia();
+	media->finishMoviePlayback();
+	if (media->isRoomPaletteFadePending()) {
+		_vm.getScreen()->clearPalette();
+		g_system->updateScreen();
+		debugC(2, kDebugRoom, "Harvester: movie '%s' deferring room palette restoration", path.c_str());
+	}
+
 	return !_vm.shouldQuit();
 }
 
diff --git a/engines/harvester/media/media_manager.cpp b/engines/harvester/media/media_manager.cpp
index f6cc9be5cdb..903d10cb02f 100644
--- a/engines/harvester/media/media_manager.cpp
+++ b/engines/harvester/media/media_manager.cpp
@@ -72,6 +72,16 @@ void MediaManager::resetScreen(int width, int height) {
 	_displayHeight = height;
 }
 
+void MediaManager::finishMoviePlayback() {
+	_roomPaletteFadePending = _fadeRoomAfterNextMovie;
+	_fadeRoomAfterNextMovie = false;
+}
+
+void MediaManager::resetMoviePaletteState() {
+	_fadeRoomAfterNextMovie = false;
+	_roomPaletteFadePending = false;
+}
+
 bool MediaManager::loadArt() {
 	Common::ScopedPtr<Art> art(new Art());
 	if (!art->load(_resources))
diff --git a/engines/harvester/media/media_manager.h b/engines/harvester/media/media_manager.h
index 3ae159ec156..b74fcd7edf0 100644
--- a/engines/harvester/media/media_manager.h
+++ b/engines/harvester/media/media_manager.h
@@ -54,6 +54,11 @@ public:
 	static float mapGammaLevelToBrightnessScale(int level);
 
 	void resetScreen(int width, int height);
+	void requestRoomFadeAfterMovie() { _fadeRoomAfterNextMovie = true; }
+	void finishMoviePlayback();
+	bool isRoomPaletteFadePending() const { return _roomPaletteFadePending; }
+	void clearRoomPaletteFade() { _roomPaletteFadePending = false; }
+	void resetMoviePaletteState();
 	bool loadArt();
 	bool loadText();
 	bool loadQuickTipsResources(bool useTextboxPanel);
@@ -85,6 +90,8 @@ private:
 	Graphics::Screen *_screen = nullptr;
 	int _displayWidth = 0;
 	int _displayHeight = 0;
+	bool _fadeRoomAfterNextMovie = false;
+	bool _roomPaletteFadePending = false;
 	Art *_art = nullptr;
 	Text *_text = nullptr;
 	Audio::SoundHandle _musicHandle;
diff --git a/engines/harvester/scene/room_presentation.cpp b/engines/harvester/scene/room_presentation.cpp
index 5f3fb7bd4dd..a055299bfef 100644
--- a/engines/harvester/scene/room_presentation.cpp
+++ b/engines/harvester/scene/room_presentation.cpp
@@ -35,6 +35,7 @@
 #include "harvester/entity.h"
 #include "harvester/flow/flow.h"
 #include "harvester/harvester.h"
+#include "harvester/media/media_manager.h"
 #include "harvester/palette_utils.h"
 #include "harvester/player/player.h"
 #include "harvester/resources.h"
@@ -473,6 +474,7 @@ Common::Error RoomPresentation::applyLightingCommand(StartupLightingCommand ligh
 	case kStartupLightingCommandNone:
 		return Common::kNoError;
 	case kStartupLightingCommandDim:
+		_engine.getMedia()->clearRoomPaletteFade();
 		_scene.targetPaletteBrightness = kDimPaletteBrightness;
 		drawRoomScene(_engine, *activeScreen, _scene, _scene.targetPaletteBrightness);
 		setScaledRoomPalette(*activeScreen, _scene.palette, _scene.targetPaletteBrightness);
@@ -480,6 +482,7 @@ Common::Error RoomPresentation::applyLightingCommand(StartupLightingCommand ligh
 		activeScreen->update();
 		return Common::kNoError;
 	case kStartupLightingCommandNormal:
+		_engine.getMedia()->clearRoomPaletteFade();
 		if (ResourceManager *resources = _engine.getResources()) {
 			if (!_scene.state.palettePath.empty() &&
 					!loadPaletteResource(*resources, _scene.state.palettePath, _scene.palette)) {
@@ -502,8 +505,8 @@ Common::Error RoomPresentation::applyLightingCommand(StartupLightingCommand ligh
 		return Common::kNoError;
 	}
 	case kStartupLightingCommandFadeIn:
-		debugC(1, kDebugRoom,
-			"Harvester: CHANGE_LIGHTING FADE_IN has no direct room-side equivalent yet; preserving control flow");
+		_engine.getMedia()->requestRoomFadeAfterMovie();
+		debugC(2, kDebugRoom, "Harvester: room palette fade queued for the next movie");
 		return Common::kNoError;
 	}
 
diff --git a/engines/harvester/scene/scene.cpp b/engines/harvester/scene/scene.cpp
index 55f0f82ab7f..dc57ca8692a 100644
--- a/engines/harvester/scene/scene.cpp
+++ b/engines/harvester/scene/scene.cpp
@@ -33,6 +33,7 @@
 #include "harvester/flow/flow.h"
 #include "harvester/harvester.h"
 #include "harvester/inventory.h"
+#include "harvester/media/media_manager.h"
 #include "harvester/player/player.h"
 #include "harvester/combat/combat.h"
 #include "harvester/entity.h"
@@ -407,15 +408,16 @@ void Scene::updateRoomInterface(bool &needsRedraw) {
 	}
 }
 
-bool Scene::drawRoomFrame(bool &needsRedraw) {
+InputResult Scene::drawRoomFrame(bool &needsRedraw) {
 	const RoomPlayerState &playerState = _player.getState();
 	const RoomIdleAnimationState &idleState = _player.getIdleState();
-	if (!needsRedraw)
-		return true;
+	const bool fadeIn = _engine.getMedia()->isRoomPaletteFadePending();
+	if (!needsRedraw && !fadeIn)
+		return InputResult();
 
 	Graphics::Screen *activeScreen = _engine.getScreen();
 	if (!activeScreen)
-		return false;
+		return InputResult::leaveRoom(Common::kNoError);
 
 	const Common::Rect inventoryPanelBounds = _inventory.getPanelBounds();
 	const bool inventorySelectionActive = _inventory.hasSelection();
@@ -489,7 +491,7 @@ bool Scene::drawRoomFrame(bool &needsRedraw) {
 				: hoverState.cursorSequence);
 	}
 
-	RoomPresentation::drawRoomScene(_engine, *activeScreen, _scene, _scene.targetPaletteBrightness);
+	RoomPresentation::drawRoomScene(_engine, *activeScreen, _scene, fadeIn ? 0.0f : _scene.targetPaletteBrightness);
 	_combatEffects.drawCombatDamagePopups(*activeScreen, _engine.isCombatDebugEnabled());
 	if (_engine.getScript() && playerState.entity) {
 		drawCombatLoadoutResourceIcons(*activeScreen, *_view.art, *_engine.getScript(),
@@ -528,7 +530,14 @@ bool Scene::drawRoomFrame(bool &needsRedraw) {
 	activeScreen->update();
 	needsRedraw = false;
 
-	return true;
+	if (fadeIn) {
+		_engine.getMedia()->clearRoomPaletteFade();
+		debugC(2, kDebugRoom, "Harvester: fading room '%s' in after movie", _scene.state.roomName.c_str());
+		Common::Error fadeError = _flow.fadeInRoomScene(_scene.palette, _scene.targetPaletteBrightness);
+		if (fadeError.getCode() != Common::kNoError)
+			return InputResult::leaveRoom(fadeError);
+	}
+	return InputResult();
 }
 
 InputResult Scene::pollRoomEvents(Input &input, bool &needsRedraw) {
@@ -783,8 +792,9 @@ InputResult Scene::runRoomFrames(const Common::String &currentRoomTarget) {
 			needsRedraw = true;
 		}
 		updateRoomInterface(needsRedraw);
-		if (!drawRoomFrame(needsRedraw))
-			return InputResult::leaveRoom(Common::kNoError);
+		const InputResult drawResult = drawRoomFrame(needsRedraw);
+		if (drawResult.returnFromRoom)
+			return drawResult;
 
 		const InputResult inputResult = pollRoomEvents(input, needsRedraw);
 		if (inputResult.returnFromRoom)
@@ -880,6 +890,11 @@ void Scene::syncGlobalTimerEntities(const Common::Array<TimerRecord> &previousTi
 }
 
 bool Scene::captureDialogueBackdrop(IndexedBitmap &backdrop) {
+	if (_engine.getMedia()->isRoomPaletteFadePending()) {
+		bool needsRedraw = true;
+		if (drawRoomFrame(needsRedraw).returnFromRoom)
+			return false;
+	}
 	return _presentation.captureDialogueBackdrop(backdrop);
 }
 
@@ -1013,6 +1028,7 @@ Common::Error SceneRunner::runRoomLoop(Flow &flow, const Common::String &targetN
 		if (transitionError.getCode() != Common::kNoError)
 			return transitionError;
 
+		_engine.getMedia()->resetMoviePaletteState();
 		SceneState scene;
 		if (!SceneEntities::loadRoomSceneResources(state, *_engine.getResources(), scene))
 			return Common::kReadingFailed;
diff --git a/engines/harvester/scene/scene.h b/engines/harvester/scene/scene.h
index 76f25876ecc..73d579db6dc 100644
--- a/engines/harvester/scene/scene.h
+++ b/engines/harvester/scene/scene.h
@@ -103,7 +103,7 @@ private:
 	void syncAnimatedRoomActorPlacement();
 	void requestPlayerGameOver(const char *reason, const Common::String &sourceName);
 	void updateRoomInterface(bool &needsRedraw);
-	bool drawRoomFrame(bool &needsRedraw);
+	InputResult drawRoomFrame(bool &needsRedraw);
 	InputResult pollRoomEvents(Input &input, bool &needsRedraw);
 	PlayerControlState preparePlayerControlState();
 	Common::Error tryActivatePendingRegion(bool &needsRedraw);




More information about the Scummvm-git-logs mailing list