[Scummvm-git-logs] scummvm master -> 461009e823f7b4f8ef5f267dcbab30694609048e

sev- noreply at scummvm.org
Sat Sep 2 09:33:01 UTC 2023


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

Summary:
e21e0ed089 SWORD1: Improve accuracy of in-game timers
394642598c SWORD1: Implement accurate fading routines
2d884572aa SWORD1: Implement fast and slow mode for timing debugging
1822ce506b SWORD1: Set slow/fast modes as sys vars
9b27c38390 SWORD1: Set a timeout for fades
4ab197b16f SWORD1: Implement fades on the main menu
f564ad8ea8 SWORD1: Fix unused var warning
dbe1a2df4f SWORD1: Make changes for code review
67052e2ef5 SWORD1: Address other issues from code review
e658ce8a16 SWORD1: Fix fade palette for Mac version
7b8efd9845 SWORD1: Fix fade to cut palette
461009e823 SWORD1: Free palette resource only when actually using it


Commit: e21e0ed089c60378cccb5dadda3327d679524871
    https://github.com/scummvm/scummvm/commit/e21e0ed089c60378cccb5dadda3327d679524871
Author: AndywinXp (andywinxp at gmail.com)
Date: 2023-09-02T11:32:51+02:00

Commit Message:
SWORD1: Improve accuracy of in-game timers

Also begin work on palette and sound fades

Changed paths:
    engines/sword1/eventman.cpp
    engines/sword1/logic.cpp
    engines/sword1/sword1.cpp
    engines/sword1/sword1.h
    engines/sword1/sworddefs.h


diff --git a/engines/sword1/eventman.cpp b/engines/sword1/eventman.cpp
index af11c7ff78b..72fdc0a60cd 100644
--- a/engines/sword1/eventman.cpp
+++ b/engines/sword1/eventman.cpp
@@ -51,6 +51,8 @@ void EventManager::checkForEvent(Object *compact) {
 					    compact->o_event_list[objCnt].o_event_script;
 					compact->o_tree.o_script_pc[compact->o_tree.o_script_level] =
 					    compact->o_event_list[objCnt].o_event_script;
+
+					break;
 				}
 			}
 	}
diff --git a/engines/sword1/logic.cpp b/engines/sword1/logic.cpp
index 017ec030e20..6c04efdb7be 100644
--- a/engines/sword1/logic.cpp
+++ b/engines/sword1/logic.cpp
@@ -990,7 +990,7 @@ int Logic::fnPause(Object *cpt, int32 id, int32 pause, int32 d, int32 e, int32 f
 }
 
 int Logic::fnPauseSeconds(Object *cpt, int32 id, int32 pause, int32 d, int32 e, int32 f, int32 z, int32 x) {
-	cpt->o_pause = pause * FRAME_RATE;
+	cpt->o_pause = pause * PAUSE_FRAME_RATE;
 	cpt->o_logic = LOGIC_pause;
 	return SCRIPT_STOP;
 }
diff --git a/engines/sword1/sword1.cpp b/engines/sword1/sword1.cpp
index f4c174b3536..6064a6fe4b6 100644
--- a/engines/sword1/sword1.cpp
+++ b/engines/sword1/sword1.cpp
@@ -34,6 +34,7 @@
 
 #include "common/config-manager.h"
 #include "common/textconsole.h"
+#include "common/timer.h"
 
 #include "engines/advancedDetector.h"
 #include "engines/util.h"
@@ -577,6 +578,8 @@ Common::Error SwordEngine::go() {
 	_control->checkForOldSaveGames();
 	setTotalPlayTime(0);
 
+	installTimerRoutines();
+
 	uint16 startPos = ConfMan.getInt("boot_param");
 	_control->readSavegameDescriptions();
 	if (startPos) {
@@ -615,6 +618,8 @@ Common::Error SwordEngine::go() {
 		}
 	}
 
+	uninstallTimerRoutines();
+
 	return Common::kNoError;
 }
 
@@ -655,28 +660,32 @@ uint8 SwordEngine::mainLoop() {
 
 		do {
 			uint32 newTime;
+			uint32 frameTime = _system->getMillis();
+
 			bool scrollFrameShown = false;
 
-			uint32 frameTime = _system->getMillis();
 			_logic->engine();
 			_logic->updateScreenParams(); // sets scrolling
 
 			_screen->draw();
 			_mouse->animate();
-			_sound->engine();
-			_menu->refresh(MENU_TOP);
-			_menu->refresh(MENU_BOT);
 
-			newTime = _system->getMillis();
-			if (newTime - frameTime < 1000 / FRAME_RATE) {
-				scrollFrameShown = _screen->showScrollFrame();
-				delay((1000 / (FRAME_RATE * 2)) - (_system->getMillis() - frameTime));
+			if (!Logic::_scriptVars[NEW_PALETTE]) {
+				newTime = _system->getMillis();
+				if (newTime - frameTime < FRAME_TIME / 2) {
+					scrollFrameShown = _screen->showScrollFrame();
+					pollInput((FRAME_TIME / 2) - (_system->getMillis() - frameTime));
+				}
 			}
 
+			_sound->engine();
+
 			newTime = _system->getMillis();
-			if ((newTime - frameTime < 1000 / FRAME_RATE) || (!scrollFrameShown))
+			if ((newTime - frameTime < FRAME_TIME) || (!scrollFrameShown))
 				_screen->updateScreen();
-			delay((1000 / FRAME_RATE) - (_system->getMillis() - frameTime));
+			pollInput((FRAME_TIME) - (_system->getMillis() - frameTime));
+
+			_vblCount = 0; // Reset the vBlank counter...
 
 			_mouse->engine(_mouseCoord.x, _mouseCoord.y, _mouseState);
 
@@ -693,26 +702,28 @@ uint8 SwordEngine::mainLoop() {
 
 			_mouseState = 0;
 			_keyPressed.reset();
+
 		} while ((Logic::_scriptVars[SCREEN] == Logic::_scriptVars[NEW_SCREEN]) && (retCode == 0) && (!shouldQuit()));
 
 		if ((retCode == 0) && (Logic::_scriptVars[SCREEN] != 53) && _systemVars.wantFade && (!shouldQuit())) {
 			_screen->fadeDownPalette();
-			int32 relDelay = (int32)_system->getMillis();
-			while (_screen->stillFading()) {
-				relDelay += (1000 / FRAME_RATE);
-				_screen->updateScreen();
-				delay(relDelay - (int32)_system->getMillis());
-			}
 		}
 
-		_sound->quitScreen();
-		_screen->quitScreen(); // close graphic resources
-		_objectMan->closeSection(Logic::_scriptVars[SCREEN]); // close the section that PLAYER has just left, if it's empty now
+		_screen->quitScreen(); // Close graphic resources
+
+		while (_screen->stillFading()) { // This indirectly also waits for FX to be faded
+			if (_vblCount >= _rate)
+				_vblCount = 0;
+		}
+
+		_sound->quitScreen(); // Purge the sound AFTER they've been faded
+
+		_objectMan->closeSection(Logic::_scriptVars[SCREEN]); // Close the section that PLAYER has just left, if it's empty now
 	}
 	return retCode;
 }
 
-void SwordEngine::delay(int32 amount) { //copied and mutilated from sky.cpp
+void SwordEngine::pollInput(uint32 delay) { //copied and mutilated from sky.cpp
 
 	Common::Event event;
 	uint32 start = _system->getMillis();
@@ -749,10 +760,10 @@ void SwordEngine::delay(int32 amount) { //copied and mutilated from sky.cpp
 
 		_system->updateScreen();
 
-		if (amount > 0)
+		if (delay > 0)
 			_system->delayMillis(10);
 
-	} while (_system->getMillis() < start + amount);
+	} while (_system->getMillis() < start + delay);
 }
 
 bool SwordEngine::mouseIsActive() {
@@ -772,4 +783,53 @@ void SwordEngine::reinitRes() {
 	_screen->draw();
 }
 
+void SwordEngine::updateTopMenu() {
+	_menu->refresh(MENU_TOP);
+}
+
+void SwordEngine::updateBottomMenu() {
+	_menu->refresh(MENU_BOT);
+}
+
+static void vblCallback(void *refCon) {
+	SwordEngine *vm = (SwordEngine *)refCon;
+
+	vm->_inTimer++;
+
+	if (vm->_inTimer == 0) {
+		vm->_vblCount++;
+		vm->_vbl60HzUSecElapsed += TIMER_USEC;
+
+		if ((vm->_vblCount == 1) || (vm->_vblCount == 5)) {
+			vm->updateTopMenu();
+		}
+
+		if ((vm->_vblCount == 3) || (vm->_vblCount == 7)) {
+			vm->updateBottomMenu();
+		}
+
+		if (vm->_vbl60HzUSecElapsed >= PALETTE_FADE_USEC) {
+			// Subtract the target interval (to handle potential drift)
+			vm->_vbl60HzUSecElapsed -= PALETTE_FADE_USEC;
+
+			// This is where you place your 60Hz logic
+			//debug("Fade palette logic!");
+		}
+
+		// TODO: Volume fading here...
+	}
+
+	vm->_inTimer--;
+}
+
+void SwordEngine::installTimerRoutines() {
+	debug(2, "SwordEngine::installTimerRoutines(): Installing timers...");
+	getTimerManager()->installTimerProc(&vblCallback, 1000000 / TIMER_RATE, this, "AILTimer");
+}
+
+void SwordEngine::uninstallTimerRoutines() {
+	debug(2, "SwordEngine::uninstallTimerRoutines(): Uninstalling timers...");
+	getTimerManager()->removeTimerProc(&vblCallback);
+}
+
 } // End of namespace Sword1
diff --git a/engines/sword1/sword1.h b/engines/sword1/sword1.h
index af71f5db4a3..59220fdb585 100644
--- a/engines/sword1/sword1.h
+++ b/engines/sword1/sword1.h
@@ -88,12 +88,21 @@ public:
 
 	uint32 _features;
 
+	int _inTimer = -1; // Is the timer running?
+	int32 _vbl60HzUSecElapsed = 0; // 60 Hz counter for palette fades
+	int _vblCount = 0; // How many vblCallback calls have been made?
+	int _rate = 8;
+
 	bool mouseIsActive();
 
 	static bool isMac() { return _systemVars.platform == Common::kPlatformMacintosh; }
 	static bool isPsx() { return _systemVars.platform == Common::kPlatformPSX; }
 	static bool isWindows() { return _systemVars.platform == Common::kPlatformWindows ; }
 
+	// Used by timer
+	void updateTopMenu();
+	void updateBottomMenu();
+
 protected:
 	// Engine APIs
 	Common::Error init();
@@ -116,7 +125,7 @@ protected:
 		return Common::String::format("sword1.%03d", slot);
 	}
 private:
-	void delay(int32 amount);
+	void pollInput(uint32 delay);
 
 	void checkCdFiles();
 	void checkCd();
@@ -125,6 +134,9 @@ private:
 
 	void reinitRes(); //Reinits the resources after a GMM load
 
