[Scummvm-git-logs] scummvm master -> 631447e36b19da872af69c1091c2e5284197d2a0

mduggan noreply at scummvm.org
Tue Dec 31 08:03:14 UTC 2024


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

Summary:
8d7393bc6b DGDS: Implement reading of Willy Beamish reset file
9329538095 DGDS: Fix willy trouble gauge rendering
a87b9e7080 DGDS: Implement Willy Beamish help menu
631447e36b DGDS: More Willy Beamish fixes


Commit: 8d7393bc6be71fb7c2859e2d70ad79b58991ca0a
    https://github.com/scummvm/scummvm/commit/8d7393bc6be71fb7c2859e2d70ad79b58991ca0a
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2024-12-31T11:15:43+11:00

Commit Message:
DGDS: Implement reading of Willy Beamish reset file

Changed paths:
    engines/dgds/scene.cpp


diff --git a/engines/dgds/scene.cpp b/engines/dgds/scene.cpp
index b7aa5d2636e..2dfc74e8bf0 100644
--- a/engines/dgds/scene.cpp
+++ b/engines/dgds/scene.cpp
@@ -1672,7 +1672,7 @@ bool GDSScene::loadRestart(const Common::String &filename, ResourceManager *reso
 
 	uint16 num = file->readUint16LE();
 	// Find matching game item and load its values
-	while (num) {
+	while (num && !file->eos()) {
 		bool found = false;
 		for (GameItem &item : _gameItems) {
 			if (item._num == num) {
@@ -1693,57 +1693,111 @@ bool GDSScene::loadRestart(const Common::String &filename, ResourceManager *reso
 	}
 	initIconSizes();
 
-	num = file->readUint16LE();
-	while (num) {
-		uint16 scene = file->readUint16LE();
-		int16 val = file->readSint16LE();
-		bool found = false;
-		for (PerSceneGlobal &glob : _perSceneGlobals) {
-			if (glob.matches(num, scene)) {
-				glob._val = val;
-				found = true;
-				break;
+	DgdsEngine *engine = DgdsEngine::getInstance();
+	Common::Array<Global *> &globs = engine->getGameGlobals()->getAllGlobals();
+
+	if (engine->getGameId() == GID_DRAGON || engine->getGameId() == GID_HOC) {
+		num = file->readUint16LE();
+		while (num && !file->eos()) {
+			uint16 scene = file->readUint16LE();
+			int16 val = file->readSint16LE();
+			bool found = false;
+			for (PerSceneGlobal &glob : _perSceneGlobals) {
+				if (glob.matches(num, scene)) {
+					glob._val = val;
+					found = true;
+					break;
+				}
 			}
+			if (!found)
+				error("Reset file references unknown scene global %d", num);
+			num = file->readUint16LE();
 		}
-		if (!found)
-			error("Reset file references unknown global %d", num);
-		num = file->readUint16LE();
-	}
 
-	/*uint32 unk = */ file->readUint32LE();
+		/*uint32 unk = */ file->readUint32LE();
 
-	DgdsEngine *engine = DgdsEngine::getInstance();
-	Common::Array<Global *> &globs = engine->getGameGlobals()->getAllGlobals();
+		if (globs.size() > 50)
+			error("Too many globals to load from RST file");
 
-	if (globs.size() > 50)
-		error("Too many globals to load from RST file");
+		int g = 0;
+		for (Global *glob : globs) {
+			int16 val = file->readUint16LE();
+			glob->setRaw(val);
+			g++;
+		}
+		// Always 50 int16s worth of globals in the file, skip any unused.
+		if (g < 50)
+			file->skip(2 * (50 - g));
 
-	int g = 0;
-	for (Global *glob : globs) {
-		int16 val = file->readUint16LE();
-		glob->setRaw(val);
-		g++;
-	}
+		uint16 triggers[100];
+		for (int i = 0; i < ARRAYSIZE(triggers); i++) {
+			triggers[i] = file->readUint16LE();
+		}
+
+		engine->_compositionBuffer.fillRect(Common::Rect(SCREEN_WIDTH, SCREEN_HEIGHT), 0);
+		// TODO: FIXME: What should this scene num be? For now hacked to work with Dragon.
+		engine->changeScene(3);
+		SDSScene *scene = engine->getScene();
+		int t = 0;
+		num = triggers[t++];
+		while (num) {
+			uint16 val = triggers[t++];
+			scene->enableTrigger(0, num, (bool)val);
+			num = triggers[t++];
+		}
+	} else {
+		// Willy Beamish stores the globals differently
+		num = file->readUint16LE();
+		while (num && !file->eos()) {
+			int16 val = file->readSint16LE();
+			bool found = false;
+			for (PerSceneGlobal &glob : _perSceneGlobals) {
+				if (glob.numMatches(num)) {
+					glob._val = val;
+					found = true;
+					break;
+				}
+			}
+			if (!found)
+				error("Reset file references unknown scene global %d", num);
+			num = file->readUint16LE();
+		}
 
-	// Always 50 int16s worth of globals in the file, skip any unused.
-	if (g < 50)
-		file->skip(2 * (50 - g));
+		/*uint32 unk = */ file->readUint32LE();
 
-	uint16 triggers[100];
-	for (int i = 0; i < ARRAYSIZE(triggers); i++) {
-		triggers[i] = file->readUint16LE();
-	}
+		num = file->readUint16LE();
+		while (num && !file->eos()) {
+			bool found = false;
+			int16 val = file->readUint16LE();
+			for (Global *glob : globs) {
+				if (glob->getNum() == num) {
+					glob->setRaw(val);
+					found = true;
+					break;
+				}
+			}
+			if (!found)
+				error("Reset file references unknown game global %d", num);
+			num = file->readUint16LE();
+		}
 
-	engine->_compositionBuffer.fillRect(Common::Rect(SCREEN_WIDTH, SCREEN_HEIGHT), 0);
-	// TODO: FIXME: What should this scene num be? For now hacked to work with Dragon.
-	engine->changeScene(3);
-	SDSScene *scene = engine->getScene();
-	int t = 0;
-	num = triggers[t++];
-	while (num) {
-		uint16 val = triggers[t++];
-		scene->enableTrigger(0, num, (bool)val);
-		num = triggers[t++];
+		//
+		// TODO: What is this block of data?  In practice there is only one of them
+		//
+		while (!file->eos()) {
+			num = file->readUint16LE();
+			if (!num)
+				break;
+			/*int16 val1 = */ file->readUint16LE();
+			/*int16 val2 = */ file->readUint16LE();
+			/*int16 val3 = */ file->readUint16LE();
+		}
+
+		/*uint16 soundBankNum = */ file->readUint16LE();
+
+		engine->_compositionBuffer.fillRect(Common::Rect(SCREEN_WIDTH, SCREEN_HEIGHT), 0);
+		// TODO: FIXME: What should this scene num be?
+		engine->changeScene(3);
 	}
 
 	return true;


Commit: 9329538095bcf8c11fccef47619fa2d815fe824a
    https://github.com/scummvm/scummvm/commit/9329538095bcf8c11fccef47619fa2d815fe824a
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2024-12-31T11:15:43+11:00

Commit Message:
DGDS: Fix willy trouble gauge rendering

Changed paths:
    engines/dgds/globals.cpp


diff --git a/engines/dgds/globals.cpp b/engines/dgds/globals.cpp
index 47fd84ccdf8..3a29b998580 100644
--- a/engines/dgds/globals.cpp
+++ b/engines/dgds/globals.cpp
@@ -335,7 +335,7 @@ public:
 			int16 newBarSize = val * 8;
 
 			// Animate the trouble bar going up or down
-			compBuf.fillRect(Common::Rect(Common::Point(0x80, 0x8a), 0x47, 3), 16);
+			compBuf.fillRect(Common::Rect(Common::Point(0x80, 0x96), 0x47, 4), 16);
 
 			for (int sz = prevBarSize; sz != newBarSize; sz += sign) {
 				RequestData::drawCorners(&compBuf, 0, 0x71, 0x25, 0x5e, 0x7e);


Commit: a87b9e7080d4e2b3cf93fb1666c10f86a84117dd
    https://github.com/scummvm/scummvm/commit/a87b9e7080d4e2b3cf93fb1666c10f86a84117dd
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2024-12-31T15:46:46+11:00

Commit Message:
DGDS: Implement Willy Beamish help menu

Changed paths:
    engines/dgds/globals.cpp
    engines/dgds/globals.h
    engines/dgds/menu.cpp
    engines/dgds/scene_op.cpp


diff --git a/engines/dgds/globals.cpp b/engines/dgds/globals.cpp
index 3a29b998580..b710eb8f949 100644
--- a/engines/dgds/globals.cpp
+++ b/engines/dgds/globals.cpp
@@ -60,14 +60,14 @@ private:
 
 
 Globals::Globals(Clock &clock) :
-_lastOpcode1SceneChageNum(0), _sceneOp12SceneNum(0), _currentSelectedItem(0),
+_lastOpcode1SceneChangeNum(0), _sceneOp12SceneNum(0), _currentSelectedItem(0),
 _gameMinsToAddOnLClick(0), _gameMinsToAddOnStartDrag(0), _gameMinsToAddOnRClick(0), _gameMinsToAddOnDragFinished(0),
 _gameMinsToAddOnObjInteraction(0), _gameIsInteractiveGlobal(0), _sceneOpcode15FromScene(0),
 _sceneOpcode15ToScene(0) {
 	_globals.push_back(clock.getGameMinsAddedGlobal(1));
 	_globals.push_back(clock.getGameTicksUpGlobal(0x64));
 	_globals.push_back(clock.getGameTicksDownGlobal(0x63));
-	_globals.push_back(new ROI16Global(0x62, &_lastOpcode1SceneChageNum));
+	_globals.push_back(new ROI16Global(0x62, &_lastOpcode1SceneChangeNum));
 	_globals.push_back(new RWI16Global(0x61, &_sceneOp12SceneNum));
 	_globals.push_back(new RWI16Global(0x60, &_currentSelectedItem));
 	_globals.push_back(clock.getDaysGlobal(0x5F));
@@ -123,7 +123,7 @@ int16 Globals::setGlobal(uint16 num, int16 val) {
 }
 
 Common::Error Globals::syncState(Common::Serializer &s) {
-	s.syncAsSint16LE(_lastOpcode1SceneChageNum);
+	s.syncAsSint16LE(_lastOpcode1SceneChangeNum);
 	s.syncAsSint16LE(_sceneOp12SceneNum);
 	s.syncAsSint16LE(_currentSelectedItem);
 	s.syncAsSint16LE(_gameMinsToAddOnLClick);
diff --git a/engines/dgds/globals.h b/engines/dgds/globals.h
index 0683caf8a3e..f025ae4144f 100644
--- a/engines/dgds/globals.h
+++ b/engines/dgds/globals.h
@@ -96,12 +96,13 @@ public:
 	int16 getGameMinsToAddOnObjInteraction() const { return _gameMinsToAddOnObjInteraction; }
 	int16 getGameIsInteractiveGlobal() { return _gameIsInteractiveGlobal; }
 
-	void setLastSceneNum(int16 num) { _lastOpcode1SceneChageNum = num; }
+	void setLastSceneNum(int16 num) { _lastOpcode1SceneChangeNum = num; }
+	int16 getLastSceneNum() const { return _lastOpcode1SceneChangeNum; }
 
 protected:
 
 	// these ones seem to be common between games
-	int16 _lastOpcode1SceneChageNum;
+	int16 _lastOpcode1SceneChangeNum;
 	int16 _sceneOp12SceneNum;
 	int16 _currentSelectedItem;
 	int16 _gameMinsToAddOnLClick;
diff --git a/engines/dgds/menu.cpp b/engines/dgds/menu.cpp
index 7f296f29a63..8b31f8e72ec 100644
--- a/engines/dgds/menu.cpp
+++ b/engines/dgds/menu.cpp
@@ -47,7 +47,7 @@ enum MenuButtonIds {
 	kMainMenuWillyLoad = 111,
 	kMainMenuWillyRestart = 112,
 	kMainMenuWillyQuit = 113,
-	kMainMenuWillyHelp = 114,
+	kMainMenuWillyHelp = 120,
 	kMainMenuWillySoundsOnOff = 115,
 	kMainMenuWillyMusicOnOff = 116,
 
@@ -230,6 +230,11 @@ void Menu::configureGadget(MenuId menu, Gadget *gadget) {
 		}
 	} else if (menu == kMenuOptions) {
 		updateOptionsGadget(gadget);
+	} else if (menu == kMenuMain && engine->getGameId() == GID_WILLY) {
+		// HACK: Enable this button which for some reason is disabled
+		// by default in data?
+		if (gadget->_gadgetNo == kMainMenuWillyHelp)
+			toggleGadget(kMainMenuWillyHelp, true);
 	}
 }
 
@@ -405,6 +410,26 @@ void Menu::onMouseLUp(const Common::Point &mouse) {
 		drawMenu(_curMenu);
 }
 
+
+static void _toggleSoundType(Audio::Mixer::SoundType soundType) {
+	DgdsEngine *engine = DgdsEngine::getInstance();
+	Audio::Mixer *mixer = engine->_mixer;
+	const char *typeStr = (soundType == Audio::Mixer::kMusicSoundType) ? "music" : "sfx";
+	if (!mixer->isSoundTypeMuted(soundType)) {
+		mixer->muteSoundType(soundType, true);
+		warning("TODO: Sync volume and pause %s", typeStr);
+		//midiPlayer->syncVolume();
+		//if (soundType == Audio::Mixer::kMusicSoundType)
+		//	engine->_soundPlayer->pauseMusic();
+	} else {
+		mixer->muteSoundType(soundType, false);
+		warning("TODO: Sync volume and resume %s", typeStr);
+		//midiPlayer->syncVolume();
+		//if (soundType == Audio::Mixer::kMusicSoundType)
+		//	engine->_soundPlayer->resumeMusic();
+	}
+}
+
 void Menu::handleClick(const Common::Point &mouse) {
 	DgdsEngine *engine = DgdsEngine::getInstance();
 	int currentScene = engine->getScene()->getNum();
@@ -421,7 +446,11 @@ void Menu::handleClick(const Common::Point &mouse) {
 	//case kMenuCalibratePlayHoC:
 	//case kMenuMouseCalibrationPlay:
 		hideMenu();
-		CursorMan.showMouse(false);
+		if (engine->getGameId() == GID_WILLY && clickedMenuItem == kMainMenuWillyHelp) {
+			engine->changeScene(80);
+		} else {
+			CursorMan.showMouse(false);
+		}
 		break;
 	case kMenuMainControls:
 		drawMenu(kMenuControls);
@@ -430,6 +459,13 @@ void Menu::handleClick(const Common::Point &mouse) {
 		drawMenu(kMenuOptions);
 		break;
 	case kMenuMainCalibrate:
+		if (engine->getGameId() == GID_WILLY) {
+			debug("TODO: Implement willy beamish credits");
+			hideMenu();
+		} else {
+			debug("Ignoring calibration request");
+		}
+		break;
 	//case kMenuJoystickCalibrationOK:
 	//case kMenuMouseCalibrationCalibrate: // NOTE: same ID as kMenuIntroJumpToGame (for HOC)
 	case kMenuIntroJumpToGame:
@@ -444,9 +480,12 @@ void Menu::handleClick(const Common::Point &mouse) {
 			drawMenu(_curMenu);
 		}
 		break;
-	case kMenuMainFiles:
+	case kMenuMainFiles: // Same ID as Play in Willy Beamish
 	//case kMenuSaveCancel:
-		drawMenu(kMenuFiles);
+		if (engine->getGameId() == GID_WILLY)
+			hideMenu();
+		else
+			drawMenu(kMenuFiles);
 		break;
 	case kMenuMainQuit:
 		drawMenu(kMenuReallyQuit);
@@ -586,6 +625,14 @@ void Menu::handleClick(const Common::Point &mouse) {
 			drawMenu(kMenuSaveBeforeArcade);
 		}
 		break;
+	case kMainMenuWillySoundsOnOff:
+		_toggleSoundType(Audio::Mixer::kSFXSoundType);
+		updateOptionsGadget(gadget);
+		break;
+	case kMainMenuWillyMusicOnOff:
+		_toggleSoundType(Audio::Mixer::kMusicSoundType);
+		updateOptionsGadget(gadget);
+		break;
 	default:
 		debug(1, "Clicked ID %d", clickedMenuItem);
 		break;
@@ -593,11 +640,8 @@ void Menu::handleClick(const Common::Point &mouse) {
 }
 
 void Menu::handleClickOptionsMenu(const Common::Point &mouse) {
-	DgdsEngine *engine = DgdsEngine::getInstance();
-	Audio::Mixer *mixer = engine->_mixer;
 	Gadget *gadget = getClickedMenuItem(mouse);
 	int16 clickedMenuItem = gadget->_gadgetNo;
-	Audio::Mixer::SoundType soundType = Audio::Mixer::kMusicSoundType;
 
 	switch (clickedMenuItem) {
 	case kMenuOptionsJoystickOnOff:
@@ -610,23 +654,13 @@ void Menu::handleClickOptionsMenu(const Common::Point &mouse) {
 	case kMenuOptionsSoundsOnOffDE:
 	case kMenuOptionsSoundsOnOffHoC:
 	case kMainMenuWillySoundsOnOff:
-		soundType = Audio::Mixer::kSFXSoundType;
-		// fall through
+		_toggleSoundType(Audio::Mixer::kSFXSoundType);
+		updateOptionsGadget(gadget);
+		break;
 	case kMenuOptionsMusicOnOff:
 	case kMenuOptionsMusicOnOffHoC:
 	case kMainMenuWillyMusicOnOff:
-		if (!mixer->isSoundTypeMuted(soundType)) {
-			mixer->muteSoundType(soundType, true);
-			warning("TODO: Sync volume and pause music");
-			//midiPlayer->syncVolume();
-			//engine->_soundPlayer->pauseMusic();
-		} else {
-			mixer->muteSoundType(soundType, false);
-			warning("TODO: Sync volume and resume music");
-			//midiPlayer->syncVolume();
-			//engine->_soundPlayer->resumeMusic();
-		}
-
+		_toggleSoundType(Audio::Mixer::kMusicSoundType);
 		updateOptionsGadget(gadget);
 		break;
 	default:
diff --git a/engines/dgds/scene_op.cpp b/engines/dgds/scene_op.cpp
index 615102f194c..7b99943c15d 100644
--- a/engines/dgds/scene_op.cpp
+++ b/engines/dgds/scene_op.cpp
@@ -173,6 +173,15 @@ bool SceneOp::runCommonOp() const {
 			return true;
 		break;
 	case kSceneOpNoop:
+		//
+		// This is run when the "quit willy beamish help" dialog item is called.
+		// There may be a nicer way to do this?
+		//
+		if (engine->getScene()->getNum() == 80 && engine->getGameId() == GID_WILLY) {
+			int16 sceneNo = engine->getGameGlobals()->getGlobal(0x61);
+			if (engine->changeScene(sceneNo))
+				return true;
+		}
 		break;
 	case kSceneOpGlobal:
 		// The globals are held by the GDS scene


Commit: 631447e36b19da872af69c1091c2e5284197d2a0
    https://github.com/scummvm/scummvm/commit/631447e36b19da872af69c1091c2e5284197d2a0
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2024-12-31T19:02:30+11:00

Commit Message:
DGDS: More Willy Beamish fixes

* Swap between look and interact mode with right mouse
* Implement credits
* Mostly fix graphical glitch in intro

Changed paths:
    engines/dgds/dgds.cpp
    engines/dgds/dgds.h
    engines/dgds/inventory.cpp
    engines/dgds/menu.cpp
    engines/dgds/menu.h
    engines/dgds/minigames/china_train.cpp
    engines/dgds/scene.cpp
    engines/dgds/scene.h
    engines/dgds/ttm.cpp


diff --git a/engines/dgds/dgds.cpp b/engines/dgds/dgds.cpp
index 0162f05765f..5e95c5b6341 100644
--- a/engines/dgds/dgds.cpp
+++ b/engines/dgds/dgds.cpp
@@ -220,7 +220,7 @@ bool DgdsEngine::changeScene(int sceneNum) {
 	_gdsScene->runChangeSceneOps();
 
 	if (!_scene->getDragItem()) {
-		int16 cursorNum = (getGameId() == GID_WILLY) ? -2 : -1;
+		int16 cursorNum = (getGameId() == GID_WILLY) ? kDgdsMouseWait : kDgdsMouseGameDefault;
 		setMouseCursor(cursorNum);
 	}
 
@@ -258,10 +258,12 @@ bool DgdsEngine::changeScene(int sceneNum) {
 }
 
 void DgdsEngine::setMouseCursor(int num) {
-	if (num == -1)
+	if (num == kDgdsMouseGameDefault)
 		num = _gdsScene->getDefaultMouseCursor();
-	else if (num == -2)
+	else if (num == kDgdsMouseWait)
 		num = _gdsScene->getDefaultMouseCursor2();
+	else if (num == kDgdsMouseLook)
+		num = _gdsScene->getOtherDefaultMouseCursor();
 
 	if (!_icons || num >= _icons->loadedFrameCount())
 		return;
@@ -439,6 +441,8 @@ void DgdsEngine::loadGameFiles() {
 
 		reqParser.parse(&invRequestData, "WINV.REQ");
 		reqParser.parse(&vcrRequestData, "WVCR.REQ");
+		if (!_isDemo)
+			_menu->readRESData("WVCR.RES");
 
 		break;
 	case GID_QUARKY:
@@ -477,7 +481,7 @@ void DgdsEngine::loadGameFiles() {
 	_gdsScene->runStartGameOps();
 	loadIcons();
 	_gdsScene->initIconSizes();
-	setMouseCursor(_gdsScene->getDefaultMouseCursor());
+	setMouseCursor(kDgdsMouseGameDefault);
 
 	_inventory->setRequestData(invRequestData);
 	_menu->setRequestData(vcrRequestData);
@@ -613,7 +617,7 @@ Common::Error DgdsEngine::run() {
 				_menu->setScreenBuffer();
 				// force mouse on
 				CursorMan.showMouse(true);
-				setMouseCursor(_gdsScene->getDefaultMouseCursor());
+				setMouseCursor(kDgdsMouseGameDefault);
 				_menu->drawMenu(_menuToTrigger);
 			} else {
 				_menu->hideMenu();
@@ -636,6 +640,7 @@ Common::Error DgdsEngine::run() {
 				default:
 					break;
 			}
+			_menu->onTick();
 			_clock.update(false);
 		} else {
 			debug(10, "****  Starting frame %d time %d ****", frameCount, _thisFrameMs);
diff --git a/engines/dgds/dgds.h b/engines/dgds/dgds.h
index 45e23f5aa49..36ec69c8a72 100644
--- a/engines/dgds/dgds.h
+++ b/engines/dgds/dgds.h
@@ -96,6 +96,12 @@ enum DgdsKeyEvent {
 	kDgdsKeyActivate,
 };
 
+enum DgdsMouseCursor {
+	kDgdsMouseGameDefault = -1,
+	kDgdsMouseWait = -2,
+	kDgdsMouseLook = -3,
+};
+
 // TODO: Enable keymapper for dragon arcade sequences
 /*
 enum DragonArcadeKeyEvent {
diff --git a/engines/dgds/inventory.cpp b/engines/dgds/inventory.cpp
index 7231bc3c7b4..3a7fd433b99 100644
--- a/engines/dgds/inventory.cpp
+++ b/engines/dgds/inventory.cpp
@@ -334,7 +334,7 @@ void Inventory::mouseMoved(const Common::Point &pt) {
 			close();
 		}
 	} else {
-		engine->setMouseCursor(engine->getGDSScene()->getDefaultMouseCursor());
+		engine->setMouseCursor(kDgdsMouseGameDefault);
 	}
 }
 
@@ -415,7 +415,7 @@ void Inventory::mouseLUp(const Common::Point &pt) {
 
 	GDSScene *gds = engine->getGDSScene();
 
-	engine->setMouseCursor(gds->getDefaultMouseCursor());
+	engine->setMouseCursor(kDgdsMouseGameDefault);
 
 	int itemsPerPage = (_itemArea->_width / _itemArea->_xStep) * (_itemArea->_height / _itemArea->_yStep);
 	if (_exitButton->containsPoint(pt)) {
diff --git a/engines/dgds/menu.cpp b/engines/dgds/menu.cpp
index 8b31f8e72ec..123f41ec337 100644
--- a/engines/dgds/menu.cpp
+++ b/engines/dgds/menu.cpp
@@ -51,6 +51,9 @@ enum MenuButtonIds {
 	kMainMenuWillySoundsOnOff = 115,
 	kMainMenuWillyMusicOnOff = 116,
 
+	kMenuWillyCreditsDone = 176,
+	kMenuWillyHelpDone = 174,
+
 	kMenuMainPlay = 120,
 	kMenuMainControls = 20,
 	kMenuMainOptions = 121,
@@ -137,7 +140,7 @@ enum MenuButtonIds {
 	kMenuTankTrainPlayArcade = 154,
 };
 
-Menu::Menu() : _curMenu(kMenuNone), _dragGadget(nullptr), _selectedItem(0), _numSelectable(0) {
+Menu::Menu() : _curMenu(kMenuNone), _dragGadget(nullptr), _selectedItem(0), _numSelectable(0), _creditsOffset(0) {
 	_screenBuffer.create(SCREEN_WIDTH, SCREEN_HEIGHT, Graphics::PixelFormat::createFormatCLUT8());
 }
 
@@ -151,6 +154,42 @@ void Menu::setRequestData(const REQFileData &data) {
 	}
 }
 
+void Menu::readRESData(const char *fname) {
+	DgdsEngine *engine = DgdsEngine::getInstance();
+	Common::SeekableReadStream *s = engine->getResourceManager()->getResource(fname);
+
+	if (!s)
+		error("Couldn't open RES file for menu help %s", fname);
+
+	_helpStrings.clear();
+	Common::Array<Common::String> message;
+	while (!s->eos() && !s->err()) {
+		Common::String str = s->readLine();
+		if (str == "!" || s->eos()) {
+			_helpStrings.push_back(message);
+			message.clear();
+		} else {
+			message.push_back(str);
+		}
+	}
+
+	delete s;
+}
+
+void Menu::loadCredits() {
+	DgdsEngine *engine = DgdsEngine::getInstance();
+	Common::SeekableReadStream *s = engine->getResourceManager()->getResource("CREDITS.RES");
+
+	if (!s)
+		error("Couldn't open CREDITS.RES");
+
+	_credits.clear();
+	while (!s->eos() && !s->err()) {
+		_credits.push_back(s->readLine());
+	}
+	_creditsOffset = 0;
+}
+
 void Menu::setScreenBuffer() {
 	Graphics::Surface *dst = g_system->lockScreen();
 	_screenBuffer.copyFrom(*dst);
@@ -238,6 +277,11 @@ void Menu::configureGadget(MenuId menu, Gadget *gadget) {
 	}
 }
 
+void Menu::onTick() {
+	if (_curMenu == kMenuWillyCredits)
+		drawMenu(kMenuWillyCredits);
+}
+
 void Menu::drawMenu(MenuId menu) {
 	bool firstDraw = (_curMenu != menu);
 	_curMenu = menu;
@@ -270,6 +314,9 @@ void Menu::drawMenu(MenuId menu) {
 
 	drawMenuText(managed);
 
+	if (_curMenu == kMenuWillyCredits)
+		drawCreditsText(managed);
+
 	// Can't use transparent blit here as the font is often color 0.
 	screen->copyRectToSurface(*managed.surfacePtr(), 0, 0, Common::Rect(screen->w, screen->h));
 
@@ -329,6 +376,45 @@ void Menu::drawMenuText(Graphics::ManagedSurface &dst) {
 	}
 }
 
+static byte _creditsColor(int y) {
+	if (y < 31 || y > 86)
+		return 17; // Cyan
+	else if (y < 32 || y > 85)
+		return 18; // Slightly darker cyan
+	else if (y < 33 || y > 84)
+		return 19; // Darker cyan
+	else if (y < 34 || y > 83)
+		return 30; // Grey
+	return 0; // Black.
+}
+
+void Menu::drawCreditsText(Graphics::ManagedSurface &dst) {
+	const DgdsFont *font = RequestData::getMenuFont();
+	const int lineHeight = font->getFontHeight();
+
+	DgdsRect dlgRect = _menuRequests[_curMenu]._rect;
+
+	const int dlgWidth = dlgRect.width;
+
+	const int yMin = 30;
+	const int yMax = 87;
+	for (uint i = 0; i < _credits.size(); i++) {
+		int dstY = i * lineHeight + yMax - _creditsOffset / 4;
+		if (dstY > yMax)
+			break;
+		if (dstY > yMin) {
+			int lineW = font->getStringWidth(_credits[i]);
+			int xoff = dlgRect.x + (dlgWidth - lineW) / 2;
+			font->drawString(dst.surfacePtr(), _credits[i], xoff, dlgRect.y + dstY, dlgRect.width, _creditsColor(dstY));
+		}
+	}
+
+	_creditsOffset++;
+
+	if ((uint)_creditsOffset / 4 > lineHeight * (_credits.size() + 1) + (yMax - yMin))
+		_creditsOffset = 0;
+}
+
 Gadget *Menu::getClickedMenuItem(const Common::Point &mouseClick) {
 	if (_curMenu == kMenuNone)
 		return nullptr;
@@ -447,6 +533,10 @@ void Menu::handleClick(const Common::Point &mouse) {
 	//case kMenuMouseCalibrationPlay:
 		hideMenu();
 		if (engine->getGameId() == GID_WILLY && clickedMenuItem == kMainMenuWillyHelp) {
+			// TODO: Based on some variable this should instead:
+			//drawMenu(kMenuWillyHelp); // with the first message from WVCR.RES
+			// The OnLine help system
+			// is not available now.
 			engine->changeScene(80);
 		} else {
 			CursorMan.showMouse(false);
@@ -458,10 +548,12 @@ void Menu::handleClick(const Common::Point &mouse) {
 	case kMenuMainOptions:
 		drawMenu(kMenuOptions);
 		break;
-	case kMenuMainCalibrate:
+	case kMenuMainCalibrate: // same as credits button in Willy Beamish
 		if (engine->getGameId() == GID_WILLY) {
 			debug("TODO: Implement willy beamish credits");
 			hideMenu();
+			loadCredits();
+			drawMenu(kMenuWillyCredits);
 		} else {
 			debug("Ignoring calibration request");
 		}
@@ -633,6 +725,9 @@ void Menu::handleClick(const Common::Point &mouse) {
 		_toggleSoundType(Audio::Mixer::kMusicSoundType);
 		updateOptionsGadget(gadget);
 		break;
+	case kMenuWillyCreditsDone:
+	case kMenuWillyHelpDone:
+		hideMenu();
 	default:
 		debug(1, "Clicked ID %d", clickedMenuItem);
 		break;
diff --git a/engines/dgds/menu.h b/engines/dgds/menu.h
index 1df2beae5c3..aaecb358a93 100644
--- a/engines/dgds/menu.h
+++ b/engines/dgds/menu.h
@@ -68,6 +68,8 @@ enum MenuId {
 	kMenuArcadeFrustrated = 47,
 	kMenuSkipPlayIntro = 50,
 	kMenuSkipArcade = 52,
+	kMenuWillyHelp = 54,
+	kMenuWillyCredits = 56,
 };
 
 class Menu {
@@ -88,29 +90,37 @@ public:
 	void hideMenu() { _curMenu = kMenuNone; }
 
 	void setRequestData(const REQFileData &data);
+	void readRESData(const char *fname);
 	void prevChoice();
 	void nextChoice();
 	void activateChoice();
+	void onTick();
 
 private:
 	Gadget *getClickedMenuItem(const Common::Point &mouseClick);
 	void drawMenuText(Graphics::ManagedSurface &dst);
+	void drawCreditsText(Graphics::ManagedSurface &dst);
 	void toggleGadget(int16 gadgetId, bool enable);
 	void configureGadget(MenuId menu, Gadget *gadget);
 	bool updateOptionsGadget(Gadget *gadget);
 	void handleClick(const Common::Point &mouse);
 	void handleClickOptionsMenu(const Common::Point &mouse);
 	void handleClickSkipPlayIntroMenu(const Common::Point &mouse);
+	void loadCredits();
 
 	void putMouseOnSelectedItem();
 	Gadget *getSelectedItem();
 
 	Common::HashMap<int, RequestData> _menuRequests;
 
+	Common::Array<Common::Array<Common::String>> _helpStrings;
+	Common::Array<Common::String> _credits;
+
 	SliderGadget *_dragGadget;
 	Common::Point _dragStartPt;
 	int _selectedItem;
 	int _numSelectable;
+	int _creditsOffset;
 };
 
 } // End of namespace Dgds
diff --git a/engines/dgds/minigames/china_train.cpp b/engines/dgds/minigames/china_train.cpp
index 49425148c5d..e769cfabfee 100644
--- a/engines/dgds/minigames/china_train.cpp
+++ b/engines/dgds/minigames/china_train.cpp
@@ -657,7 +657,7 @@ void ChinaTrain::init() { // aka arcadeInit
 	drawFrame();
 
 	// ensure mouse cursor is on
-	engine->setMouseCursor(-1);
+	engine->setMouseCursor(kDgdsMouseGameDefault);
 
 	engine->setMenuToTrigger(kMenuSkipArcade);
 
diff --git a/engines/dgds/scene.cpp b/engines/dgds/scene.cpp
index 2dfc74e8bf0..36544c09286 100644
--- a/engines/dgds/scene.cpp
+++ b/engines/dgds/scene.cpp
@@ -510,7 +510,7 @@ bool SDSScene::_dlgWithFlagLo8IsClosing = false;
 DialogFlags SDSScene::_sceneDialogFlags = kDlgFlagNone;
 
 SDSScene::SDSScene() : _num(-1), _dragItem(nullptr), _shouldClearDlg(false), _ignoreMouseUp(false),
-	_field6_0x14(0), _rbuttonDown(false), _lbuttonDown(false) {
+_field6_0x14(0), _rbuttonDown(false), _lbuttonDown(false), _isLookMode(false) {
 }
 
 bool SDSScene::load(const Common::String &filename, ResourceManager *resourceManager, Decompressor *decompressor) {
@@ -1178,10 +1178,10 @@ void SDSScene::mouseMoved(const Common::Point &pt) {
 	const HotArea *area = findAreaUnderMouse(pt);
 	DgdsEngine *engine = DgdsEngine::getInstance();
 
-	int16 cursorNum = 0;
+	int16 cursorNum = _isLookMode ? kDgdsMouseLook : kDgdsMouseGameDefault;
 	if (!dlg) {
 		if (area)
-			cursorNum = area->_cursorNum;
+			cursorNum = _isLookMode ? area->_cursorNum2 : area->_cursorNum;
 	}
 
 	if (_dragItem) {
@@ -1257,6 +1257,11 @@ void SDSScene::mouseLUp(const Common::Point &pt) {
 		return;
 	}
 
+	if (_isLookMode) {
+		rightButtonAction(pt);
+		return;
+	}
+
 	const HotArea *area = findAreaUnderMouse(pt);
 	if (!area)
 		return;
@@ -1386,7 +1391,7 @@ void SDSScene::onDragFinish(const Common::Point &pt) {
 		}
 	}
 
-	engine->setMouseCursor(gdsScene->getDefaultMouseCursor());
+	engine->setMouseCursor(kDgdsMouseGameDefault);
 	_dragItem = nullptr;
 }
 
@@ -1404,9 +1409,18 @@ void SDSScene::mouseRUp(const Common::Point &pt) {
 		return;
 	}
 
-	// Update the cursor..
-	mouseMoved(pt);
+	if (DgdsEngine::getInstance()->getGameId() == GID_WILLY) {
+		// Willy toggles between look/act mode on right click
+		_isLookMode = !_isLookMode;
+		mouseMoved(pt);
+	} else {
+		// Other games do right-button action straight away.
+		mouseMoved(pt);
+		rightButtonAction(pt);
+	}
+}
 
+void SDSScene::rightButtonAction(const Common::Point &pt) {
 	const HotArea *area = findAreaUnderMouse(pt);
 	if (!area)
 		return;
diff --git a/engines/dgds/scene.h b/engines/dgds/scene.h
index 37e1317ff57..b2c55a0de03 100644
--- a/engines/dgds/scene.h
+++ b/engines/dgds/scene.h
@@ -341,6 +341,7 @@ protected:
 private:
 	Dialog *getVisibleDialog();
 	bool readTalkData(Common::SeekableReadStream *s, TalkData &dst);
+	void rightButtonAction(const Common::Point &pt);
 
 	int _num;
 	Common::Array<SceneOp> _enterSceneOps;
@@ -368,6 +369,7 @@ private:
 	bool _ignoreMouseUp;
 	bool _lbuttonDown;
 	bool _rbuttonDown;
+	bool _isLookMode;
 
 	static bool _dlgWithFlagLo8IsClosing;
 	static DialogFlags _sceneDialogFlags;
diff --git a/engines/dgds/ttm.cpp b/engines/dgds/ttm.cpp
index 6742e474b61..744f6addaf1 100644
--- a/engines/dgds/ttm.cpp
+++ b/engines/dgds/ttm.cpp
@@ -826,12 +826,16 @@ bool TTMInterpreter::handleOperation(TTMEnviro &env, TTMSeq &seq, uint16 op, byt
 				g_system->delayMillis(5);
 			}
 		}
-		// Clear all the buffers
-		_vm->getBackgroundBuffer().fillRect(Common::Rect(SCREEN_WIDTH, SCREEN_HEIGHT), 0);
+		if (ivals[1] == 256) {
+			// Clear the background only if we faded everything??
+			_vm->getBackgroundBuffer().fillRect(Common::Rect(SCREEN_WIDTH, SCREEN_HEIGHT), 0);
+		}
+		// Other buffers are always cleared.
 		_vm->getStoredAreaBuffer().fillRect(Common::Rect(SCREEN_WIDTH, SCREEN_HEIGHT), 0);
 		_vm->_compositionBuffer.fillRect(Common::Rect(SCREEN_WIDTH, SCREEN_HEIGHT), 0);
-		// reset to previous palette.
-		_vm->getGamePals()->setFade(ivals[0], ivals[1], ivals[2], 0);
+		// Reset to previous palette - except in Willy Beamish?
+		if (_vm->getGameId() != GID_WILLY)
+			_vm->getGamePals()->setFade(ivals[0], ivals[1], ivals[2], 0);
 		break;
 	case 0x4120: { // FADE IN:	colorno,ncolors,targetcol,speed:byte
 		if (seq._executed) // this is a one-shot op.




More information about the Scummvm-git-logs mailing list