+	void installTimerRoutines();
+	void uninstallTimerRoutines();
+
 	uint8 mainLoop();
 
 	Common::Point _mouseCoord;
diff --git a/engines/sword1/sworddefs.h b/engines/sword1/sworddefs.h
index 75b09e6280a..58a109c6a90 100644
--- a/engines/sword1/sworddefs.h
+++ b/engines/sword1/sworddefs.h
@@ -28,13 +28,18 @@ namespace Sword1 {
 
 #define LOOPED 1
 
-#define FRAME_RATE          12                      // number of frames per second (max rate)
-#define SCREEN_WIDTH        640
-#define SCREEN_DEPTH        400
-#define SCREEN_LEFT_EDGE    128
-#define SCREEN_RIGHT_EDGE   (128+SCREEN_WIDTH-1)
-#define SCREEN_TOP_EDGE     128
-#define SCREEN_BOTTOM_EDGE  (128+SCREEN_DEPTH-1)
+#define FRAME_TIME            80  // 80ms, for exactly 12.5Hz
+#define PAUSE_FRAME_RATE      12  // This frame time is only used in fnPauseSeconds(), like for the original
+#define TIMER_RATE            100
+#define TIMER_USEC            1000000 / TIMER_RATE
+#define PALETTE_FADE_RATE     60
+#define PALETTE_FADE_USEC     16667
+#define SCREEN_WIDTH          640
+#define SCREEN_DEPTH          400
+#define SCREEN_LEFT_EDGE      128
+#define SCREEN_RIGHT_EDGE     (128+SCREEN_WIDTH-1)
+#define SCREEN_TOP_EDGE       128
+#define SCREEN_BOTTOM_EDGE    (128+SCREEN_DEPTH-1)
 #define TYPE_FLOOR 1
 #define TYPE_MOUSE 2
 #define TYPE_SPRITE 3


Commit: 394642598c6d7ef14b5aa6e99717805050654b2c
    https://github.com/scummvm/scummvm/commit/394642598c6d7ef14b5aa6e99717805050654b2c
Author: AndywinXp (andywinxp at gmail.com)
Date: 2023-09-02T11:32:51+02:00

Commit Message:
SWORD1: Implement accurate fading routines

Changed paths:
    engines/sword1/control.cpp
    engines/sword1/control.h
    engines/sword1/logic.cpp
    engines/sword1/screen.cpp
    engines/sword1/screen.h
    engines/sword1/sound.cpp
    engines/sword1/sword1.cpp
    engines/sword1/sword1.h


diff --git a/engines/sword1/control.cpp b/engines/sword1/control.cpp
index fb36d0be71b..107a02aecad 100644
--- a/engines/sword1/control.cpp
+++ b/engines/sword1/control.cpp
@@ -228,7 +228,8 @@ void ControlButton::setSelected(uint8 selected) {
 	draw();
 }
 
-Control::Control(Common::SaveFileManager *saveFileMan, ResMan *pResMan, ObjectMan *pObjMan, OSystem *system, Mouse *pMouse, Sound *pSound, Music *pMusic) {
+Control::Control(SwordEngine *vm, Common::SaveFileManager *saveFileMan, ResMan *pResMan, ObjectMan *pObjMan, OSystem *system, Mouse *pMouse, Sound *pSound, Music *pMusic, Screen *pScreen) {
+	_vm = vm;
 	_saveFileMan = saveFileMan;
 	_resMan = pResMan;
 	_objMan = pObjMan;
@@ -236,6 +237,7 @@ Control::Control(Common::SaveFileManager *saveFileMan, ResMan *pResMan, ObjectMa
 	_mouse = pMouse;
 	_music = pMusic;
 	_sound = pSound;
+	_screen = pScreen;
 	_lStrings = loadCustomStrings("strings.txt") ? _customStrings : _languageStrings + SwordEngine::_systemVars.language * 20;
 	_selectedButton = 255;
 	_panelShown = false;
@@ -323,23 +325,31 @@ uint8 Control::runPanel() {
 	_font = (uint8 *)_resMan->openFetchRes(fontId);
 	_redFont = (uint8 *)_resMan->openFetchRes(redFontId);
 
-	uint8 *pal = (uint8 *)_resMan->openFetchRes(SR_PALETTE);
-	uint8 *palOut = (uint8 *)malloc(256 * 3);
-	for (uint16 cnt = 1; cnt < 256; cnt++) {
-		palOut[cnt * 3 + 0] = pal[cnt * 3 + 0] << 2;
-		palOut[cnt * 3 + 1] = pal[cnt * 3 + 1] << 2;
-		palOut[cnt * 3 + 2] = pal[cnt * 3 + 2] << 2;
-	}
-	palOut[0] = palOut[1] = palOut[2] = 0;
-	_resMan->resClose(SR_PALETTE);
-	_system->getPaletteManager()->setPalette(palOut, 0, 256);
-	free(palOut);
+	//uint8 *pal = (uint8 *)_resMan->openFetchRes(SR_PALETTE);
+
+	//uint8 *palOut = (uint8 *)malloc(256 * 3);
+	//for (uint16 cnt = 1; cnt < 256; cnt++) {
+	//	palOut[cnt * 3 + 0] = pal[cnt * 3 + 0] << 2;
+	//	palOut[cnt * 3 + 1] = pal[cnt * 3 + 1] << 2;
+	//	palOut[cnt * 3 + 2] = pal[cnt * 3 + 2] << 2;
+	//}
+	//palOut[0] = palOut[1] = palOut[2] = 0;
+	//_resMan->resClose(SR_PALETTE);
+	//_system->getPaletteManager()->setPalette(palOut, 0, 256);
+	//free(palOut);
 	uint8 mode = 0, newMode = BUTTON_MAIN_PANEL;
 	bool fullRefresh = false;
 	_mouse->controlPanel(true);
 	uint8 retVal = CONTROL_NOTHING_DONE;
 	_music->startMusic(61, 1);
+	setupMainPanel();
 
+	_screen->fnSetFadeTargetPalette(0, 256, SR_PALETTE);
+	_screen->fnSetFadeTargetPalette(0, 1, 0, true);
+	_screen->startFadePaletteDown(1);
+	_vm->waitForFade();
+
+	//clearAllFx();
 	do {
 		if (newMode) {
 			mode = newMode;
@@ -426,6 +436,9 @@ uint8 Control::runPanel() {
 		ConfMan.flushToDisk();
 	}
 
+	//_screen->startFadePaletteDown(1);
+	//_vm->waitForFade();
+
 	destroyButtons();
 	_resMan->resClose(fontId);
 	_resMan->resClose(redFontId);
@@ -603,6 +616,11 @@ void Control::setupMainPanel() {
 			renderText(_lStrings[STR_RESTART], 285, 260 + 40, TEXT_LEFT_ALIGN);
 		renderText(_lStrings[STR_QUIT], 285, 296 + 40, TEXT_LEFT_ALIGN);
 	}
+
+	_screen->fnSetFadeTargetPalette(0, 256, SR_PALETTE);
+	_screen->fnSetFadeTargetPalette(0, 1, 0, true);
+	_screen->startFadePaletteUp(1);
+	_vm->waitForFade();
 }
 
 void Control::setupSaveRestorePanel(bool saving) {
diff --git a/engines/sword1/control.h b/engines/sword1/control.h
index 1c13ceaf005..cc6a8ee25e2 100644
--- a/engines/sword1/control.h
+++ b/engines/sword1/control.h
@@ -35,11 +35,13 @@ class MemoryWriteStreamDynamic;
 
 namespace Sword1 {
 
+class SwordEngine;
 class ObjectMan;
 class ResMan;
 class Mouse;
 class Music;
 class Sound;
+class Screen;
 
 #define SAVEGAME_HEADER MKTAG('B','S','_','1')
 #define SAVEGAME_VERSION 2
@@ -83,7 +85,7 @@ struct ButtonInfo {
 
 class Control {
 public:
-	Control(Common::SaveFileManager *saveFileMan, ResMan *pResMan, ObjectMan *pObjMan, OSystem *system, Mouse *pMouse, Sound *pSound, Music *pMusic);
+	Control(SwordEngine *vm, Common::SaveFileManager *saveFileMan, ResMan *pResMan, ObjectMan *pObjMan, OSystem *system, Mouse *pMouse, Sound *pSound, Music *pMusic, Screen *pScreen);
 	uint8 runPanel();
 	void doRestore();
 	void askForCd();
@@ -146,6 +148,7 @@ private:
 	bool loadCustomStrings(const char* filename);
 	uint8 _customStrings[20][43];
 	const uint8(*_lStrings)[43];
+	SwordEngine *_vm;
 	Common::SaveFileManager *_saveFileMan;
 	ObjectMan *_objMan;
 	ResMan *_resMan;
@@ -153,6 +156,7 @@ private:
 	Mouse *_mouse;
 	Music *_music;
 	Sound *_sound;
+	Screen *_screen;
 	uint8 *_font, *_redFont;
 	uint8 *_screenBuf;
 	Common::KeyState _keyPressed;
diff --git a/engines/sword1/logic.cpp b/engines/sword1/logic.cpp
index 6c04efdb7be..1aeccf89325 100644
--- a/engines/sword1/logic.cpp
+++ b/engines/sword1/logic.cpp
@@ -922,32 +922,33 @@ int Logic::fnFullSetFrame(Object *cpt, int32 id, int32 cdt, int32 spr, int32 fra
 }
 
 int Logic::fnFadeDown(Object *cpt, int32 id, int32 speed, int32 d, int32 e, int32 f, int32 z, int32 x) {
-	_screen->fadeDownPalette();
+	_vm->startFadePaletteDown(speed);
 	return SCRIPT_CONT;
 }
 
 int Logic::fnFadeUp(Object *cpt, int32 id, int32 speed, int32 d, int32 e, int32 f, int32 z, int32 x) {
-	_screen->fadeUpPalette();
+	_vm->startFadePaletteUp(speed);
 	return SCRIPT_CONT;
 }
 
 int Logic::fnCheckFade(Object *cpt, int32 id, int32 c, int32 d, int32 e, int32 f, int32 z, int32 x) {
-	_scriptVars[RETURN_VALUE] = (uint8)_screen->stillFading();
+	_scriptVars[RETURN_VALUE] = _screen->stillFading();
 	return SCRIPT_CONT;
 }
 
 int Logic::fnSetSpritePalette(Object *cpt, int32 id, int32 spritePal, int32 d, int32 e, int32 f, int32 z, int32 x) {
-	_screen->fnSetPalette(184, 72, spritePal, false);
+	_screen->fnSetPalette(184, 72, spritePal);
 	return SCRIPT_CONT;
 }
 
 int Logic::fnSetWholePalette(Object *cpt, int32 id, int32 spritePal, int32 d, int32 e, int32 f, int32 z, int32 x) {
-	_screen->fnSetPalette(0, 256, spritePal, false);
+	_screen->fnSetPalette(0, 256, spritePal);
 	return SCRIPT_CONT;
 }
 
 int Logic::fnSetFadeTargetPalette(Object *cpt, int32 id, int32 spritePal, int32 d, int32 e, int32 f, int32 z, int32 x) {
-	_screen->fnSetPalette(0, 184, spritePal, true);
+	_screen->fnSetFadeTargetPalette(0, 184, spritePal, false);
+	_screen->fnSetFadeTargetPalette(0, 1, 0, true);
 	return SCRIPT_CONT;
 }
 
diff --git a/engines/sword1/screen.cpp b/engines/sword1/screen.cpp
index 568dcd274fd..8cc62dbcd82 100644
--- a/engines/sword1/screen.cpp
+++ b/engines/sword1/screen.cpp
@@ -38,10 +38,11 @@
 
 namespace Sword1 {
 
-#define SCROLL_FRACTION 16
-#define MAX_SCROLL_DISTANCE 8
-#define FADE_UP 1
-#define FADE_DOWN -1
+#define SCROLL_FRACTION      16
+#define MAX_SCROLL_DISTANCE  8
+#define NO_FADE              0
+#define FADE_UP              1
+#define FADE_DOWN           -1
 
 Screen::Screen(OSystem *system, ResMan *pResMan, ObjectMan *pObjMan) {
 	_system = system;
@@ -49,7 +50,6 @@ Screen::Screen(OSystem *system, ResMan *pResMan, ObjectMan *pObjMan) {
 	_objMan = pObjMan;
 	_screenBuf = _screenGrid = NULL;
 	_backLength = _foreLength = _sortLength = 0;
-	_fadingStep = 0;
 	_currentScreen = 0xFFFF;
 	_updatePalette = false;
 	_psxCache.decodedBackground = NULL;
@@ -78,8 +78,6 @@ Screen::Screen(OSystem *system, ResMan *pResMan, ObjectMan *pObjMan) {
 	_scrnSizeY = 0;
 	_gridSizeX = 0;
 	_gridSizeY = 0;
-	_fadingDirection = 0;
-	_isBlack = 0;
 }
 
 Screen::~Screen() {
@@ -140,19 +138,39 @@ void Screen::setScrolling(int16 offsetX, int16 offsetY) {
 	}
 }
 
-void Screen::fadeDownPalette() {
-	if (!_isBlack) { // don't fade down twice
-		_fadingStep = 15;
-		_fadingDirection = FADE_DOWN;
+void Screen::startFadePaletteDown(int speed) {
+	if (SwordEngine::_systemVars.wantFade) {
+		_paletteFadeInfo.paletteIndex = speed;
+		_paletteFadeInfo.paletteCount = 64;
+		_paletteFadeInfo.fadeCount = 0;
+		_paletteFadeInfo.paletteStatus = FADE_DOWN;
+	} else {
+		_system->getPaletteManager()->setPalette(_zeroPalette, 0, 256);
 	}
 }
 
-void Screen::fadeUpPalette() {
-	_fadingStep = 1;
-	_fadingDirection = FADE_UP;
+void Screen::startFadePaletteUp(int speed) {
+	if (SwordEngine::_systemVars.wantFade) {
+		// Set up the source palette;
+		// We are deliberately casting these to signed byte,
+		// because we want to allow them to go below zero.
+		for (int i = 0; i < 256 * 3; i++)
+			((int8 *)_paletteFadeInfo.srcPalette)[i] = ((int8 *)_paletteFadeInfo.dstPalette)[i] - 63;
+
+		// Start the fade
+		_paletteFadeInfo.paletteIndex = speed;
+		_paletteFadeInfo.paletteCount = 64;
+		_paletteFadeInfo.fadeCount = 0;
+		_paletteFadeInfo.paletteStatus = FADE_UP;
+	} else {
+		_system->getPaletteManager()->setPalette(_currentPalette, 0, 256);
+
+		// Set up the source palette
+		memcpy((uint8 *)_paletteFadeInfo.srcPalette, (uint8 *)_currentPalette, 256 * 3);
+	}
 }
 
-void Screen::fnSetPalette(uint8 start, uint16 length, uint32 id, bool fadeUp) {
+void Screen::fnSetPalette(uint8 start, uint16 length, uint32 id) {
 	uint8 *palData = (uint8 *)_resMan->openFetchRes(id);
 	if (start == 0) // force color 0 to black
 		palData[0] = palData[1] = palData[2] = 0;
@@ -168,14 +186,28 @@ void Screen::fnSetPalette(uint8 start, uint16 length, uint32 id, bool fadeUp) {
 		_targetPalette[(start + cnt) * 3 + 2] = palData[cnt * 3 + 2] << 2;
 	}
 	_resMan->resClose(id);
-	_isBlack = false;
-	if (fadeUp) {
-		_fadingStep = 1;
-		_fadingDirection = FADE_UP;
-		memset(_currentPalette, 0, 256 * 3);
-		_system->getPaletteManager()->setPalette(_currentPalette, 0, 256);
-	} else
-		_system->getPaletteManager()->setPalette(_targetPalette + 3 * start, start, length);
+
+	_system->getPaletteManager()->setPalette(_targetPalette + 3 * start, start, length);
+}
+
+void Screen::fnSetFadeTargetPalette(uint8 start, uint16 length, uint32 id, bool toBlack) {
+	byte *rgbData = nullptr;
+
+	if (toBlack) {
+		rgbData = const_cast<byte *>(_black);
+	} else {
+		rgbData = (byte *) _resMan->openFetchRes(id);
+	}
+
+	if (SwordEngine::_systemVars.wantFade) {
+		memcpy(_currentPalette + (start * 3), rgbData, length * 3);
+		memcpy(_paletteFadeInfo.dstPalette + (start * 3), rgbData, length * 3);
+		memset(_paletteFadeInfo.srcPalette + (start * 3), 0, length * 3);
+	} else {
+		memcpy(_currentPalette + (start * 3), rgbData, length * 3);
+	}
+
+	_resMan->resClose(id);
 }
 
 void Screen::fullRefresh() {
@@ -183,8 +215,62 @@ void Screen::fullRefresh() {
 	_system->getPaletteManager()->setPalette(_targetPalette, 0, 256);
 }
 
-bool Screen::stillFading() {
-	return (_fadingStep != 0);
+int16 Screen::stillFading() {
+	if (SwordEngine::_systemVars.wantFade)
+		return _paletteFadeInfo.paletteStatus;
+	else
+		return 0;
+}
+
+
+void Screen::fadePalette() {
+	_paletteFadeInfo.fadeCount++;
+
+	if (_paletteFadeInfo.fadeCount == _paletteFadeInfo.paletteIndex) {
+		_paletteFadeInfo.fadeCount = 0;
+
+		if (_paletteFadeInfo.paletteStatus == NO_FADE)
+			return;
+
+		// Set the whole palette to the current source.
+		// But first, remember that these are 6 bit values, and
+		// they have to be shifted left two times before using them.
+		byte outPal[256 * 3];
+		for (int i = 0; i < 256 * 3; i++) {
+			// Remember that we previously allowed the RGB values
+			// to go below zero? It's time to account for that;
+			// This contributes to producing the correct palette fading effect.
+			int8 curValueSigned = (int8)_paletteFadeInfo.srcPalette[i];
+			if (curValueSigned < 0)
+				curValueSigned = 0;
+
+			outPal[i] = ((byte)curValueSigned) << 2;
+		}
+
+		_system->getPaletteManager()->setPalette((const byte *)outPal, 0, 256);
+
+		_paletteFadeInfo.paletteCount--;
+
+		if (_paletteFadeInfo.paletteCount == 0) {
+			_paletteFadeInfo.paletteStatus = NO_FADE;
+		} else {
+			if (_paletteFadeInfo.paletteStatus == FADE_DOWN) {
+				// Fade down
+				for (int i = 0; i < 256 * 3; i++) {
+					if (_paletteFadeInfo.srcPalette[i] > 0)
+						_paletteFadeInfo.srcPalette[i]--;
+				}
+			} else if (_paletteFadeInfo.paletteStatus == FADE_UP) {
+				// Fade up
+				for (int i = 0; i < 256 * 3; i++) {
+					// Remember, we might have previously obtained negative values!
+					if ((int8)_paletteFadeInfo.srcPalette[i] < (int8)_paletteFadeInfo.dstPalette[i]) {
+						_paletteFadeInfo.srcPalette[i]++;
+					}
+				}
+			}
+		}
+	}
 }
 
 bool Screen::showScrollFrame() {
@@ -204,20 +290,17 @@ bool Screen::showScrollFrame() {
 
 void Screen::updateScreen() {
 	if (Logic::_scriptVars[NEW_PALETTE]) {
-		_fadingStep = 1;
-		_fadingDirection = FADE_UP;
 		_updatePalette = true;
 		Logic::_scriptVars[NEW_PALETTE] = 0;
 	}
+
 	if (_updatePalette) {
-		fnSetPalette(0, 184, _roomDefTable[_currentScreen].palettes[0], false);
-		fnSetPalette(184, 72, _roomDefTable[_currentScreen].palettes[1], false);
+		fnSetFadeTargetPalette(0, 184, _roomDefTable[_currentScreen].palettes[0]);
+		fnSetFadeTargetPalette(184, 72, _roomDefTable[_currentScreen].palettes[1]);
+		fnSetFadeTargetPalette(0, 1, 0, true);
+		startFadePaletteUp(1);
 		_updatePalette = false;
 	}
-	if (_fadingStep) {
-		fadePalette();
-		_system->getPaletteManager()->setPalette(_currentPalette, 0, 256);
-	}
 
 	uint16 scrlX = (uint16)Logic::_scriptVars[SCROLL_OFFSET_X];
 	uint16 scrlY = (uint16)Logic::_scriptVars[SCROLL_OFFSET_Y];
@@ -463,6 +546,19 @@ void Screen::draw() {
 	_backLength = _sortLength = _foreLength = 0;
 }
 
+void Screen::initFadePaletteServer() {
+	memset(_zeroPalette, 0, sizeof(_zeroPalette));
+
+	// Initialise the palette info variables.
+	_paletteFadeInfo.paletteStatus = 0;
+	_paletteFadeInfo.paletteIndex = 0;
+
+	memset(_paletteFadeInfo.dstPalette, 0, sizeof(_paletteFadeInfo.dstPalette));
+	memset(_paletteFadeInfo.srcPalette, 0, sizeof(_paletteFadeInfo.srcPalette));
+
+	_system->getPaletteManager()->setPalette((const byte *)_paletteFadeInfo.srcPalette, 0, 256);
+}
+
 void Screen::processImage(uint32 id) {
 	Object *compact;
 	FrameHeader *frameHead;
@@ -1142,23 +1238,6 @@ void Screen::flushPsxCache() {
 	}
 }
 
-void Screen::fadePalette() {
-	if (_fadingStep == 16)
-		memcpy(_currentPalette, _targetPalette, 256 * 3);
-	else if ((_fadingStep == 1) && (_fadingDirection == FADE_DOWN)) {
-		memset(_currentPalette, 0, 3 * 256);
-	} else
-		for (uint16 cnt = 0; cnt < 256 * 3; cnt++)
-			_currentPalette[cnt] = (_targetPalette[cnt] * _fadingStep) >> 4;
-
-	_fadingStep += _fadingDirection;
-	if (_fadingStep == 17) {
-		_fadingStep = 0;
-		_isBlack = false;
-	} else if (_fadingStep == 0)
-		_isBlack = true;
-}
-
 void Screen::fnSetParallax(uint32 screen, uint32 resId) {
 	_roomDefTable[screen].parallax[0] = resId;
 }
@@ -1232,7 +1311,41 @@ void Screen::spriteClipAndSet(uint16 *pSprX, uint16 *pSprY, uint16 *pSprWidth, u
 }
 
 void Screen::fnFlash(uint8 color) {
-	warning("stub: Screen::fnFlash(%d)", color);
+	const byte *targetColor = _white;
+
+	switch (color) {
+	case FLASH_RED:
+		targetColor = _red;
+		break;
+	case FLASH_BLUE:
+		targetColor = _blue;
+		break;
+	case BORDER_YELLOW:
+		targetColor = _yellow;
+		break;
+	case BORDER_GREEN:
+		targetColor = _green;
+		break;
+	case BORDER_PURPLE:
+		targetColor = _purple;
+		break;
+	case BORDER_BLACK:
+		targetColor = _black;
+		break;
+	default:
+		warning("Screen::fnFlash(%d): Bogus color", color);
+		return;
+	}
+
+	_system->getPaletteManager()->setPalette(_currentPalette, 0, 1);
+
+	if (color == FLASH_RED || color == FLASH_BLUE) {
+		// This is what the original did here to induce a small wait cycle
+		// to correctly display the color before it is turned back to black...
+		for (int i = 0; i < 20000; ++i);
+
+		_system->getPaletteManager()->setPalette(_black, 0, 1);
+	}
 }
 
 // ------------------- Menu screen interface ---------------------------
diff --git a/engines/sword1/screen.h b/engines/sword1/screen.h
index 188a71bcb7c..8489c73125c 100644
--- a/engines/sword1/screen.h
+++ b/engines/sword1/screen.h
@@ -76,6 +76,7 @@ public:
 	void clearScreen();
 	void useTextManager(Text *pTextMan);
 	void draw();
+	void initFadePaletteServer();
 
 	void quitScreen();
 	void newScreen(uint32 screen);
@@ -83,10 +84,12 @@ public:
 	void setScrolling(int16 offsetX, int16 offsetY);
 	void addToGraphicList(uint8 listId, uint32 objId);
 
-	void fadeDownPalette();
-	void fadeUpPalette();
-	void fnSetPalette(uint8 start, uint16 length, uint32 id, bool fadeUp);
-	bool stillFading();
+	void startFadePaletteDown(int speed);
+	void startFadePaletteUp(int speed);
+	void fadePalette();
+	void fnSetPalette(uint8 start, uint16 length, uint32 id);
+	void fnSetFadeTargetPalette(uint8 start, uint16 length, uint32 id, bool toBlack = false);
+	int16 stillFading();
 	void fullRefresh();
 
 	bool showScrollFrame();
@@ -95,11 +98,31 @@ public:
 
 	void fnSetParallax(uint32 screen, uint32 resId);
 	void fnFlash(uint8 color);
-	void fnBorder(uint8 color);
 
 	static void decompressHIF(uint8 *src, uint8 *dest);
 
 private:
+	// The original values are 6-bit RGB numbers, so they have to be shifted
+	const byte _white[3]  = { 63 << 2, 63 << 2, 63 << 2};
+	const byte _red[3]    = { 63 << 2, 0  << 2, 0  << 2};
+	const byte _blue[3]   = { 0  << 2, 0  << 2, 63 << 2};
+	const byte _yellow[3] = { 63 << 2, 63 << 2, 0  << 2};
+	const byte _green[3]  = { 0  << 2, 63 << 2, 0  << 2};
+	const byte _purple[3] = { 32 << 2, 0  << 2, 32 << 2};
+	const byte _black[3]  = { 0  << 2, 0  << 2, 0  << 2};
+	const byte _grey[3]   = { 32 << 2, 32 << 2, 32 << 2};
+
+	struct PaletteFadeInfo {
+		int16 paletteStatus;
+		int16 paletteIndex;
+		int16 paletteCount;
+		int16 fadeCount;
+		byte srcPalette[256 * 3];
+		byte dstPalette[256 * 3];
+	};
+
+	PaletteFadeInfo _paletteFadeInfo;
+
 	// for router debugging
 	void drawLine(uint16 x1, uint16 y1, uint16 x2, uint16 y2);
 	void vline(uint16 x, uint16 y1, uint16 y2);
@@ -125,7 +148,6 @@ private:
 	void decompressRLE0(uint8 *src, uint32 compSize, uint8 *dest);
 	void decompressTony(uint8 *src, uint32 compSize, uint8 *dest);
 	void fastShrink(uint8 *src, uint32 width, uint32 height, uint32 scale, uint8 *dest);
-	void fadePalette();
 
 	void flushPsxCache();
 
@@ -158,10 +180,7 @@ private:
 
 	uint8 _targetPalette[256 * 3];
 	uint8 _currentPalette[256 * 3]; // for fading
-	uint8 _fadingStep;
-	int8  _fadingDirection; // 1 for fade up, -1 for fade down
-	bool _isBlack; // if the logic already faded down the palette, this is set to show the
-	               // mainloop that no further fading is necessary.
+	uint8 _zeroPalette[256 * 3];
 };
 
 } // End of namespace Sword1
diff --git a/engines/sword1/sound.cpp b/engines/sword1/sound.cpp
index 4781fa17722..cf3783ce571 100644
--- a/engines/sword1/sound.cpp
+++ b/engines/sword1/sound.cpp
@@ -199,6 +199,9 @@ int Sound::addToQueue(int32 fxNo) {
 }
 
 void Sound::engine() {
+	// TODO: FX fading step
+
+
 	// first of all, add any random sfx to the queue...
 	for (uint16 cnt = 0; cnt < TOTAL_FX_PER_ROOM; cnt++) {
 		uint16 fxNo = _roomsFixedFx[Logic::_scriptVars[SCREEN]][cnt];
diff --git a/engines/sword1/sword1.cpp b/engines/sword1/sword1.cpp
index 6064a6fe4b6..06d1740a55d 100644
--- a/engines/sword1/sword1.cpp
+++ b/engines/sword1/sword1.cpp
@@ -158,7 +158,7 @@ Common::Error SwordEngine::init() {
 	_logic->initialize();
 	_objectMan->initialize();
 	_mouse->initialize();
-	_control = new Control(_saveFileMan, _resMan, _objectMan, _system, _mouse, _sound, _music);
+	_control = new Control(this, _saveFileMan, _resMan, _objectMan, _system, _mouse, _sound, _music, _screen);
 
 	return Common::kNoError;
 }
@@ -578,6 +578,7 @@ Common::Error SwordEngine::go() {
 	_control->checkForOldSaveGames();
 	setTotalPlayTime(0);
 
+	_screen->initFadePaletteServer();
 	installTimerRoutines();
 
 	uint16 startPos = ConfMan.getInt("boot_param");
@@ -685,7 +686,7 @@ uint8 SwordEngine::mainLoop() {
 				_screen->updateScreen();
 			pollInput((FRAME_TIME) - (_system->getMillis() - frameTime));
 
-			_vblCount = 0; // Reset the vBlank counter...
+			_vblCount = 0; // Reset the vBlank counter for the other timers...
 
 			_mouse->engine(_mouseCoord.x, _mouseCoord.y, _mouseState);
 
@@ -706,15 +707,11 @@ uint8 SwordEngine::mainLoop() {
 		} while ((Logic::_scriptVars[SCREEN] == Logic::_scriptVars[NEW_SCREEN]) && (retCode == 0) && (!shouldQuit()));
 
 		if ((retCode == 0) && (Logic::_scriptVars[SCREEN] != 53) && _systemVars.wantFade && (!shouldQuit())) {
-			_screen->fadeDownPalette();
+			_screen->startFadePaletteDown(1);
 		}
 
 		_screen->quitScreen(); // Close graphic resources
-
-		while (_screen->stillFading()) { // This indirectly also waits for FX to be faded
-			if (_vblCount >= _rate)
-				_vblCount = 0;
-		}
+		waitForFade();
 
 		_sound->quitScreen(); // Purge the sound AFTER they've been faded
 
@@ -723,6 +720,15 @@ uint8 SwordEngine::mainLoop() {
 	return retCode;
 }
 
+void SwordEngine::waitForFade() {
+	while (_screen->stillFading()) { // This indirectly also waits for FX to be faded
+		if (_vblCount >= _rate)
+			_vblCount = 0;
+
+		pollInput(0);
+	}
+}
+
 void SwordEngine::pollInput(uint32 delay) { //copied and mutilated from sky.cpp
 
 	Common::Event event;
@@ -791,6 +797,22 @@ void SwordEngine::updateBottomMenu() {
 	_menu->refresh(MENU_BOT);
 }
 
+void SwordEngine::fadePaletteStep() {
+	_screen->fadePalette();
+}
+
+void SwordEngine::startFadePaletteDown(int speed) {
+	_screen->startFadePaletteDown(speed);
+
+	// Fade audio here
+}
+
+void SwordEngine::startFadePaletteUp(int speed) {
+	_screen->startFadePaletteUp(speed);
+
+	// Fade audio here
+}
+
 static void vblCallback(void *refCon) {
 	SwordEngine *vm = (SwordEngine *)refCon;
 
@@ -809,11 +831,9 @@ static void vblCallback(void *refCon) {
 		}
 
 		if (vm->_vbl60HzUSecElapsed >= PALETTE_FADE_USEC) {
-			// Subtract the target interval (to handle potential drift)
 			vm->_vbl60HzUSecElapsed -= PALETTE_FADE_USEC;
 
-			// This is where you place your 60Hz logic
-			//debug("Fade palette logic!");
+			vm->fadePaletteStep();
 		}
 
 		// TODO: Volume fading here...
diff --git a/engines/sword1/sword1.h b/engines/sword1/sword1.h
index 59220fdb585..b14f66fb87f 100644
--- a/engines/sword1/sword1.h
+++ b/engines/sword1/sword1.h
@@ -80,6 +80,8 @@ struct SystemVars {
 
 class SwordEngine : public Engine {
 	friend class SwordConsole;
+	friend class Screen;
+
 public:
 	SwordEngine(OSystem *syst, const ADGameDescription *gameDesc);
 	~SwordEngine() override;
@@ -102,6 +104,10 @@ public:
 	// Used by timer
 	void updateTopMenu();
 	void updateBottomMenu();
+	void fadePaletteStep();
+	void startFadePaletteDown(int speed);
+	void startFadePaletteUp(int speed);
+	void waitForFade();
 
 protected:
 	// Engine APIs


Commit: 2d884572aa54e76731b8bf3a118831f17120d962
    https://github.com/scummvm/scummvm/commit/2d884572aa54e76731b8bf3a118831f17120d962
Author: AndywinXp (andywinxp at gmail.com)
Date: 2023-09-02T11:32:51+02:00

Commit Message:
SWORD1: Implement fast and slow mode for timing debugging

They can only be activated via the original debug keys ('1' and '4'),
and only if ScummVM is launched in debug mode.

Changed paths:
    engines/sword1/sword1.cpp
    engines/sword1/sword1.h
    engines/sword1/sworddefs.h


diff --git a/engines/sword1/sword1.cpp b/engines/sword1/sword1.cpp
index 06d1740a55d..6c21d94ae81 100644
--- a/engines/sword1/sword1.cpp
+++ b/engines/sword1/sword1.cpp
@@ -116,6 +116,7 @@ Common::Error SwordEngine::init() {
 	_systemVars.wantFade = true;
 	_systemVars.realLanguage = Common::parseLanguage(ConfMan.get("language"));
 	_systemVars.isLangRtl = false;
+	_systemVars.debugMode = (gDebugLevel >= 0);
 
 	switch (_systemVars.realLanguage) {
 	case Common::DE_DEU:
@@ -247,6 +248,70 @@ void SwordEngine::flagsToBool(bool *dest, uint8 flags) {
 	}
 }
 
+uint8 SwordEngine::checkKeys() {
+	uint8 retCode = 0;
+	if (_systemVars.forceRestart) {
+		retCode = CONTROL_RESTART_GAME;
+	} else {
+		switch (_keyPressed.keycode) {
+		case Common::KEYCODE_F5:
+		case Common::KEYCODE_ESCAPE:
+			if ((Logic::_scriptVars[MOUSE_STATUS] & 1) && (Logic::_scriptVars[GEORGE_HOLDING_PIECE] == 0)) {
+				/*
+				 * saveGameFlag = 1;
+				 * snrStatus = 1;
+				*/
+				retCode = _control->runPanel();
+				if (retCode == CONTROL_NOTHING_DONE)
+					_screen->fullRefresh();
+			}
+			break;
+		default:
+			break;
+		}
+
+		// Debug keys!
+		if (!_systemVars.isDemo && _systemVars.debugMode) {
+			switch (_keyPressed.keycode) {
+			case Common::KEYCODE_1: // Slow mode
+				{
+					if (_slowMode) {
+						_slowMode = false;
+						_targetFrameTime = DEFAULT_FRAME_TIME; // 12.5Hz
+					} else {
+						_slowMode = true;
+						_targetFrameTime = SLOW_FRAME_TIME; // 2Hz
+					}
+
+					_fastMode = false; // For good measure...
+
+					_rate = _targetFrameTime / 10;
+				}
+				break;
+			case Common::KEYCODE_4: // Fast mode
+				{
+					if (_fastMode) {
+						_fastMode = false;
+						_targetFrameTime = DEFAULT_FRAME_TIME; // 12.5Hz
+					} else {
+						_fastMode = true;
+						_targetFrameTime = FAST_FRAME_TIME; // 100Hz
+					}
+
+					_slowMode = false; // For good measure...
+
+					_rate = _targetFrameTime / 10;
+				}
+				break;
+			default:
+				break;
+			}
+		}
+	}
+
+	return retCode;
+}
+
 static const char *const errorMsgs[] = {
 	"The file \"%s\" is missing and the game doesn't work without it.\n"
 	"Please copy it from CD %d and try starting the game again.\n"
@@ -673,33 +738,24 @@ uint8 SwordEngine::mainLoop() {
 
 			if (!Logic::_scriptVars[NEW_PALETTE]) {
 				newTime = _system->getMillis();
-				if (newTime - frameTime < FRAME_TIME / 2) {
+				if ((int32)(newTime - frameTime) < _targetFrameTime / 2) {
 					scrollFrameShown = _screen->showScrollFrame();
-					pollInput((FRAME_TIME / 2) - (_system->getMillis() - frameTime));
+					pollInput((_targetFrameTime / 2) - (_system->getMillis() - frameTime));
 				}
 			}
 
 			_sound->engine();
 
 			newTime = _system->getMillis();
-			if ((newTime - frameTime < FRAME_TIME) || (!scrollFrameShown))
+			if (((int32)(newTime - frameTime) < _targetFrameTime) || (!scrollFrameShown))
 				_screen->updateScreen();
-			pollInput((FRAME_TIME) - (_system->getMillis() - frameTime));
+			pollInput((_targetFrameTime) - (_system->getMillis() - frameTime));
 
 			_vblCount = 0; // Reset the vBlank counter for the other timers...
 
 			_mouse->engine(_mouseCoord.x, _mouseCoord.y, _mouseState);
 
-			if (_systemVars.forceRestart)
-				retCode = CONTROL_RESTART_GAME;
-
-			// The control panel is triggered by F5 or ESC.
-			else if (((_keyPressed.keycode == Common::KEYCODE_F5 || _keyPressed.keycode == Common::KEYCODE_ESCAPE)
-			          && (Logic::_scriptVars[MOUSE_STATUS] & 1)) || (_systemVars.controlPanelMode)) {
-				retCode = _control->runPanel();
-				if (retCode == CONTROL_NOTHING_DONE)
-					_screen->fullRefresh();
-			}
+			retCode = checkKeys();
 
 			_mouseState = 0;
 			_keyPressed.reset();
diff --git a/engines/sword1/sword1.h b/engines/sword1/sword1.h
index b14f66fb87f..d05e98db3ac 100644
--- a/engines/sword1/sword1.h
+++ b/engines/sword1/sword1.h
@@ -76,6 +76,7 @@ struct SystemVars {
 	Common::Platform platform;
 	Common::Language realLanguage;
 	bool isLangRtl;
+	bool debugMode;
 };
 
 class SwordEngine : public Engine {
@@ -93,7 +94,10 @@ public:
 	int _inTimer = -1; // Is the timer running?
 	int32 _vbl60HzUSecElapsed = 0; // 60 Hz counter for palette fades
 	int _vblCount = 0; // How many vblCallback calls have been made?
-	int _rate = 8;
+	int _rate = DEFAULT_FRAME_TIME / 10;
+	int _targetFrameTime = DEFAULT_FRAME_TIME;
+	bool _slowMode = false;
+	bool _fastMode = false;
 
 	bool mouseIsActive();
 
@@ -132,6 +136,7 @@ protected:
 	}
 private:
 	void pollInput(uint32 delay);
+	uint8 checkKeys();
 
 	void checkCdFiles();
 	void checkCd();
diff --git a/engines/sword1/sworddefs.h b/engines/sword1/sworddefs.h
index 58a109c6a90..bc6127e57d7 100644
--- a/engines/sword1/sworddefs.h
+++ b/engines/sword1/sworddefs.h
@@ -28,7 +28,9 @@ namespace Sword1 {
 
 #define LOOPED 1
 
-#define FRAME_TIME            80  // 80ms, for exactly 12.5Hz
+#define DEFAULT_FRAME_TIME    80  // 80ms, for exactly 12.5Hz
+#define FAST_FRAME_TIME       10  // 10ms, for 100Hz
+#define SLOW_FRAME_TIME       500 // 500ms, for 2Hz
 #define PAUSE_FRAME_RATE      12  // This frame time is only used in fnPauseSeconds(), like for the original
 #define TIMER_RATE            100
 #define TIMER_USEC            1000000 / TIMER_RATE


Commit: 1822ce506b8e108bd5ddc379205c8117ed6fa812
    https://github.com/scummvm/scummvm/commit/1822ce506b8e108bd5ddc379205c8117ed6fa812
Author: AndywinXp (andywinxp at gmail.com)
Date: 2023-09-02T11:32:51+02:00

Commit Message:
SWORD1: Set slow/fast modes as sys vars

Changed paths:
    engines/sword1/sword1.cpp
    engines/sword1/sword1.h


diff --git a/engines/sword1/sword1.cpp b/engines/sword1/sword1.cpp
index 6c21d94ae81..d6dd6ca50ca 100644
--- a/engines/sword1/sword1.cpp
+++ b/engines/sword1/sword1.cpp
@@ -117,6 +117,8 @@ Common::Error SwordEngine::init() {
 	_systemVars.realLanguage = Common::parseLanguage(ConfMan.get("language"));
 	_systemVars.isLangRtl = false;
 	_systemVars.debugMode = (gDebugLevel >= 0);
+	_systemVars.slowMode = false;
+	_systemVars.fastMode = false;
 
 	switch (_systemVars.realLanguage) {
 	case Common::DE_DEU:
@@ -275,30 +277,30 @@ uint8 SwordEngine::checkKeys() {
 			switch (_keyPressed.keycode) {
 			case Common::KEYCODE_1: // Slow mode
 				{
-					if (_slowMode) {
-						_slowMode = false;
+					if (_systemVars.slowMode) {
+						_systemVars.slowMode = false;
 						_targetFrameTime = DEFAULT_FRAME_TIME; // 12.5Hz
 					} else {
-						_slowMode = true;
+						_systemVars.slowMode = true;
 						_targetFrameTime = SLOW_FRAME_TIME; // 2Hz
 					}
 
-					_fastMode = false; // For good measure...
+					_systemVars.fastMode = false; // For good measure...
 
 					_rate = _targetFrameTime / 10;
 				}
 				break;
 			case Common::KEYCODE_4: // Fast mode
 				{
-					if (_fastMode) {
-						_fastMode = false;
+					if (_systemVars.fastMode) {
+						_systemVars.fastMode = false;
 						_targetFrameTime = DEFAULT_FRAME_TIME; // 12.5Hz
 					} else {
-						_fastMode = true;
+						_systemVars.fastMode = true;
 						_targetFrameTime = FAST_FRAME_TIME; // 100Hz
 					}
 
-					_slowMode = false; // For good measure...
+					_systemVars.slowMode = false; // For good measure...
 
 					_rate = _targetFrameTime / 10;
 				}
diff --git a/engines/sword1/sword1.h b/engines/sword1/sword1.h
index d05e98db3ac..e4a95b87c91 100644
--- a/engines/sword1/sword1.h
+++ b/engines/sword1/sword1.h
@@ -61,22 +61,23 @@ class Music;
 class Control;
 
 struct SystemVars {
-	bool    runningFromCd;
-	uint32  currentCD;          // starts at zero, then either 1 or 2 depending on section being played
-	uint32  justRestoredGame;   // see main() in sword.c & New_screen() in gtm_core.c
-
-	uint8   controlPanelMode;   // 1 death screen version of the control panel, 2 = successful end of game, 3 = force restart
-	bool    forceRestart;
-	bool    wantFade;           // when true => fade during scene change, else cut.
-	bool   playSpeech;
-	bool   showText;
-	uint8   language;
-	bool    isDemo;
-	bool    isSpanishDemo;
+	bool             runningFromCd;
+	uint32           currentCD;          // starts at zero, then either 1 or 2 depending on section being played
+	uint32           justRestoredGame;   // see main() in sword.c & New_screen() in gtm_core.c
+	uint8            controlPanelMode;   // 1 death screen version of the control panel, 2 = successful end of game, 3 = force restart
+	bool             forceRestart;
+	bool             wantFade;           // when true => fade during scene change, else cut.
+	bool             playSpeech;
+	bool             showText;
+	uint8            language;
+	bool             isDemo;
+	bool             isSpanishDemo;
 	Common::Platform platform;
 	Common::Language realLanguage;
-	bool isLangRtl;
-	bool debugMode;
+	bool             isLangRtl;
+	bool             debugMode;
+	bool             slowMode;
+	bool             fastMode;
 };
 
 class SwordEngine : public Engine {
@@ -96,8 +97,6 @@ public:
 	int _vblCount = 0; // How many vblCallback calls have been made?
 	int _rate = DEFAULT_FRAME_TIME / 10;
 	int _targetFrameTime = DEFAULT_FRAME_TIME;
-	bool _slowMode = false;
-	bool _fastMode = false;
 
 	bool mouseIsActive();
 


Commit: 9b27c38390eb29590f3e44ad16c251b747e78a9c
    https://github.com/scummvm/scummvm/commit/9b27c38390eb29590f3e44ad16c251b747e78a9c
Author: AndywinXp (andywinxp at gmail.com)
Date: 2023-09-02T11:32:51+02:00

Commit Message:
SWORD1: Set a timeout for fades

Changed paths:
    engines/sword1/sword1.cpp


diff --git a/engines/sword1/sword1.cpp b/engines/sword1/sword1.cpp
index d6dd6ca50ca..cc0f6a896de 100644
--- a/engines/sword1/sword1.cpp
+++ b/engines/sword1/sword1.cpp
@@ -779,11 +779,17 @@ uint8 SwordEngine::mainLoop() {
 }
 
 void SwordEngine::waitForFade() {
+	uint32 startTime = _system->getMillis();
 	while (_screen->stillFading()) { // This indirectly also waits for FX to be faded
 		if (_vblCount >= _rate)
 			_vblCount = 0;
 
 		pollInput(0);
+
+		// In the remote event that this wait cycle gets
+		// stuck during debugging, trigger a timeout
+		if (_system->getMillis() - startTime > 2000)
+			break;
 	}
 }
 


Commit: 4ab197b16fc64fcc819bd0a5763a374636b22941
    https://github.com/scummvm/scummvm/commit/4ab197b16fc64fcc819bd0a5763a374636b22941
Author: AndywinXp (andywinxp at gmail.com)
Date: 2023-09-02T11:32:51+02:00

Commit Message:
SWORD1: Implement fades on the main menu

Had to reshuffle some stuff to make it work properly,
and in order to set up everything for future changes.

Changed paths:
    engines/sword1/control.cpp
    engines/sword1/control.h
    engines/sword1/logic.h
    engines/sword1/mouse.cpp
    engines/sword1/screen.cpp
    engines/sword1/screen.h
    engines/sword1/sound.h
    engines/sword1/sword1.cpp


diff --git a/engines/sword1/control.cpp b/engines/sword1/control.cpp
index 107a02aecad..d1f68133a75 100644
--- a/engines/sword1/control.cpp
+++ b/engines/sword1/control.cpp
@@ -228,7 +228,7 @@ void ControlButton::setSelected(uint8 selected) {
 	draw();
 }
 
-Control::Control(SwordEngine *vm, Common::SaveFileManager *saveFileMan, ResMan *pResMan, ObjectMan *pObjMan, OSystem *system, Mouse *pMouse, Sound *pSound, Music *pMusic, Screen *pScreen) {
+Control::Control(SwordEngine *vm, Common::SaveFileManager *saveFileMan, ResMan *pResMan, ObjectMan *pObjMan, OSystem *system, Mouse *pMouse, Sound *pSound, Music *pMusic, Screen *pScreen, Logic *pLogic) {
 	_vm = vm;
 	_saveFileMan = saveFileMan;
 	_resMan = pResMan;
@@ -238,6 +238,8 @@ Control::Control(SwordEngine *vm, Common::SaveFileManager *saveFileMan, ResMan *
 	_music = pMusic;
 	_sound = pSound;
 	_screen = pScreen;
+	_logic = pLogic;
+
 	_lStrings = loadCustomStrings("strings.txt") ? _customStrings : _languageStrings + SwordEngine::_systemVars.language * 20;
 	_selectedButton = 255;
 	_panelShown = false;
@@ -307,16 +309,30 @@ uint8 Control::runPanel() {
 	_tempThumbnail = new Common::MemoryWriteStreamDynamic(DisposeAfterUse::YES);
 	Graphics::saveThumbnail(*_tempThumbnail);
 
+	_logic->fnWipeHands(nullptr, 0, 0, 0, 0, 0, 0, 0);
+	_logic->fnEndMenu(nullptr, 0, 0, 0, 0, 0, 0, 0);
+
+	// Fade video and sounds down
+	_screen->startFadePaletteDown(1);
+	_vm->waitForFade();
+	_sound->quitScreen();
+
+	int previousMusic = Logic::_scriptVars[CURRENT_MUSIC];
+	_logic->fnPlayMusic(nullptr, 0, 61, LOOPED, 0, 0, 0, 0);
+	Logic::_scriptVars[CURRENT_MUSIC] = previousMusic;
+
 	_panelShown = true;
 	_mouseDown = false;
 	_restoreBuf = NULL;
 	_keyPressed.reset();
 	_numButtons = 0;
+
+	// Clear the whole screen
 	_screenBuf = (uint8 *)malloc(640 * 480);
 	memset(_screenBuf, 0, 640 * 480);
 	_system->copyRectToScreen(_screenBuf, 640, 0, 0, 640, 480);
-	_sound->quitScreen();
 
+	// Gather font resources
 	uint32 fontId = SR_FONT, redFontId = SR_REDFONT;
 	if (SwordEngine::_systemVars.language == BS1_CZECH) {
 		fontId = CZECH_SR_FONT;
@@ -325,31 +341,25 @@ uint8 Control::runPanel() {
 	_font = (uint8 *)_resMan->openFetchRes(fontId);
 	_redFont = (uint8 *)_resMan->openFetchRes(redFontId);
 
-	//uint8 *pal = (uint8 *)_resMan->openFetchRes(SR_PALETTE);
-
-	//uint8 *palOut = (uint8 *)malloc(256 * 3);
-	//for (uint16 cnt = 1; cnt < 256; cnt++) {
-	//	palOut[cnt * 3 + 0] = pal[cnt * 3 + 0] << 2;
-	//	palOut[cnt * 3 + 1] = pal[cnt * 3 + 1] << 2;
-	//	palOut[cnt * 3 + 2] = pal[cnt * 3 + 2] << 2;
-	//}
-	//palOut[0] = palOut[1] = palOut[2] = 0;
-	//_resMan->resClose(SR_PALETTE);
-	//_system->getPaletteManager()->setPalette(palOut, 0, 256);
-	//free(palOut);
+	// Set up mouse
+	_mouse->controlPanel(true);
+
 	uint8 mode = 0, newMode = BUTTON_MAIN_PANEL;
 	bool fullRefresh = false;
-	_mouse->controlPanel(true);
 	uint8 retVal = CONTROL_NOTHING_DONE;
-	_music->startMusic(61, 1);
+
+	// Set up the image and the correct palette for fading up
+	if (SwordEngine::isPsx())
+		destroyButtons();
 	setupMainPanel();
 
 	_screen->fnSetFadeTargetPalette(0, 256, SR_PALETTE);
 	_screen->fnSetFadeTargetPalette(0, 1, 0, true);
-	_screen->startFadePaletteDown(1);
+
+	// Fade up
+	_screen->startFadePaletteUp(1);
 	_vm->waitForFade();
 
-	//clearAllFx();
 	do {
 		if (newMode) {
 			mode = newMode;
@@ -401,7 +411,7 @@ uint8 Control::runPanel() {
 			fullRefresh = false;
 			_system->copyRectToScreen(_screenBuf, SCREEN_WIDTH, 0, 0, SCREEN_WIDTH, 480);
 		}
-		delay(1000 / 12);
+		delay(DEFAULT_FRAME_TIME);
 		newMode = getClicks(mode, &retVal);
 	} while ((newMode != BUTTON_DONE) && (retVal == 0) && (!Engine::shouldQuit()));
 
@@ -436,22 +446,57 @@ uint8 Control::runPanel() {
 		ConfMan.flushToDisk();
 	}
 
-	//_screen->startFadePaletteDown(1);
-	//_vm->waitForFade();
+	// Fade out video and sounds
+	bool didRestoreRestartOrQuit =
+		Engine::shouldQuit() ||
+		(retVal & CONTROL_RESTART_GAME) ||
+		(retVal & CONTROL_GAME_RESTORED);
+
+	if (didRestoreRestartOrQuit || (Logic::_scriptVars[CURRENT_MUSIC] == 0)) {
+		_logic->fnStopMusic(nullptr, 0, 0, 0, 0, 0, 0, 0);
+	}
 
+	_screen->startFadePaletteDown(1);
+	_vm->waitForFade();
+
+	_logic->fnNormalMouse(nullptr, 0, 0, 0, 0, 0, 0, 0);
+	Logic::_scriptVars[NEW_PALETTE] = 1;
+
+	// Clear the control panel resources and the free the temp screen buffer
 	destroyButtons();
 	_resMan->resClose(fontId);
 	_resMan->resClose(redFontId);
 	memset(_screenBuf, 0, 640 * 480);
 	_system->copyRectToScreen(_screenBuf, 640, 0, 0, 640, 480);
 	free(_screenBuf);
+
+	// Restore mouse
 	_mouse->controlPanel(false);
-	// Can also be used to end the control panel music.
-	_music->startMusic(Logic::_scriptVars[CURRENT_MUSIC], 1);
-	_sound->newScreen(Logic::_scriptVars[SCREEN]);
-	_panelShown = false;
+
+	// If DONE or SAVE was selected, try restoring audio
+	if (!didRestoreRestartOrQuit) {
+		// Restore sound effects...
+		for (int j = 0; j < TOTAL_FX_PER_ROOM; j++) {
+			if (int fxNo = Sound::_roomsFixedFx[Logic::_scriptVars[SCREEN]][j]) {
+				if (Sound::_fxList[fxNo].type == FX_LOOP)
+					_logic->fnPlayFx(nullptr, 0, fxNo, 0, 0, 0, 0, 0);
+			} else {
+				break; // Drop out as soon as we come across a zero, rather than searching the whole list...
+			}
+		}
+
+		// Restore in-game music...
+		if (Logic::_scriptVars[CURRENT_MUSIC]) {
+			_logic->fnPlayMusic(nullptr, 0, Logic::_scriptVars[CURRENT_MUSIC], LOOPED, 0, 0, 0, 0);
+		}
+	}
+
+	// Delete the temporary thumbnail
 	delete _tempThumbnail;
 	_tempThumbnail = 0;
+
+	_panelShown = false;
+
 	return retVal;
 }
 
@@ -616,11 +661,6 @@ void Control::setupMainPanel() {
 			renderText(_lStrings[STR_RESTART], 285, 260 + 40, TEXT_LEFT_ALIGN);
 		renderText(_lStrings[STR_QUIT], 285, 296 + 40, TEXT_LEFT_ALIGN);
 	}
-
-	_screen->fnSetFadeTargetPalette(0, 256, SR_PALETTE);
-	_screen->fnSetFadeTargetPalette(0, 1, 0, true);
-	_screen->startFadePaletteUp(1);
-	_vm->waitForFade();
 }
 
 void Control::setupSaveRestorePanel(bool saving) {
diff --git a/engines/sword1/control.h b/engines/sword1/control.h
index cc6a8ee25e2..f4fde4ac26e 100644
--- a/engines/sword1/control.h
+++ b/engines/sword1/control.h
@@ -42,6 +42,7 @@ class Mouse;
 class Music;
 class Sound;
 class Screen;
+class Logic;
 
 #define SAVEGAME_HEADER MKTAG('B','S','_','1')
 #define SAVEGAME_VERSION 2
@@ -85,7 +86,7 @@ struct ButtonInfo {
 
 class Control {
 public:
-	Control(SwordEngine *vm, Common::SaveFileManager *saveFileMan, ResMan *pResMan, ObjectMan *pObjMan, OSystem *system, Mouse *pMouse, Sound *pSound, Music *pMusic, Screen *pScreen);
+	Control(SwordEngine *vm, Common::SaveFileManager *saveFileMan, ResMan *pResMan, ObjectMan *pObjMan, OSystem *system, Mouse *pMouse, Sound *pSound, Music *pMusic, Screen *pScreen, Logic *pLogic);
 	uint8 runPanel();
 	void doRestore();
 	void askForCd();
@@ -157,6 +158,7 @@ private:
 	Music *_music;
 	Sound *_sound;
 	Screen *_screen;
+	Logic *_logic;
 	uint8 *_font, *_redFont;
 	uint8 *_screenBuf;
 	Common::KeyState _keyPressed;
diff --git a/engines/sword1/logic.h b/engines/sword1/logic.h
index c38c42ca124..73fe9cfc54d 100644
--- a/engines/sword1/logic.h
+++ b/engines/sword1/logic.h
@@ -53,6 +53,7 @@ class Logic;
 typedef int (Logic::*BSMcodeTable)(Object *, int32, int32, int32, int32, int32, int32, int32);
 
 class Logic {
+	friend class Control;
 public:
 	Logic(SwordEngine *vm, ObjectMan *pObjMan, ResMan *resMan, Screen *pScreen, Mouse *pMouse, Sound *pSound, Music *pMusic, Menu *pMenu, OSystem *system, Audio::Mixer *mixer);
 	~Logic();
diff --git a/engines/sword1/mouse.cpp b/engines/sword1/mouse.cpp
index 72267ef1bf4..a326b4cf401 100644
--- a/engines/sword1/mouse.cpp
+++ b/engines/sword1/mouse.cpp
@@ -71,12 +71,10 @@ void Mouse::controlPanel(bool on) { // true on entering cpanel, false when leavi
 	if (on) {
 		savedPtrId = _currentPtrId;
 		_mouseOverride = true;
-		setLuggage(0, 0);
 		setPointer(MSE_POINTER, 0);
 	} else {
 		_currentPtrId = savedPtrId;
 		_mouseOverride = false;
-		setLuggage(_currentLuggageId, 0);
 		setPointer(_currentPtrId, 0);
 	}
 }
diff --git a/engines/sword1/screen.cpp b/engines/sword1/screen.cpp
index 8cc62dbcd82..1e11c470b98 100644
--- a/engines/sword1/screen.cpp
+++ b/engines/sword1/screen.cpp
@@ -210,9 +210,10 @@ void Screen::fnSetFadeTargetPalette(uint8 start, uint16 length, uint32 id, bool
 	_resMan->resClose(id);
 }
 
-void Screen::fullRefresh() {
+void Screen::fullRefresh(bool soft) {
 	_fullRefresh = true;
-	_system->getPaletteManager()->setPalette(_targetPalette, 0, 256);
+	if (!soft)
+		_system->getPaletteManager()->setPalette(_targetPalette, 0, 256);
 }
 
 int16 Screen::stillFading() {
diff --git a/engines/sword1/screen.h b/engines/sword1/screen.h
index 8489c73125c..448bec2ee4b 100644
--- a/engines/sword1/screen.h
+++ b/engines/sword1/screen.h
@@ -90,7 +90,7 @@ public:
 	void fnSetPalette(uint8 start, uint16 length, uint32 id);
 	void fnSetFadeTargetPalette(uint8 start, uint16 length, uint32 id, bool toBlack = false);
 	int16 stillFading();
-	void fullRefresh();
+	void fullRefresh(bool soft = false);
 
 	bool showScrollFrame();
 	void updateScreen();
diff --git a/engines/sword1/sound.h b/engines/sword1/sound.h
index 72475d27ef5..093dfe0f79b 100644
--- a/engines/sword1/sound.h
+++ b/engines/sword1/sound.h
@@ -79,6 +79,7 @@ enum CowMode {
 
 class Sound {
 	friend class SwordConsole;
+	friend class Control;
 public:
 	Sound(Audio::Mixer *mixer, ResMan *pResMan);
 	~Sound();
diff --git a/engines/sword1/sword1.cpp b/engines/sword1/sword1.cpp
index cc0f6a896de..b93b4cbf7cd 100644
--- a/engines/sword1/sword1.cpp
+++ b/engines/sword1/sword1.cpp
@@ -161,7 +161,7 @@ Common::Error SwordEngine::init() {
 	_logic->initialize();
 	_objectMan->initialize();
 	_mouse->initialize();
-	_control = new Control(this, _saveFileMan, _resMan, _objectMan, _system, _mouse, _sound, _music, _screen);
+	_control = new Control(this, _saveFileMan, _resMan, _objectMan, _system, _mouse, _sound, _music, _screen, _logic);
 
 	return Common::kNoError;
 }
@@ -259,13 +259,12 @@ uint8 SwordEngine::checkKeys() {
 		case Common::KEYCODE_F5:
 		case Common::KEYCODE_ESCAPE:
 			if ((Logic::_scriptVars[MOUSE_STATUS] & 1) && (Logic::_scriptVars[GEORGE_HOLDING_PIECE] == 0)) {
-				/*
-				 * saveGameFlag = 1;
-				 * snrStatus = 1;
-				*/
 				retCode = _control->runPanel();
-				if (retCode == CONTROL_NOTHING_DONE)
-					_screen->fullRefresh();
+				if (retCode == CONTROL_NOTHING_DONE) {
+					_screen->fullRefresh(true);
+					Logic::_scriptVars[NEW_PALETTE] = 1;
+				}
+
 			}
 			break;
 		default:


Commit: f564ad8ea89450eef06c866fb91be2b8005979d7
    https://github.com/scummvm/scummvm/commit/f564ad8ea89450eef06c866fb91be2b8005979d7
Author: AndywinXp (andywinxp at gmail.com)
Date: 2023-09-02T11:32:51+02:00

Commit Message:
SWORD1: Fix unused var warning

Changed paths:
    engines/sword1/screen.cpp


diff --git a/engines/sword1/screen.cpp b/engines/sword1/screen.cpp
index 1e11c470b98..3ae7233c0c5 100644
--- a/engines/sword1/screen.cpp
+++ b/engines/sword1/screen.cpp
@@ -1338,7 +1338,7 @@ void Screen::fnFlash(uint8 color) {
 		return;
 	}
 
-	_system->getPaletteManager()->setPalette(_currentPalette, 0, 1);
+	_system->getPaletteManager()->setPalette(targetColor, 0, 1);
 
 	if (color == FLASH_RED || color == FLASH_BLUE) {
 		// This is what the original did here to induce a small wait cycle


Commit: dbe1a2df4f64a96ca2cb55c5acd98c2b3ab07f99
    https://github.com/scummvm/scummvm/commit/dbe1a2df4f64a96ca2cb55c5acd98c2b3ab07f99
Author: AndywinXp (andywinxp at gmail.com)
Date: 2023-09-02T11:32:51+02:00

Commit Message:
SWORD1: Make changes for code review

Changed paths:
    engines/sword1/screen.cpp
    engines/sword1/sword1.cpp


diff --git a/engines/sword1/screen.cpp b/engines/sword1/screen.cpp
index 3ae7233c0c5..31e409efdc5 100644
--- a/engines/sword1/screen.cpp
+++ b/engines/sword1/screen.cpp
@@ -227,47 +227,48 @@ int16 Screen::stillFading() {
 void Screen::fadePalette() {
 	_paletteFadeInfo.fadeCount++;
 
-	if (_paletteFadeInfo.fadeCount == _paletteFadeInfo.paletteIndex) {
-		_paletteFadeInfo.fadeCount = 0;
+	if (_paletteFadeInfo.fadeCount != _paletteFadeInfo.paletteIndex)
+		return;
 
-		if (_paletteFadeInfo.paletteStatus == NO_FADE)
-			return;
-
-		// Set the whole palette to the current source.
-		// But first, remember that these are 6 bit values, and
-		// they have to be shifted left two times before using them.
-		byte outPal[256 * 3];
-		for (int i = 0; i < 256 * 3; i++) {
-			// Remember that we previously allowed the RGB values
-			// to go below zero? It's time to account for that;
-			// This contributes to producing the correct palette fading effect.
-			int8 curValueSigned = (int8)_paletteFadeInfo.srcPalette[i];
-			if (curValueSigned < 0)
-				curValueSigned = 0;
-
-			outPal[i] = ((byte)curValueSigned) << 2;
-		}
+	_paletteFadeInfo.fadeCount = 0;
 
-		_system->getPaletteManager()->setPalette((const byte *)outPal, 0, 256);
+	if (_paletteFadeInfo.paletteStatus == NO_FADE)
+		return;
 
-		_paletteFadeInfo.paletteCount--;
+	// Set the whole palette to the current source.
+	// But first, remember that these are 6 bit values, and
+	// they have to be shifted left two times before using them.
+	byte outPal[256 * 3];
+	for (int i = 0; i < 256 * 3; i++) {
+		// Remember that we previously allowed the RGB values
+		// to go below zero? It's time to account for that;
+		// This contributes to producing the correct palette fading effect.
+		int8 curValueSigned = (int8)_paletteFadeInfo.srcPalette[i];
+		if (curValueSigned < 0)
+			curValueSigned = 0;
 
-		if (_paletteFadeInfo.paletteCount == 0) {
-			_paletteFadeInfo.paletteStatus = NO_FADE;
-		} else {
-			if (_paletteFadeInfo.paletteStatus == FADE_DOWN) {
-				// Fade down
-				for (int i = 0; i < 256 * 3; i++) {
-					if (_paletteFadeInfo.srcPalette[i] > 0)
-						_paletteFadeInfo.srcPalette[i]--;
-				}
-			} else if (_paletteFadeInfo.paletteStatus == FADE_UP) {
-				// Fade up
-				for (int i = 0; i < 256 * 3; i++) {
-					// Remember, we might have previously obtained negative values!
-					if ((int8)_paletteFadeInfo.srcPalette[i] < (int8)_paletteFadeInfo.dstPalette[i]) {
-						_paletteFadeInfo.srcPalette[i]++;
-					}
+		outPal[i] = ((byte)curValueSigned) << 2;
+	}
+
+	_system->getPaletteManager()->setPalette((const byte *)outPal, 0, 256);
+
+	_paletteFadeInfo.paletteCount--;
+
+	if (_paletteFadeInfo.paletteCount == 0) {
+		_paletteFadeInfo.paletteStatus = NO_FADE;
+	} else {
+		if (_paletteFadeInfo.paletteStatus == FADE_DOWN) {
+			// Fade down
+			for (int i = 0; i < 256 * 3; i++) {
+				if (_paletteFadeInfo.srcPalette[i] > 0)
+					_paletteFadeInfo.srcPalette[i]--;
+			}
+		} else if (_paletteFadeInfo.paletteStatus == FADE_UP) {
+			// Fade up
+			for (int i = 0; i < 256 * 3; i++) {
+				// Remember, we might have previously obtained negative values!
+				if ((int8)_paletteFadeInfo.srcPalette[i] < (int8)_paletteFadeInfo.dstPalette[i]) {
+					_paletteFadeInfo.srcPalette[i]++;
 				}
 			}
 		}
diff --git a/engines/sword1/sword1.cpp b/engines/sword1/sword1.cpp
index b93b4cbf7cd..60b62242b73 100644
--- a/engines/sword1/sword1.cpp
+++ b/engines/sword1/sword1.cpp
@@ -867,13 +867,13 @@ void SwordEngine::fadePaletteStep() {
 void SwordEngine::startFadePaletteDown(int speed) {
 	_screen->startFadePaletteDown(speed);
 
-	// Fade audio here
+	// TODO: Fade audio here
 }
 
 void SwordEngine::startFadePaletteUp(int speed) {
 	_screen->startFadePaletteUp(speed);
 
-	// Fade audio here
+	// TODO: Fade audio here
 }
 
 static void vblCallback(void *refCon) {


Commit: 67052e2ef5f3628f80bed6affd4576371883183a
    https://github.com/scummvm/scummvm/commit/67052e2ef5f3628f80bed6affd4576371883183a
Author: AndywinXp (andywinxp at gmail.com)
Date: 2023-09-02T11:32:51+02:00

Commit Message:
SWORD1: Address other issues from code review

Changed paths:
    engines/sword1/control.cpp
    engines/sword1/screen.cpp
    engines/sword1/screen.h


diff --git a/engines/sword1/control.cpp b/engines/sword1/control.cpp
index d1f68133a75..808da56b365 100644
--- a/engines/sword1/control.cpp
+++ b/engines/sword1/control.cpp
@@ -344,7 +344,7 @@ uint8 Control::runPanel() {
 	// Set up mouse
 	_mouse->controlPanel(true);
 
-	uint8 mode = 0, newMode = BUTTON_MAIN_PANEL;
+	uint8 mode = BUTTON_MAIN_PANEL, newMode = 0;
 	bool fullRefresh = false;
 	uint8 retVal = CONTROL_NOTHING_DONE;
 
diff --git a/engines/sword1/screen.cpp b/engines/sword1/screen.cpp
index 31e409efdc5..965d58833d5 100644
--- a/engines/sword1/screen.cpp
+++ b/engines/sword1/screen.cpp
@@ -191,12 +191,12 @@ void Screen::fnSetPalette(uint8 start, uint16 length, uint32 id) {
 }
 
 void Screen::fnSetFadeTargetPalette(uint8 start, uint16 length, uint32 id, bool toBlack) {
-	byte *rgbData = nullptr;
+	const uint8 *rgbData = nullptr;
 
 	if (toBlack) {
-		rgbData = const_cast<byte *>(_black);
+		rgbData = _black;
 	} else {
-		rgbData = (byte *) _resMan->openFetchRes(id);
+		rgbData = (const uint8 *) _resMan->openFetchRes(id);
 	}
 
 	if (SwordEngine::_systemVars.wantFade) {
@@ -1313,7 +1313,7 @@ void Screen::spriteClipAndSet(uint16 *pSprX, uint16 *pSprY, uint16 *pSprWidth, u
 }
 
 void Screen::fnFlash(uint8 color) {
-	const byte *targetColor = _white;
+	const uint8 *targetColor = _white;
 
 	switch (color) {
 	case FLASH_RED:
@@ -1344,7 +1344,11 @@ void Screen::fnFlash(uint8 color) {
 	if (color == FLASH_RED || color == FLASH_BLUE) {
 		// This is what the original did here to induce a small wait cycle
 		// to correctly display the color before it is turned back to black...
-		for (int i = 0; i < 20000; ++i);
+		//
+		// for (int i = 0; i < 20000; ++i);
+		//
+		// We induce a delay instead
+		_system->delayMillis(200);
 
 		_system->getPaletteManager()->setPalette(_black, 0, 1);
 	}
diff --git a/engines/sword1/screen.h b/engines/sword1/screen.h
index 448bec2ee4b..6cd1a4ca74a 100644
--- a/engines/sword1/screen.h
+++ b/engines/sword1/screen.h
@@ -103,22 +103,22 @@ public:
 
 private:
 	// The original values are 6-bit RGB numbers, so they have to be shifted
-	const byte _white[3]  = { 63 << 2, 63 << 2, 63 << 2};
-	const byte _red[3]    = { 63 << 2, 0  << 2, 0  << 2};
-	const byte _blue[3]   = { 0  << 2, 0  << 2, 63 << 2};
-	const byte _yellow[3] = { 63 << 2, 63 << 2, 0  << 2};
-	const byte _green[3]  = { 0  << 2, 63 << 2, 0  << 2};
-	const byte _purple[3] = { 32 << 2, 0  << 2, 32 << 2};
-	const byte _black[3]  = { 0  << 2, 0  << 2, 0  << 2};
-	const byte _grey[3]   = { 32 << 2, 32 << 2, 32 << 2};
+	const uint8 _white[3]  = { 63 << 2, 63 << 2, 63 << 2};
+	const uint8 _red[3]    = { 63 << 2, 0  << 2, 0  << 2};
+	const uint8 _blue[3]   = { 0  << 2, 0  << 2, 63 << 2};
+	const uint8 _yellow[3] = { 63 << 2, 63 << 2, 0  << 2};
+	const uint8 _green[3]  = { 0  << 2, 63 << 2, 0  << 2};
+	const uint8 _purple[3] = { 32 << 2, 0  << 2, 32 << 2};
+	const uint8 _black[3]  = { 0  << 2, 0  << 2, 0  << 2};
+	const uint8 _grey[3]   = { 32 << 2, 32 << 2, 32 << 2};
 
 	struct PaletteFadeInfo {
 		int16 paletteStatus;
 		int16 paletteIndex;
 		int16 paletteCount;
 		int16 fadeCount;
-		byte srcPalette[256 * 3];
-		byte dstPalette[256 * 3];
+		uint8 srcPalette[256 * 3];
+		uint8 dstPalette[256 * 3];
 	};
 
 	PaletteFadeInfo _paletteFadeInfo;


Commit: e658ce8a164f79400ced1f50c14cea042e47b06d
    https://github.com/scummvm/scummvm/commit/e658ce8a164f79400ced1f50c14cea042e47b06d
Author: AndywinXp (andywinxp at gmail.com)
Date: 2023-09-02T11:32:51+02:00

Commit Message:
SWORD1: Fix fade palette for Mac version

Changed paths:
    engines/sword1/screen.cpp


diff --git a/engines/sword1/screen.cpp b/engines/sword1/screen.cpp
index 965d58833d5..f2d09b4437a 100644
--- a/engines/sword1/screen.cpp
+++ b/engines/sword1/screen.cpp
@@ -300,6 +300,10 @@ void Screen::updateScreen() {
 		fnSetFadeTargetPalette(0, 184, _roomDefTable[_currentScreen].palettes[0]);
 		fnSetFadeTargetPalette(184, 72, _roomDefTable[_currentScreen].palettes[1]);
 		fnSetFadeTargetPalette(0, 1, 0, true);
+		// Bug #8636: Force color 255 to black
+		if (SwordEngine::isMac())
+			fnSetFadeTargetPalette(255, 1, 0, true);
+
 		startFadePaletteUp(1);
 		_updatePalette = false;
 	}


Commit: 7b8efd98459fb58929af14293cb6e0ba9801542e
    https://github.com/scummvm/scummvm/commit/7b8efd98459fb58929af14293cb6e0ba9801542e
Author: AndywinXp (andywinxp at gmail.com)
Date: 2023-09-02T11:32:51+02:00

Commit Message:
SWORD1: Fix fade to cut palette

Changed paths:
    engines/sword1/screen.cpp


diff --git a/engines/sword1/screen.cpp b/engines/sword1/screen.cpp
index f2d09b4437a..ad21e442e8f 100644
--- a/engines/sword1/screen.cpp
+++ b/engines/sword1/screen.cpp
@@ -163,10 +163,18 @@ void Screen::startFadePaletteUp(int speed) {
 		_paletteFadeInfo.fadeCount = 0;
 		_paletteFadeInfo.paletteStatus = FADE_UP;
 	} else {
-		_system->getPaletteManager()->setPalette(_currentPalette, 0, 256);
-
 		// Set up the source palette
 		memcpy((uint8 *)_paletteFadeInfo.srcPalette, (uint8 *)_currentPalette, 256 * 3);
+
+		// Remember: whenever we are showing the palette to the outside world
+		// we have to shift it, because these are 6-bit values!
+		uint8 shiftedPalette[768];
+
+		for (int i = 0; i < sizeof(shiftedPalette); i++) {
+			shiftedPalette[i] = _currentPalette[i] << 2;
+		}
+
+		_system->getPaletteManager()->setPalette(shiftedPalette, 0, 256);
 	}
 }
 


Commit: 461009e823f7b4f8ef5f267dcbab30694609048e
    https://github.com/scummvm/scummvm/commit/461009e823f7b4f8ef5f267dcbab30694609048e
Author: AndywinXp (andywinxp at gmail.com)
Date: 2023-09-02T11:32:51+02:00

Commit Message:
SWORD1: Free palette resource only when actually using it

Changed paths:
    engines/sword1/screen.cpp


diff --git a/engines/sword1/screen.cpp b/engines/sword1/screen.cpp
index ad21e442e8f..6c31e8f5f08 100644
--- a/engines/sword1/screen.cpp
+++ b/engines/sword1/screen.cpp
@@ -215,7 +215,9 @@ void Screen::fnSetFadeTargetPalette(uint8 start, uint16 length, uint32 id, bool
 		memcpy(_currentPalette + (start * 3), rgbData, length * 3);
 	}
 
-	_resMan->resClose(id);
+	if (!toBlack) {
+		_resMan->resClose(id);
+	}
 }
 
 void Screen::fullRefresh(bool soft) {




More information about the Scummvm-git-logs mailing list