[Scummvm-git-logs] scummvm master -> a952852d8c431cfbd5b03d20736c0ec22e7a6643
lotharsm
noreply at scummvm.org
Sat Aug 6 11:34:23 UTC 2022
This automated email contains information about 58 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
1e9d51c28a SCUMM: COMI: Implement the original main menu
7e4d844969 SCUMM: DETECTION: Add an option for activating the original GUI
fabaeb4b83 SCUMM: COMI: Implement original GUI
811548dc05 SCUMM: COMI: Use _screenTop when marking rects as dirty
759ae2e47e SCUMM: COMI: Set keyScript parameters in case they are missing at loading
c4d0e3b80a SCUMM: COMI: Fix mishandling of cursor state in GUI
9072aa007f SCUMM: COMI: Fix default cursor colors during SMUSH videos
6760cc1353 SCUMM: COMI: Implement banners for voiceMode toggle
51d0b8ef06 SCUMM: COMI: Implement iMUSE buffer toggle GUI banner
61535ee8c9 SCUMM: DiMUSE: Increment upper and lower limit for roundRobinSetBufferCount()
e43d40e344 SCUMM: Add original GUI support for COMI Demo
52bb4dd739 SCUMM: Fix comment and private member names
fb2fcbf30e SCUMM: COMI: Implement savegame thumbnails
d04d8cc00c SCUMM: COMI: Disable autosaving if original GUI is in place
b395a94beb SCUMM: COMI: Insert a workaround for mouse input in the main menu
3ce00256b3 SCUMM: Fix getPaletteColorFromRGB() behavior with 0xFF and 0x00 values
36efab0a73 SCUMM: COMI (Demo): Fix banner height handling
1e0a61d64c SCUMM: COMI: Use ARRAYSIZE macro in overflow check
bce4020ec1 SCUMM: COMI: Insert missing updatePalette() call
da69dec129 SCUMM: COMI: Fix original GUI savegames on ScummVM loading from launcher
e01ea96054 SCUMM: DETECTION: improve readability of enableOriginalGUI declaration
85d3c5f5ac SCUMM: COMI: Implement remaining banners for demo
a14f897bc4 SCUMM: Move high-level GUI handling to gfx_gui.cpp
e78c671b45 SCUMM: Fix non-Windows compiling
f0d371d96e SCUMM: Fix warnings
f3702305ce SCUMM: COMI: Clean up input code
7fea664d20 SCUMM: COMI: Fix screen restoring in some edge cases
a121b5773f SCUMM: COMI: Fix regression after processKeyboard() refactoring
dfa6a898cf SCUMM: COMI: Remove leftover from refactoring
22f00bc16e SCUMM: Remove very old obsolete workaround
1fc726787d SCUMM: COMI: Limit demo keys to demo only
f9010ca824 SCUMM: COMI: Fix original GUI glitches with blastTexts and blastObjects
cb0e7cee16 SCUMM: Fix compilation without v7-8 enabled
5b58afff61 SCUMM: COMI: Fix texts/objects glitch when exiting through main menu
6ee5f03ffa SCUMM: v7-8: Fix correct moment to call checkExecVerbs()
1561996dff SCUMM: v7-8: Apply blast pipeline corrections also to v7
a0cbacf261 SCUMM: v7-8: Amend removing call to removeBlastTexts()
73586c04a3 SCUMM: COMI: Prevent saving from the GMM on the original main menu
1ac282c1e8 SCUMM: COMI: Add fallback thumbnail for original menu
cb7e459264 SCUMM: Fix subtitles parameters not being saved
e1f0b5a25d SCUMM: COMI (non-demo): Disable + and - keys for original GUI
ced78b19d5 SCUMM: COMI: Fix some more text/GUI rendering glitches
b35bd37b0a SCUMM: Disable any GMM option key if the original GUI is in use
276e7620c7 SCUMM: Use PaletteLookup for internal GUI
a4fd38b894 SCUMM: v7: Amend checkExecVerbs() being called earlier
b30e2ab98a SCUMM: v7-8: Add missing removeBlastTexts() call in startScene()
c9c4f8026b SCUMM: COMI: Improve handling of GUI during SMUSH videos
f8defefe1e SCUMM: Don't restore mouse position when using the original GUI
660fb3dbef SCUMM: COMI: Remove unnecessary sum in thumbnail handling
559f055d37 SCUMM: Skip mousePosition resume on load for original GUI regardless of savegame version
3b2ccffbaa SCUMM: COMI: Add support for the ScummVM standard thumbnail in the savescreen
2c9d7fd2ee SCUMM: COMI: Change how blastObject rects are restored for v8
1d6cfd62b8 SCUMM: COMI: Deactivate frame limiter on the menu
917655b50a SCUMM: Don't clear the GUI banners while SMUSH is active
09a43c7134 SCUMM: COMI: Always show the cursor during confirmExitDialog()
555a519783 SCUMM: COMI: Improve accuracy for banner input handling
7ac1b327e1 SCUMM: COMI: Fix clearBanner() regression causing glitches on calls after SMUSH movies
a952852d8c SCUMM: Properly sync options between original and ScummVM GUIs
Commit: 1e9d51c28a67837fee2249ab9f38a6657dce6f9f
https://github.com/scummvm/scummvm/commit/1e9d51c28a67837fee2249ab9f38a6657dce6f9f
Author: AndywinXp (andywinxp at gmail.com)
Date: 2022-08-06T13:33:56+02:00
Commit Message:
SCUMM: COMI: Implement the original main menu
Every functionality has been implemented (audio options, text options, saving and loading).
The only thing currently missing from the menu is the thumbnail handling.
Changed paths:
engines/scumm/imuse_digi/dimuse_cmds.cpp
engines/scumm/imuse_digi/dimuse_engine.cpp
engines/scumm/imuse_digi/dimuse_engine.h
engines/scumm/input.cpp
engines/scumm/saveload.cpp
engines/scumm/script_v8.cpp
engines/scumm/scumm.cpp
engines/scumm/scumm.h
engines/scumm/vars.cpp
diff --git a/engines/scumm/imuse_digi/dimuse_cmds.cpp b/engines/scumm/imuse_digi/dimuse_cmds.cpp
index 8da2bd45219..034b1d31b6a 100644
--- a/engines/scumm/imuse_digi/dimuse_cmds.cpp
+++ b/engines/scumm/imuse_digi/dimuse_cmds.cpp
@@ -49,8 +49,7 @@ int IMuseDigital::cmdsHandleCmd(int cmd, uint8 *ptr, int a, int b, int c, int d,
case 4:
return cmdsResume();
case 7:
- _groupsHandler->setGroupVol(a, b);
- break;
+ return _groupsHandler->setGroupVol(a, b);
case 8:
cmdsStartSound(a, b);
break;
diff --git a/engines/scumm/imuse_digi/dimuse_engine.cpp b/engines/scumm/imuse_digi/dimuse_engine.cpp
index d59dad6264e..533b9673dc6 100644
--- a/engines/scumm/imuse_digi/dimuse_engine.cpp
+++ b/engines/scumm/imuse_digi/dimuse_engine.cpp
@@ -315,6 +315,12 @@ void IMuseDigital::saveLoadEarly(Common::Serializer &s) {
_curMusicCue = 0;
} else {
diMUSESaveLoad(s);
+
+ if (s.isLoading() && _vm->isUsingOriginalGUI()) {
+ diMUSESetMusicGroupVol(diMUSEGetMusicGroupVol());
+ diMUSESetVoiceGroupVol(diMUSEGetVoiceGroupVol());
+ diMUSESetSFXGroupVol(diMUSEGetSFXGroupVol());
+ }
}
}
@@ -359,21 +365,23 @@ void IMuseDigital::diMUSEHeartbeat() {
waveOutCallback();
- // Update volumes
+ if (!_vm->isUsingOriginalGUI()) {
+ // Update volumes
- if (_curMixerMusicVolume != _mixer->getVolumeForSoundType(Audio::Mixer::kMusicSoundType)) {
- _curMixerMusicVolume = _mixer->getVolumeForSoundType(Audio::Mixer::kMusicSoundType);
- diMUSESetMusicGroupVol(CLIP(_mixer->getVolumeForSoundType(Audio::Mixer::kMusicSoundType) / 2, 0, 127));
- }
+ if (_curMixerMusicVolume != _mixer->getVolumeForSoundType(Audio::Mixer::kMusicSoundType)) {
+ _curMixerMusicVolume = _mixer->getVolumeForSoundType(Audio::Mixer::kMusicSoundType);
+ diMUSESetMusicGroupVol(CLIP(_mixer->getVolumeForSoundType(Audio::Mixer::kMusicSoundType) / 2, 0, 127));
+ }
- if (_curMixerSpeechVolume != _mixer->getVolumeForSoundType(Audio::Mixer::kSpeechSoundType)) {
- _curMixerSpeechVolume = _mixer->getVolumeForSoundType(Audio::Mixer::kSpeechSoundType);
- diMUSESetVoiceGroupVol(CLIP(_mixer->getVolumeForSoundType(Audio::Mixer::kSpeechSoundType) / 2, 0, 127));
- }
+ if (_curMixerSpeechVolume != _mixer->getVolumeForSoundType(Audio::Mixer::kSpeechSoundType)) {
+ _curMixerSpeechVolume = _mixer->getVolumeForSoundType(Audio::Mixer::kSpeechSoundType);
+ diMUSESetVoiceGroupVol(CLIP(_mixer->getVolumeForSoundType(Audio::Mixer::kSpeechSoundType) / 2, 0, 127));
+ }
- if (_curMixerSFXVolume != _mixer->getVolumeForSoundType(Audio::Mixer::kSFXSoundType)) {
- _curMixerSFXVolume = _mixer->getVolumeForSoundType(Audio::Mixer::kSFXSoundType);
- diMUSESetSFXGroupVol(CLIP(_mixer->getVolumeForSoundType(Audio::Mixer::kSFXSoundType) / 2, 0, 127));
+ if (_curMixerSFXVolume != _mixer->getVolumeForSoundType(Audio::Mixer::kSFXSoundType)) {
+ _curMixerSFXVolume = _mixer->getVolumeForSoundType(Audio::Mixer::kSFXSoundType);
+ diMUSESetSFXGroupVol(CLIP(_mixer->getVolumeForSoundType(Audio::Mixer::kSFXSoundType) / 2, 0, 127));
+ }
}
// Handle fades and triggers
@@ -659,6 +667,7 @@ void IMuseDigital::parseScriptCmds(int cmd, int soundId, int sub_cmd, int d, int
int b = soundId;
int c = sub_cmd;
int id;
+ int volume = b;
switch (cmd) {
case 0x1000:
// SetState
@@ -678,15 +687,27 @@ void IMuseDigital::parseScriptCmds(int cmd, int soundId, int sub_cmd, int d, int
break;
case 0x2000:
// SetGroupSfxVolume
- diMUSESetSFXGroupVol(CLIP(_mixer->getVolumeForSoundType(Audio::Mixer::kSFXSoundType) / 2, 0, 127));
+ if (!_vm->isUsingOriginalGUI()) {
+ volume = CLIP(_mixer->getVolumeForSoundType(Audio::Mixer::kSFXSoundType) / 2, 0, 127);
+ }
+
+ diMUSESetSFXGroupVol(volume);
break;
case 0x2001:
// SetGroupVoiceVolume
- diMUSESetVoiceGroupVol(CLIP(_mixer->getVolumeForSoundType(Audio::Mixer::kSpeechSoundType) / 2, 0, 127));
+ if (!_vm->isUsingOriginalGUI()) {
+ volume = CLIP(_mixer->getVolumeForSoundType(Audio::Mixer::kSpeechSoundType) / 2, 0, 127);
+ }
+
+ diMUSESetVoiceGroupVol(volume);
break;
case 0x2002:
// SetGroupMusicVolume
- diMUSESetMusicGroupVol(CLIP(_mixer->getVolumeForSoundType(Audio::Mixer::kMusicSoundType) / 2, 0, 127));
+ if (!_vm->isUsingOriginalGUI()) {
+ volume = CLIP(_mixer->getVolumeForSoundType(Audio::Mixer::kMusicSoundType) / 2, 0, 127);
+ }
+
+ diMUSESetMusicGroupVol(volume);
break;
case 10: // StopAllSounds
case 12: // SetParam
@@ -813,6 +834,30 @@ int IMuseDigital::diMUSELipSync(int soundId, int syncId, int msPos, int32 &width
return waveLipSync(soundId, syncId, msPos, width, height);
}
+int IMuseDigital::diMUSEGetMusicGroupVol() {
+ if (_vm->isUsingOriginalGUI()) {
+ return diMUSESetGroupVol(DIMUSE_GROUP_MUSIC, -1);
+ }
+
+ return _mixer->getVolumeForSoundType(Audio::Mixer::kMusicSoundType) / 2;
+}
+
+int IMuseDigital::diMUSEGetSFXGroupVol() {
+ if (_vm->isUsingOriginalGUI()) {
+ return diMUSESetGroupVol(DIMUSE_GROUP_SFX, -1);
+ }
+
+ return _mixer->getVolumeForSoundType(Audio::Mixer::kSFXSoundType) / 2;
+}
+
+int IMuseDigital::diMUSEGetVoiceGroupVol() {
+ if (_vm->isUsingOriginalGUI()) {
+ return diMUSESetGroupVol(DIMUSE_GROUP_SPEECH, -1);
+ }
+
+ return _mixer->getVolumeForSoundType(Audio::Mixer::kSpeechSoundType) / 2;
+}
+
int IMuseDigital::diMUSESetMusicGroupVol(int volume) {
debug(5, "IMuseDigital::diMUSESetMusicGroupVol(): %d", volume);
if (_isEarlyDiMUSE)
diff --git a/engines/scumm/imuse_digi/dimuse_engine.h b/engines/scumm/imuse_digi/dimuse_engine.h
index 23e6931537a..36247ce7717 100644
--- a/engines/scumm/imuse_digi/dimuse_engine.h
+++ b/engines/scumm/imuse_digi/dimuse_engine.h
@@ -373,6 +373,9 @@ public:
void diMUSEQueryStream(int soundId, int32 &bufSize, int32 &criticalSize, int32 &freeSpace, int &paused);
int diMUSEFeedStream(int soundId, uint8 *srcBuf, int32 sizeToFeed, int paused);
int diMUSELipSync(int soundId, int syncId, int msPos, int32 &width, int32 &height);
+ int diMUSEGetMusicGroupVol();
+ int diMUSEGetSFXGroupVol();
+ int diMUSEGetVoiceGroupVol();
int diMUSESetMusicGroupVol(int volume);
int diMUSESetSFXGroupVol(int volume);
int diMUSESetVoiceGroupVol(int volume);
diff --git a/engines/scumm/input.cpp b/engines/scumm/input.cpp
index 6330fe04a1c..788c957876c 100644
--- a/engines/scumm/input.cpp
+++ b/engines/scumm/input.cpp
@@ -377,13 +377,25 @@ void ScummEngine::processInput() {
#ifdef ENABLE_SCUMM_7_8
void ScummEngine_v8::processKeyboard(Common::KeyState lastKeyHit) {
- // F1 (the trigger for the original save/load dialog) is mapped to F5
+ // F1 (the trigger for the original save/load dialog) is mapped to F5,
+ // unless we chose to use the original GUI
if (!(_game.features & GF_DEMO) && lastKeyHit.keycode == Common::KEYCODE_F1 && lastKeyHit.hasFlags(0)) {
- lastKeyHit = Common::KeyState(Common::KEYCODE_F5, 319);
+ if (isUsingOriginalGUI()) {
+ lastKeyHit = Common::KeyState(Common::KEYCODE_F1, 315);
+ } else {
+ lastKeyHit = Common::KeyState(Common::KEYCODE_F5, 319);
+ }
+
+ }
+
+ // If we are using the original GUI, remap F5 to F1
+ if (isUsingOriginalGUI() && !(_game.features & GF_DEMO) && lastKeyHit.keycode == Common::KEYCODE_F5 && lastKeyHit.hasFlags(0)) {
+ lastKeyHit = Common::KeyState(Common::KEYCODE_F1, 315);
}
- // Alt-F5 should bring up the original save/load dialog, so map it to F1.
- if (!(_game.features & GF_DEMO) && lastKeyHit.keycode == Common::KEYCODE_F5 && lastKeyHit.hasFlags(Common::KBD_ALT)) {
+ // Alt-F5 should bring up the original save/load dialog, so map it to F1,
+ // again, unless we chose to use the original GUI
+ if (!isUsingOriginalGUI() && !(_game.features & GF_DEMO) && lastKeyHit.keycode == Common::KEYCODE_F5 && lastKeyHit.hasFlags(Common::KBD_ALT)) {
lastKeyHit = Common::KeyState(Common::KEYCODE_F1, 315);
}
@@ -668,9 +680,8 @@ void ScummEngine::processKeyboard(Common::KeyState lastKeyHit) {
// Map arrow keys to number keys in the SEGA version of MI to support
// scrolling to conversation choices. See bug report #2013 for details.
_mouseAndKeyboardStat = lastKeyHit.keycode - Common::KEYCODE_UP + 54;
- } else if (_game.id == GID_LOOM && _game.platform == Common::kPlatformPCEngine) {
- // Map arrow keys to number keys in the PCEngine version of Loom to support
- // the menu screen.
+ } else if (isUsingOriginalGUI() || (_game.id == GID_LOOM && _game.platform == Common::kPlatformPCEngine)) {
+ // Map arrow keys to number keys in games which use the original menu screen.
switch (lastKeyHit.keycode) {
case Common::KEYCODE_UP:
_mouseAndKeyboardStat = 328;
@@ -697,7 +708,11 @@ void ScummEngine::processKeyboard(Common::KeyState lastKeyHit) {
}
} else {
- _mouseAndKeyboardStat = lastKeyHit.ascii;
+ // Map the DEL key when using the original GUI; used when writing the savegame name.
+ if (isUsingOriginalGUI() && lastKeyHit.keycode == Common::KEYCODE_DELETE)
+ _mouseAndKeyboardStat = 339;
+ else
+ _mouseAndKeyboardStat = lastKeyHit.ascii;
}
}
diff --git a/engines/scumm/saveload.cpp b/engines/scumm/saveload.cpp
index 47bd5f5d887..274794620f1 100644
--- a/engines/scumm/saveload.cpp
+++ b/engines/scumm/saveload.cpp
@@ -156,6 +156,54 @@ void ScummEngine::requestLoad(int slot) {
_saveLoadFlag = 2; // 2 for load
}
+void ScummEngine::copyHeapSaveGameToFile(int slot, const char *saveName) {
+ Common::String fileName;
+ SaveGameHeader hdr;
+ bool saveFailed = false;
+ uint32 heapFileSize;
+
+ Common::SeekableReadStream *heapSaveFile = openSaveFileForReading(1, true, fileName);
+ hdr.type = heapSaveFile->readUint32BE();
+ hdr.size = heapSaveFile->readUint32LE();
+ hdr.ver = heapSaveFile->readUint32LE();
+ heapSaveFile->read(hdr.name, sizeof(hdr.name));
+ Common::strlcpy(hdr.name, saveName, sizeof(hdr.name));
+
+ heapFileSize = (uint32)heapSaveFile->size();
+ if (heapSaveFile->err() || hdr.type != MKTAG('S','C','V','M')) {
+ saveFailed = true;
+ } else {
+ Common::WriteStream *saveFile = openSaveFileForWriting(slot, false, fileName);
+ if (!saveFile) {
+ saveFailed = true;
+ } else {
+ saveFile->writeUint32BE(hdr.type);
+ saveFile->writeUint32LE(hdr.size);
+ saveFile->writeUint32LE(hdr.ver);
+ saveFile->write(hdr.name, sizeof(hdr.name));
+
+ heapSaveFile->seek(sizeof(hdr), SEEK_SET);
+ while (!heapSaveFile->eos()) {
+ byte b = heapSaveFile->readByte();
+ saveFile->writeByte(b);
+ }
+
+ saveFile->finalize();
+ if (saveFile->err())
+ saveFailed = true;
+
+ delete saveFile;
+ }
+ }
+
+ if (saveFailed)
+ debug(1, "State save as '%s' FAILED", fileName.c_str());
+ else
+ debug(1, "State saved as '%s'", fileName.c_str());
+
+
+}
+
Common::SeekableReadStream *ScummEngine::openSaveFileForReading(int slot, bool compat, Common::String &fileName) {
fileName = makeSavegameName(slot, compat);
return _saveFileMan->openForLoading(fileName);
@@ -1653,6 +1701,19 @@ void ScummEngine_v7::saveLoadWithSerializer(Common::Serializer &s) {
// WORKAROUND bug #3483: Reset the default charset color to a sane value.
_string[0]._default.charset = 1;
}
+
+ // The original Save/Load screen for COMI saves a heap savegame when it is entered
+ // and the same heap savegame is restored when it is exited, so let's refresh these
+ // variables so that they are not lost. The original doesn't do this as it appears
+ // to handle these temporary heap savegames a little differently, but this should
+ // suffice...
+ if (isUsingOriginalGUI() && _game.version == 8) {
+ if (ConfMan.hasKey("original_gui_saveload_page", _targetName))
+ VAR(VAR_SAVELOAD_PAGE) = ConfMan.getInt("original_gui_saveload_page");
+
+ if (ConfMan.hasKey("original_gui_object_labels", _targetName))
+ VAR(VAR_OBJECT_LABEL_FLAG) = ConfMan.getInt("original_gui_object_labels");
+ }
}
#endif
diff --git a/engines/scumm/script_v8.cpp b/engines/scumm/script_v8.cpp
index a46b40dcf2b..d200d5cf6ba 100644
--- a/engines/scumm/script_v8.cpp
+++ b/engines/scumm/script_v8.cpp
@@ -289,7 +289,7 @@ void ScummEngine_v8::writeVar(uint var, int value) {
if (!(var & 0xF0000000)) {
assertRange(0, var, _numVariables - 1, "variable (writing)");
- if (var == VAR_CHARINC) {
+ if (!isUsingOriginalGUI() && var == VAR_CHARINC) {
// Did the user override the talkspeed manually? Then use that.
// Otherwise, use the value specified by the game script.
// Note: To determine whether there was a user override, we only
@@ -1120,9 +1120,11 @@ void ScummEngine_v8::o8_kernelSetFunctions() {
break;
}
case 26: { // saveGameWrite
- // FIXME: This doesn't work
- char *address = (char *)getStringAddress(args[2]);
- debug(0, "o8_kernelSetFunctions: saveGame(%d, %s)", args[1], address);
+ char *saveName = (char *)getStringAddress(args[2]);
+ debug(0, "o8_kernelSetFunctions: saveGame(%d, %s)", args[1], saveName);
+ if (isUsingOriginalGUI()) {
+ copyHeapSaveGameToFile(args[1], saveName);
+ }
break;
}
case 27: // saveGameRead
@@ -1148,6 +1150,24 @@ void ScummEngine_v8::o8_kernelSetFunctions() {
int idx = args[1];
int value = args[2];
const char *str = (const char *)getStringAddress(idx);
+ if (isUsingOriginalGUI()) {
+ if (!strcmp(str, "SFX Volume"))
+ ConfMan.setInt("sfx_volume", value * 2);
+ else if (!strcmp(str, "Voice Volume"))
+ ConfMan.setInt("speech_volume", value * 2);
+ else if (!strcmp(str, "Music Volume"))
+ ConfMan.setInt("music_volume", value * 2);
+ else if (!strcmp(str, "Text Status"))
+ ConfMan.setInt("original_gui_text_status", value);
+ else if (!strcmp(str, "Text Speed"))
+ ConfMan.setInt("original_gui_text_speed", value);
+ else if (!strcmp(str, "Object Names"))
+ ConfMan.setInt("original_gui_object_labels", value);
+ else if (!strcmp(str, "Saveload Page"))
+ ConfMan.setInt("original_gui_saveload_page", value);
+
+ ConfMan.flushToDisk();
+ }
debugC(DEBUG_GENERAL,"o8_kernelSetFunctions: writeRegistryValue(%s, %d)", str, value);
}
@@ -1156,10 +1176,14 @@ void ScummEngine_v8::o8_kernelSetFunctions() {
debug(0, "o8_kernelSetFunctions: paletteSetIntensity(%d, %d)", args[1], args[2]);
break;
case 34: // queryQuit
- if (ConfMan.getBool("confirm_exit"))
+ if (isUsingOriginalGUI()) {
confirmExitDialog();
- else
- quitGame();
+ } else {
+ if (ConfMan.getBool("confirm_exit"))
+ confirmExitDialog();
+ else
+ quitGame();
+ }
break;
case 108: // buildPaletteShadow
setShadowPalette(args[1], args[2], args[3], args[4], args[5], args[6]);
@@ -1234,13 +1258,13 @@ void ScummEngine_v8::o8_kernelGetFunctions() {
}
break;
case 0xDD: // getGroupSfxVol
- push(_mixer->getVolumeForSoundType(Audio::Mixer::kSFXSoundType) / 2);
+ push(_imuseDigital->diMUSEGetSFXGroupVol());
break;
case 0xDE: // getGroupVoiceVol
- push(_mixer->getVolumeForSoundType(Audio::Mixer::kSpeechSoundType) / 2);
+ push(_imuseDigital->diMUSEGetVoiceGroupVol());
break;
case 0xDF: // getGroupMusicVol
- push(_mixer->getVolumeForSoundType(Audio::Mixer::kMusicSoundType) / 2);
+ push(_imuseDigital->diMUSEGetMusicGroupVol());
break;
case 0xE0: // readRegistryValue
{
@@ -1253,13 +1277,16 @@ void ScummEngine_v8::o8_kernelGetFunctions() {
else if (!strcmp(str, "Music Volume"))
push(ConfMan.getInt("music_volume") / 2);
else if (!strcmp(str, "Text Status"))
- push(ConfMan.getBool("subtitles"));
+ push(isUsingOriginalGUI() ? ConfMan.getInt("original_gui_text_status") : ConfMan.getBool("subtitles"));
+ else if (!strcmp(str, "Text Speed"))
+ push(ConfMan.getInt("original_gui_text_speed"));
else if (!strcmp(str, "Object Names"))
- push(ConfMan.getBool("object_labels"));
+ push(isUsingOriginalGUI() ? ConfMan.getInt("original_gui_object_labels") : ConfMan.getBool("object_labels"));
else if (!strcmp(str, "Saveload Page"))
- push(14);
+ push(ConfMan.getInt("original_gui_saveload_page"));
else // Use defaults
push(-1);
+
debugC(DEBUG_GENERAL,"o8_kernelGetFunctions: readRegistryValue(%s)", str);
}
break;
diff --git a/engines/scumm/scumm.cpp b/engines/scumm/scumm.cpp
index 2f0f0444f95..386fd5963ca 100644
--- a/engines/scumm/scumm.cpp
+++ b/engines/scumm/scumm.cpp
@@ -2059,6 +2059,25 @@ void ScummEngine::setupMusic(int midi, const Common::String &macInstrumentFile)
}
void ScummEngine::syncSoundSettings() {
+ if (isUsingOriginalGUI() && _game.version == 8) {
+ _voiceMode = ConfMan.getInt("original_gui_text_status");
+
+ if (VAR_VOICE_MODE != 0xFF)
+ VAR(VAR_VOICE_MODE) = _voiceMode;
+
+ if (ConfMan.hasKey("original_gui_text_speed", _targetName)) {
+ _defaultTalkDelay = ConfMan.getInt("original_gui_text_speed");
+
+ // In the original GUI the talk delay is represented as text speed,
+ // so we have to invert the value:
+ // - 9 is the highest text speed possible;
+ // - 0 is the lowest text speed possible.
+ if (VAR_CHARINC != 0xFF)
+ VAR(VAR_CHARINC) = 9 - _defaultTalkDelay;
+ }
+ return;
+ }
+
Engine::syncSoundSettings();
// Sync the engine with the config manager
@@ -2534,7 +2553,7 @@ void ScummEngine::scummLoop_handleSaveLoad() {
bool success;
Common::U32String errMsg;
- if (_game.version == 8 && _saveTemporaryState)
+ if (_game.version == 8 && (_saveTemporaryState || isUsingOriginalGUI()))
VAR(VAR_GAME_LOADED) = 0;
Common::String filename;
@@ -2553,7 +2572,7 @@ void ScummEngine::scummLoop_handleSaveLoad() {
if (!success)
errMsg = _("Failed to load saved game from file:\n\n%s");
- if (success && _saveTemporaryState && VAR_GAME_LOADED != 0xFF)
+ if (success && (_saveTemporaryState || isUsingOriginalGUI()) && VAR_GAME_LOADED != 0xFF)
VAR(VAR_GAME_LOADED) = (_game.version == 8) ? 1 : 203;
}
@@ -2945,6 +2964,13 @@ void ScummEngine::restart() {
runBootscript();
}
+bool ScummEngine::isUsingOriginalGUI() {
+ if (_game.version == 8)
+ return _useOriginalGUI;
+
+ return false;
+}
+
void ScummEngine::runBootscript() {
int args[NUM_SCRIPT_LOCAL];
memset(args, 0, sizeof(args));
diff --git a/engines/scumm/scumm.h b/engines/scumm/scumm.h
index 671f5a8b217..0d92b0586a2 100644
--- a/engines/scumm/scumm.h
+++ b/engines/scumm/scumm.h
@@ -386,6 +386,7 @@ public:
ResourceManager *_res = nullptr;
bool _enableEnhancements = false;
+ bool _useOriginalGUI = true;
bool _enableAudioOverride = false;
protected:
@@ -482,6 +483,7 @@ protected:
public:
void pauseGame();
void restart();
+ bool isUsingOriginalGUI();
protected:
Dialog *_pauseDialog = nullptr;
@@ -619,6 +621,7 @@ protected:
void loadResource(Common::Serializer &ser, ResType type, ResId idx);
void loadResourceOLD(Common::Serializer &ser, ResType type, ResId idx); // "Obsolete"
+ void copyHeapSaveGameToFile(int slot, const char *saveName);
virtual Common::SeekableReadStream *openSaveFileForReading(int slot, bool compat, Common::String &fileName);
virtual Common::WriteStream *openSaveFileForWriting(int slot, bool compat, Common::String &fileName);
@@ -1443,6 +1446,8 @@ public:
byte VAR_RIGHTBTN_HOLD = 0xFF; // V6/V72HE/V7/V8
byte VAR_SAVELOAD_SCRIPT = 0xFF; // V6/V7 (not HE)
byte VAR_SAVELOAD_SCRIPT2 = 0xFF; // V6/V7 (not HE)
+ byte VAR_SAVELOAD_PAGE = 0xFF; // V8
+ byte VAR_OBJECT_LABEL_FLAG = 0xFF; // V8
// V6/V7 specific variables (FT & Sam & Max specific)
byte VAR_CHARSET_MASK = 0xFF;
diff --git a/engines/scumm/vars.cpp b/engines/scumm/vars.cpp
index e6244610bf7..66fca7a50ae 100644
--- a/engines/scumm/vars.cpp
+++ b/engines/scumm/vars.cpp
@@ -558,6 +558,9 @@ void ScummEngine_v8::setupScummVars() {
VAR_KEYPRESS = 132;
VAR_BLAST_ABOVE_TEXT = 133;
VAR_SYNC = 134;
+
+ VAR_SAVELOAD_PAGE = 175;
+ VAR_OBJECT_LABEL_FLAG = 176;
}
#endif
Commit: 7e4d844969515bb5c67b98bd69ad54f056c718c3
https://github.com/scummvm/scummvm/commit/7e4d844969515bb5c67b98bd69ad54f056c718c3
Author: AndywinXp (andywinxp at gmail.com)
Date: 2022-08-06T13:33:56+02:00
Commit Message:
SCUMM: DETECTION: Add an option for activating the original GUI
Changed paths:
engines/scumm/detection.cpp
engines/scumm/detection.h
engines/scumm/detection_tables.h
engines/scumm/scumm.cpp
engines/scumm/scumm.h
diff --git a/engines/scumm/detection.cpp b/engines/scumm/detection.cpp
index 8522c68cff9..05751c0e84d 100644
--- a/engines/scumm/detection.cpp
+++ b/engines/scumm/detection.cpp
@@ -243,6 +243,15 @@ static const ExtraGuiOption audioOverride {
0
};
+static const ExtraGuiOption enableOriginalGUI{
+ _s("Enable the original GUI and Menu"),
+ _s("Allow the game to use the in-engine graphical interface and the original save/load menu."),
+ "original_gui",
+ true,
+ 0,
+ 0
+};
+
const ExtraGuiOptions ScummMetaEngineDetection::getExtraGuiOptions(const Common::String &target) const {
ExtraGuiOptions options;
// Query the GUI options
@@ -252,6 +261,9 @@ const ExtraGuiOptions ScummMetaEngineDetection::getExtraGuiOptions(const Common:
const Common::String guiOptions = parseGameGUIOptions(guiOptionsString);
const Common::Platform platform = Common::parsePlatform(ConfMan.get("platform", target));
+ if (target.empty() || guiOptions.contains(GUIO_ORIGINALGUI)) {
+ options.push_back(enableOriginalGUI);
+ }
if (target.empty() || guiOptions.contains(GUIO_ENHANCEMENTS)) {
options.push_back(enableEnhancements);
}
diff --git a/engines/scumm/detection.h b/engines/scumm/detection.h
index a47610cc733..2f19047a5ee 100644
--- a/engines/scumm/detection.h
+++ b/engines/scumm/detection.h
@@ -32,6 +32,7 @@ namespace Scumm {
#define GUIO_TRIM_FMTOWNS_TO_200_PIXELS GUIO_GAMEOPTIONS1
#define GUIO_ENHANCEMENTS GUIO_GAMEOPTIONS2
#define GUIO_AUDIO_OVERRIDE GUIO_GAMEOPTIONS3
+#define GUIO_ORIGINALGUI GUIO_GAMEOPTIONS4
/**
* Descriptor of a specific SCUMM game. Used internally to store
diff --git a/engines/scumm/detection_tables.h b/engines/scumm/detection_tables.h
index b018396bad6..2e4ba1acb16 100644
--- a/engines/scumm/detection_tables.h
+++ b/engines/scumm/detection_tables.h
@@ -221,7 +221,7 @@ static const GameSettings gameVariantsTable[] = {
{"dig", "Demo", 0, GID_DIG, 7, 0, MDT_NONE, GF_DEMO, UNK, GUIO1(GUIO_NOMIDI)},
{"dig", "Steam", "steam", GID_DIG, 7, 0, MDT_NONE, 0, UNK, GUIO1(GUIO_NOMIDI)},
- {"comi", "", 0, GID_CMI, 8, 0, MDT_NONE, 0, Common::kPlatformWindows, GUIO2(GUIO_NOMIDI, GUIO_NOASPECT)},
+ {"comi", "", 0, GID_CMI, 8, 0, MDT_NONE, 0, Common::kPlatformWindows, GUIO3(GUIO_NOMIDI, GUIO_NOASPECT, GUIO_ORIGINALGUI)},
{"comi", "Demo", 0, GID_CMI, 8, 0, MDT_NONE, GF_DEMO, Common::kPlatformWindows, GUIO2(GUIO_NOMIDI, GUIO_NOASPECT)},
// Humongous Entertainment Scumm Version 6
diff --git a/engines/scumm/scumm.cpp b/engines/scumm/scumm.cpp
index 386fd5963ca..2bbc6d22541 100644
--- a/engines/scumm/scumm.cpp
+++ b/engines/scumm/scumm.cpp
@@ -1377,6 +1377,9 @@ void ScummEngine::setupScumm(const Common::String &macResourceFile) {
#ifdef ENABLE_SCUMM_7_8
void ScummEngine_v7::setupScumm(const Common::String &macResourceFile) {
+ if (ConfMan.hasKey("original_gui"))
+ _useOriginalGUI = ConfMan.getBool("original_gui");
+
if (_game.id == GID_DIG && (_game.features & GF_DEMO))
_smushFrameRate = 15;
else
diff --git a/engines/scumm/scumm.h b/engines/scumm/scumm.h
index 0d92b0586a2..324f38be6bc 100644
--- a/engines/scumm/scumm.h
+++ b/engines/scumm/scumm.h
@@ -386,7 +386,7 @@ public:
ResourceManager *_res = nullptr;
bool _enableEnhancements = false;
- bool _useOriginalGUI = true;
+ bool _useOriginalGUI = false;
bool _enableAudioOverride = false;
protected:
Commit: fabaeb4b838d080857612a1237d5038d1a156b72
https://github.com/scummvm/scummvm/commit/fabaeb4b838d080857612a1237d5038d1a156b72
Author: AndywinXp (andywinxp at gmail.com)
Date: 2022-08-06T13:33:56+02:00
Commit Message:
SCUMM: COMI: Implement original GUI
Changed paths:
engines/scumm/cursor.cpp
engines/scumm/dialogs.cpp
engines/scumm/dialogs.h
engines/scumm/gfx.cpp
engines/scumm/input.cpp
engines/scumm/palette.cpp
engines/scumm/resource.cpp
engines/scumm/script.cpp
engines/scumm/script_v8.cpp
engines/scumm/scumm.cpp
engines/scumm/scumm.h
engines/scumm/scumm_v7.h
engines/scumm/smush/smush_player.cpp
engines/scumm/smush/smush_player.h
engines/scumm/string_v7.cpp
diff --git a/engines/scumm/cursor.cpp b/engines/scumm/cursor.cpp
index ce2cb4f9682..e7b541608c6 100644
--- a/engines/scumm/cursor.cpp
+++ b/engines/scumm/cursor.cpp
@@ -89,6 +89,29 @@ static const byte default_v6_cursor[] = {
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0x00,0x0F,0x00, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
};
+static const byte default_v8_cursor[] = {
+ 0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE, 0x00,0x0F,0x0F,0x00, 0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,
+ 0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE, 0x00,0x0F,0x0F,0x00, 0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,
+ 0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE, 0x00,0x0F,0x0F,0x00, 0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,
+ 0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE, 0x00,0x0F,0x0F,0x00, 0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,
+ 0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE, 0x00,0x0F,0x0F,0x00, 0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,
+ 0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE, 0x00,0x0F,0x0F,0x00, 0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,
+ 0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE, 0x00,0x0F,0x0F,0x00, 0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,
+ 0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE, 0x00,0x0F,0x0F,0x00, 0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0xFE,0xFE,0xFE,0xFE, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F, 0xFE,0xFE,0xFE,0xFE, 0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,
+ 0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F, 0xFE,0xFE,0xFE,0xFE, 0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0xFE,0xFE,0xFE,0xFE, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE, 0x00,0x0F,0x0F,0x00, 0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,
+ 0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE, 0x00,0x0F,0x0F,0x00, 0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,
+ 0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE, 0x00,0x0F,0x0F,0x00, 0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,
+ 0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE, 0x00,0x0F,0x0F,0x00, 0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,
+ 0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE, 0x00,0x0F,0x0F,0x00, 0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,
+ 0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE, 0x00,0x0F,0x0F,0x00, 0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,
+ 0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE, 0x00,0x0F,0x0F,0x00, 0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,
+ 0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE, 0x00,0x0F,0x0F,0x00, 0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,
+};
+
void ScummEngine_v5::animateCursor() {
if (_cursor.animate) {
if (!(_cursor.animateIndex & 0x1)) {
@@ -157,8 +180,15 @@ void ScummEngine_v6::grabCursor(int x, int y, int w, int h) {
}
void ScummEngine_v6::setDefaultCursor() {
- setCursorHotspot(7, 6);
- setCursorFromBuffer(default_v6_cursor, 16, 13, 16);
+ if (_game.version == 8) {
+ setCursorHotspot(9, 9);
+ setCursorFromBuffer(default_v8_cursor, 20, 20, 20);
+ setCursorTransparency(0xFE);
+ } else {
+ setCursorHotspot(7, 6);
+ setCursorFromBuffer(default_v6_cursor, 16, 13, 16);
+ }
+
}
void ScummEngine_v6::setCursorFromBuffer(const byte *ptr, int width, int height, int pitch) {
diff --git a/engines/scumm/dialogs.cpp b/engines/scumm/dialogs.cpp
index fe9271bdd50..d90d929119b 100644
--- a/engines/scumm/dialogs.cpp
+++ b/engines/scumm/dialogs.cpp
@@ -74,7 +74,16 @@ static const ResString string_map_table_v8[] = {
{0, "/BT__017/Saving '%s'"},
{0, "/BT__018/Loading '%s'"},
{0, "/BT__019/Name your SAVE game"},
- {0, "/BT__020/Select a game to LOAD"}
+ {0, "/BT__020/Select a game to LOAD"},
+ {0, "/BT__028/Do you want to replace this saved game? (Y/N)Y"},
+ {0, "/SYST200/Are you sure you want to quit?"},
+ {0, "/SYST201/Yes"},
+ {0, "/SYST202/No"},
+ {0, "/SYST203/iMuse buffer count changed to %d"},
+ {0, "/BT_104/Voice and Text"},
+ {0, "/BT_105/Text Display Only"},
+ {0, "/BT_103/Voice Only"},
+ {0, "/SYST300/y"},
};
static const ResString string_map_table_v7[] = {
@@ -426,6 +435,22 @@ void InfoDialog::reflowLayout() {
_text->setSize(_w, _h);
}
+const char *InfoDialog::getPlainEngineString(int stringno) {
+ if (stringno == 0)
+ return nullptr;
+
+ if (_vm->_game.version == 8)
+ return (const char *)string_map_table_v8[stringno - 1].string;
+ else if (_vm->_game.version == 7)
+ return (const char *)_vm->getStringAddressVar(string_map_table_v7[stringno - 1].num);
+ else if (_vm->_game.version == 6)
+ return (const char *)_vm->getStringAddressVar(string_map_table_v6[stringno - 1].num);
+ else if (_vm->_game.version >= 3)
+ return (const char *)_vm->getStringAddress(string_map_table_v345[stringno - 1].num);
+ else
+ return (const char *)(string_map_table_v345[stringno - 1].string);
+}
+
const Common::U32String InfoDialog::queryResString(int stringno) {
byte buf[256];
byte reverseBuf[256];
diff --git a/engines/scumm/dialogs.h b/engines/scumm/dialogs.h
index 8edbbb870ef..41c48efd6b2 100644
--- a/engines/scumm/dialogs.h
+++ b/engines/scumm/dialogs.h
@@ -91,6 +91,7 @@ public:
}
void reflowLayout() override;
+ const char *getPlainEngineString(int stringno);
protected:
diff --git a/engines/scumm/gfx.cpp b/engines/scumm/gfx.cpp
index f6120f01a9a..8b7ea050f58 100644
--- a/engines/scumm/gfx.cpp
+++ b/engines/scumm/gfx.cpp
@@ -1418,6 +1418,25 @@ void ScummEngine::drawBox(int x, int y, int x2, int y2, int color) {
if ((vs = findVirtScreen(y)) == nullptr)
return;
+ if (_game.version == 8) {
+ width = _screenWidth + 8;
+ height = _screenHeight;
+ int effX2 = x2;
+ int effX;
+ if (width >= x2) {
+ effX = x;
+ } else {
+ effX2 = width;
+ effX = x;
+ if (x < 0)
+ effX = 0;
+ }
+ backbuff = vs->getPixels(effX, y);
+ fill(backbuff, vs->pitch, color, effX2, y2, vs->format.bytesPerPixel);
+ markRectAsDirty(vs->number, effX, effX + effX2, y, y + y2);
+ return;
+ }
+
// Indy4 Amiga always uses the room or verb palette map to match colors to
// the currently setup palette, thus we need to select it over here too.
// Done like the original interpreter.
@@ -1554,6 +1573,89 @@ void ScummEngine::drawBox(int x, int y, int x2, int y2, int color) {
}
}
+void ScummEngine::drawLine(int x1, int y1, int x2, int y2, int color) {
+ int effColor, black, white;
+ int effX1, effY1;
+ int width, height, widthAccumulator, heightAccumulator, horizontalStrips, originalHeight;
+ int nudgeX, nudgeY;
+
+ bool canDrawPixel, noColorSpecified;
+
+ VirtScreen *vs;
+
+ if ((vs = findVirtScreen(y1)) == nullptr)
+ return;
+
+ black = getPaletteColorFromRGB(_currentPalette, 0x00, 0x00, 0x00);
+ white = getPaletteColorFromRGB(_currentPalette, 0xFC, 0xFC, 0xFC);
+
+ noColorSpecified = false;
+ effColor = color;
+ if (color == -1) {
+ noColorSpecified = true;
+ effColor = white;
+ }
+
+ effX1 = x1;
+ effY1 = y1;
+ width = abs(x2 - x1);
+ height = abs(y2 - y1);
+ originalHeight = height;
+
+ if (height <= width)
+ height = width;
+
+ widthAccumulator = 0;
+ heightAccumulator = 0;
+
+ drawPixel(vs, x1, y1, effColor);
+
+ if (height >= 0) {
+ horizontalStrips = height + 1;
+ do {
+ widthAccumulator += width;
+ canDrawPixel = false;
+ heightAccumulator += originalHeight;
+ if (widthAccumulator > height) {
+ canDrawPixel = true;
+ widthAccumulator -= height;
+ nudgeX = 1;
+ if (x2 - x1 < 0)
+ nudgeX = -1;
+ effX1 += nudgeX;
+ }
+
+ if (heightAccumulator > height) {
+ canDrawPixel = true;
+ heightAccumulator -= height;
+ nudgeY = 1;
+ if (y2 - y1 < 0)
+ nudgeY = -1;
+ effY1 += nudgeY;
+ }
+
+ if (canDrawPixel) {
+ drawPixel(vs, effX1, effY1, effColor);
+ if (noColorSpecified) {
+ if (effColor != white)
+ effColor = white;
+ else
+ effColor = black;
+ }
+ }
+
+ horizontalStrips--;
+ } while (horizontalStrips);
+ }
+}
+
+void ScummEngine::drawPixel(VirtScreen *vs, int x, int y, int16 color) {
+ if (x >= 0 && y >= 0 && _screenWidth + 8 > x && _screenHeight > y) {
+ memset(vs->getPixels(x, y), color, 1);
+ markRectAsDirty(vs->number, x, x + 1, y, y + 1);
+ }
+}
+
/**
* Moves the screen content by the offset specified via dx/dy.
* Only the region from x=0 till x=height-1 is affected.
diff --git a/engines/scumm/input.cpp b/engines/scumm/input.cpp
index 788c957876c..d9c9ce5e04c 100644
--- a/engines/scumm/input.cpp
+++ b/engines/scumm/input.cpp
@@ -38,8 +38,9 @@
#include "scumm/scumm_v6.h"
#include "scumm/scumm_v8.h"
#include "scumm/sound.h"
+#include "scumm/dialogs.h"
-
+#include "graphics/cursorman.h"
namespace Scumm {
@@ -378,35 +379,72 @@ void ScummEngine::processInput() {
#ifdef ENABLE_SCUMM_7_8
void ScummEngine_v8::processKeyboard(Common::KeyState lastKeyHit) {
// F1 (the trigger for the original save/load dialog) is mapped to F5,
- // unless we chose to use the original GUI
+ // unless we chose to use the original GUI.
if (!(_game.features & GF_DEMO) && lastKeyHit.keycode == Common::KEYCODE_F1 && lastKeyHit.hasFlags(0)) {
if (isUsingOriginalGUI()) {
lastKeyHit = Common::KeyState(Common::KEYCODE_F1, 315);
} else {
lastKeyHit = Common::KeyState(Common::KEYCODE_F5, 319);
}
-
}
- // If we are using the original GUI, remap F5 to F1
+ // If we are using the original GUI, remap F5 to F1.
if (isUsingOriginalGUI() && !(_game.features & GF_DEMO) && lastKeyHit.keycode == Common::KEYCODE_F5 && lastKeyHit.hasFlags(0)) {
lastKeyHit = Common::KeyState(Common::KEYCODE_F1, 315);
}
// Alt-F5 should bring up the original save/load dialog, so map it to F1,
- // again, unless we chose to use the original GUI
+ // again, unless we chose to use the original GUI.
if (!isUsingOriginalGUI() && !(_game.features & GF_DEMO) && lastKeyHit.keycode == Common::KEYCODE_F5 && lastKeyHit.hasFlags(Common::KBD_ALT)) {
lastKeyHit = Common::KeyState(Common::KEYCODE_F1, 315);
}
// If a key script was specified (a V8 feature), and it's trigger
// key was pressed, run it. Usually used to display the built-in menu.
- if (_keyScriptNo && (_keyScriptKey == lastKeyHit.ascii)) {
+ if (!isSmushActive() && _keyScriptNo && (_keyScriptKey == lastKeyHit.ascii)) {
runScript(_keyScriptNo, 0, 0, 0);
return;
}
- // Fall back to V7 behavior
+ // Set up an InfoDialog object for fetching the internal strings.
+ InfoDialog d(this, 0);
+
+ if (isUsingOriginalGUI() && lastKeyHit.keycode == VAR(VAR_PAUSE_KEY)) {
+ // Force the cursor OFF...
+ int8 oldCursorState = _cursor.state;
+ _cursor.state = 0;
+ CursorMan.showMouse(_cursor.state > 0);
+ showBannerAndPause(0, -1, d.getPlainEngineString(4));
+ _cursor.state = oldCursorState;
+ return;
+ }
+
+ if (isUsingOriginalGUI() && VAR(VAR_VERSION_KEY) != 0 &&
+ lastKeyHit.keycode == Common::KEYCODE_v && lastKeyHit.hasFlags(Common::KBD_CTRL)) {
+ showBannerAndPause(0, -1, _dataFileVersionString);
+ // This is not the string being used by the interpreter, which is instead hardcoded
+ // in the executable. The one used here is found in the data files.
+ showBannerAndPause(0, -1, _engineVersionString);
+ return;
+ }
+
+ if (isUsingOriginalGUI() &&
+ (lastKeyHit.keycode == Common::KEYCODE_c && lastKeyHit.hasFlags(Common::KBD_CTRL))) {
+ // Force the cursor to be ON...
+ int8 oldCursorState = _cursor.state;
+ _cursor.state = 1;
+ CursorMan.showMouse(_cursor.state > 0);
+ confirmExitDialog();
+ _cursor.state = oldCursorState;
+
+ // If SMUSH is active, manually force the old cursor state...
+ if (isSmushActive()) {
+ CursorMan.showMouse(_cursor.state > 0);
+ }
+ return;
+ }
+
+ // Fall back to V7 behavior...
ScummEngine_v7::processKeyboard(lastKeyHit);
}
@@ -452,6 +490,34 @@ void ScummEngine_v7::processKeyboard(Common::KeyState lastKeyHit) {
ScummEngine_v6::processKeyboard(lastKeyHit);
}
}
+
+void ScummEngine_v7::waitForBannerInput(int32 waitTime, Common::KeyState &ks, bool &leftBtnClicked, bool &rightBtnClicked) {
+ if (waitTime && waitTime != -1) {
+ uint32 millis = _system->getMillis();
+ while (((_system->getMillis() - millis) * (_timerFrequency / 4) / 1000) < waitTime) {
+ waitForTimer(1); // Allow the engine to update the screen and fetch new inputs...
+ ks = _keyPressed;
+ leftBtnClicked = (_leftBtnPressed & msClicked) != 0;
+ rightBtnClicked = (_rightBtnPressed & msClicked) != 0;
+ if (&ks || leftBtnClicked || rightBtnClicked)
+ return;
+
+ if (shouldQuit())
+ return;
+ }
+ } else {
+ while (ks == Common::KEYCODE_INVALID && !leftBtnClicked && !rightBtnClicked) {
+ waitForTimer(1); // Allow the engine to update the screen and fetch new inputs...
+ ks = _keyPressed;
+ leftBtnClicked = (_leftBtnPressed & msClicked) != 0;
+ rightBtnClicked = (_rightBtnPressed & msClicked) != 0;
+
+ if (shouldQuit())
+ return;
+ }
+ }
+}
+
#endif
void ScummEngine_v6::processKeyboard(Common::KeyState lastKeyHit) {
diff --git a/engines/scumm/palette.cpp b/engines/scumm/palette.cpp
index 76f431ba98c..34df8b06e56 100644
--- a/engines/scumm/palette.cpp
+++ b/engines/scumm/palette.cpp
@@ -1498,6 +1498,73 @@ const byte *ScummEngine::getPalettePtr(int palindex, int room) {
return cptr;
}
+uint32 ScummEngine::getPaletteColorFromRGB(byte *palette, byte r, byte g, byte b) {
+ uint32 color, black, white;
+
+ if ((r == 0xFF && b == 0xFF && g == 0xFF) || (r == 0x00 && g == 0x00 && b == 0x00)) {
+ fetchBlackAndWhite(black, white, palette, 256);
+
+ if (r) {
+ color = black;
+ } else {
+ color = white;
+ }
+ color = 0xFF;
+ } else {
+ color = findClosestPaletteColor(palette, 256, r, g, b);
+ }
+
+ return color;
+}
+
+void ScummEngine::fetchBlackAndWhite(uint32 &black, uint32 &white, byte *palette, int paletteEntries) {
+ int max = 0;
+ int r, g, b;
+ int componentsSum;
+ int min = 1000;
+
+ for (int elementId = 0; elementId < paletteEntries; elementId++) {
+ r = palette[0];
+ g = palette[1];
+ b = palette[2];
+
+ componentsSum = r + g + b;
+ if (elementId > 0 && componentsSum >= max) {
+ max = componentsSum;
+ white = elementId;
+ }
+
+ if (componentsSum <= min) {
+ min = componentsSum;
+ black = elementId;
+ }
+
+ palette += 3;
+ }
+}
+
+uint32 ScummEngine::findClosestPaletteColor(byte *palette, int numOfSlots, byte r, byte g, byte b) {
+ uint32 color = 0;
+ uint32 redSquareDiff, blueSquareDiff, greenSquareDiff, weightedColorError;
+ uint32 minErr = 10000000;
+
+ // Iterate through the palette slots to find a color with the minimum
+ // weighted error with respect to our queried RGB values.
+ for (int i = 0; numOfSlots > i; ++i) {
+ redSquareDiff = (r - palette[0]) * (r - palette[0]);
+ greenSquareDiff = (g - palette[1]) * (g - palette[1]);
+ blueSquareDiff = (b - palette[2]) * (b - palette[2]);
+
+ weightedColorError = 3 * redSquareDiff + 5 * greenSquareDiff + 2 * blueSquareDiff;
+ if (3 * redSquareDiff + 5 * greenSquareDiff + 2 * blueSquareDiff < minErr) {
+ color = i;
+ minErr = 3 * redSquareDiff + 5 * greenSquareDiff + 2 * blueSquareDiff;
+ }
+ palette += 3;
+ }
+ return color;
+}
+
void ScummEngine::updatePalette() {
if (_game.features & GF_16BIT_COLOR)
return;
diff --git a/engines/scumm/resource.cpp b/engines/scumm/resource.cpp
index 1f903655a69..89d5d0d7cb6 100644
--- a/engines/scumm/resource.cpp
+++ b/engines/scumm/resource.cpp
@@ -1202,8 +1202,8 @@ void ScummEngine_v5::readMAXS(int blockSize) {
#ifdef ENABLE_SCUMM_7_8
void ScummEngine_v8::readMAXS(int blockSize) {
- _fileHandle->seek(50, SEEK_CUR); // Skip over SCUMM engine version
- _fileHandle->seek(50, SEEK_CUR); // Skip over data file version
+ _fileHandle->read(_engineVersionString, 50);
+ _fileHandle->read(_dataFileVersionString, 50);
_numVariables = _fileHandle->readUint32LE(); // 1500
_numBitVariables = _fileHandle->readUint32LE(); // 2048
_fileHandle->readUint32LE(); // 40
@@ -1230,8 +1230,8 @@ void ScummEngine_v8::readMAXS(int blockSize) {
}
void ScummEngine_v7::readMAXS(int blockSize) {
- _fileHandle->seek(50, SEEK_CUR); // Skip over SCUMM engine version
- _fileHandle->seek(50, SEEK_CUR); // Skip over data file version
+ _fileHandle->read(_engineVersionString, 50);
+ _fileHandle->read(_dataFileVersionString, 50);
_numVariables = _fileHandle->readUint16LE();
_numBitVariables = _fileHandle->readUint16LE();
_fileHandle->readUint16LE();
diff --git a/engines/scumm/script.cpp b/engines/scumm/script.cpp
index 804e7023aed..1312c1f031d 100644
--- a/engines/scumm/script.cpp
+++ b/engines/scumm/script.cpp
@@ -29,6 +29,7 @@
#include "scumm/util.h"
#include "scumm/scumm_v0.h"
#include "scumm/scumm_v2.h"
+#include "scumm/scumm_v7.h"
#include "scumm/sound.h"
#include "scumm/verbs.h"
diff --git a/engines/scumm/script_v8.cpp b/engines/scumm/script_v8.cpp
index d200d5cf6ba..e52d0ab2cd7 100644
--- a/engines/scumm/script_v8.cpp
+++ b/engines/scumm/script_v8.cpp
@@ -1093,7 +1093,8 @@ void ScummEngine_v8::o8_kernelSetFunctions() {
setScaleSlot(args[1], args[2], args[3], args[4], args[5], args[6], args[7]);
break;
case 22: // setBannerColors
-// debug(0, "o8_kernelSetFunctions: setBannerColors(%d, %d, %d, %d)", args[1], args[2], args[3], args[4]);
+ debug(0, "o8_kernelSetFunctions: setBannerColors(%d, %d, %d, %d)", args[1], args[2], args[3], args[4]);
+ setBannerColors(args[1], args[2], args[3], args[4]);
break;
case 23: // setActorChoreLimbFrame
a = derefActor(args[1], "o8_kernelSetFunctions:setActorChoreLimbFrame");
diff --git a/engines/scumm/scumm.cpp b/engines/scumm/scumm.cpp
index 2bbc6d22541..58e00814f5d 100644
--- a/engines/scumm/scumm.cpp
+++ b/engines/scumm/scumm.cpp
@@ -1419,6 +1419,8 @@ void ScummEngine_v7::setupScumm(const Common::String &macResourceFile) {
_insane = nullptr;
_splayer = new SmushPlayer(this, _imuseDigital, _insane);
+
+ initBanners();
}
#endif
@@ -3126,6 +3128,442 @@ void ScummEngine::versionDialog() {
runDialog(*_versionDialog);
}
+#ifdef ENABLE_SCUMM_7_8
+void ScummEngine_v7::initBanners() {
+ setPalColor(7, 0x5A, 0x5A, 0x5A);
+ setPalColor(8, 0x46, 0x46, 0x46);
+ setPalColor(15, 0x8C, 0x8C, 0x8C);
+
+ setBannerColors(1, 0x00, 0x00, 0x00);
+ setBannerColors(2, 0xA8, 0xA8, 0xA8);
+ setBannerColors(3, 0x00, 0x00, 0x00);
+ setBannerColors(4, 0xFC, 0xFC, 0x54);
+ setBannerColors(5, 0x54, 0x54, 0xFC);
+ setBannerColors(6, 0xA8, 0xA8, 0xA8);
+ setBannerColors(7, 0x00, 0x00, 0x00);
+ setBannerColors(8, 0xFC, 0xFC, 0x54);
+ setBannerColors(9, 0x54, 0x54, 0xFC);
+ setBannerColors(10, 0xFC, 0xFC, 0xFC);
+ setBannerColors(11, 0x54, 0x54, 0x54);
+ setBannerColors(12, 0xFC, 0xFC, 0xFC);
+ setBannerColors(13, 0x54, 0x54, 0x54);
+ setBannerColors(14, 0x00, 0x00, 0x00);
+ setBannerColors(15, 0xA8, 0xA8, 0xA8);
+ setBannerColors(16, 0xFC, 0xFC, 0xFC);
+ setBannerColors(17, 0x54, 0x54, 0x54);
+ setBannerColors(18, 0xFC, 0xFC, 0xFC);
+ setBannerColors(19, 0x54, 0x54, 0x54);
+ setBannerColors(20, 0xFC, 0x00, 0x00);
+ setBannerColors(21, 0xA8, 0xA8, 0xA8);
+ setBannerColors(22, 0xFC, 0xFC, 0xFC);
+ setBannerColors(23, 0x54, 0x54, 0x54);
+ setBannerColors(24, 0xFC, 0xFC, 0xFC);
+ setBannerColors(25, 0x54, 0x54, 0x54);
+ setBannerColors(26, 0x00, 0x00, 0x00);
+ setBannerColors(27, 0xA8, 0xA8, 0xA8);
+ setBannerColors(28, 0xFC, 0xFC, 0xFC);
+ setBannerColors(29, 0x54, 0x54, 0x54);
+ setBannerColors(30, 0xFC, 0xFC, 0xFC);
+ setBannerColors(31, 0x54, 0x54, 0x54);
+}
+
+Common::KeyState ScummEngine_v7::showBannerAndPause(int bannerId, int32 waitTime, const char *msg) {
+ char bannerMsg[512];
+ char localizedY[512];
+ char *ptrToBreak;
+ int bannerMsgWidth, bannerMsgHeight, roundedWidth;
+ int startingPointX, startingPointY;
+ int xPos, yPos;
+ int rightLineColor, leftLineColor, bottomLineColor, topLineColor;
+ int primaryLineColor, primaryFillColor;
+ InfoDialog d(this, 0);
+
+ // Fetch the translated string for the message...
+ convertMessageToString((const byte *)msg, (byte *)bannerMsg, sizeof(bannerMsg));
+ ptrToBreak = strstr(bannerMsg, "\\n");
+ if (ptrToBreak) { // Change the line break, if any...
+ ptrToBreak[0] = '\n';
+ ptrToBreak[1] = '\r';
+ }
+
+ // Pause the engine
+ PauseToken pt = pauseEngine();
+
+ // Gather the colors needed for the banner
+ primaryFillColor = getBannerColor(6 * bannerId + 15);
+ primaryLineColor = getBannerColor(6 * bannerId + 14);
+ topLineColor = getBannerColor(6 * bannerId + 16);
+ bottomLineColor = getBannerColor(6 * bannerId + 17);
+ leftLineColor = getBannerColor(6 * bannerId + 18);
+ rightLineColor = getBannerColor(6 * bannerId + 19);
+
+ // Backup the current charsetId, since we're going to switch
+ // to charsetId == 1...
+ int oldId = _charset->getCurID();
+ _charset->setCurID(1);
+
+ // Take all the necessary measurements for the box which
+ // will contain the string...
+ bannerMsgHeight = _textV7->getStringHeight(bannerMsg) + 5;
+ bannerMsgWidth = _textV7->getStringWidth(bannerMsg);
+ if (bannerMsgWidth < 100)
+ bannerMsgWidth = 100;
+
+ roundedWidth = (((bannerMsgWidth + 15) & 0xFFF0) + 8) / 2;
+ startingPointX = _screenWidth / 2 - roundedWidth - 4;
+ startingPointY = _screenHeight / 2 - 10;
+ xPos = _screenWidth / 2 + roundedWidth + 3;
+ yPos = 1 - bannerMsgHeight;
+
+ // Save the pixels which will be overwritten by the banner,
+ // so that we can restore them later...
+ if (!_bannerMem) {
+ _bannerMemSize = bannerMsgHeight * (_screenWidth + 8);
+ _bannerMem = (byte *)malloc(bannerMsgHeight * (_screenWidth + 8) * sizeof(byte));
+ if (_bannerMem)
+ memcpy(
+ _bannerMem,
+ &_virtscr[kMainVirtScreen].getPixels(0, 0)[(_screenWidth + 8) * (_screenHeight / 2 - 10)],
+ _bannerMemSize);
+ }
+
+ // Set up the GUI control, specifying all the related colors, the message and the position...
+ setUpInternalGUIControl(0, primaryFillColor, primaryLineColor,
+ topLineColor, bottomLineColor, leftLineColor, rightLineColor, 0, 0,
+ startingPointX, startingPointY, xPos, yPos,
+ bannerMsg, true);
+
+ // Draw it!
+ drawInternalGUIControl(0, 0);
+ drawDirtyScreenParts();
+
+ // Wait until the engine receives a new Keyboard or Mouse input,
+ // unless we have specified a positive waitTime: in that case, the banner
+ // will stay on screen until an input has been received or until the time-out.
+ Common::KeyState ks = Common::KEYCODE_INVALID;
+ bool leftBtnPressed = false, rightBtnPressed = false;
+ waitForBannerInput(waitTime, ks, leftBtnPressed, rightBtnPressed);
+ clearBanner();
+
+ // Finally, resume the engine, clear the input state, and restore the charset.
+ pt.clear();
+ clearClickedStatus();
+ if (oldId)
+ _charset->setCurID(oldId);
+
+ // Fetch the localized confirmation letter and substitute it with the 'y' of 'yes'
+ convertMessageToString((const byte *)d.getPlainEngineString(29), (byte *)localizedY, sizeof(localizedY));
+
+ if (tolower(localizedY[0]) == ks.ascii || toupper((localizedY[0]) == ks.ascii))
+ ks = Common::KEYCODE_y;
+
+ return ks;
+}
+
+void ScummEngine_v7::clearBanner() {
+ // Restore the GFX content which was under the banner,
+ // and then mark that part of the screen as dirty.
+ if (_bannerMem) {
+ memcpy(
+ &_virtscr[kMainVirtScreen].getPixels(0, 0)[(_screenWidth + 8) * (_screenHeight / 2 - 10)],
+ _bannerMem,
+ _bannerMemSize);
+ free(_bannerMem);
+ _bannerMem = nullptr;
+
+ if (isSmushActive()) {
+ return;
+ }
+
+ markRectAsDirty(_virtscr[kMainVirtScreen].number, 0, _screenWidth + 8, 0, _screenHeight);
+ drawDirtyScreenParts();
+ }
+}
+
+void ScummEngine_v7::setBannerColors(int bannerId, byte r, byte g, byte b) {
+ if (bannerId < 0 || bannerId > 50) {
+ debug(1, "ScummEngine::setBannerColors(): invalid slot %d out of range (min %d, max %d)", bannerId, 0, 50);
+ return;
+ }
+
+ bannerColors[bannerId] = r | (b << 16) | (g << 8);
+}
+
+int ScummEngine_v7::getBannerColor(int bannerId) {
+ byte r, g, b;
+ byte *palette = isSmushActive() ? _splayer->getVideoPalette() : _currentPalette;
+ r = (bannerColors[bannerId] >> 0) & 0xFF;
+ g = (bannerColors[bannerId] >> 8) & 0xFF;
+ b = (bannerColors[bannerId] >> 16) & 0xFF;
+ return getPaletteColorFromRGB(palette, r, g, b);
+}
+
+void ScummEngine_v7::setUpInternalGUIControl(int id, int primaryFillColor, int primaryLineColor,
+ int topLineColor, int bottomLineColor, int leftLineColor, int rightLineColor,
+ int secondaryLineColor, int secondaryFillColor,
+ int anchorPointX, int anchorPointY, int x, int y, char *label, bool centerFlag) {
+
+ int effX, effY;
+ InternalGUIControl *ctrl;
+
+ effX = x;
+ ctrl = &_internalGUIControls[id];
+ if (x < 0)
+ effX = anchorPointX - x;
+ effY = y;
+ if (y < 0)
+ effY = anchorPointY - y;
+ ctrl->relativeCenterX = anchorPointX;
+ ctrl->relativeCenterY = anchorPointY;
+ ctrl->xPos = effX;
+ ctrl->yPos = effY;
+ ctrl->label = label;
+ ctrl->centerText = centerFlag;
+ ctrl->primaryFillColor = primaryFillColor;
+ ctrl->topLineColor = topLineColor;
+ ctrl->bottomLineColor = bottomLineColor;
+ ctrl->leftLineColor = leftLineColor;
+ ctrl->rightLineColor = rightLineColor;
+ ctrl->primaryLineColor = primaryLineColor;
+ ctrl->secondaryLineColor = secondaryLineColor;
+ ctrl->secondaryFillColor = secondaryFillColor;
+}
+
+void ScummEngine_v7::drawInternalGUIControl(int id, bool useSecondaryColor) {
+ InternalGUIControl *ctrl;
+ int relCentX, relCentY, textHeight;
+ int x, y, textXPos, textYPos;
+ int lineColor, fillColor;
+ int boxSizeX, boxSizeY;
+
+ bool centerFlag;
+ char buttonString[512];
+
+ ctrl = &_internalGUIControls[id];
+ relCentX = ctrl->relativeCenterX;
+ if (ctrl->relativeCenterX != -1) {
+ relCentY = ctrl->relativeCenterY;
+ x = ctrl->xPos;
+ y = ctrl->yPos;
+
+ boxSizeX = x - ctrl->relativeCenterX;
+ boxSizeY = y - relCentY;
+
+ fillColor = useSecondaryColor ? ctrl->secondaryFillColor : ctrl->primaryFillColor;
+
+ // Draw the main box...
+ drawBox(relCentX + 1, relCentY + 1, boxSizeX - 2, boxSizeY - 2, fillColor);
+
+ // Draw the contour lines for the box; each of the lines is doubled to give a 3D effect.
+ drawLine(relCentX + 1, relCentY, x - 1, relCentY, ctrl->topLineColor);
+ drawLine(relCentX + 1, y, x - 1, y, ctrl->bottomLineColor);
+ drawLine(relCentX, relCentY + 1, relCentX, y - 1, ctrl->leftLineColor);
+ drawLine(x, relCentY + 1, x, y - 1, ctrl->rightLineColor);
+
+ drawLine(relCentX + 1, relCentY + 1, x - 1, relCentY + 1, ctrl->topLineColor);
+ drawLine(relCentX + 1, y - 1, x - 1, y - 1, ctrl->bottomLineColor);
+ drawLine(relCentX + 1, relCentY + 1, relCentX + 1, y - 1, ctrl->leftLineColor);
+ drawLine(x - 1, relCentY + 1, x - 1, y - 1, ctrl->rightLineColor);
+
+ // Calculate the positioning for the text
+ int oldId = _charset->getCurID();
+ _charset->setCurID(1);
+ textHeight = _textV7->getStringHeight(buttonString);
+ centerFlag = ctrl->centerText;
+
+ if (centerFlag)
+ textXPos = relCentX + boxSizeX / 2;
+ else
+ textXPos = relCentX + 2;
+
+ textYPos = relCentY + (boxSizeY - textHeight) / 2 + 1;
+
+ // Finally, choose the color and enqueue the text message
+ if (useSecondaryColor)
+ lineColor = ctrl->secondaryLineColor;
+ else
+ lineColor = ctrl->primaryLineColor;
+
+ if (ctrl->label)
+ strcpy(buttonString, ctrl->label);
+ else
+ strcpy(buttonString, "null button");
+
+ enqueueText((const byte *)buttonString, textXPos, textYPos, lineColor, 1, (TextStyleFlags)centerFlag);
+
+ // Restore the previous charset
+ if (oldId)
+ _charset->setCurID(oldId);
+ }
+}
+
+int ScummEngine_v7::getInternalGUIControlFromCoordinates(int x, int y) {
+ int id = 0;
+ while (_internalGUIControls[id].relativeCenterX == -1 ||
+ _internalGUIControls[id].relativeCenterX > x ||
+ _internalGUIControls[id].xPos < x ||
+ _internalGUIControls[id].relativeCenterY > y ||
+ _internalGUIControls[id]. yPos < y) {
+
+ id++;
+ if (id >= sizeof(_internalGUIControls))
+ return -1;
+ }
+ return id;
+}
+
+void ScummEngine_v7::confirmExitDialog() {
+ if (isUsingOriginalGUI()) {
+ int boxWidth, strWidth;
+ int ctrlId;
+ char yesLabelPtr[512];
+ char noLabelPtr[512];
+ char msgLabelPtr[512];
+ byte *curGrabbedCursor;
+ int curCursorWidth, curCursorHeight, curCursorHotspotX, curCursorHotspotY;
+
+ InfoDialog d(this, 0);
+
+ // "Are you sure you want to quit?"
+ convertMessageToString((const byte *)d.getPlainEngineString(22), (byte *)msgLabelPtr, sizeof(msgLabelPtr));
+ // "Yes"
+ convertMessageToString((const byte *)d.getPlainEngineString(23), (byte *)yesLabelPtr, sizeof(yesLabelPtr));
+ // "No"
+ convertMessageToString((const byte *)d.getPlainEngineString(24), (byte *)noLabelPtr, sizeof(noLabelPtr));
+
+ // Pause the engine...
+ PauseToken pt = pauseEngine();
+
+ // Backup the current cursor graphics and parameters
+ // and set up the internal v8 cursor...
+ curGrabbedCursor = (byte *)malloc(sizeof(_grabbedCursor));
+ memcpy(curGrabbedCursor, _grabbedCursor, sizeof(_grabbedCursor));
+ curCursorWidth = _cursor.width;
+ curCursorHeight = _cursor.height;
+ curCursorHotspotX = _cursor.hotspotX;
+ curCursorHotspotY = _cursor.hotspotY;
+ setDefaultCursor();
+
+ // Backup the current charsetId, since we're going to switch
+ // to charsetId == 1 and start taking measurements for the box...
+ int oldId = _charset->getCurID();
+ _charset->setCurID(1);
+
+ boxWidth = ((_textV7->getStringHeight(msgLabelPtr) + 32) & 0xFFF0) + 8;
+ if (boxWidth <= 400)
+ boxWidth = 400;
+
+ // Set up and draw the main box
+ setUpInternalGUIControl(
+ 0,
+ getBannerColor(33),
+ getBannerColor(32),
+ getBannerColor(34),
+ getBannerColor(35),
+ getBannerColor(36),
+ getBannerColor(37),
+ 0,
+ 0,
+ 320 - boxWidth / 2,
+ 190,
+ boxWidth / 2 + 319,
+ -90,
+ _emptyMsg,
+ true);
+
+ drawInternalGUIControl(0, 0);
+
+ // The text is drawn as a separate entity
+ enqueueText((const byte *)msgLabelPtr, 320, 200, getBannerColor(32), 1, (TextStyleFlags) true);
+
+ // Now set up and draw the Yes and No buttons...
+ if (_textV7->getStringWidth(noLabelPtr) <= _textV7->getStringWidth(yesLabelPtr)) {
+ strWidth = _textV7->getStringWidth(yesLabelPtr);
+ } else {
+ strWidth = _textV7->getStringWidth(noLabelPtr);
+ }
+
+ if (strWidth <= 120)
+ strWidth = 120;
+
+ setUpInternalGUIControl(
+ 0,
+ getBannerColor(45),
+ getBannerColor(44),
+ getBannerColor(46),
+ getBannerColor(47),
+ getBannerColor(48),
+ getBannerColor(49),
+ 0,
+ 0,
+ 420 - (strWidth / 2),
+ 240, -strWidth,
+ -30,
+ noLabelPtr,
+ true);
+
+ drawInternalGUIControl(0, 0);
+
+ setUpInternalGUIControl(
+ 0,
+ getBannerColor(39),
+ getBannerColor(38),
+ getBannerColor(40),
+ getBannerColor(41),
+ getBannerColor(42),
+ getBannerColor(43),
+ 0,
+ 0,
+ 220 - (strWidth / 2),
+ 240,
+ -strWidth,
+ -30,
+ yesLabelPtr,
+ true);
+
+ drawInternalGUIControl(0, 0);
+
+ // Done, draw everything to screen!
+ drawDirtyScreenParts();
+
+ // Stay in the dialog while we keep pressing CTRL-C...
+ Common::KeyState ks;
+ bool leftBtnPressed = false, rightBtnPressed = false;
+ do {
+ clearClickedStatus();
+ ks = Common::KEYCODE_INVALID;
+ waitForBannerInput(-1, ks, leftBtnPressed, rightBtnPressed);
+ } while (ks.keycode == Common::KEYCODE_LCTRL ||
+ ks.keycode == Common::KEYCODE_RCTRL ||
+ (ks.keycode == Common::KEYCODE_c && ks.hasFlags(Common::KBD_CTRL)));
+
+ ctrlId = getInternalGUIControlFromCoordinates(_mouse.x, _mouse.y);
+ if (leftBtnPressed && ctrlId == 0 || (toupper(ks.ascii) == yesLabelPtr[0]))
+ quitGame();
+
+ // Restore the previous cursor...
+ setCursorHotspot(curCursorHotspotX, curCursorHotspotY);
+ setCursorFromBuffer(curGrabbedCursor, curCursorWidth, curCursorHeight, curCursorWidth);
+ free(curGrabbedCursor);
+
+ // The interpreter makes us wait 45 full frames;
+ // let's wait half that time...
+ waitForTimer(45 * 2);
+
+ // Since we're not explicitly clearing the dialog graphics, set up a full redraw...
+ _fullRedraw = true;
+
+ // Finally, resume the engine, clear the input state, and restore the charset.
+ pt.clear();
+ clearClickedStatus();
+ if (oldId)
+ _charset->setCurID(oldId);
+ } else {
+ ScummEngine::confirmExitDialog();
+ }
+}
+#endif
+
void ScummEngine::confirmExitDialog() {
ConfirmDialog d(this, 6);
diff --git a/engines/scumm/scumm.h b/engines/scumm/scumm.h
index 324f38be6bc..a9d7ef1cc71 100644
--- a/engines/scumm/scumm.h
+++ b/engines/scumm/scumm.h
@@ -490,7 +490,7 @@ protected:
Dialog *_messageDialog = nullptr;
Dialog *_versionDialog = nullptr;
- void confirmExitDialog();
+ virtual void confirmExitDialog();
void confirmRestartDialog();
void pauseDialog();
void messageDialog(const Common::U32String &message);
@@ -661,6 +661,9 @@ protected:
int _scummStackPos = 0;
int _vmStack[256];
+ char _engineVersionString[50];
+ char _dataFileVersionString[50];
+
OpcodeEntry _opcodes[256];
virtual void setupOpcodes() = 0;
@@ -1007,6 +1010,8 @@ protected:
void drawRoomObjects(int arg);
void drawRoomObject(int i, int arg);
void drawBox(int x, int y, int x2, int y2, int color);
+ void drawLine(int x1, int y1, int x2, int y2, int color);
+ void drawPixel(VirtScreen *vs, int x, int y, int16 color);
void moveScreen(int dx, int dy, int height);
@@ -1044,9 +1049,13 @@ protected:
void stopCycle(int i);
virtual void palManipulateInit(int resID, int start, int end, int time);
void palManipulate();
+ uint32 findClosestPaletteColor(byte *palette, int numOfSlots, byte r, byte g, byte b);
+
public:
uint8 *getHEPaletteSlot(uint16 palSlot);
uint16 get16BitColor(uint8 r, uint8 g, uint8 b);
+ uint32 getPaletteColorFromRGB(byte *palette, byte r, byte g, byte b);
+ void fetchBlackAndWhite(uint32 &black, uint32 &white, byte *palette, int paletteEntries);
int remapPaletteColor(int r, int g, int b, int threshold); // Used by Actor::remapActorPalette
void readPCEPalette(const byte **ptr, byte **dest, int numEntries);
void colorPCEToRGB(uint16 color, byte *r, byte *g, byte *b);
@@ -1264,7 +1273,7 @@ protected:
void drawString(int a, const byte *msg);
void fakeBidiString(byte *ltext, bool ignoreVerb) const;
void debugMessage(const byte *msg);
- void showMessageDialog(const byte *msg);
+ virtual void showMessageDialog(const byte *msg);
virtual int convertMessageToString(const byte *msg, byte *dst, int dstSize);
int convertIntMessage(byte *dst, int dstSize, int var);
diff --git a/engines/scumm/scumm_v7.h b/engines/scumm/scumm_v7.h
index 6f3919f6269..b899634fbda 100644
--- a/engines/scumm/scumm_v7.h
+++ b/engines/scumm/scumm_v7.h
@@ -65,6 +65,23 @@ public:
int32 offset;
};
+ struct InternalGUIControl {
+ int relativeCenterX;
+ int relativeCenterY;
+ int xPos;
+ int yPos;
+ int primaryFillColor;
+ int topLineColor;
+ int bottomLineColor;
+ int leftLineColor;
+ int rightLineColor;
+ int primaryLineColor;
+ int secondaryLineColor;
+ int secondaryFillColor;
+ bool centerText;
+ char *label;
+ };
+
protected:
TextRenderer_v7 *_textV7;
Common::Rect _defaultTextClipRect;
@@ -93,6 +110,12 @@ protected:
int _subtitleQueuePos;
SubtitleText _subtitleQueue[20];
+ int32 bannerColors[50]; // Colors for the original GUI
+ byte *_bannerMem = nullptr;
+ uint32 _bannerMemSize = 0;
+ InternalGUIControl _internalGUIControls[30];
+ char _emptyMsg[1] = "";
+
public:
void processSubtitleQueue();
void addSubtitleToQueue(const byte *text, const Common::Point &pos, byte color, byte charset, bool center, bool wrap);
@@ -132,12 +155,27 @@ protected:
void createTextRenderer(GlyphRenderer_v7 *gr) override;
void enqueueText(const byte *text, int x, int y, byte color, byte charset, TextStyleFlags flags);
void drawBlastTexts() override;
+ void showMessageDialog(const byte *msg) override;
void actorTalk(const byte *msg) override;
void translateText(const byte *text, byte *trans_buff) override;
void loadLanguageBundle() override;
void playSpeech(const byte *ptr);
+ void initBanners();
+ Common::KeyState showBannerAndPause(int bannerId, int32 waitTime, const char *msg);
+ void waitForBannerInput(int32 waitTime, Common::KeyState &ks, bool &leftBtnClicked, bool &rightBtnClicked);
+ void clearBanner();
+ void setBannerColors(int bannerId, byte r, byte g, byte b);
+ int getBannerColor(int bannerId);
+ void setUpInternalGUIControl(int id, int primaryFillColor, int primaryLineColor,
+ int topLineColor, int bottomLineColor, int leftLineColor, int rightLineColor,
+ int secondaryLineColor, int secondaryFillColor,
+ int anchorPointX, int anchorPointY, int x, int y, char *label, bool centerFlag);
+ void drawInternalGUIControl(int id, bool useSecondaryColor);
+ int getInternalGUIControlFromCoordinates(int x, int y);
+ void confirmExitDialog() override;
+
void drawVerb(int verb, int mode) override;
void pauseEngineIntern(bool pause) override;
diff --git a/engines/scumm/smush/smush_player.cpp b/engines/scumm/smush/smush_player.cpp
index f0a05496e9d..dfb1532f5ba 100644
--- a/engines/scumm/smush/smush_player.cpp
+++ b/engines/scumm/smush/smush_player.cpp
@@ -738,6 +738,10 @@ void SmushPlayer::handleNewPalette(int32 subSize, Common::SeekableReadStream &b)
setDirtyColors(0, 255);
}
+byte *SmushPlayer::getVideoPalette() {
+ return _pal;
+}
+
void smush_decode_codec1(byte *dst, const byte *src, int left, int top, int width, int height, int pitch);
void smush_decode_codec20(byte *dst, const byte *src, int left, int top, int width, int height, int pitch);
diff --git a/engines/scumm/smush/smush_player.h b/engines/scumm/smush/smush_player.h
index 5f957908b79..a813c62a0d5 100644
--- a/engines/scumm/smush/smush_player.h
+++ b/engines/scumm/smush/smush_player.h
@@ -180,6 +180,7 @@ public:
void setGroupVolume(int groupId, int volValue);
void processDispatches(int16 feedSize);
bool isAudioCallbackEnabled();
+ byte *getVideoPalette();
protected:
int _width, _height;
diff --git a/engines/scumm/string_v7.cpp b/engines/scumm/string_v7.cpp
index 0f031d12841..dbed0a8233d 100644
--- a/engines/scumm/string_v7.cpp
+++ b/engines/scumm/string_v7.cpp
@@ -491,6 +491,24 @@ void ScummEngine_v8::printString(int m, const byte *msg) {
}
}
+void ScummEngine_v7::showMessageDialog(const byte *msg) {
+ if (isUsingOriginalGUI()) {
+ int textColor = _string[3].color;
+ if (textColor)
+ setBannerColors(
+ 26,
+ _currentPalette[3 * textColor],
+ _currentPalette[3 * textColor + 1],
+ _currentPalette[3 * textColor + 2]);
+ Common::KeyState ks = showBannerAndPause(2, -1, (const char *)msg);
+
+ if (VAR_KEYPRESS != 0xFF)
+ VAR(VAR_KEYPRESS) = ks.ascii;
+ } else {
+ ScummEngine::showMessageDialog(msg);
+ }
+}
+
#pragma mark -
#pragma mark --- V7 subtitle queue code ---
#pragma mark -
Commit: 811548dc054cb164a87f01b33fceab19fdf16e99
https://github.com/scummvm/scummvm/commit/811548dc054cb164a87f01b33fceab19fdf16e99
Author: AndywinXp (andywinxp at gmail.com)
Date: 2022-08-06T13:33:56+02:00
Commit Message:
SCUMM: COMI: Use _screenTop when marking rects as dirty
Changed paths:
engines/scumm/gfx.cpp
engines/scumm/scumm.cpp
diff --git a/engines/scumm/gfx.cpp b/engines/scumm/gfx.cpp
index 8b7ea050f58..210773c75b8 100644
--- a/engines/scumm/gfx.cpp
+++ b/engines/scumm/gfx.cpp
@@ -1431,9 +1431,9 @@ void ScummEngine::drawBox(int x, int y, int x2, int y2, int color) {
if (x < 0)
effX = 0;
}
- backbuff = vs->getPixels(effX, y);
+ backbuff = vs->getPixels(effX, y + _screenTop);
fill(backbuff, vs->pitch, color, effX2, y2, vs->format.bytesPerPixel);
- markRectAsDirty(vs->number, effX, effX + effX2, y, y + y2);
+ markRectAsDirty(vs->number, effX, effX + effX2, y + _screenTop, y + y2 + _screenTop);
return;
}
@@ -1651,8 +1651,8 @@ void ScummEngine::drawLine(int x1, int y1, int x2, int y2, int color) {
void ScummEngine::drawPixel(VirtScreen *vs, int x, int y, int16 color) {
if (x >= 0 && y >= 0 && _screenWidth + 8 > x && _screenHeight > y) {
- memset(vs->getPixels(x, y), color, 1);
- markRectAsDirty(vs->number, x, x + 1, y, y + 1);
+ memset(vs->getPixels(x, y + _screenTop), color, 1);
+ markRectAsDirty(vs->number, x, x + 1, y + _screenTop, y + 1 + _screenTop);
}
}
diff --git a/engines/scumm/scumm.cpp b/engines/scumm/scumm.cpp
index 58e00814f5d..5321a720a83 100644
--- a/engines/scumm/scumm.cpp
+++ b/engines/scumm/scumm.cpp
@@ -3223,7 +3223,7 @@ Common::KeyState ScummEngine_v7::showBannerAndPause(int bannerId, int32 waitTime
if (_bannerMem)
memcpy(
_bannerMem,
- &_virtscr[kMainVirtScreen].getPixels(0, 0)[(_screenWidth + 8) * (_screenHeight / 2 - 10)],
+ &_virtscr[kMainVirtScreen].getPixels(0, _screenTop)[(_screenWidth + 8) * (_screenHeight / 2 - 10)],
_bannerMemSize);
}
@@ -3265,7 +3265,7 @@ void ScummEngine_v7::clearBanner() {
// and then mark that part of the screen as dirty.
if (_bannerMem) {
memcpy(
- &_virtscr[kMainVirtScreen].getPixels(0, 0)[(_screenWidth + 8) * (_screenHeight / 2 - 10)],
+ &_virtscr[kMainVirtScreen].getPixels(0, _screenTop)[(_screenWidth + 8) * (_screenHeight / 2 - 10)],
_bannerMem,
_bannerMemSize);
free(_bannerMem);
@@ -3275,7 +3275,7 @@ void ScummEngine_v7::clearBanner() {
return;
}
- markRectAsDirty(_virtscr[kMainVirtScreen].number, 0, _screenWidth + 8, 0, _screenHeight);
+ markRectAsDirty(_virtscr[kMainVirtScreen].number, 0, _screenWidth + 8, _screenTop, _screenHeight + _screenTop);
drawDirtyScreenParts();
}
}
Commit: 759ae2e47e3a6a360ddc10f95d63e9187357f952
https://github.com/scummvm/scummvm/commit/759ae2e47e3a6a360ddc10f95d63e9187357f952
Author: AndywinXp (andywinxp at gmail.com)
Date: 2022-08-06T13:33:56+02:00
Commit Message:
SCUMM: COMI: Set keyScript parameters in case they are missing at loading
Changed paths:
engines/scumm/saveload.cpp
engines/scumm/script_v8.cpp
engines/scumm/scumm_v8.h
diff --git a/engines/scumm/saveload.cpp b/engines/scumm/saveload.cpp
index 274794620f1..6592a7e1d10 100644
--- a/engines/scumm/saveload.cpp
+++ b/engines/scumm/saveload.cpp
@@ -36,6 +36,7 @@
#include "scumm/resource.h"
#include "scumm/scumm_v0.h"
#include "scumm/scumm_v7.h"
+#include "scumm/scumm_v8.h"
#include "scumm/sound.h"
#include "scumm/he/sprite_he.h"
#include "scumm/verbs.h"
@@ -595,6 +596,12 @@ bool ScummEngine::loadState(int slot, bool compat, Common::String &filename) {
if (_game.version >= 7) {
((ScummEngine_v7 *)this)->removeBlastTexts();
}
+
+ if (_game.version == 8 && isUsingOriginalGUI()) {
+ // If we are loading a savegame from the ScummVM launcher these two
+ // variables are going to be unassigned, since the game does not save these
+ ((ScummEngine_v8 *)this)->setKeyScriptVars(0x13B, 0x1C0);
+ }
#endif
// Restore the virtual screens and force a fade to black.
diff --git a/engines/scumm/script_v8.cpp b/engines/scumm/script_v8.cpp
index e52d0ab2cd7..681308dda4d 100644
--- a/engines/scumm/script_v8.cpp
+++ b/engines/scumm/script_v8.cpp
@@ -335,6 +335,11 @@ void ScummEngine_v8::writeVar(uint var, int value) {
error("Illegal varbits (w)");
}
+void ScummEngine_v8::setKeyScriptVars(int keyScriptKey, int keyScriptNo) {
+ _keyScriptKey = keyScriptKey;
+ _keyScriptNo = keyScriptNo;
+}
+
void ScummEngine_v8::decodeParseString(int m, int n) {
byte b = fetchScriptByte();
@@ -1137,8 +1142,7 @@ void ScummEngine_v8::o8_kernelSetFunctions() {
debug(0, "o8_kernelSetFunctions: saveGameStampScreenshot(%d, %d, %d, %d, %d, %d)", args[1], args[2], args[3], args[4], args[5], args[6]);
break;
case 29: // setKeyScript
- _keyScriptKey = args[1];
- _keyScriptNo = args[2];
+ setKeyScriptVars(args[1], args[2]);
break;
case 30: // killAllScriptsButMe
killAllScriptsExceptCurrent();
diff --git a/engines/scumm/scumm_v8.h b/engines/scumm/scumm_v8.h
index 9f68e44a213..8993ba64f32 100644
--- a/engines/scumm/scumm_v8.h
+++ b/engines/scumm/scumm_v8.h
@@ -43,6 +43,8 @@ public:
ScummEngine_v8(OSystem *syst, const DetectorResult &dr);
~ScummEngine_v8() override;
+ void setKeyScriptVars(int _keyScriptKey, int _keyScriptNo);
+
protected:
void setupOpcodes() override;
Commit: c4d0e3b80a8c640dfa0a045b6a47c93a117b9a9a
https://github.com/scummvm/scummvm/commit/c4d0e3b80a8c640dfa0a045b6a47c93a117b9a9a
Author: AndywinXp (andywinxp at gmail.com)
Date: 2022-08-06T13:33:56+02:00
Commit Message:
SCUMM: COMI: Fix mishandling of cursor state in GUI
Changed paths:
engines/scumm/input.cpp
engines/scumm/scumm.cpp
diff --git a/engines/scumm/input.cpp b/engines/scumm/input.cpp
index d9c9ce5e04c..bca0e20cccd 100644
--- a/engines/scumm/input.cpp
+++ b/engines/scumm/input.cpp
@@ -434,13 +434,12 @@ void ScummEngine_v8::processKeyboard(Common::KeyState lastKeyHit) {
int8 oldCursorState = _cursor.state;
_cursor.state = 1;
CursorMan.showMouse(_cursor.state > 0);
+
confirmExitDialog();
- _cursor.state = oldCursorState;
- // If SMUSH is active, manually force the old cursor state...
- if (isSmushActive()) {
- CursorMan.showMouse(_cursor.state > 0);
- }
+ // Restore the old cursor state...
+ _cursor.state = oldCursorState;
+ CursorMan.showMouse(_cursor.state > 0);
return;
}
diff --git a/engines/scumm/scumm.cpp b/engines/scumm/scumm.cpp
index 5321a720a83..da40c4921dc 100644
--- a/engines/scumm/scumm.cpp
+++ b/engines/scumm/scumm.cpp
@@ -3420,7 +3420,7 @@ void ScummEngine_v7::confirmExitDialog() {
char noLabelPtr[512];
char msgLabelPtr[512];
byte *curGrabbedCursor;
- int curCursorWidth, curCursorHeight, curCursorHotspotX, curCursorHotspotY;
+ int curCursorWidth, curCursorHeight, curCursorHotspotX, curCursorHotspotY, curCursorState;
InfoDialog d(this, 0);
@@ -3438,6 +3438,7 @@ void ScummEngine_v7::confirmExitDialog() {
// and set up the internal v8 cursor...
curGrabbedCursor = (byte *)malloc(sizeof(_grabbedCursor));
memcpy(curGrabbedCursor, _grabbedCursor, sizeof(_grabbedCursor));
+ curCursorState = isSmushActive() ? 0 : _cursor.state;
curCursorWidth = _cursor.width;
curCursorHeight = _cursor.height;
curCursorHotspotX = _cursor.hotspotX;
@@ -3542,6 +3543,8 @@ void ScummEngine_v7::confirmExitDialog() {
quitGame();
// Restore the previous cursor...
+ _cursor.state = curCursorState;
+ CursorMan.showMouse(_cursor.state > 0);
setCursorHotspot(curCursorHotspotX, curCursorHotspotY);
setCursorFromBuffer(curGrabbedCursor, curCursorWidth, curCursorHeight, curCursorWidth);
free(curGrabbedCursor);
Commit: 9072aa007f330821b591790b07b37d48c1e214e1
https://github.com/scummvm/scummvm/commit/9072aa007f330821b591790b07b37d48c1e214e1
Author: AndywinXp (andywinxp at gmail.com)
Date: 2022-08-06T13:33:56+02:00
Commit Message:
SCUMM: COMI: Fix default cursor colors during SMUSH videos
Changed paths:
engines/scumm/cursor.cpp
engines/scumm/palette.cpp
engines/scumm/scumm.h
engines/scumm/scumm_v6.h
engines/scumm/scumm_v7.h
engines/scumm/scumm_v8.h
diff --git a/engines/scumm/cursor.cpp b/engines/scumm/cursor.cpp
index e7b541608c6..adcdb9f5bb1 100644
--- a/engines/scumm/cursor.cpp
+++ b/engines/scumm/cursor.cpp
@@ -35,6 +35,8 @@
#include "scumm/scumm.h"
#include "scumm/scumm_v2.h"
#include "scumm/scumm_v5.h"
+#include "scumm/scumm_v8.h"
+#include "scumm/smush/smush_player.h"
namespace Scumm {
@@ -180,16 +182,83 @@ void ScummEngine_v6::grabCursor(int x, int y, int w, int h) {
}
void ScummEngine_v6::setDefaultCursor() {
- if (_game.version == 8) {
- setCursorHotspot(9, 9);
- setCursorFromBuffer(default_v8_cursor, 20, 20, 20);
- setCursorTransparency(0xFE);
- } else {
- setCursorHotspot(7, 6);
- setCursorFromBuffer(default_v6_cursor, 16, 13, 16);
+ setCursorHotspot(7, 6);
+ setCursorFromBuffer(default_v6_cursor, 16, 13, 16);
+}
+
+#ifdef ENABLE_SCUMM_7_8
+void ScummEngine_v7::setDefaultCursor() {
+ byte *palette = isSmushActive() ? _splayer->getVideoPalette() : _currentPalette;
+ byte cursorBuffer[400];
+ byte cursorPixel;
+ int /* black,*/ white, inverseRgbIdx;
+ int rgbIdx = 0;
+
+ /* The interpreter does this, but we don't need it, at least for v8.
+ * See below for details.
+ *
+ * do {
+ * black = getPaletteColorFromRGB(palette, rgbIdx, rgbIdx, rgbIdx);
+ * ++rgbIdx;
+ * } while (black == 1 && rgbIdx != 100);
+ * rgbIdx = 0;
+ */
+ do {
+ inverseRgbIdx = 0xFF - rgbIdx++;
+ white = getPaletteColorFromRGB(palette, inverseRgbIdx, inverseRgbIdx, inverseRgbIdx);
+ } while (white == 1 && rgbIdx != 100);
+
+ for (int i = 0; i < sizeof(default_v8_cursor); ++i) {
+ cursorPixel = default_v8_cursor[i];
+
+ if (isSmushActive() && cursorPixel == 0x0F)
+ cursorPixel = white;
+
+ /* The interpreter also performs this substitution.
+ * we can't since we handle the palette in a different way and we wouldn't
+ * find the same color the interpreter finds.
+ *
+ * if (cursorPixel == 0x00)
+ * cursorPixel = black;
+ */
+
+ cursorBuffer[i] = (byte)(cursorPixel & 0xFF);
}
+ setCursorHotspot(9, 9);
+ setCursorFromBuffer(cursorBuffer, 20, 20, 20);
+ setCursorTransparency(0xFE);
+}
+
+void ScummEngine_v8::setCursorTransparency(int a) {
+ int i, size;
+
+ size = _cursor.width * _cursor.height;
+
+ for (i = 0; i < size; i++)
+ if (_grabbedCursor[i] == (byte)a)
+ _grabbedCursor[i] = isSmushActive() ? 0xFE : 0xFF;
+
+ updateCursor();
+}
+
+void ScummEngine_v8::updateCursor() {
+ int transColor = isSmushActive() ? 0xFE : 0xFF;
+#ifdef USE_RGB_COLOR
+ Graphics::PixelFormat format = _system->getScreenFormat();
+ CursorMan.replaceCursor(_grabbedCursor, _cursor.width, _cursor.height,
+ _cursor.hotspotX, _cursor.hotspotY,
+ transColor,
+ false,
+ &format);
+#else
+ CursorMan.replaceCursor(_grabbedCursor, _cursor.width, _cursor.height,
+ _cursor.hotspotX, _cursor.hotspotY,
+ transColor,
+ false);
+#endif
}
+#endif
void ScummEngine_v6::setCursorFromBuffer(const byte *ptr, int width, int height, int pitch) {
uint size;
diff --git a/engines/scumm/palette.cpp b/engines/scumm/palette.cpp
index 34df8b06e56..cb97e14b9f0 100644
--- a/engines/scumm/palette.cpp
+++ b/engines/scumm/palette.cpp
@@ -1499,7 +1499,7 @@ const byte *ScummEngine::getPalettePtr(int palindex, int room) {
}
uint32 ScummEngine::getPaletteColorFromRGB(byte *palette, byte r, byte g, byte b) {
- uint32 color, black, white;
+ uint32 color, black = 0x00, white = 0xFF;
if ((r == 0xFF && b == 0xFF && g == 0xFF) || (r == 0x00 && g == 0x00 && b == 0x00)) {
fetchBlackAndWhite(black, white, palette, 256);
diff --git a/engines/scumm/scumm.h b/engines/scumm/scumm.h
index a9d7ef1cc71..c0c9b0537b2 100644
--- a/engines/scumm/scumm.h
+++ b/engines/scumm/scumm.h
@@ -474,10 +474,11 @@ protected:
virtual void clearClickedStatus();
// Cursor/palette
- void updateCursor();
+ virtual void updateCursor();
virtual void animateCursor() {}
virtual void updatePalette();
-
+ virtual void setDefaultCursor() {};
+ virtual void setCursorTransparency(int a) {};
virtual void resetCursors() {}
public:
diff --git a/engines/scumm/scumm_v6.h b/engines/scumm/scumm_v6.h
index f4dd5b811a0..fcb1c6f764c 100644
--- a/engines/scumm/scumm_v6.h
+++ b/engines/scumm/scumm_v6.h
@@ -136,8 +136,8 @@ protected:
virtual void writeArray(int array, int index, int base, int value);
void shuffleArray(int num, int minIdx, int maxIdx);
- virtual void setDefaultCursor();
- void setCursorTransparency(int a);
+ void setDefaultCursor() override;
+ void setCursorTransparency(int a) override;
void setCursorHotspot(int x, int y);
virtual void setCursorFromImg(uint img, uint room, uint imgindex);
diff --git a/engines/scumm/scumm_v7.h b/engines/scumm/scumm_v7.h
index b899634fbda..bb0010c3c79 100644
--- a/engines/scumm/scumm_v7.h
+++ b/engines/scumm/scumm_v7.h
@@ -176,6 +176,8 @@ protected:
int getInternalGUIControlFromCoordinates(int x, int y);
void confirmExitDialog() override;
+ void setDefaultCursor() override;
+
void drawVerb(int verb, int mode) override;
void pauseEngineIntern(bool pause) override;
diff --git a/engines/scumm/scumm_v8.h b/engines/scumm/scumm_v8.h
index 8993ba64f32..b94f1e65483 100644
--- a/engines/scumm/scumm_v8.h
+++ b/engines/scumm/scumm_v8.h
@@ -69,7 +69,8 @@ protected:
int getObjectIdFromOBIM(const byte *obim) override;
void processKeyboard(Common::KeyState lastKeyHit) override;
-
+ void updateCursor() override;
+ void setCursorTransparency(int a) override;
void desaturatePalette(int hueScale, int satScale, int lightScale, int startColor, int endColor);
Commit: 6760cc135366cd41170e5031e50f988eb06aeabc
https://github.com/scummvm/scummvm/commit/6760cc135366cd41170e5031e50f988eb06aeabc
Author: AndywinXp (andywinxp at gmail.com)
Date: 2022-08-06T13:33:56+02:00
Commit Message:
SCUMM: COMI: Implement banners for voiceMode toggle
Changed paths:
engines/scumm/input.cpp
diff --git a/engines/scumm/input.cpp b/engines/scumm/input.cpp
index bca0e20cccd..f3cdc7ad8dc 100644
--- a/engines/scumm/input.cpp
+++ b/engines/scumm/input.cpp
@@ -443,6 +443,32 @@ void ScummEngine_v8::processKeyboard(Common::KeyState lastKeyHit) {
return;
}
+ if (isUsingOriginalGUI() &&
+ (lastKeyHit.keycode == Common::KEYCODE_t && lastKeyHit.hasFlags(Common::KBD_CTRL))) {
+ int voiceMode = VAR(VAR_VOICE_MODE);
+
+ voiceMode++;
+ if (voiceMode >= 3) {
+ voiceMode = 0;
+ }
+
+ switch (voiceMode) {
+ case 0: // "Voice Only"
+ showBannerAndPause(0, 120, d.getPlainEngineString(28));
+ break;
+ case 1: // "Voice and Text"
+ showBannerAndPause(0, 120, d.getPlainEngineString(26));
+ break;
+ default: // "Text Display Only"
+ showBannerAndPause(0, 120, d.getPlainEngineString(27));
+ }
+
+ ConfMan.setInt("original_gui_text_status", voiceMode);
+ ConfMan.flushToDisk();
+ syncSoundSettings();
+ return;
+ }
+
// Fall back to V7 behavior...
ScummEngine_v7::processKeyboard(lastKeyHit);
}
@@ -498,7 +524,7 @@ void ScummEngine_v7::waitForBannerInput(int32 waitTime, Common::KeyState &ks, bo
ks = _keyPressed;
leftBtnClicked = (_leftBtnPressed & msClicked) != 0;
rightBtnClicked = (_rightBtnPressed & msClicked) != 0;
- if (&ks || leftBtnClicked || rightBtnClicked)
+ if (ks.keycode != Common::KEYCODE_INVALID || leftBtnClicked || rightBtnClicked)
return;
if (shouldQuit())
Commit: 51d0b8ef063ceb544684a0d76f4ee8a6ead3383d
https://github.com/scummvm/scummvm/commit/51d0b8ef063ceb544684a0d76f4ee8a6ead3383d
Author: AndywinXp (andywinxp at gmail.com)
Date: 2022-08-06T13:33:56+02:00
Commit Message:
SCUMM: COMI: Implement iMUSE buffer toggle GUI banner
Changed paths:
engines/scumm/imuse_digi/dimuse_engine.cpp
engines/scumm/imuse_digi/dimuse_engine.h
engines/scumm/input.cpp
engines/scumm/scumm.cpp
engines/scumm/scumm_v7.h
diff --git a/engines/scumm/imuse_digi/dimuse_engine.cpp b/engines/scumm/imuse_digi/dimuse_engine.cpp
index 533b9673dc6..36188c0540f 100644
--- a/engines/scumm/imuse_digi/dimuse_engine.cpp
+++ b/engines/scumm/imuse_digi/dimuse_engine.cpp
@@ -121,6 +121,8 @@ IMuseDigital::IMuseDigital(ScummEngine_v7 *scumm, Audio::Mixer *mixer)
_maxQueuedStreams = 4;
}
+ _nominalBufferCount = _maxQueuedStreams;
+
_vm->getTimerManager()->installTimerProc(timer_handler, 1000000 / _callbackFps, this, "IMuseDigital");
}
@@ -148,6 +150,18 @@ IMuseDigital::~IMuseDigital() {
free(_audioNames);
}
+int IMuseDigital::roundRobinSetBufferCount() {
+ int minStreams = _nominalBufferCount - 2;
+ int maxStreams = _nominalBufferCount + 2;
+ _maxQueuedStreams++;
+
+ if (_maxQueuedStreams > maxStreams) {
+ _maxQueuedStreams = minStreams;
+ }
+
+ return _maxQueuedStreams;
+}
+
void IMuseDigital::stopSound(int sound) {
diMUSEStopSound(sound);
}
diff --git a/engines/scumm/imuse_digi/dimuse_engine.h b/engines/scumm/imuse_digi/dimuse_engine.h
index 36247ce7717..fa9e5069b10 100644
--- a/engines/scumm/imuse_digi/dimuse_engine.h
+++ b/engines/scumm/imuse_digi/dimuse_engine.h
@@ -91,6 +91,7 @@ private:
int _outputSampleRate;
int _maxQueuedStreams; // maximum number of streams which can be queued before they are played
+ int _nominalBufferCount;
int _currentSpeechVolume, _currentSpeechFrequency, _currentSpeechPan;
int _curMixerMusicVolume, _curMixerSpeechVolume, _curMixerSFXVolume;
@@ -395,6 +396,7 @@ public:
int clampNumber(int value, int minValue, int maxValue);
int clampTuning(int value, int minValue, int maxValue);
int checkHookId(int &trackHookId, int sampleHookId);
+ int roundRobinSetBufferCount();
// CMDs
int cmdsHandleCmd(int cmd, uint8 *ptr = nullptr,
diff --git a/engines/scumm/input.cpp b/engines/scumm/input.cpp
index f3cdc7ad8dc..a39aadd173c 100644
--- a/engines/scumm/input.cpp
+++ b/engines/scumm/input.cpp
@@ -29,6 +29,7 @@
#include "scumm/dialogs.h"
#include "scumm/insane/insane.h"
#include "scumm/imuse/imuse.h"
+#include "scumm/imuse_digi/dimuse_engine.h"
#ifdef ENABLE_HE
#include "scumm/he/intern_he.h"
#include "scumm/he/logic_he.h"
@@ -414,6 +415,7 @@ void ScummEngine_v8::processKeyboard(Common::KeyState lastKeyHit) {
int8 oldCursorState = _cursor.state;
_cursor.state = 0;
CursorMan.showMouse(_cursor.state > 0);
+ // "Game Paused. Press SPACE to Continue."
showBannerAndPause(0, -1, d.getPlainEngineString(4));
_cursor.state = oldCursorState;
return;
@@ -469,6 +471,14 @@ void ScummEngine_v8::processKeyboard(Common::KeyState lastKeyHit) {
return;
}
+ if (isUsingOriginalGUI() &&
+ (lastKeyHit.keycode == Common::KEYCODE_b && lastKeyHit.hasFlags(Common::KBD_CTRL))) {
+ int curBufferCount = _imuseDigital->roundRobinSetBufferCount();
+ // iMuse buffer count changed to %d
+ showBannerAndPause(0, 90, d.getPlainEngineString(25), curBufferCount);
+ return;
+ }
+
// Fall back to V7 behavior...
ScummEngine_v7::processKeyboard(lastKeyHit);
}
diff --git a/engines/scumm/scumm.cpp b/engines/scumm/scumm.cpp
index da40c4921dc..795377b9ca0 100644
--- a/engines/scumm/scumm.cpp
+++ b/engines/scumm/scumm.cpp
@@ -3167,8 +3167,9 @@ void ScummEngine_v7::initBanners() {
setBannerColors(31, 0x54, 0x54, 0x54);
}
-Common::KeyState ScummEngine_v7::showBannerAndPause(int bannerId, int32 waitTime, const char *msg) {
+Common::KeyState ScummEngine_v7::showBannerAndPause(int bannerId, int32 waitTime, const char *msg, ...) {
char bannerMsg[512];
+ char localizedMsg[512];
char localizedY[512];
char *ptrToBreak;
int bannerMsgWidth, bannerMsgHeight, roundedWidth;
@@ -3179,13 +3180,19 @@ Common::KeyState ScummEngine_v7::showBannerAndPause(int bannerId, int32 waitTime
InfoDialog d(this, 0);
// Fetch the translated string for the message...
- convertMessageToString((const byte *)msg, (byte *)bannerMsg, sizeof(bannerMsg));
- ptrToBreak = strstr(bannerMsg, "\\n");
+ convertMessageToString((const byte *)msg, (byte *)localizedMsg, sizeof(localizedMsg));
+ ptrToBreak = strstr(localizedMsg, "\\n");
if (ptrToBreak) { // Change the line break, if any...
ptrToBreak[0] = '\n';
ptrToBreak[1] = '\r';
}
+ // Format the string with the arguments...
+ va_list va;
+ va_start(va, msg);
+ vsnprintf(bannerMsg, sizeof(bannerMsg), localizedMsg, va);
+ va_end(va);
+
// Pause the engine
PauseToken pt = pauseEngine();
diff --git a/engines/scumm/scumm_v7.h b/engines/scumm/scumm_v7.h
index bb0010c3c79..56f30066864 100644
--- a/engines/scumm/scumm_v7.h
+++ b/engines/scumm/scumm_v7.h
@@ -163,7 +163,7 @@ protected:
void playSpeech(const byte *ptr);
void initBanners();
- Common::KeyState showBannerAndPause(int bannerId, int32 waitTime, const char *msg);
+ Common::KeyState showBannerAndPause(int bannerId, int32 waitTime, const char *msg, ...);
void waitForBannerInput(int32 waitTime, Common::KeyState &ks, bool &leftBtnClicked, bool &rightBtnClicked);
void clearBanner();
void setBannerColors(int bannerId, byte r, byte g, byte b);
Commit: 61535ee8c98c5f3b8564568c414a603af0dd27e3
https://github.com/scummvm/scummvm/commit/61535ee8c98c5f3b8564568c414a603af0dd27e3
Author: AndywinXp (andywinxp at gmail.com)
Date: 2022-08-06T13:33:56+02:00
Commit Message:
SCUMM: DiMUSE: Increment upper and lower limit for roundRobinSetBufferCount()
Changed paths:
engines/scumm/imuse_digi/dimuse_engine.cpp
diff --git a/engines/scumm/imuse_digi/dimuse_engine.cpp b/engines/scumm/imuse_digi/dimuse_engine.cpp
index 36188c0540f..79beb31c1c4 100644
--- a/engines/scumm/imuse_digi/dimuse_engine.cpp
+++ b/engines/scumm/imuse_digi/dimuse_engine.cpp
@@ -151,8 +151,8 @@ IMuseDigital::~IMuseDigital() {
}
int IMuseDigital::roundRobinSetBufferCount() {
- int minStreams = _nominalBufferCount - 2;
- int maxStreams = _nominalBufferCount + 2;
+ int minStreams = _nominalBufferCount - 3;
+ int maxStreams = _nominalBufferCount + 3;
_maxQueuedStreams++;
if (_maxQueuedStreams > maxStreams) {
Commit: e43d40e344bd517e9d53b5ed87f2af840834439d
https://github.com/scummvm/scummvm/commit/e43d40e344bd517e9d53b5ed87f2af840834439d
Author: AndywinXp (andywinxp at gmail.com)
Date: 2022-08-06T13:33:56+02:00
Commit Message:
SCUMM: Add original GUI support for COMI Demo
Where "support" means "it shows most of the original banners and it doesn't crash" :-)
Changed paths:
engines/scumm/detection_tables.h
engines/scumm/input.cpp
engines/scumm/scumm.cpp
diff --git a/engines/scumm/detection_tables.h b/engines/scumm/detection_tables.h
index 2e4ba1acb16..46d61af7435 100644
--- a/engines/scumm/detection_tables.h
+++ b/engines/scumm/detection_tables.h
@@ -222,7 +222,7 @@ static const GameSettings gameVariantsTable[] = {
{"dig", "Steam", "steam", GID_DIG, 7, 0, MDT_NONE, 0, UNK, GUIO1(GUIO_NOMIDI)},
{"comi", "", 0, GID_CMI, 8, 0, MDT_NONE, 0, Common::kPlatformWindows, GUIO3(GUIO_NOMIDI, GUIO_NOASPECT, GUIO_ORIGINALGUI)},
- {"comi", "Demo", 0, GID_CMI, 8, 0, MDT_NONE, GF_DEMO, Common::kPlatformWindows, GUIO2(GUIO_NOMIDI, GUIO_NOASPECT)},
+ {"comi", "Demo", 0, GID_CMI, 8, 0, MDT_NONE, GF_DEMO, Common::kPlatformWindows, GUIO3(GUIO_NOMIDI, GUIO_NOASPECT, GUIO_ORIGINALGUI)},
// Humongous Entertainment Scumm Version 6
{"activity", "", 0, GID_HEGAME, 6, 62, MDT_ADLIB | MDT_MIDI, GF_USE_KEY, UNK, GUIO2(GUIO_NOLAUNCHLOAD, GUIO_AUDIO_OVERRIDE)},
diff --git a/engines/scumm/input.cpp b/engines/scumm/input.cpp
index a39aadd173c..feac1e3c3a0 100644
--- a/engines/scumm/input.cpp
+++ b/engines/scumm/input.cpp
@@ -390,19 +390,19 @@ void ScummEngine_v8::processKeyboard(Common::KeyState lastKeyHit) {
}
// If we are using the original GUI, remap F5 to F1.
- if (isUsingOriginalGUI() && !(_game.features & GF_DEMO) && lastKeyHit.keycode == Common::KEYCODE_F5 && lastKeyHit.hasFlags(0)) {
+ if (isUsingOriginalGUI() && lastKeyHit.keycode == Common::KEYCODE_F5 && lastKeyHit.hasFlags(0)) {
lastKeyHit = Common::KeyState(Common::KEYCODE_F1, 315);
}
// Alt-F5 should bring up the original save/load dialog, so map it to F1,
// again, unless we chose to use the original GUI.
- if (!isUsingOriginalGUI() && !(_game.features & GF_DEMO) && lastKeyHit.keycode == Common::KEYCODE_F5 && lastKeyHit.hasFlags(Common::KBD_ALT)) {
+ if (!isUsingOriginalGUI() && lastKeyHit.keycode == Common::KEYCODE_F5 && lastKeyHit.hasFlags(Common::KBD_ALT)) {
lastKeyHit = Common::KeyState(Common::KEYCODE_F1, 315);
}
// If a key script was specified (a V8 feature), and it's trigger
// key was pressed, run it. Usually used to display the built-in menu.
- if (!isSmushActive() && _keyScriptNo && (_keyScriptKey == lastKeyHit.ascii)) {
+ if (!(_game.features & GF_DEMO) && !isSmushActive() && _keyScriptNo && (_keyScriptKey == lastKeyHit.ascii)) {
runScript(_keyScriptNo, 0, 0, 0);
return;
}
@@ -432,16 +432,24 @@ void ScummEngine_v8::processKeyboard(Common::KeyState lastKeyHit) {
if (isUsingOriginalGUI() &&
(lastKeyHit.keycode == Common::KEYCODE_c && lastKeyHit.hasFlags(Common::KBD_CTRL))) {
- // Force the cursor to be ON...
- int8 oldCursorState = _cursor.state;
- _cursor.state = 1;
- CursorMan.showMouse(_cursor.state > 0);
+ if (_game.features & GF_DEMO) {
+ Common::KeyState ks = showBannerAndPause(0, -1, d.getPlainEngineString(6));
+ if (ks.keycode == Common::KEYCODE_y) {
+ quitGame();
+ }
+ } else {
+ // Force the cursor to be ON...
+ int8 oldCursorState = _cursor.state;
+ _cursor.state = 1;
+ CursorMan.showMouse(_cursor.state > 0);
- confirmExitDialog();
+ confirmExitDialog();
+
+ // Restore the old cursor state...
+ _cursor.state = oldCursorState;
+ CursorMan.showMouse(_cursor.state > 0);
+ }
- // Restore the old cursor state...
- _cursor.state = oldCursorState;
- CursorMan.showMouse(_cursor.state > 0);
return;
}
diff --git a/engines/scumm/scumm.cpp b/engines/scumm/scumm.cpp
index 795377b9ca0..4faabb8dc14 100644
--- a/engines/scumm/scumm.cpp
+++ b/engines/scumm/scumm.cpp
@@ -3182,7 +3182,7 @@ Common::KeyState ScummEngine_v7::showBannerAndPause(int bannerId, int32 waitTime
// Fetch the translated string for the message...
convertMessageToString((const byte *)msg, (byte *)localizedMsg, sizeof(localizedMsg));
ptrToBreak = strstr(localizedMsg, "\\n");
- if (ptrToBreak) { // Change the line break, if any...
+ if (!(_game.features & GF_DEMO) && ptrToBreak) { // Change the line break, if any...
ptrToBreak[0] = '\n';
ptrToBreak[1] = '\r';
}
Commit: 52bb4dd739991fc7a50c1e70ee869f6c3490a3f5
https://github.com/scummvm/scummvm/commit/52bb4dd739991fc7a50c1e70ee869f6c3490a3f5
Author: AndywinXp (andywinxp at gmail.com)
Date: 2022-08-06T13:33:56+02:00
Commit Message:
SCUMM: Fix comment and private member names
Changed paths:
engines/scumm/input.cpp
engines/scumm/scumm.cpp
engines/scumm/scumm_v7.h
diff --git a/engines/scumm/input.cpp b/engines/scumm/input.cpp
index feac1e3c3a0..04b1f443571 100644
--- a/engines/scumm/input.cpp
+++ b/engines/scumm/input.cpp
@@ -482,7 +482,7 @@ void ScummEngine_v8::processKeyboard(Common::KeyState lastKeyHit) {
if (isUsingOriginalGUI() &&
(lastKeyHit.keycode == Common::KEYCODE_b && lastKeyHit.hasFlags(Common::KBD_CTRL))) {
int curBufferCount = _imuseDigital->roundRobinSetBufferCount();
- // iMuse buffer count changed to %d
+ // "iMuse buffer count changed to %d"
showBannerAndPause(0, 90, d.getPlainEngineString(25), curBufferCount);
return;
}
diff --git a/engines/scumm/scumm.cpp b/engines/scumm/scumm.cpp
index 4faabb8dc14..eec12f7689c 100644
--- a/engines/scumm/scumm.cpp
+++ b/engines/scumm/scumm.cpp
@@ -3293,15 +3293,15 @@ void ScummEngine_v7::setBannerColors(int bannerId, byte r, byte g, byte b) {
return;
}
- bannerColors[bannerId] = r | (b << 16) | (g << 8);
+ _bannerColors[bannerId] = r | (b << 16) | (g << 8);
}
int ScummEngine_v7::getBannerColor(int bannerId) {
byte r, g, b;
byte *palette = isSmushActive() ? _splayer->getVideoPalette() : _currentPalette;
- r = (bannerColors[bannerId] >> 0) & 0xFF;
- g = (bannerColors[bannerId] >> 8) & 0xFF;
- b = (bannerColors[bannerId] >> 16) & 0xFF;
+ r = (_bannerColors[bannerId] >> 0) & 0xFF;
+ g = (_bannerColors[bannerId] >> 8) & 0xFF;
+ b = (_bannerColors[bannerId] >> 16) & 0xFF;
return getPaletteColorFromRGB(palette, r, g, b);
}
diff --git a/engines/scumm/scumm_v7.h b/engines/scumm/scumm_v7.h
index 56f30066864..86bc8cdbbab 100644
--- a/engines/scumm/scumm_v7.h
+++ b/engines/scumm/scumm_v7.h
@@ -110,7 +110,7 @@ protected:
int _subtitleQueuePos;
SubtitleText _subtitleQueue[20];
- int32 bannerColors[50]; // Colors for the original GUI
+ int32 _bannerColors[50]; // Colors for the original GUI
byte *_bannerMem = nullptr;
uint32 _bannerMemSize = 0;
InternalGUIControl _internalGUIControls[30];
Commit: fb2fcbf30ee24af98d892af93630c302545e25ba
https://github.com/scummvm/scummvm/commit/fb2fcbf30ee24af98d892af93630c302545e25ba
Author: AndywinXp (andywinxp at gmail.com)
Date: 2022-08-06T13:33:56+02:00
Commit Message:
SCUMM: COMI: Implement savegame thumbnails
Changed paths:
engines/scumm/gfx.cpp
engines/scumm/palette.cpp
engines/scumm/saveload.cpp
engines/scumm/script_v8.cpp
engines/scumm/scumm.cpp
engines/scumm/scumm.h
engines/scumm/scumm_v8.h
diff --git a/engines/scumm/gfx.cpp b/engines/scumm/gfx.cpp
index 210773c75b8..a4705aec6d2 100644
--- a/engines/scumm/gfx.cpp
+++ b/engines/scumm/gfx.cpp
@@ -1649,9 +1649,13 @@ void ScummEngine::drawLine(int x1, int y1, int x2, int y2, int color) {
}
}
-void ScummEngine::drawPixel(VirtScreen *vs, int x, int y, int16 color) {
+void ScummEngine::drawPixel(VirtScreen *vs, int x, int y, int16 color, bool useBackbuffer) {
if (x >= 0 && y >= 0 && _screenWidth + 8 > x && _screenHeight > y) {
- memset(vs->getPixels(x, y + _screenTop), color, 1);
+ if (useBackbuffer)
+ memset(vs->getBackPixels(x, y + _screenTop), color, 1);
+ else
+ memset(vs->getPixels(x, y + _screenTop), color, 1);
+
markRectAsDirty(vs->number, x, x + 1, y + _screenTop, y + 1 + _screenTop);
}
}
diff --git a/engines/scumm/palette.cpp b/engines/scumm/palette.cpp
index cb97e14b9f0..6f1069f0193 100644
--- a/engines/scumm/palette.cpp
+++ b/engines/scumm/palette.cpp
@@ -1517,6 +1517,10 @@ uint32 ScummEngine::getPaletteColorFromRGB(byte *palette, byte r, byte g, byte b
return color;
}
+uint32 ScummEngine::getPackedRGBColorFromPalette(byte *palette, uint32 color) {
+ return palette[3 * color] | (palette[3 * color + 1] << 8) | (palette[3 * color + 2] << 16);
+}
+
void ScummEngine::fetchBlackAndWhite(uint32 &black, uint32 &white, byte *palette, int paletteEntries) {
int max = 0;
int r, g, b;
diff --git a/engines/scumm/saveload.cpp b/engines/scumm/saveload.cpp
index 6592a7e1d10..02712c5f4e0 100644
--- a/engines/scumm/saveload.cpp
+++ b/engines/scumm/saveload.cpp
@@ -201,9 +201,155 @@ void ScummEngine::copyHeapSaveGameToFile(int slot, const char *saveName) {
debug(1, "State save as '%s' FAILED", fileName.c_str());
else
debug(1, "State saved as '%s'", fileName.c_str());
+}
+
+#ifdef ENABLE_SCUMM_7_8
+void ScummEngine_v8::stampShotEnqueue(int slot, int boxX, int boxY, int boxWidth, int boxHeight, int brightness) {
+ if (_stampShotsInQueue >= sizeof(_stampShots))
+ error("ScummEngine_v8::stampShotEnqueue(): overflow in the queue");
+
+ _stampShots[_stampShotsInQueue].slot = slot;
+ _stampShots[_stampShotsInQueue].boxX = boxX;
+ _stampShots[_stampShotsInQueue].boxY = boxY;
+ _stampShots[_stampShotsInQueue].boxWidth = boxWidth;
+ _stampShots[_stampShotsInQueue].boxHeight = boxHeight;
+ _stampShots[_stampShotsInQueue].brightness = brightness;
+ _stampShotsInQueue++;
+}
+
+void ScummEngine_v8::stampShotDequeue() {
+ for (int i = 0; i < _stampShotsInQueue; i++) {
+ stampScreenShot(
+ _stampShots[i].slot,
+ _stampShots[i].boxX,
+ _stampShots[i].boxY,
+ _stampShots[i].boxWidth,
+ _stampShots[i].boxHeight,
+ _stampShots[i].brightness);
+ }
+
+ _stampShotsInQueue = 0;
+}
+
+void ScummEngine_v8::stampScreenShot(int slot, int boxX, int boxY, int boxWidth, int boxHeight, int brightness) {
+ int pixelX, pixelY;
+ int color, pixelColor, rgb;
+ int heightSlice, widthSlice;
+
+ bool success = false;
+ byte tmpPalette[256];
+
+ VirtScreen *vs = &_virtscr[kMainVirtScreen];
+
+ success = fetchInternalSaveStateThumbnail(slot == 0 ? 1 : slot, slot == 0);
+
+ if (success) {
+ for (int i = 0; i < 256; i++) {
+ rgb = _savegameThumbnailPalette[i];
+ tmpPalette[i] = remapPaletteColor(
+ brightness * ((rgb & 0xFF) >> 0) / 0xFF,
+ brightness * ((rgb & 0xFF00) >> 8) / 0xFF,
+ brightness * ((rgb & 0xFF0000) >> 16) / 0xFF,
+ -1);
+ }
+
+ heightSlice = 0;
+ for (int i = 0; i < boxHeight; i++) {
+ pixelY = boxY + i;
+ widthSlice = 0;
+ for (int j = 0; j < boxWidth; j++) {
+ color = _savegameThumbnail[160 * (heightSlice / boxHeight) + (widthSlice / boxWidth)];
+ pixelX = j + boxX;
+ pixelColor = tmpPalette[color + 0];
+ drawPixel(vs, pixelX, pixelY, pixelColor, false); // In the frontbuffer
+ drawPixel(vs, pixelX, pixelY, pixelColor, true); // In the backbuffer
+ widthSlice += 160;
+ }
+ heightSlice += 120;
+ }
+
+ }
+}
+
+void ScummEngine_v8::createInternalSaveStateThumbnail() {
+ byte *tempBitmap = (byte *)malloc(_screenWidth * _screenHeight * sizeof(byte));
+ VirtScreen *vs = &_virtscr[kMainVirtScreen];
+
+
+ byte *screen = vs->getPixels(0, _screenTop);
+
+ if (tempBitmap) {
+ for (int i = 0; i < _screenHeight; i++) {
+ screen = vs->getPixels(0, _screenTop + i);
+ memcpy(&tempBitmap[_screenWidth * i], screen, _screenWidth * sizeof(byte));
+ }
+
+ for (int i = 0; i < 256; i++) {
+ _savegameThumbnailPalette[i] = getPackedRGBColorFromPalette(_currentPalette, i);
+ }
+
+ for (int i = 0; i < 120; i++) {
+ for (int j = 0; j < 160; j++) {
+ _savegameThumbnail[i * 160 + j] = tempBitmap[4 * (i * _screenWidth + j)];
+ }
+ }
+
+ free(tempBitmap);
+ }
+}
+
+bool ScummEngine_v8::fetchInternalSaveStateThumbnail(int slotId, bool isHeapSave) {
+ SaveGameHeader hdr;
+ int sb, sh;
+ Common::String filename;
+ Common::SeekableReadStream *in = openSaveFileForReading(slotId, isHeapSave, filename);
+ if (!in)
+ return false;
+
+ // In order to fetch the internal COMI thumbnail, we perform the same routine
+ // used during normal loading, stripped down to support only version 106 onwards...
+ hdr.type = in->readUint32BE();
+ hdr.size = in->readUint32LE();
+ hdr.ver = in->readUint32LE();
+ in->read(hdr.name, sizeof(hdr.name));
+
+ if (in->err() || hdr.type != MKTAG('S', 'C', 'V', 'M')) {
+ warning("Invalid savegame header for savegame '%s'", filename.c_str());
+ delete in;
+ return false;
+ }
+
+ if (hdr.ver > 0xFFFFFF)
+ hdr.ver = SWAP_BYTES_32(hdr.ver);
+
+ // Reject save games which do not contain the internal thumbnail...
+ if (hdr.ver < VER(106)) {
+ return false;
+ }
+ Graphics::skipThumbnail(*in);
+ SaveStateMetaInfos infos;
+ if (!loadInfos(in, &infos)) {
+ warning("Info section could not be found");
+ delete in;
+ return false;
+ }
+
+ hdr.name[sizeof(hdr.name) - 1] = 0;
+ _saveLoadDescription = hdr.name;
+
+
+ // Now do the actual loading
+ Common::Serializer ser(in, nullptr);
+ ser.setVersion(hdr.ver);
+ ser.syncArray(_savegameThumbnail, 19200, Common::Serializer::Byte, VER(106));
+ ser.syncArray(_savegameThumbnailPalette, 256, Common::Serializer::Uint32LE, VER(106));
+
+ delete in;
+ return true;
}
+#endif
Common::SeekableReadStream *ScummEngine::openSaveFileForReading(int slot, bool compat, Common::String &fileName) {
fileName = makeSavegameName(slot, compat);
@@ -1694,6 +1840,17 @@ void syncWithSerializer(Common::Serializer &s, ScummEngine_v7::SubtitleText &st)
s.syncAsByte(st.actorSpeechMsg, VER(61));
}
+void ScummEngine_v8::saveLoadWithSerializer(Common::Serializer &s) {
+ // Save/load the savegame thumbnail for COMI
+ s.syncArray(_savegameThumbnail, 19200, Common::Serializer::Byte, VER(106));
+ s.syncArray(_savegameThumbnailPalette, 256, Common::Serializer::Uint32LE, VER(106));
+
+ // Also save the banner colors for the GUI
+ s.syncArray(_bannerColors, 50, Common::Serializer::Uint32LE, VER(106));
+
+ ScummEngine_v7::saveLoadWithSerializer(s);
+}
+
void ScummEngine_v7::saveLoadWithSerializer(Common::Serializer &s) {
ScummEngine::saveLoadWithSerializer(s);
diff --git a/engines/scumm/script_v8.cpp b/engines/scumm/script_v8.cpp
index 681308dda4d..7742afcda10 100644
--- a/engines/scumm/script_v8.cpp
+++ b/engines/scumm/script_v8.cpp
@@ -1138,8 +1138,9 @@ void ScummEngine_v8::o8_kernelSetFunctions() {
_saveLoadFlag = 2;
_saveTemporaryState = false;
break;
- case 28: // saveGameStampScreenshot
- debug(0, "o8_kernelSetFunctions: saveGameStampScreenshot(%d, %d, %d, %d, %d, %d)", args[1], args[2], args[3], args[4], args[5], args[6]);
+ case 28: // stampShotEnqueue
+ debug(0, "o8_kernelSetFunctions: stampShotEnqueue(%d, %d, %d, %d, %d, %d)", args[1], args[2], args[3], args[4], args[5], args[6]);
+ stampShotEnqueue(args[1], args[2], args[3], args[4], args[5], args[6]);
break;
case 29: // setKeyScript
setKeyScriptVars(args[1], args[2]);
diff --git a/engines/scumm/scumm.cpp b/engines/scumm/scumm.cpp
index eec12f7689c..d041f038c83 100644
--- a/engines/scumm/scumm.cpp
+++ b/engines/scumm/scumm.cpp
@@ -2439,6 +2439,13 @@ load_game:
towns_processPalCycleField();
#endif
+#ifdef ENABLE_SCUMM_7_8
+ // Dequeue the stamp shots for the main menu of COMI
+ if (_game.version == 8) {
+ ((ScummEngine_v8 *)this)->stampShotDequeue();
+ }
+#endif
+
if (_currentRoom == 0) {
if (_game.version > 3)
CHARSET_1();
@@ -2787,6 +2794,10 @@ void ScummEngine_v6::scummLoop_handleSaveLoad() {
#ifdef ENABLE_SCUMM_7_8
void ScummEngine_v8::scummLoop_handleSaveLoad() {
+ if (_saveLoadFlag == 1) {
+ createInternalSaveStateThumbnail();
+ }
+
ScummEngine::scummLoop_handleSaveLoad();
removeBlastObjects();
diff --git a/engines/scumm/scumm.h b/engines/scumm/scumm.h
index c0c9b0537b2..b1815c928bd 100644
--- a/engines/scumm/scumm.h
+++ b/engines/scumm/scumm.h
@@ -1012,7 +1012,7 @@ protected:
void drawRoomObject(int i, int arg);
void drawBox(int x, int y, int x2, int y2, int color);
void drawLine(int x1, int y1, int x2, int y2, int color);
- void drawPixel(VirtScreen *vs, int x, int y, int16 color);
+ void drawPixel(VirtScreen *vs, int x, int y, int16 color, bool useBackbuffer = false);
void moveScreen(int dx, int dy, int height);
@@ -1056,6 +1056,7 @@ public:
uint8 *getHEPaletteSlot(uint16 palSlot);
uint16 get16BitColor(uint8 r, uint8 g, uint8 b);
uint32 getPaletteColorFromRGB(byte *palette, byte r, byte g, byte b);
+ uint32 getPackedRGBColorFromPalette(byte *palette, uint32 color);
void fetchBlackAndWhite(uint32 &black, uint32 &white, byte *palette, int paletteEntries);
int remapPaletteColor(int r, int g, int b, int threshold); // Used by Actor::remapActorPalette
void readPCEPalette(const byte **ptr, byte **dest, int numEntries);
diff --git a/engines/scumm/scumm_v8.h b/engines/scumm/scumm_v8.h
index b94f1e65483..f6975cfd6a9 100644
--- a/engines/scumm/scumm_v8.h
+++ b/engines/scumm/scumm_v8.h
@@ -37,6 +37,20 @@ protected:
int _objectIDMapSize;
ObjectNameId *_objectIDMap;
+ struct StampShot {
+ int slot;
+ int boxX;
+ int boxY;
+ int boxWidth;
+ int boxHeight;
+ int brightness;
+ };
+
+ int _savegameThumbnailPalette[256];
+ byte _savegameThumbnail[160 * 120]; // One fourth of the nominal 640x480 resolution
+ StampShot _stampShots[20];
+ int _stampShotsInQueue = 0;
+
int _keyScriptKey, _keyScriptNo;
public:
@@ -44,6 +58,7 @@ public:
~ScummEngine_v8() override;
void setKeyScriptVars(int _keyScriptKey, int _keyScriptNo);
+ void stampShotDequeue();
protected:
void setupOpcodes() override;
@@ -73,6 +88,11 @@ protected:
void setCursorTransparency(int a) override;
void desaturatePalette(int hueScale, int satScale, int lightScale, int startColor, int endColor);
+ void stampShotEnqueue(int slot, int boxX, int boxY, int boxWidth, int boxHeight, int brightness);
+ void stampScreenShot(int slot, int boxX, int boxY, int boxWidth, int boxHeight, int brightness);
+ void saveLoadWithSerializer(Common::Serializer &s) override;
+ void createInternalSaveStateThumbnail();
+ bool fetchInternalSaveStateThumbnail(int slotId, bool isHeapSave);
/* Version 8 script opcodes */
void o8_mod();
Commit: d04d8cc00cd330f931cd7492684ba4ec9d476d69
https://github.com/scummvm/scummvm/commit/d04d8cc00cd330f931cd7492684ba4ec9d476d69
Author: AndywinXp (andywinxp at gmail.com)
Date: 2022-08-06T13:33:56+02:00
Commit Message:
SCUMM: COMI: Disable autosaving if original GUI is in place
Changed paths:
engines/scumm/saveload.cpp
diff --git a/engines/scumm/saveload.cpp b/engines/scumm/saveload.cpp
index 02712c5f4e0..7018d103c52 100644
--- a/engines/scumm/saveload.cpp
+++ b/engines/scumm/saveload.cpp
@@ -103,6 +103,10 @@ bool ScummEngine::canLoadGameStateCurrently() {
}
Common::Error ScummEngine::saveGameState(int slot, const Common::String &desc, bool isAutosave) {
+ // Disable autosaving if the original GUI is in place
+ if (isAutosave && isUsingOriginalGUI())
+ return Common::kNoError;
+
requestSave(slot, desc);
return Common::kNoError;
}
Commit: b395a94beb8027ad7d5bb4cd52d43c66af81b991
https://github.com/scummvm/scummvm/commit/b395a94beb8027ad7d5bb4cd52d43c66af81b991
Author: AndywinXp (andywinxp at gmail.com)
Date: 2022-08-06T13:33:56+02:00
Commit Message:
SCUMM: COMI: Insert a workaround for mouse input in the main menu
Changed paths:
engines/scumm/input.cpp
diff --git a/engines/scumm/input.cpp b/engines/scumm/input.cpp
index 04b1f443571..79f2e05fad4 100644
--- a/engines/scumm/input.cpp
+++ b/engines/scumm/input.cpp
@@ -365,6 +365,24 @@ void ScummEngine::processInput() {
} else if (_game.version >= 7) {
VAR(VAR_LEFTBTN_DOWN) = (_leftBtnPressed & msClicked) != 0;
VAR(VAR_RIGHTBTN_DOWN) = (_rightBtnPressed & msClicked) != 0;
+
+ // WORKAROUND: In COMI main menu, sometimes clicks are not registered
+ // correctly; in particular there usually a situation in which both
+ // states for a mouse button (msClicked and msDown) are being captured.
+ // Apparently this is not what the script expects: it asks for the
+ // mouse button being held down (why?) but not clicked (again, why?).
+ //
+ // Instead of mangling our very sturdy input system just for this use
+ // case, we just insert this little hack to make sure that the menu
+ // works as intended. After all, this all just might be caused by the
+ // difference between the (very slow...) mouse polling rate of the original
+ // and ours.
+ if (isUsingOriginalGUI() && _game.id == GID_CMI && _currentRoom == 92) {
+ VAR(VAR_LEFTBTN_HOLD) = (_leftBtnPressed & msDown) != 0;
+ VAR(VAR_RIGHTBTN_HOLD) = (_rightBtnPressed & msDown) != 0;
+ VAR(VAR_LEFTBTN_DOWN) = 0;
+ VAR(VAR_RIGHTBTN_DOWN) = 0;
+ }
}
}
Commit: 3ce00256b3645d024487df4388096bf0642b9d0c
https://github.com/scummvm/scummvm/commit/3ce00256b3645d024487df4388096bf0642b9d0c
Author: AndywinXp (andywinxp at gmail.com)
Date: 2022-08-06T13:33:56+02:00
Commit Message:
SCUMM: Fix getPaletteColorFromRGB() behavior with 0xFF and 0x00 values
Changed paths:
engines/scumm/palette.cpp
diff --git a/engines/scumm/palette.cpp b/engines/scumm/palette.cpp
index 6f1069f0193..3de108d2ac5 100644
--- a/engines/scumm/palette.cpp
+++ b/engines/scumm/palette.cpp
@@ -1504,12 +1504,11 @@ uint32 ScummEngine::getPaletteColorFromRGB(byte *palette, byte r, byte g, byte b
if ((r == 0xFF && b == 0xFF && g == 0xFF) || (r == 0x00 && g == 0x00 && b == 0x00)) {
fetchBlackAndWhite(black, white, palette, 256);
- if (r) {
+ if (!r) {
color = black;
} else {
color = white;
}
- color = 0xFF;
} else {
color = findClosestPaletteColor(palette, 256, r, g, b);
}
Commit: 36efab0a73fdec1acb870f459acd4044b4035138
https://github.com/scummvm/scummvm/commit/36efab0a73fdec1acb870f459acd4044b4035138
Author: AndywinXp (andywinxp at gmail.com)
Date: 2022-08-06T13:33:56+02:00
Commit Message:
SCUMM: COMI (Demo): Fix banner height handling
Changed paths:
engines/scumm/scumm.cpp
diff --git a/engines/scumm/scumm.cpp b/engines/scumm/scumm.cpp
index d041f038c83..a0258517da6 100644
--- a/engines/scumm/scumm.cpp
+++ b/engines/scumm/scumm.cpp
@@ -3222,7 +3222,8 @@ Common::KeyState ScummEngine_v7::showBannerAndPause(int bannerId, int32 waitTime
// Take all the necessary measurements for the box which
// will contain the string...
- bannerMsgHeight = _textV7->getStringHeight(bannerMsg) + 5;
+ bool isCOMIDemo = (_game.id == GID_CMI && (_game.features & GF_DEMO) != 0);
+ bannerMsgHeight = (isCOMIDemo ? _textV7->getStringHeight("ABC x °x") : _textV7->getStringHeight(bannerMsg)) + 5;
bannerMsgWidth = _textV7->getStringWidth(bannerMsg);
if (bannerMsgWidth < 100)
bannerMsgWidth = 100;
Commit: 1e0a61d64cf26587433df214451773e85e876cc3
https://github.com/scummvm/scummvm/commit/1e0a61d64cf26587433df214451773e85e876cc3
Author: AndywinXp (andywinxp at gmail.com)
Date: 2022-08-06T13:33:56+02:00
Commit Message:
SCUMM: COMI: Use ARRAYSIZE macro in overflow check
Changed paths:
engines/scumm/saveload.cpp
diff --git a/engines/scumm/saveload.cpp b/engines/scumm/saveload.cpp
index 7018d103c52..96f2f398e09 100644
--- a/engines/scumm/saveload.cpp
+++ b/engines/scumm/saveload.cpp
@@ -209,7 +209,7 @@ void ScummEngine::copyHeapSaveGameToFile(int slot, const char *saveName) {
#ifdef ENABLE_SCUMM_7_8
void ScummEngine_v8::stampShotEnqueue(int slot, int boxX, int boxY, int boxWidth, int boxHeight, int brightness) {
- if (_stampShotsInQueue >= sizeof(_stampShots))
+ if (_stampShotsInQueue >= (int)ARRAYSIZE(_stampShots))
error("ScummEngine_v8::stampShotEnqueue(): overflow in the queue");
_stampShots[_stampShotsInQueue].slot = slot;
Commit: bce4020ec1c555610d83da880cde3b0b5a71cb8d
https://github.com/scummvm/scummvm/commit/bce4020ec1c555610d83da880cde3b0b5a71cb8d
Author: AndywinXp (andywinxp at gmail.com)
Date: 2022-08-06T13:33:56+02:00
Commit Message:
SCUMM: COMI: Insert missing updatePalette() call
Changed paths:
engines/scumm/scumm.cpp
diff --git a/engines/scumm/scumm.cpp b/engines/scumm/scumm.cpp
index a0258517da6..665dd7e4c24 100644
--- a/engines/scumm/scumm.cpp
+++ b/engines/scumm/scumm.cpp
@@ -3144,6 +3144,7 @@ void ScummEngine_v7::initBanners() {
setPalColor(7, 0x5A, 0x5A, 0x5A);
setPalColor(8, 0x46, 0x46, 0x46);
setPalColor(15, 0x8C, 0x8C, 0x8C);
+ updatePalette();
setBannerColors(1, 0x00, 0x00, 0x00);
setBannerColors(2, 0xA8, 0xA8, 0xA8);
Commit: da69dec1293767075d255fd4ecbed804502c890f
https://github.com/scummvm/scummvm/commit/da69dec1293767075d255fd4ecbed804502c890f
Author: AndywinXp (andywinxp at gmail.com)
Date: 2022-08-06T13:33:56+02:00
Commit Message:
SCUMM: COMI: Fix original GUI savegames on ScummVM loading from launcher
Changed paths:
engines/scumm/saveload.cpp
engines/scumm/scumm.cpp
diff --git a/engines/scumm/saveload.cpp b/engines/scumm/saveload.cpp
index 96f2f398e09..31a037746bc 100644
--- a/engines/scumm/saveload.cpp
+++ b/engines/scumm/saveload.cpp
@@ -304,7 +304,6 @@ void ScummEngine_v8::createInternalSaveStateThumbnail() {
bool ScummEngine_v8::fetchInternalSaveStateThumbnail(int slotId, bool isHeapSave) {
SaveGameHeader hdr;
- int sb, sh;
Common::String filename;
Common::SeekableReadStream *in = openSaveFileForReading(slotId, isHeapSave, filename);
if (!in)
diff --git a/engines/scumm/scumm.cpp b/engines/scumm/scumm.cpp
index 665dd7e4c24..9684335cf81 100644
--- a/engines/scumm/scumm.cpp
+++ b/engines/scumm/scumm.cpp
@@ -2565,7 +2565,7 @@ void ScummEngine::scummLoop_handleSaveLoad() {
bool success;
Common::U32String errMsg;
- if (_game.version == 8 && (_saveTemporaryState || isUsingOriginalGUI()))
+ if (_game.version == 8 && VAR_GAME_LOADED != 0xFF)
VAR(VAR_GAME_LOADED) = 0;
Common::String filename;
@@ -2584,7 +2584,7 @@ void ScummEngine::scummLoop_handleSaveLoad() {
if (!success)
errMsg = _("Failed to load saved game from file:\n\n%s");
- if (success && (_saveTemporaryState || isUsingOriginalGUI()) && VAR_GAME_LOADED != 0xFF)
+ if (success && (_saveTemporaryState || _game.version == 8) && VAR_GAME_LOADED != 0xFF)
VAR(VAR_GAME_LOADED) = (_game.version == 8) ? 1 : 203;
}
@@ -2798,6 +2798,13 @@ void ScummEngine_v8::scummLoop_handleSaveLoad() {
createInternalSaveStateThumbnail();
}
+ // Needed for newer savegames saved within the original GUI
+ if (_loadFromLauncher && VAR_GAME_LOADED != 0xFF) {
+ _loadFromLauncher = false;
+ VAR(VAR_GAME_LOADED) = 1;
+ return;
+ }
+
ScummEngine::scummLoop_handleSaveLoad();
removeBlastObjects();
Commit: e01ea96054471be6c1a6b154dacf30020e306c0b
https://github.com/scummvm/scummvm/commit/e01ea96054471be6c1a6b154dacf30020e306c0b
Author: AndywinXp (andywinxp at gmail.com)
Date: 2022-08-06T13:33:56+02:00
Commit Message:
SCUMM: DETECTION: improve readability of enableOriginalGUI declaration
Changed paths:
engines/scumm/detection.cpp
diff --git a/engines/scumm/detection.cpp b/engines/scumm/detection.cpp
index 05751c0e84d..d8ca1e94621 100644
--- a/engines/scumm/detection.cpp
+++ b/engines/scumm/detection.cpp
@@ -243,7 +243,7 @@ static const ExtraGuiOption audioOverride {
0
};
-static const ExtraGuiOption enableOriginalGUI{
+static const ExtraGuiOption enableOriginalGUI = {
_s("Enable the original GUI and Menu"),
_s("Allow the game to use the in-engine graphical interface and the original save/load menu."),
"original_gui",
Commit: 85d3c5f5ac950991989a23a603b27e850e9e0abc
https://github.com/scummvm/scummvm/commit/85d3c5f5ac950991989a23a603b27e850e9e0abc
Author: AndywinXp (andywinxp at gmail.com)
Date: 2022-08-06T13:33:56+02:00
Commit Message:
SCUMM: COMI: Implement remaining banners for demo
Changed paths:
engines/scumm/dialogs.cpp
engines/scumm/input.cpp
engines/scumm/script.cpp
diff --git a/engines/scumm/dialogs.cpp b/engines/scumm/dialogs.cpp
index d90d929119b..eb4926f9395 100644
--- a/engines/scumm/dialogs.cpp
+++ b/engines/scumm/dialogs.cpp
@@ -60,7 +60,7 @@ static const ResString string_map_table_v8[] = {
{0, "/BT__004/Error reading disk %c, (%c%d) Press Button."},
{0, "/BT__002/Game Paused. Press SPACE to Continue."},
{0, "/BT__005/Are you sure you want to restart? (Y/N)"}, //BOOT.004
- {0, "/BT__006/Are you sure you want to quit? (Y/N)"}, //BOOT.005
+ {0, "/BT__006/Are you sure you want to quit? (Y/N)"}, //BOOT.005
{0, "/BT__008/Save"},
{0, "/BT__009/Load"},
{0, "/BT__010/Play"},
@@ -84,6 +84,11 @@ static const ResString string_map_table_v8[] = {
{0, "/BT_105/Text Display Only"},
{0, "/BT_103/Voice Only"},
{0, "/SYST300/y"},
+ {0, "/BOOT.005/Are you sure you want to quit? (Y-N)"}, // Demo strings
+ {0, "/NEW.23/Text Speed Slow ========== Fast"},
+ {0, "/NEW.24/Music Volume Low ========= High"},
+ {0, "/NEW.25/Voice Volume Low ========= High"},
+ {0, "/NEW.26/Sfx Volume Low ========= High"}
};
static const ResString string_map_table_v7[] = {
diff --git a/engines/scumm/input.cpp b/engines/scumm/input.cpp
index 79f2e05fad4..d0d0ca7d8d2 100644
--- a/engines/scumm/input.cpp
+++ b/engines/scumm/input.cpp
@@ -397,6 +397,8 @@ void ScummEngine::processInput() {
#ifdef ENABLE_SCUMM_7_8
void ScummEngine_v8::processKeyboard(Common::KeyState lastKeyHit) {
+ char tempStr[64];
+
// F1 (the trigger for the original save/load dialog) is mapped to F5,
// unless we chose to use the original GUI.
if (!(_game.features & GF_DEMO) && lastKeyHit.keycode == Common::KEYCODE_F1 && lastKeyHit.hasFlags(0)) {
@@ -451,7 +453,8 @@ void ScummEngine_v8::processKeyboard(Common::KeyState lastKeyHit) {
if (isUsingOriginalGUI() &&
(lastKeyHit.keycode == Common::KEYCODE_c && lastKeyHit.hasFlags(Common::KBD_CTRL))) {
if (_game.features & GF_DEMO) {
- Common::KeyState ks = showBannerAndPause(0, -1, d.getPlainEngineString(6));
+ // "Are you sure you want to quit? (Y-N)"
+ Common::KeyState ks = showBannerAndPause(0, -1, d.getPlainEngineString(30));
if (ks.keycode == Common::KEYCODE_y) {
quitGame();
}
@@ -505,6 +508,137 @@ void ScummEngine_v8::processKeyboard(Common::KeyState lastKeyHit) {
return;
}
+ // "Music Volume Low ========= High"
+ if (isUsingOriginalGUI() &&
+ (lastKeyHit.keycode == Common::KEYCODE_o || lastKeyHit.keycode == Common::KEYCODE_p)) {
+ Common::KeyState ks = lastKeyHit;
+
+ int volume = _imuseDigital->diMUSEGetMusicGroupVol();
+ do {
+ if (ks.keycode == Common::KEYCODE_o) {
+ volume -= 16;
+ if (volume < 0)
+ volume = 0;
+ } else {
+ volume += 16;
+ if (volume > 127)
+ volume = 127;
+ }
+
+ strcpy_s(tempStr, d.getPlainEngineString(32));
+ char *ptrToChar = strchr(tempStr, '=');
+ memset(ptrToChar, '\v', 9);
+ ptrToChar[volume / 15] = '\f';
+
+ showBannerAndPause(0, 0, tempStr);
+ ks = Common::KEYCODE_INVALID;
+ bool leftBtnPressed = false, rightBtnPressed = false;
+ waitForBannerInput(60, ks, leftBtnPressed, rightBtnPressed);
+ } while (ks.keycode == Common::KEYCODE_o || ks.keycode == Common::KEYCODE_p);
+ clearBanner();
+ _imuseDigital->diMUSESetMusicGroupVol(volume);
+ return;
+ }
+
+ // "Voice Volume Low ========= High"
+ if (isUsingOriginalGUI() &&
+ (lastKeyHit.keycode == Common::KEYCODE_k || lastKeyHit.keycode == Common::KEYCODE_l)) {
+ Common::KeyState ks = lastKeyHit;
+
+ int volume = _imuseDigital->diMUSEGetVoiceGroupVol();
+ do {
+ if (ks.keycode == Common::KEYCODE_k) {
+ volume -= 16;
+ if (volume < 0)
+ volume = 0;
+ } else {
+ volume += 16;
+ if (volume > 127)
+ volume = 127;
+ }
+
+ strcpy_s(tempStr, d.getPlainEngineString(33));
+ char *ptrToChar = strchr(tempStr, '=');
+ memset(ptrToChar, '\v', 9);
+ ptrToChar[volume / 15] = '\f';
+
+ showBannerAndPause(0, 0, tempStr);
+ ks = Common::KEYCODE_INVALID;
+ bool leftBtnPressed = false, rightBtnPressed = false;
+ waitForBannerInput(60, ks, leftBtnPressed, rightBtnPressed);
+ } while (ks.keycode == Common::KEYCODE_k || ks.keycode == Common::KEYCODE_l);
+ clearBanner();
+ _imuseDigital->diMUSESetVoiceGroupVol(volume);
+ return;
+ }
+
+ // "Sfx Volume Low ========= High"
+ if (isUsingOriginalGUI() &&
+ (lastKeyHit.keycode == Common::KEYCODE_n || lastKeyHit.keycode == Common::KEYCODE_m)) {
+ Common::KeyState ks = lastKeyHit;
+
+ int volume = _imuseDigital->diMUSEGetSFXGroupVol();
+ do {
+ if (ks.keycode == Common::KEYCODE_n) {
+ volume -= 16;
+ if (volume < 0)
+ volume = 0;
+ } else {
+ volume += 16;
+ if (volume > 127)
+ volume = 127;
+ }
+
+ strcpy_s(tempStr, d.getPlainEngineString(34));
+ char *ptrToChar = strchr(tempStr, '=');
+ memset(ptrToChar, '\v', 9);
+ ptrToChar[volume / 15] = '\f';
+
+ showBannerAndPause(0, 0, tempStr);
+ ks = Common::KEYCODE_INVALID;
+ bool leftBtnPressed = false, rightBtnPressed = false;
+ waitForBannerInput(60, ks, leftBtnPressed, rightBtnPressed);
+ } while (ks.keycode == Common::KEYCODE_n || ks.keycode == Common::KEYCODE_m);
+ clearBanner();
+ _imuseDigital->diMUSESetSFXGroupVol(volume);
+ return;
+ }
+
+ // "Text Speed Slow ========== Fast"
+ if (isUsingOriginalGUI() &&
+ (lastKeyHit.ascii == '+' || lastKeyHit.ascii == '-')) {
+ if (VAR_CHARINC == 0xFF)
+ return;
+
+ Common::KeyState ks = lastKeyHit;
+
+ int volume = _imuseDigital->diMUSEGetSFXGroupVol();
+ do {
+ if (ks.ascii == '+') {
+ VAR(VAR_CHARINC) -= 1;
+ if (VAR(VAR_CHARINC) < 0)
+ VAR(VAR_CHARINC) = 0;
+ } else {
+ VAR(VAR_CHARINC) += 1;
+ if (VAR(VAR_CHARINC) > 9)
+ VAR(VAR_CHARINC) = 9;
+ }
+
+ strcpy_s(tempStr, d.getPlainEngineString(31));
+ char *ptrToChar = strchr(tempStr, '=');
+ memset(ptrToChar, '\v', 10);
+ ptrToChar[9 - VAR(VAR_CHARINC)] = '\f';
+
+ showBannerAndPause(0, 0, tempStr);
+ ks = Common::KEYCODE_INVALID;
+ bool leftBtnPressed = false, rightBtnPressed = false;
+ waitForBannerInput(60, ks, leftBtnPressed, rightBtnPressed);
+ } while (ks.ascii == '+' || ks.ascii == '-');
+ clearBanner();
+ _imuseDigital->diMUSESetSFXGroupVol(volume);
+ return;
+ }
+
// Fall back to V7 behavior...
ScummEngine_v7::processKeyboard(lastKeyHit);
}
diff --git a/engines/scumm/script.cpp b/engines/scumm/script.cpp
index 1312c1f031d..804e7023aed 100644
--- a/engines/scumm/script.cpp
+++ b/engines/scumm/script.cpp
@@ -29,7 +29,6 @@
#include "scumm/util.h"
#include "scumm/scumm_v0.h"
#include "scumm/scumm_v2.h"
-#include "scumm/scumm_v7.h"
#include "scumm/sound.h"
#include "scumm/verbs.h"
Commit: a14f897bc4117ae0a9fdb537203d3547bf2c13f1
https://github.com/scummvm/scummvm/commit/a14f897bc4117ae0a9fdb537203d3547bf2c13f1
Author: AndywinXp (andywinxp at gmail.com)
Date: 2022-08-06T13:33:56+02:00
Commit Message:
SCUMM: Move high-level GUI handling to gfx_gui.cpp
Changed paths:
A engines/scumm/gfx_gui.cpp
engines/scumm/module.mk
engines/scumm/scumm.cpp
diff --git a/engines/scumm/gfx_gui.cpp b/engines/scumm/gfx_gui.cpp
new file mode 100644
index 00000000000..538559e3a30
--- /dev/null
+++ b/engines/scumm/gfx_gui.cpp
@@ -0,0 +1,483 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "scumm/scumm.h"
+#include "scumm/scumm_v7.h"
+#include "scumm/gfx.h"
+#include "scumm/dialogs.h"
+#include "scumm/charset.h"
+#include "scumm/string_v7.h"
+#include "scumm/smush/smush_player.h"
+
+#include "graphics/cursorman.h"
+
+namespace Scumm {
+
+#ifdef ENABLE_SCUMM_7_8
+void ScummEngine_v7::initBanners() {
+ setPalColor(7, 0x5A, 0x5A, 0x5A);
+ setPalColor(8, 0x46, 0x46, 0x46);
+ setPalColor(15, 0x8C, 0x8C, 0x8C);
+ updatePalette();
+
+ setBannerColors(1, 0x00, 0x00, 0x00);
+ setBannerColors(2, 0xA8, 0xA8, 0xA8);
+ setBannerColors(3, 0x00, 0x00, 0x00);
+ setBannerColors(4, 0xFC, 0xFC, 0x54);
+ setBannerColors(5, 0x54, 0x54, 0xFC);
+ setBannerColors(6, 0xA8, 0xA8, 0xA8);
+ setBannerColors(7, 0x00, 0x00, 0x00);
+ setBannerColors(8, 0xFC, 0xFC, 0x54);
+ setBannerColors(9, 0x54, 0x54, 0xFC);
+ setBannerColors(10, 0xFC, 0xFC, 0xFC);
+ setBannerColors(11, 0x54, 0x54, 0x54);
+ setBannerColors(12, 0xFC, 0xFC, 0xFC);
+ setBannerColors(13, 0x54, 0x54, 0x54);
+ setBannerColors(14, 0x00, 0x00, 0x00);
+ setBannerColors(15, 0xA8, 0xA8, 0xA8);
+ setBannerColors(16, 0xFC, 0xFC, 0xFC);
+ setBannerColors(17, 0x54, 0x54, 0x54);
+ setBannerColors(18, 0xFC, 0xFC, 0xFC);
+ setBannerColors(19, 0x54, 0x54, 0x54);
+ setBannerColors(20, 0xFC, 0x00, 0x00);
+ setBannerColors(21, 0xA8, 0xA8, 0xA8);
+ setBannerColors(22, 0xFC, 0xFC, 0xFC);
+ setBannerColors(23, 0x54, 0x54, 0x54);
+ setBannerColors(24, 0xFC, 0xFC, 0xFC);
+ setBannerColors(25, 0x54, 0x54, 0x54);
+ setBannerColors(26, 0x00, 0x00, 0x00);
+ setBannerColors(27, 0xA8, 0xA8, 0xA8);
+ setBannerColors(28, 0xFC, 0xFC, 0xFC);
+ setBannerColors(29, 0x54, 0x54, 0x54);
+ setBannerColors(30, 0xFC, 0xFC, 0xFC);
+ setBannerColors(31, 0x54, 0x54, 0x54);
+}
+
+Common::KeyState ScummEngine_v7::showBannerAndPause(int bannerId, int32 waitTime, const char *msg, ...) {
+ char bannerMsg[512];
+ char localizedMsg[512];
+ char localizedY[512];
+ char *ptrToBreak;
+ int bannerMsgWidth, bannerMsgHeight, roundedWidth;
+ int startingPointX, startingPointY;
+ int xPos, yPos;
+ int rightLineColor, leftLineColor, bottomLineColor, topLineColor;
+ int primaryLineColor, primaryFillColor;
+ InfoDialog d(this, 0);
+
+ // Fetch the translated string for the message...
+ convertMessageToString((const byte *)msg, (byte *)localizedMsg, sizeof(localizedMsg));
+ ptrToBreak = strstr(localizedMsg, "\\n");
+ if (!(_game.features & GF_DEMO) && ptrToBreak) { // Change the line break, if any...
+ ptrToBreak[0] = '\n';
+ ptrToBreak[1] = '\r';
+ }
+
+ // Format the string with the arguments...
+ va_list va;
+ va_start(va, msg);
+ vsnprintf(bannerMsg, sizeof(bannerMsg), localizedMsg, va);
+ va_end(va);
+
+ // Pause the engine
+ PauseToken pt = pauseEngine();
+
+ // Gather the colors needed for the banner
+ primaryFillColor = getBannerColor(6 * bannerId + 15);
+ primaryLineColor = getBannerColor(6 * bannerId + 14);
+ topLineColor = getBannerColor(6 * bannerId + 16);
+ bottomLineColor = getBannerColor(6 * bannerId + 17);
+ leftLineColor = getBannerColor(6 * bannerId + 18);
+ rightLineColor = getBannerColor(6 * bannerId + 19);
+
+ // Backup the current charsetId, since we're going to switch
+ // to charsetId == 1...
+ int oldId = _charset->getCurID();
+ _charset->setCurID(1);
+
+ // Take all the necessary measurements for the box which
+ // will contain the string...
+ bool isCOMIDemo = (_game.id == GID_CMI && (_game.features & GF_DEMO) != 0);
+ bannerMsgHeight = (isCOMIDemo ? _textV7->getStringHeight("ABC x °x") : _textV7->getStringHeight(bannerMsg)) + 5;
+ bannerMsgWidth = _textV7->getStringWidth(bannerMsg);
+ if (bannerMsgWidth < 100)
+ bannerMsgWidth = 100;
+
+ roundedWidth = (((bannerMsgWidth + 15) & 0xFFF0) + 8) / 2;
+ startingPointX = _screenWidth / 2 - roundedWidth - 4;
+ startingPointY = _screenHeight / 2 - 10;
+ xPos = _screenWidth / 2 + roundedWidth + 3;
+ yPos = 1 - bannerMsgHeight;
+
+ // Save the pixels which will be overwritten by the banner,
+ // so that we can restore them later...
+ if (!_bannerMem) {
+ _bannerMemSize = bannerMsgHeight * (_screenWidth + 8);
+ _bannerMem = (byte *)malloc(bannerMsgHeight * (_screenWidth + 8) * sizeof(byte));
+ if (_bannerMem)
+ memcpy(
+ _bannerMem,
+ &_virtscr[kMainVirtScreen].getPixels(0, _screenTop)[(_screenWidth + 8) * (_screenHeight / 2 - 10)],
+ _bannerMemSize);
+ }
+
+ // Set up the GUI control, specifying all the related colors, the message and the position...
+ setUpInternalGUIControl(0, primaryFillColor, primaryLineColor,
+ topLineColor, bottomLineColor, leftLineColor, rightLineColor, 0, 0,
+ startingPointX, startingPointY, xPos, yPos,
+ bannerMsg, true);
+
+ // Draw it!
+ drawInternalGUIControl(0, 0);
+ drawDirtyScreenParts();
+
+ // Wait until the engine receives a new Keyboard or Mouse input,
+ // unless we have specified a positive waitTime: in that case, the banner
+ // will stay on screen until an input has been received or until the time-out.
+ Common::KeyState ks = Common::KEYCODE_INVALID;
+ bool leftBtnPressed = false, rightBtnPressed = false;
+ if (waitTime) {
+ waitForBannerInput(waitTime, ks, leftBtnPressed, rightBtnPressed);
+ clearBanner();
+ }
+
+ // Finally, resume the engine, clear the input state, and restore the charset.
+ pt.clear();
+ clearClickedStatus();
+ if (oldId)
+ _charset->setCurID(oldId);
+
+ // Fetch the localized confirmation letter and substitute it with the 'y' of 'yes'
+ convertMessageToString((const byte *)d.getPlainEngineString(29), (byte *)localizedY, sizeof(localizedY));
+
+ if (tolower(localizedY[0]) == ks.ascii || toupper((localizedY[0]) == ks.ascii))
+ ks = Common::KEYCODE_y;
+
+ return ks;
+}
+
+void ScummEngine_v7::clearBanner() {
+ // Restore the GFX content which was under the banner,
+ // and then mark that part of the screen as dirty.
+ if (_bannerMem) {
+ memcpy(
+ &_virtscr[kMainVirtScreen].getPixels(0, _screenTop)[(_screenWidth + 8) * (_screenHeight / 2 - 10)],
+ _bannerMem,
+ _bannerMemSize);
+ free(_bannerMem);
+ _bannerMem = nullptr;
+
+ if (isSmushActive()) {
+ return;
+ }
+
+ markRectAsDirty(_virtscr[kMainVirtScreen].number, 0, _screenWidth + 8, _screenTop, _screenHeight + _screenTop);
+ drawDirtyScreenParts();
+ }
+}
+
+void ScummEngine_v7::setBannerColors(int bannerId, byte r, byte g, byte b) {
+ if (bannerId < 0 || bannerId > 50) {
+ debug(1, "ScummEngine::setBannerColors(): invalid slot %d out of range (min %d, max %d)", bannerId, 0, 50);
+ return;
+ }
+
+ _bannerColors[bannerId] = r | (b << 16) | (g << 8);
+}
+
+int ScummEngine_v7::getBannerColor(int bannerId) {
+ byte r, g, b;
+ byte *palette = isSmushActive() ? _splayer->getVideoPalette() : _currentPalette;
+ r = (_bannerColors[bannerId] >> 0) & 0xFF;
+ g = (_bannerColors[bannerId] >> 8) & 0xFF;
+ b = (_bannerColors[bannerId] >> 16) & 0xFF;
+ return getPaletteColorFromRGB(palette, r, g, b);
+}
+
+void ScummEngine_v7::setUpInternalGUIControl(int id, int primaryFillColor, int primaryLineColor,
+ int topLineColor, int bottomLineColor, int leftLineColor, int rightLineColor,
+ int secondaryLineColor, int secondaryFillColor,
+ int anchorPointX, int anchorPointY, int x, int y, char *label, bool centerFlag) {
+
+ int effX, effY;
+ InternalGUIControl *ctrl;
+
+ effX = x;
+ ctrl = &_internalGUIControls[id];
+ if (x < 0)
+ effX = anchorPointX - x;
+ effY = y;
+ if (y < 0)
+ effY = anchorPointY - y;
+ ctrl->relativeCenterX = anchorPointX;
+ ctrl->relativeCenterY = anchorPointY;
+ ctrl->xPos = effX;
+ ctrl->yPos = effY;
+ ctrl->label = label;
+ ctrl->centerText = centerFlag;
+ ctrl->primaryFillColor = primaryFillColor;
+ ctrl->topLineColor = topLineColor;
+ ctrl->bottomLineColor = bottomLineColor;
+ ctrl->leftLineColor = leftLineColor;
+ ctrl->rightLineColor = rightLineColor;
+ ctrl->primaryLineColor = primaryLineColor;
+ ctrl->secondaryLineColor = secondaryLineColor;
+ ctrl->secondaryFillColor = secondaryFillColor;
+}
+
+void ScummEngine_v7::drawInternalGUIControl(int id, bool useSecondaryColor) {
+ InternalGUIControl *ctrl;
+ int relCentX, relCentY, textHeight;
+ int x, y, textXPos, textYPos;
+ int lineColor, fillColor;
+ int boxSizeX, boxSizeY;
+
+ bool centerFlag;
+ char buttonString[512];
+
+ ctrl = &_internalGUIControls[id];
+ relCentX = ctrl->relativeCenterX;
+ if (ctrl->relativeCenterX != -1) {
+ relCentY = ctrl->relativeCenterY;
+ x = ctrl->xPos;
+ y = ctrl->yPos;
+
+ boxSizeX = x - ctrl->relativeCenterX;
+ boxSizeY = y - relCentY;
+
+ fillColor = useSecondaryColor ? ctrl->secondaryFillColor : ctrl->primaryFillColor;
+
+ // Draw the main box...
+ drawBox(relCentX + 1, relCentY + 1, boxSizeX - 2, boxSizeY - 2, fillColor);
+
+ // Draw the contour lines for the box; each of the lines is doubled to give a 3D effect.
+ drawLine(relCentX + 1, relCentY, x - 1, relCentY, ctrl->topLineColor);
+ drawLine(relCentX + 1, y, x - 1, y, ctrl->bottomLineColor);
+ drawLine(relCentX, relCentY + 1, relCentX, y - 1, ctrl->leftLineColor);
+ drawLine(x, relCentY + 1, x, y - 1, ctrl->rightLineColor);
+
+ drawLine(relCentX + 1, relCentY + 1, x - 1, relCentY + 1, ctrl->topLineColor);
+ drawLine(relCentX + 1, y - 1, x - 1, y - 1, ctrl->bottomLineColor);
+ drawLine(relCentX + 1, relCentY + 1, relCentX + 1, y - 1, ctrl->leftLineColor);
+ drawLine(x - 1, relCentY + 1, x - 1, y - 1, ctrl->rightLineColor);
+
+ // Calculate the positioning for the text
+ int oldId = _charset->getCurID();
+ _charset->setCurID(1);
+ textHeight = _textV7->getStringHeight(buttonString);
+ centerFlag = ctrl->centerText;
+
+ if (centerFlag)
+ textXPos = relCentX + boxSizeX / 2;
+ else
+ textXPos = relCentX + 2;
+
+ textYPos = relCentY + (boxSizeY - textHeight) / 2 + 1;
+
+ // Finally, choose the color and enqueue the text message
+ if (useSecondaryColor)
+ lineColor = ctrl->secondaryLineColor;
+ else
+ lineColor = ctrl->primaryLineColor;
+
+ if (ctrl->label)
+ strcpy(buttonString, ctrl->label);
+ else
+ strcpy(buttonString, "null button");
+
+ enqueueText((const byte *)buttonString, textXPos, textYPos, lineColor, 1, (TextStyleFlags)centerFlag);
+
+ // Restore the previous charset
+ if (oldId)
+ _charset->setCurID(oldId);
+ }
+}
+
+int ScummEngine_v7::getInternalGUIControlFromCoordinates(int x, int y) {
+ int id = 0;
+ while (_internalGUIControls[id].relativeCenterX == -1 ||
+ _internalGUIControls[id].relativeCenterX > x ||
+ _internalGUIControls[id].xPos < x ||
+ _internalGUIControls[id].relativeCenterY > y ||
+ _internalGUIControls[id].yPos < y) {
+
+ id++;
+ if (id >= sizeof(_internalGUIControls))
+ return -1;
+ }
+ return id;
+}
+
+void ScummEngine_v7::confirmExitDialog() {
+ if (isUsingOriginalGUI()) {
+ int boxWidth, strWidth;
+ int ctrlId;
+ char yesLabelPtr[512];
+ char noLabelPtr[512];
+ char msgLabelPtr[512];
+ byte *curGrabbedCursor;
+ int curCursorWidth, curCursorHeight, curCursorHotspotX, curCursorHotspotY, curCursorState;
+
+ InfoDialog d(this, 0);
+
+ // "Are you sure you want to quit?"
+ convertMessageToString((const byte *)d.getPlainEngineString(22), (byte *)msgLabelPtr, sizeof(msgLabelPtr));
+ // "Yes"
+ convertMessageToString((const byte *)d.getPlainEngineString(23), (byte *)yesLabelPtr, sizeof(yesLabelPtr));
+ // "No"
+ convertMessageToString((const byte *)d.getPlainEngineString(24), (byte *)noLabelPtr, sizeof(noLabelPtr));
+
+ // Pause the engine...
+ PauseToken pt = pauseEngine();
+
+ // Backup the current cursor graphics and parameters
+ // and set up the internal v8 cursor...
+ curGrabbedCursor = (byte *)malloc(sizeof(_grabbedCursor));
+ memcpy(curGrabbedCursor, _grabbedCursor, sizeof(_grabbedCursor));
+ curCursorState = isSmushActive() ? 0 : _cursor.state;
+ curCursorWidth = _cursor.width;
+ curCursorHeight = _cursor.height;
+ curCursorHotspotX = _cursor.hotspotX;
+ curCursorHotspotY = _cursor.hotspotY;
+ setDefaultCursor();
+
+ // Backup the current charsetId, since we're going to switch
+ // to charsetId == 1 and start taking measurements for the box...
+ int oldId = _charset->getCurID();
+ _charset->setCurID(1);
+
+ boxWidth = ((_textV7->getStringHeight(msgLabelPtr) + 32) & 0xFFF0) + 8;
+ if (boxWidth <= 400)
+ boxWidth = 400;
+
+ // Set up and draw the main box
+ setUpInternalGUIControl(
+ 0,
+ getBannerColor(33),
+ getBannerColor(32),
+ getBannerColor(34),
+ getBannerColor(35),
+ getBannerColor(36),
+ getBannerColor(37),
+ 0,
+ 0,
+ 320 - boxWidth / 2,
+ 190,
+ boxWidth / 2 + 319,
+ -90,
+ _emptyMsg,
+ true);
+
+ drawInternalGUIControl(0, 0);
+
+ // The text is drawn as a separate entity
+ enqueueText((const byte *)msgLabelPtr, 320, 200, getBannerColor(32), 1, (TextStyleFlags) true);
+
+ // Now set up and draw the Yes and No buttons...
+ if (_textV7->getStringWidth(noLabelPtr) <= _textV7->getStringWidth(yesLabelPtr)) {
+ strWidth = _textV7->getStringWidth(yesLabelPtr);
+ } else {
+ strWidth = _textV7->getStringWidth(noLabelPtr);
+ }
+
+ if (strWidth <= 120)
+ strWidth = 120;
+
+ setUpInternalGUIControl(
+ 0,
+ getBannerColor(45),
+ getBannerColor(44),
+ getBannerColor(46),
+ getBannerColor(47),
+ getBannerColor(48),
+ getBannerColor(49),
+ 0,
+ 0,
+ 420 - (strWidth / 2),
+ 240, -strWidth,
+ -30,
+ noLabelPtr,
+ true);
+
+ drawInternalGUIControl(0, 0);
+
+ setUpInternalGUIControl(
+ 0,
+ getBannerColor(39),
+ getBannerColor(38),
+ getBannerColor(40),
+ getBannerColor(41),
+ getBannerColor(42),
+ getBannerColor(43),
+ 0,
+ 0,
+ 220 - (strWidth / 2),
+ 240,
+ -strWidth,
+ -30,
+ yesLabelPtr,
+ true);
+
+ drawInternalGUIControl(0, 0);
+
+ // Done, draw everything to screen!
+ drawDirtyScreenParts();
+
+ // Stay in the dialog while we keep pressing CTRL-C...
+ Common::KeyState ks;
+ bool leftBtnPressed = false, rightBtnPressed = false;
+ do {
+ clearClickedStatus();
+ ks = Common::KEYCODE_INVALID;
+ waitForBannerInput(-1, ks, leftBtnPressed, rightBtnPressed);
+ } while (ks.keycode == Common::KEYCODE_LCTRL ||
+ ks.keycode == Common::KEYCODE_RCTRL ||
+ (ks.keycode == Common::KEYCODE_c && ks.hasFlags(Common::KBD_CTRL)));
+
+ ctrlId = getInternalGUIControlFromCoordinates(_mouse.x, _mouse.y);
+ if (leftBtnPressed && ctrlId == 0 || (toupper(ks.ascii) == yesLabelPtr[0]))
+ quitGame();
+
+ // Restore the previous cursor...
+ _cursor.state = curCursorState;
+ CursorMan.showMouse(_cursor.state > 0);
+ setCursorHotspot(curCursorHotspotX, curCursorHotspotY);
+ setCursorFromBuffer(curGrabbedCursor, curCursorWidth, curCursorHeight, curCursorWidth);
+ free(curGrabbedCursor);
+
+ // The interpreter makes us wait 45 full frames;
+ // let's wait half that time...
+ waitForTimer(45 * 2);
+
+ // Since we're not explicitly clearing the dialog graphics, set up a full redraw...
+ _fullRedraw = true;
+
+ // Finally, resume the engine, clear the input state, and restore the charset.
+ pt.clear();
+ clearClickedStatus();
+ if (oldId)
+ _charset->setCurID(oldId);
+ } else {
+ ScummEngine::confirmExitDialog();
+ }
+}
+#endif
+}
diff --git a/engines/scumm/module.mk b/engines/scumm/module.mk
index 02f4802739c..d8686d2c672 100644
--- a/engines/scumm/module.mk
+++ b/engines/scumm/module.mk
@@ -16,6 +16,7 @@ MODULE_OBJS := \
dialogs.o \
file.o \
file_nes.o \
+ gfx_gui.o \
gfx_mac.o \
gfx_towns.o \
gfx.o \
diff --git a/engines/scumm/scumm.cpp b/engines/scumm/scumm.cpp
index 9684335cf81..d58146abfa2 100644
--- a/engines/scumm/scumm.cpp
+++ b/engines/scumm/scumm.cpp
@@ -3146,454 +3146,6 @@ void ScummEngine::versionDialog() {
runDialog(*_versionDialog);
}
-#ifdef ENABLE_SCUMM_7_8
-void ScummEngine_v7::initBanners() {
- setPalColor(7, 0x5A, 0x5A, 0x5A);
- setPalColor(8, 0x46, 0x46, 0x46);
- setPalColor(15, 0x8C, 0x8C, 0x8C);
- updatePalette();
-
- setBannerColors(1, 0x00, 0x00, 0x00);
- setBannerColors(2, 0xA8, 0xA8, 0xA8);
- setBannerColors(3, 0x00, 0x00, 0x00);
- setBannerColors(4, 0xFC, 0xFC, 0x54);
- setBannerColors(5, 0x54, 0x54, 0xFC);
- setBannerColors(6, 0xA8, 0xA8, 0xA8);
- setBannerColors(7, 0x00, 0x00, 0x00);
- setBannerColors(8, 0xFC, 0xFC, 0x54);
- setBannerColors(9, 0x54, 0x54, 0xFC);
- setBannerColors(10, 0xFC, 0xFC, 0xFC);
- setBannerColors(11, 0x54, 0x54, 0x54);
- setBannerColors(12, 0xFC, 0xFC, 0xFC);
- setBannerColors(13, 0x54, 0x54, 0x54);
- setBannerColors(14, 0x00, 0x00, 0x00);
- setBannerColors(15, 0xA8, 0xA8, 0xA8);
- setBannerColors(16, 0xFC, 0xFC, 0xFC);
- setBannerColors(17, 0x54, 0x54, 0x54);
- setBannerColors(18, 0xFC, 0xFC, 0xFC);
- setBannerColors(19, 0x54, 0x54, 0x54);
- setBannerColors(20, 0xFC, 0x00, 0x00);
- setBannerColors(21, 0xA8, 0xA8, 0xA8);
- setBannerColors(22, 0xFC, 0xFC, 0xFC);
- setBannerColors(23, 0x54, 0x54, 0x54);
- setBannerColors(24, 0xFC, 0xFC, 0xFC);
- setBannerColors(25, 0x54, 0x54, 0x54);
- setBannerColors(26, 0x00, 0x00, 0x00);
- setBannerColors(27, 0xA8, 0xA8, 0xA8);
- setBannerColors(28, 0xFC, 0xFC, 0xFC);
- setBannerColors(29, 0x54, 0x54, 0x54);
- setBannerColors(30, 0xFC, 0xFC, 0xFC);
- setBannerColors(31, 0x54, 0x54, 0x54);
-}
-
-Common::KeyState ScummEngine_v7::showBannerAndPause(int bannerId, int32 waitTime, const char *msg, ...) {
- char bannerMsg[512];
- char localizedMsg[512];
- char localizedY[512];
- char *ptrToBreak;
- int bannerMsgWidth, bannerMsgHeight, roundedWidth;
- int startingPointX, startingPointY;
- int xPos, yPos;
- int rightLineColor, leftLineColor, bottomLineColor, topLineColor;
- int primaryLineColor, primaryFillColor;
- InfoDialog d(this, 0);
-
- // Fetch the translated string for the message...
- convertMessageToString((const byte *)msg, (byte *)localizedMsg, sizeof(localizedMsg));
- ptrToBreak = strstr(localizedMsg, "\\n");
- if (!(_game.features & GF_DEMO) && ptrToBreak) { // Change the line break, if any...
- ptrToBreak[0] = '\n';
- ptrToBreak[1] = '\r';
- }
-
- // Format the string with the arguments...
- va_list va;
- va_start(va, msg);
- vsnprintf(bannerMsg, sizeof(bannerMsg), localizedMsg, va);
- va_end(va);
-
- // Pause the engine
- PauseToken pt = pauseEngine();
-
- // Gather the colors needed for the banner
- primaryFillColor = getBannerColor(6 * bannerId + 15);
- primaryLineColor = getBannerColor(6 * bannerId + 14);
- topLineColor = getBannerColor(6 * bannerId + 16);
- bottomLineColor = getBannerColor(6 * bannerId + 17);
- leftLineColor = getBannerColor(6 * bannerId + 18);
- rightLineColor = getBannerColor(6 * bannerId + 19);
-
- // Backup the current charsetId, since we're going to switch
- // to charsetId == 1...
- int oldId = _charset->getCurID();
- _charset->setCurID(1);
-
- // Take all the necessary measurements for the box which
- // will contain the string...
- bool isCOMIDemo = (_game.id == GID_CMI && (_game.features & GF_DEMO) != 0);
- bannerMsgHeight = (isCOMIDemo ? _textV7->getStringHeight("ABC x °x") : _textV7->getStringHeight(bannerMsg)) + 5;
- bannerMsgWidth = _textV7->getStringWidth(bannerMsg);
- if (bannerMsgWidth < 100)
- bannerMsgWidth = 100;
-
- roundedWidth = (((bannerMsgWidth + 15) & 0xFFF0) + 8) / 2;
- startingPointX = _screenWidth / 2 - roundedWidth - 4;
- startingPointY = _screenHeight / 2 - 10;
- xPos = _screenWidth / 2 + roundedWidth + 3;
- yPos = 1 - bannerMsgHeight;
-
- // Save the pixels which will be overwritten by the banner,
- // so that we can restore them later...
- if (!_bannerMem) {
- _bannerMemSize = bannerMsgHeight * (_screenWidth + 8);
- _bannerMem = (byte *)malloc(bannerMsgHeight * (_screenWidth + 8) * sizeof(byte));
- if (_bannerMem)
- memcpy(
- _bannerMem,
- &_virtscr[kMainVirtScreen].getPixels(0, _screenTop)[(_screenWidth + 8) * (_screenHeight / 2 - 10)],
- _bannerMemSize);
- }
-
- // Set up the GUI control, specifying all the related colors, the message and the position...
- setUpInternalGUIControl(0, primaryFillColor, primaryLineColor,
- topLineColor, bottomLineColor, leftLineColor, rightLineColor, 0, 0,
- startingPointX, startingPointY, xPos, yPos,
- bannerMsg, true);
-
- // Draw it!
- drawInternalGUIControl(0, 0);
- drawDirtyScreenParts();
-
- // Wait until the engine receives a new Keyboard or Mouse input,
- // unless we have specified a positive waitTime: in that case, the banner
- // will stay on screen until an input has been received or until the time-out.
- Common::KeyState ks = Common::KEYCODE_INVALID;
- bool leftBtnPressed = false, rightBtnPressed = false;
- waitForBannerInput(waitTime, ks, leftBtnPressed, rightBtnPressed);
- clearBanner();
-
- // Finally, resume the engine, clear the input state, and restore the charset.
- pt.clear();
- clearClickedStatus();
- if (oldId)
- _charset->setCurID(oldId);
-
- // Fetch the localized confirmation letter and substitute it with the 'y' of 'yes'
- convertMessageToString((const byte *)d.getPlainEngineString(29), (byte *)localizedY, sizeof(localizedY));
-
- if (tolower(localizedY[0]) == ks.ascii || toupper((localizedY[0]) == ks.ascii))
- ks = Common::KEYCODE_y;
-
- return ks;
-}
-
-void ScummEngine_v7::clearBanner() {
- // Restore the GFX content which was under the banner,
- // and then mark that part of the screen as dirty.
- if (_bannerMem) {
- memcpy(
- &_virtscr[kMainVirtScreen].getPixels(0, _screenTop)[(_screenWidth + 8) * (_screenHeight / 2 - 10)],
- _bannerMem,
- _bannerMemSize);
- free(_bannerMem);
- _bannerMem = nullptr;
-
- if (isSmushActive()) {
- return;
- }
-
- markRectAsDirty(_virtscr[kMainVirtScreen].number, 0, _screenWidth + 8, _screenTop, _screenHeight + _screenTop);
- drawDirtyScreenParts();
- }
-}
-
-void ScummEngine_v7::setBannerColors(int bannerId, byte r, byte g, byte b) {
- if (bannerId < 0 || bannerId > 50) {
- debug(1, "ScummEngine::setBannerColors(): invalid slot %d out of range (min %d, max %d)", bannerId, 0, 50);
- return;
- }
-
- _bannerColors[bannerId] = r | (b << 16) | (g << 8);
-}
-
-int ScummEngine_v7::getBannerColor(int bannerId) {
- byte r, g, b;
- byte *palette = isSmushActive() ? _splayer->getVideoPalette() : _currentPalette;
- r = (_bannerColors[bannerId] >> 0) & 0xFF;
- g = (_bannerColors[bannerId] >> 8) & 0xFF;
- b = (_bannerColors[bannerId] >> 16) & 0xFF;
- return getPaletteColorFromRGB(palette, r, g, b);
-}
-
-void ScummEngine_v7::setUpInternalGUIControl(int id, int primaryFillColor, int primaryLineColor,
- int topLineColor, int bottomLineColor, int leftLineColor, int rightLineColor,
- int secondaryLineColor, int secondaryFillColor,
- int anchorPointX, int anchorPointY, int x, int y, char *label, bool centerFlag) {
-
- int effX, effY;
- InternalGUIControl *ctrl;
-
- effX = x;
- ctrl = &_internalGUIControls[id];
- if (x < 0)
- effX = anchorPointX - x;
- effY = y;
- if (y < 0)
- effY = anchorPointY - y;
- ctrl->relativeCenterX = anchorPointX;
- ctrl->relativeCenterY = anchorPointY;
- ctrl->xPos = effX;
- ctrl->yPos = effY;
- ctrl->label = label;
- ctrl->centerText = centerFlag;
- ctrl->primaryFillColor = primaryFillColor;
- ctrl->topLineColor = topLineColor;
- ctrl->bottomLineColor = bottomLineColor;
- ctrl->leftLineColor = leftLineColor;
- ctrl->rightLineColor = rightLineColor;
- ctrl->primaryLineColor = primaryLineColor;
- ctrl->secondaryLineColor = secondaryLineColor;
- ctrl->secondaryFillColor = secondaryFillColor;
-}
-
-void ScummEngine_v7::drawInternalGUIControl(int id, bool useSecondaryColor) {
- InternalGUIControl *ctrl;
- int relCentX, relCentY, textHeight;
- int x, y, textXPos, textYPos;
- int lineColor, fillColor;
- int boxSizeX, boxSizeY;
-
- bool centerFlag;
- char buttonString[512];
-
- ctrl = &_internalGUIControls[id];
- relCentX = ctrl->relativeCenterX;
- if (ctrl->relativeCenterX != -1) {
- relCentY = ctrl->relativeCenterY;
- x = ctrl->xPos;
- y = ctrl->yPos;
-
- boxSizeX = x - ctrl->relativeCenterX;
- boxSizeY = y - relCentY;
-
- fillColor = useSecondaryColor ? ctrl->secondaryFillColor : ctrl->primaryFillColor;
-
- // Draw the main box...
- drawBox(relCentX + 1, relCentY + 1, boxSizeX - 2, boxSizeY - 2, fillColor);
-
- // Draw the contour lines for the box; each of the lines is doubled to give a 3D effect.
- drawLine(relCentX + 1, relCentY, x - 1, relCentY, ctrl->topLineColor);
- drawLine(relCentX + 1, y, x - 1, y, ctrl->bottomLineColor);
- drawLine(relCentX, relCentY + 1, relCentX, y - 1, ctrl->leftLineColor);
- drawLine(x, relCentY + 1, x, y - 1, ctrl->rightLineColor);
-
- drawLine(relCentX + 1, relCentY + 1, x - 1, relCentY + 1, ctrl->topLineColor);
- drawLine(relCentX + 1, y - 1, x - 1, y - 1, ctrl->bottomLineColor);
- drawLine(relCentX + 1, relCentY + 1, relCentX + 1, y - 1, ctrl->leftLineColor);
- drawLine(x - 1, relCentY + 1, x - 1, y - 1, ctrl->rightLineColor);
-
- // Calculate the positioning for the text
- int oldId = _charset->getCurID();
- _charset->setCurID(1);
- textHeight = _textV7->getStringHeight(buttonString);
- centerFlag = ctrl->centerText;
-
- if (centerFlag)
- textXPos = relCentX + boxSizeX / 2;
- else
- textXPos = relCentX + 2;
-
- textYPos = relCentY + (boxSizeY - textHeight) / 2 + 1;
-
- // Finally, choose the color and enqueue the text message
- if (useSecondaryColor)
- lineColor = ctrl->secondaryLineColor;
- else
- lineColor = ctrl->primaryLineColor;
-
- if (ctrl->label)
- strcpy(buttonString, ctrl->label);
- else
- strcpy(buttonString, "null button");
-
- enqueueText((const byte *)buttonString, textXPos, textYPos, lineColor, 1, (TextStyleFlags)centerFlag);
-
- // Restore the previous charset
- if (oldId)
- _charset->setCurID(oldId);
- }
-}
-
-int ScummEngine_v7::getInternalGUIControlFromCoordinates(int x, int y) {
- int id = 0;
- while (_internalGUIControls[id].relativeCenterX == -1 ||
- _internalGUIControls[id].relativeCenterX > x ||
- _internalGUIControls[id].xPos < x ||
- _internalGUIControls[id].relativeCenterY > y ||
- _internalGUIControls[id]. yPos < y) {
-
- id++;
- if (id >= sizeof(_internalGUIControls))
- return -1;
- }
- return id;
-}
-
-void ScummEngine_v7::confirmExitDialog() {
- if (isUsingOriginalGUI()) {
- int boxWidth, strWidth;
- int ctrlId;
- char yesLabelPtr[512];
- char noLabelPtr[512];
- char msgLabelPtr[512];
- byte *curGrabbedCursor;
- int curCursorWidth, curCursorHeight, curCursorHotspotX, curCursorHotspotY, curCursorState;
-
- InfoDialog d(this, 0);
-
- // "Are you sure you want to quit?"
- convertMessageToString((const byte *)d.getPlainEngineString(22), (byte *)msgLabelPtr, sizeof(msgLabelPtr));
- // "Yes"
- convertMessageToString((const byte *)d.getPlainEngineString(23), (byte *)yesLabelPtr, sizeof(yesLabelPtr));
- // "No"
- convertMessageToString((const byte *)d.getPlainEngineString(24), (byte *)noLabelPtr, sizeof(noLabelPtr));
-
- // Pause the engine...
- PauseToken pt = pauseEngine();
-
- // Backup the current cursor graphics and parameters
- // and set up the internal v8 cursor...
- curGrabbedCursor = (byte *)malloc(sizeof(_grabbedCursor));
- memcpy(curGrabbedCursor, _grabbedCursor, sizeof(_grabbedCursor));
- curCursorState = isSmushActive() ? 0 : _cursor.state;
- curCursorWidth = _cursor.width;
- curCursorHeight = _cursor.height;
- curCursorHotspotX = _cursor.hotspotX;
- curCursorHotspotY = _cursor.hotspotY;
- setDefaultCursor();
-
- // Backup the current charsetId, since we're going to switch
- // to charsetId == 1 and start taking measurements for the box...
- int oldId = _charset->getCurID();
- _charset->setCurID(1);
-
- boxWidth = ((_textV7->getStringHeight(msgLabelPtr) + 32) & 0xFFF0) + 8;
- if (boxWidth <= 400)
- boxWidth = 400;
-
- // Set up and draw the main box
- setUpInternalGUIControl(
- 0,
- getBannerColor(33),
- getBannerColor(32),
- getBannerColor(34),
- getBannerColor(35),
- getBannerColor(36),
- getBannerColor(37),
- 0,
- 0,
- 320 - boxWidth / 2,
- 190,
- boxWidth / 2 + 319,
- -90,
- _emptyMsg,
- true);
-
- drawInternalGUIControl(0, 0);
-
- // The text is drawn as a separate entity
- enqueueText((const byte *)msgLabelPtr, 320, 200, getBannerColor(32), 1, (TextStyleFlags) true);
-
- // Now set up and draw the Yes and No buttons...
- if (_textV7->getStringWidth(noLabelPtr) <= _textV7->getStringWidth(yesLabelPtr)) {
- strWidth = _textV7->getStringWidth(yesLabelPtr);
- } else {
- strWidth = _textV7->getStringWidth(noLabelPtr);
- }
-
- if (strWidth <= 120)
- strWidth = 120;
-
- setUpInternalGUIControl(
- 0,
- getBannerColor(45),
- getBannerColor(44),
- getBannerColor(46),
- getBannerColor(47),
- getBannerColor(48),
- getBannerColor(49),
- 0,
- 0,
- 420 - (strWidth / 2),
- 240, -strWidth,
- -30,
- noLabelPtr,
- true);
-
- drawInternalGUIControl(0, 0);
-
- setUpInternalGUIControl(
- 0,
- getBannerColor(39),
- getBannerColor(38),
- getBannerColor(40),
- getBannerColor(41),
- getBannerColor(42),
- getBannerColor(43),
- 0,
- 0,
- 220 - (strWidth / 2),
- 240,
- -strWidth,
- -30,
- yesLabelPtr,
- true);
-
- drawInternalGUIControl(0, 0);
-
- // Done, draw everything to screen!
- drawDirtyScreenParts();
-
- // Stay in the dialog while we keep pressing CTRL-C...
- Common::KeyState ks;
- bool leftBtnPressed = false, rightBtnPressed = false;
- do {
- clearClickedStatus();
- ks = Common::KEYCODE_INVALID;
- waitForBannerInput(-1, ks, leftBtnPressed, rightBtnPressed);
- } while (ks.keycode == Common::KEYCODE_LCTRL ||
- ks.keycode == Common::KEYCODE_RCTRL ||
- (ks.keycode == Common::KEYCODE_c && ks.hasFlags(Common::KBD_CTRL)));
-
- ctrlId = getInternalGUIControlFromCoordinates(_mouse.x, _mouse.y);
- if (leftBtnPressed && ctrlId == 0 || (toupper(ks.ascii) == yesLabelPtr[0]))
- quitGame();
-
- // Restore the previous cursor...
- _cursor.state = curCursorState;
- CursorMan.showMouse(_cursor.state > 0);
- setCursorHotspot(curCursorHotspotX, curCursorHotspotY);
- setCursorFromBuffer(curGrabbedCursor, curCursorWidth, curCursorHeight, curCursorWidth);
- free(curGrabbedCursor);
-
- // The interpreter makes us wait 45 full frames;
- // let's wait half that time...
- waitForTimer(45 * 2);
-
- // Since we're not explicitly clearing the dialog graphics, set up a full redraw...
- _fullRedraw = true;
-
- // Finally, resume the engine, clear the input state, and restore the charset.
- pt.clear();
- clearClickedStatus();
- if (oldId)
- _charset->setCurID(oldId);
- } else {
- ScummEngine::confirmExitDialog();
- }
-}
-#endif
-
void ScummEngine::confirmExitDialog() {
ConfirmDialog d(this, 6);
Commit: e78c671b45956052559690cc084176c20ca80f7b
https://github.com/scummvm/scummvm/commit/e78c671b45956052559690cc084176c20ca80f7b
Author: AndywinXp (andywinxp at gmail.com)
Date: 2022-08-06T13:33:56+02:00
Commit Message:
SCUMM: Fix non-Windows compiling
Changed paths:
engines/scumm/input.cpp
diff --git a/engines/scumm/input.cpp b/engines/scumm/input.cpp
index d0d0ca7d8d2..ca353d4d504 100644
--- a/engines/scumm/input.cpp
+++ b/engines/scumm/input.cpp
@@ -525,7 +525,7 @@ void ScummEngine_v8::processKeyboard(Common::KeyState lastKeyHit) {
volume = 127;
}
- strcpy_s(tempStr, d.getPlainEngineString(32));
+ strcpy(tempStr, d.getPlainEngineString(32));
char *ptrToChar = strchr(tempStr, '=');
memset(ptrToChar, '\v', 9);
ptrToChar[volume / 15] = '\f';
@@ -557,7 +557,7 @@ void ScummEngine_v8::processKeyboard(Common::KeyState lastKeyHit) {
volume = 127;
}
- strcpy_s(tempStr, d.getPlainEngineString(33));
+ strcpy(tempStr, d.getPlainEngineString(33));
char *ptrToChar = strchr(tempStr, '=');
memset(ptrToChar, '\v', 9);
ptrToChar[volume / 15] = '\f';
@@ -589,7 +589,7 @@ void ScummEngine_v8::processKeyboard(Common::KeyState lastKeyHit) {
volume = 127;
}
- strcpy_s(tempStr, d.getPlainEngineString(34));
+ strcpy(tempStr, d.getPlainEngineString(34));
char *ptrToChar = strchr(tempStr, '=');
memset(ptrToChar, '\v', 9);
ptrToChar[volume / 15] = '\f';
@@ -624,7 +624,7 @@ void ScummEngine_v8::processKeyboard(Common::KeyState lastKeyHit) {
VAR(VAR_CHARINC) = 9;
}
- strcpy_s(tempStr, d.getPlainEngineString(31));
+ strcpy(tempStr, d.getPlainEngineString(31));
char *ptrToChar = strchr(tempStr, '=');
memset(ptrToChar, '\v', 10);
ptrToChar[9 - VAR(VAR_CHARINC)] = '\f';
Commit: f0d371d96e19e2fb8d6ba730a6bbb7862dd8e16c
https://github.com/scummvm/scummvm/commit/f0d371d96e19e2fb8d6ba730a6bbb7862dd8e16c
Author: AndywinXp (andywinxp at gmail.com)
Date: 2022-08-06T13:33:56+02:00
Commit Message:
SCUMM: Fix warnings
Changed paths:
engines/scumm/cursor.cpp
engines/scumm/gfx_gui.cpp
engines/scumm/palette.cpp
engines/scumm/saveload.cpp
diff --git a/engines/scumm/cursor.cpp b/engines/scumm/cursor.cpp
index adcdb9f5bb1..b3d7583314e 100644
--- a/engines/scumm/cursor.cpp
+++ b/engines/scumm/cursor.cpp
@@ -208,7 +208,7 @@ void ScummEngine_v7::setDefaultCursor() {
white = getPaletteColorFromRGB(palette, inverseRgbIdx, inverseRgbIdx, inverseRgbIdx);
} while (white == 1 && rgbIdx != 100);
- for (int i = 0; i < sizeof(default_v8_cursor); ++i) {
+ for (int i = 0; i < ARRAYSIZE(default_v8_cursor); i++) {
cursorPixel = default_v8_cursor[i];
if (isSmushActive() && cursorPixel == 0x0F)
diff --git a/engines/scumm/gfx_gui.cpp b/engines/scumm/gfx_gui.cpp
index 538559e3a30..bcb823519a4 100644
--- a/engines/scumm/gfx_gui.cpp
+++ b/engines/scumm/gfx_gui.cpp
@@ -320,7 +320,7 @@ int ScummEngine_v7::getInternalGUIControlFromCoordinates(int x, int y) {
_internalGUIControls[id].yPos < y) {
id++;
- if (id >= sizeof(_internalGUIControls))
+ if (id >= ARRAYSIZE(_internalGUIControls))
return -1;
}
return id;
@@ -453,7 +453,7 @@ void ScummEngine_v7::confirmExitDialog() {
(ks.keycode == Common::KEYCODE_c && ks.hasFlags(Common::KBD_CTRL)));
ctrlId = getInternalGUIControlFromCoordinates(_mouse.x, _mouse.y);
- if (leftBtnPressed && ctrlId == 0 || (toupper(ks.ascii) == yesLabelPtr[0]))
+ if ((leftBtnPressed && ctrlId == 0) || (toupper(ks.ascii) == yesLabelPtr[0]))
quitGame();
// Restore the previous cursor...
diff --git a/engines/scumm/palette.cpp b/engines/scumm/palette.cpp
index 3de108d2ac5..75cfcd49c30 100644
--- a/engines/scumm/palette.cpp
+++ b/engines/scumm/palette.cpp
@@ -1559,9 +1559,9 @@ uint32 ScummEngine::findClosestPaletteColor(byte *palette, int numOfSlots, byte
blueSquareDiff = (b - palette[2]) * (b - palette[2]);
weightedColorError = 3 * redSquareDiff + 5 * greenSquareDiff + 2 * blueSquareDiff;
- if (3 * redSquareDiff + 5 * greenSquareDiff + 2 * blueSquareDiff < minErr) {
+ if (weightedColorError < minErr) {
color = i;
- minErr = 3 * redSquareDiff + 5 * greenSquareDiff + 2 * blueSquareDiff;
+ minErr = weightedColorError;
}
palette += 3;
}
diff --git a/engines/scumm/saveload.cpp b/engines/scumm/saveload.cpp
index 31a037746bc..c53db76a98c 100644
--- a/engines/scumm/saveload.cpp
+++ b/engines/scumm/saveload.cpp
@@ -165,7 +165,6 @@ void ScummEngine::copyHeapSaveGameToFile(int slot, const char *saveName) {
Common::String fileName;
SaveGameHeader hdr;
bool saveFailed = false;
- uint32 heapFileSize;
Common::SeekableReadStream *heapSaveFile = openSaveFileForReading(1, true, fileName);
hdr.type = heapSaveFile->readUint32BE();
@@ -174,7 +173,6 @@ void ScummEngine::copyHeapSaveGameToFile(int slot, const char *saveName) {
heapSaveFile->read(hdr.name, sizeof(hdr.name));
Common::strlcpy(hdr.name, saveName, sizeof(hdr.name));
- heapFileSize = (uint32)heapSaveFile->size();
if (heapSaveFile->err() || hdr.type != MKTAG('S','C','V','M')) {
saveFailed = true;
} else {
Commit: f3702305ce5f395199d2b38a30b890e4361e3524
https://github.com/scummvm/scummvm/commit/f3702305ce5f395199d2b38a30b890e4361e3524
Author: AndywinXp (andywinxp at gmail.com)
Date: 2022-08-06T13:33:56+02:00
Commit Message:
SCUMM: COMI: Clean up input code
Changed paths:
engines/scumm/input.cpp
diff --git a/engines/scumm/input.cpp b/engines/scumm/input.cpp
index ca353d4d504..6ab5674952b 100644
--- a/engines/scumm/input.cpp
+++ b/engines/scumm/input.cpp
@@ -397,250 +397,237 @@ void ScummEngine::processInput() {
#ifdef ENABLE_SCUMM_7_8
void ScummEngine_v8::processKeyboard(Common::KeyState lastKeyHit) {
- char tempStr[64];
-
- // F1 (the trigger for the original save/load dialog) is mapped to F5,
- // unless we chose to use the original GUI.
- if (!(_game.features & GF_DEMO) && lastKeyHit.keycode == Common::KEYCODE_F1 && lastKeyHit.hasFlags(0)) {
- if (isUsingOriginalGUI()) {
+ if (isUsingOriginalGUI()) {
+ // Set up an InfoDialog object for fetching the internal strings.
+ InfoDialog d(this, 0);
+ char tempStr[64];
+
+ // Main menu (allow both F1 and F5) mapping; unlike in
+ // the past we choose not to enable it without the
+ // original GUI selected as an option
+ if (!(_game.features & GF_DEMO) &&
+ (lastKeyHit.keycode == Common::KEYCODE_F1 || lastKeyHit.keycode == Common::KEYCODE_F5) &&
+ lastKeyHit.hasFlags(0)) {
lastKeyHit = Common::KeyState(Common::KEYCODE_F1, 315);
- } else {
- lastKeyHit = Common::KeyState(Common::KEYCODE_F5, 319);
}
- }
-
- // If we are using the original GUI, remap F5 to F1.
- if (isUsingOriginalGUI() && lastKeyHit.keycode == Common::KEYCODE_F5 && lastKeyHit.hasFlags(0)) {
- lastKeyHit = Common::KeyState(Common::KEYCODE_F1, 315);
- }
-
- // Alt-F5 should bring up the original save/load dialog, so map it to F1,
- // again, unless we chose to use the original GUI.
- if (!isUsingOriginalGUI() && lastKeyHit.keycode == Common::KEYCODE_F5 && lastKeyHit.hasFlags(Common::KBD_ALT)) {
- lastKeyHit = Common::KeyState(Common::KEYCODE_F1, 315);
- }
-
- // If a key script was specified (a V8 feature), and it's trigger
- // key was pressed, run it. Usually used to display the built-in menu.
- if (!(_game.features & GF_DEMO) && !isSmushActive() && _keyScriptNo && (_keyScriptKey == lastKeyHit.ascii)) {
- runScript(_keyScriptNo, 0, 0, 0);
- return;
- }
- // Set up an InfoDialog object for fetching the internal strings.
- InfoDialog d(this, 0);
-
- if (isUsingOriginalGUI() && lastKeyHit.keycode == VAR(VAR_PAUSE_KEY)) {
- // Force the cursor OFF...
- int8 oldCursorState = _cursor.state;
- _cursor.state = 0;
- CursorMan.showMouse(_cursor.state > 0);
- // "Game Paused. Press SPACE to Continue."
- showBannerAndPause(0, -1, d.getPlainEngineString(4));
- _cursor.state = oldCursorState;
- return;
- }
-
- if (isUsingOriginalGUI() && VAR(VAR_VERSION_KEY) != 0 &&
- lastKeyHit.keycode == Common::KEYCODE_v && lastKeyHit.hasFlags(Common::KBD_CTRL)) {
- showBannerAndPause(0, -1, _dataFileVersionString);
- // This is not the string being used by the interpreter, which is instead hardcoded
- // in the executable. The one used here is found in the data files.
- showBannerAndPause(0, -1, _engineVersionString);
- return;
- }
+ // Actually show the main menu screen...
+ if (!(_game.features & GF_DEMO) && !isSmushActive() && _keyScriptNo && (_keyScriptKey == lastKeyHit.ascii)) {
+ runScript(_keyScriptNo, 0, 0, 0);
+ return;
+ }
- if (isUsingOriginalGUI() &&
- (lastKeyHit.keycode == Common::KEYCODE_c && lastKeyHit.hasFlags(Common::KBD_CTRL))) {
- if (_game.features & GF_DEMO) {
- // "Are you sure you want to quit? (Y-N)"
- Common::KeyState ks = showBannerAndPause(0, -1, d.getPlainEngineString(30));
- if (ks.keycode == Common::KEYCODE_y) {
- quitGame();
- }
- } else {
- // Force the cursor to be ON...
+ if (lastKeyHit.keycode == VAR(VAR_PAUSE_KEY)) {
+ // Force the cursor OFF...
int8 oldCursorState = _cursor.state;
- _cursor.state = 1;
+ _cursor.state = 0;
CursorMan.showMouse(_cursor.state > 0);
-
- confirmExitDialog();
-
- // Restore the old cursor state...
+ // "Game Paused. Press SPACE to Continue."
+ showBannerAndPause(0, -1, d.getPlainEngineString(4));
_cursor.state = oldCursorState;
- CursorMan.showMouse(_cursor.state > 0);
+ return;
}
- return;
- }
+ if (VAR(VAR_VERSION_KEY) != 0 &&
+ lastKeyHit.keycode == Common::KEYCODE_v && lastKeyHit.hasFlags(Common::KBD_CTRL)) {
+ showBannerAndPause(0, -1, _dataFileVersionString);
+ // This is not the string being used by the interpreter, which is instead hardcoded
+ // in the executable. The one used here is found in the data files.
+ showBannerAndPause(0, -1, _engineVersionString);
+ return;
+ }
- if (isUsingOriginalGUI() &&
- (lastKeyHit.keycode == Common::KEYCODE_t && lastKeyHit.hasFlags(Common::KBD_CTRL))) {
- int voiceMode = VAR(VAR_VOICE_MODE);
+ if (lastKeyHit.keycode == Common::KEYCODE_c && lastKeyHit.hasFlags(Common::KBD_CTRL)) {
+ if (_game.features & GF_DEMO) {
+ // "Are you sure you want to quit? (Y-N)"
+ Common::KeyState ks = showBannerAndPause(0, -1, d.getPlainEngineString(30));
+ if (ks.keycode == Common::KEYCODE_y) {
+ quitGame();
+ }
+ } else {
+ // Force the cursor to be ON...
+ int8 oldCursorState = _cursor.state;
+ _cursor.state = 1;
+ CursorMan.showMouse(_cursor.state > 0);
- voiceMode++;
- if (voiceMode >= 3) {
- voiceMode = 0;
- }
+ confirmExitDialog();
- switch (voiceMode) {
- case 0: // "Voice Only"
- showBannerAndPause(0, 120, d.getPlainEngineString(28));
- break;
- case 1: // "Voice and Text"
- showBannerAndPause(0, 120, d.getPlainEngineString(26));
- break;
- default: // "Text Display Only"
- showBannerAndPause(0, 120, d.getPlainEngineString(27));
+ // Restore the old cursor state...
+ _cursor.state = oldCursorState;
+ CursorMan.showMouse(_cursor.state > 0);
+ }
+ return;
}
- ConfMan.setInt("original_gui_text_status", voiceMode);
- ConfMan.flushToDisk();
- syncSoundSettings();
- return;
- }
+ if (lastKeyHit.keycode == Common::KEYCODE_t && lastKeyHit.hasFlags(Common::KBD_CTRL)) {
+ int voiceMode = VAR(VAR_VOICE_MODE);
- if (isUsingOriginalGUI() &&
- (lastKeyHit.keycode == Common::KEYCODE_b && lastKeyHit.hasFlags(Common::KBD_CTRL))) {
- int curBufferCount = _imuseDigital->roundRobinSetBufferCount();
- // "iMuse buffer count changed to %d"
- showBannerAndPause(0, 90, d.getPlainEngineString(25), curBufferCount);
- return;
- }
+ voiceMode++;
+ if (voiceMode >= 3) {
+ voiceMode = 0;
+ }
- // "Music Volume Low ========= High"
- if (isUsingOriginalGUI() &&
- (lastKeyHit.keycode == Common::KEYCODE_o || lastKeyHit.keycode == Common::KEYCODE_p)) {
- Common::KeyState ks = lastKeyHit;
-
- int volume = _imuseDigital->diMUSEGetMusicGroupVol();
- do {
- if (ks.keycode == Common::KEYCODE_o) {
- volume -= 16;
- if (volume < 0)
- volume = 0;
- } else {
- volume += 16;
- if (volume > 127)
- volume = 127;
+ switch (voiceMode) {
+ case 0: // "Voice Only"
+ showBannerAndPause(0, 120, d.getPlainEngineString(28));
+ break;
+ case 1: // "Voice and Text"
+ showBannerAndPause(0, 120, d.getPlainEngineString(26));
+ break;
+ default: // "Text Display Only"
+ showBannerAndPause(0, 120, d.getPlainEngineString(27));
}
- strcpy(tempStr, d.getPlainEngineString(32));
- char *ptrToChar = strchr(tempStr, '=');
- memset(ptrToChar, '\v', 9);
- ptrToChar[volume / 15] = '\f';
-
- showBannerAndPause(0, 0, tempStr);
- ks = Common::KEYCODE_INVALID;
- bool leftBtnPressed = false, rightBtnPressed = false;
- waitForBannerInput(60, ks, leftBtnPressed, rightBtnPressed);
- } while (ks.keycode == Common::KEYCODE_o || ks.keycode == Common::KEYCODE_p);
- clearBanner();
- _imuseDigital->diMUSESetMusicGroupVol(volume);
- return;
- }
+ ConfMan.setInt("original_gui_text_status", voiceMode);
+ ConfMan.flushToDisk();
+ syncSoundSettings();
+ return;
+ }
- // "Voice Volume Low ========= High"
- if (isUsingOriginalGUI() &&
- (lastKeyHit.keycode == Common::KEYCODE_k || lastKeyHit.keycode == Common::KEYCODE_l)) {
- Common::KeyState ks = lastKeyHit;
-
- int volume = _imuseDigital->diMUSEGetVoiceGroupVol();
- do {
- if (ks.keycode == Common::KEYCODE_k) {
- volume -= 16;
- if (volume < 0)
- volume = 0;
- } else {
- volume += 16;
- if (volume > 127)
- volume = 127;
- }
+ if (lastKeyHit.keycode == Common::KEYCODE_b && lastKeyHit.hasFlags(Common::KBD_CTRL)) {
+ int curBufferCount = _imuseDigital->roundRobinSetBufferCount();
+ // "iMuse buffer count changed to %d"
+ showBannerAndPause(0, 90, d.getPlainEngineString(25), curBufferCount);
+ return;
+ }
- strcpy(tempStr, d.getPlainEngineString(33));
- char *ptrToChar = strchr(tempStr, '=');
- memset(ptrToChar, '\v', 9);
- ptrToChar[volume / 15] = '\f';
-
- showBannerAndPause(0, 0, tempStr);
- ks = Common::KEYCODE_INVALID;
- bool leftBtnPressed = false, rightBtnPressed = false;
- waitForBannerInput(60, ks, leftBtnPressed, rightBtnPressed);
- } while (ks.keycode == Common::KEYCODE_k || ks.keycode == Common::KEYCODE_l);
- clearBanner();
- _imuseDigital->diMUSESetVoiceGroupVol(volume);
- return;
- }
+ // "Music Volume Low ========= High"
+ if (isUsingOriginalGUI() &&
+ (lastKeyHit.keycode == Common::KEYCODE_o || lastKeyHit.keycode == Common::KEYCODE_p)) {
+ Common::KeyState ks = lastKeyHit;
+
+ int volume = _imuseDigital->diMUSEGetMusicGroupVol();
+ do {
+ if (ks.keycode == Common::KEYCODE_o) {
+ volume -= 16;
+ if (volume < 0)
+ volume = 0;
+ } else {
+ volume += 16;
+ if (volume > 127)
+ volume = 127;
+ }
- // "Sfx Volume Low ========= High"
- if (isUsingOriginalGUI() &&
- (lastKeyHit.keycode == Common::KEYCODE_n || lastKeyHit.keycode == Common::KEYCODE_m)) {
- Common::KeyState ks = lastKeyHit;
-
- int volume = _imuseDigital->diMUSEGetSFXGroupVol();
- do {
- if (ks.keycode == Common::KEYCODE_n) {
- volume -= 16;
- if (volume < 0)
- volume = 0;
- } else {
- volume += 16;
- if (volume > 127)
- volume = 127;
- }
+ strcpy(tempStr, d.getPlainEngineString(32));
+ char *ptrToChar = strchr(tempStr, '=');
+ memset(ptrToChar, '\v', 9);
+ ptrToChar[volume / 15] = '\f';
+
+ showBannerAndPause(0, 0, tempStr);
+ ks = Common::KEYCODE_INVALID;
+ bool leftBtnPressed = false, rightBtnPressed = false;
+ waitForBannerInput(60, ks, leftBtnPressed, rightBtnPressed);
+ } while (ks.keycode == Common::KEYCODE_o || ks.keycode == Common::KEYCODE_p);
+ clearBanner();
+ _imuseDigital->diMUSESetMusicGroupVol(volume);
+ return;
+ }
- strcpy(tempStr, d.getPlainEngineString(34));
- char *ptrToChar = strchr(tempStr, '=');
- memset(ptrToChar, '\v', 9);
- ptrToChar[volume / 15] = '\f';
-
- showBannerAndPause(0, 0, tempStr);
- ks = Common::KEYCODE_INVALID;
- bool leftBtnPressed = false, rightBtnPressed = false;
- waitForBannerInput(60, ks, leftBtnPressed, rightBtnPressed);
- } while (ks.keycode == Common::KEYCODE_n || ks.keycode == Common::KEYCODE_m);
- clearBanner();
- _imuseDigital->diMUSESetSFXGroupVol(volume);
- return;
- }
+ // "Voice Volume Low ========= High"
+ if (lastKeyHit.keycode == Common::KEYCODE_k || lastKeyHit.keycode == Common::KEYCODE_l) {
+ Common::KeyState ks = lastKeyHit;
+
+ int volume = _imuseDigital->diMUSEGetVoiceGroupVol();
+ do {
+ if (ks.keycode == Common::KEYCODE_k) {
+ volume -= 16;
+ if (volume < 0)
+ volume = 0;
+ } else {
+ volume += 16;
+ if (volume > 127)
+ volume = 127;
+ }
- // "Text Speed Slow ========== Fast"
- if (isUsingOriginalGUI() &&
- (lastKeyHit.ascii == '+' || lastKeyHit.ascii == '-')) {
- if (VAR_CHARINC == 0xFF)
+ strcpy(tempStr, d.getPlainEngineString(33));
+ char *ptrToChar = strchr(tempStr, '=');
+ memset(ptrToChar, '\v', 9);
+ ptrToChar[volume / 15] = '\f';
+
+ showBannerAndPause(0, 0, tempStr);
+ ks = Common::KEYCODE_INVALID;
+ bool leftBtnPressed = false, rightBtnPressed = false;
+ waitForBannerInput(60, ks, leftBtnPressed, rightBtnPressed);
+ } while (ks.keycode == Common::KEYCODE_k || ks.keycode == Common::KEYCODE_l);
+ clearBanner();
+ _imuseDigital->diMUSESetVoiceGroupVol(volume);
return;
+ }
- Common::KeyState ks = lastKeyHit;
+ // "Sfx Volume Low ========= High"
+ if (lastKeyHit.keycode == Common::KEYCODE_n || lastKeyHit.keycode == Common::KEYCODE_m) {
+ Common::KeyState ks = lastKeyHit;
+
+ int volume = _imuseDigital->diMUSEGetSFXGroupVol();
+ do {
+ if (ks.keycode == Common::KEYCODE_n) {
+ volume -= 16;
+ if (volume < 0)
+ volume = 0;
+ } else {
+ volume += 16;
+ if (volume > 127)
+ volume = 127;
+ }
- int volume = _imuseDigital->diMUSEGetSFXGroupVol();
- do {
- if (ks.ascii == '+') {
- VAR(VAR_CHARINC) -= 1;
- if (VAR(VAR_CHARINC) < 0)
- VAR(VAR_CHARINC) = 0;
- } else {
- VAR(VAR_CHARINC) += 1;
- if (VAR(VAR_CHARINC) > 9)
- VAR(VAR_CHARINC) = 9;
- }
+ strcpy(tempStr, d.getPlainEngineString(34));
+ char *ptrToChar = strchr(tempStr, '=');
+ memset(ptrToChar, '\v', 9);
+ ptrToChar[volume / 15] = '\f';
+
+ showBannerAndPause(0, 0, tempStr);
+ ks = Common::KEYCODE_INVALID;
+ bool leftBtnPressed = false, rightBtnPressed = false;
+ waitForBannerInput(60, ks, leftBtnPressed, rightBtnPressed);
+ } while (ks.keycode == Common::KEYCODE_n || ks.keycode == Common::KEYCODE_m);
+ clearBanner();
+ _imuseDigital->diMUSESetSFXGroupVol(volume);
+ return;
+ }
- strcpy(tempStr, d.getPlainEngineString(31));
- char *ptrToChar = strchr(tempStr, '=');
- memset(ptrToChar, '\v', 10);
- ptrToChar[9 - VAR(VAR_CHARINC)] = '\f';
-
- showBannerAndPause(0, 0, tempStr);
- ks = Common::KEYCODE_INVALID;
- bool leftBtnPressed = false, rightBtnPressed = false;
- waitForBannerInput(60, ks, leftBtnPressed, rightBtnPressed);
- } while (ks.ascii == '+' || ks.ascii == '-');
- clearBanner();
- _imuseDigital->diMUSESetSFXGroupVol(volume);
- return;
+ // "Text Speed Slow ========== Fast"
+ if (lastKeyHit.ascii == '+' || lastKeyHit.ascii == '-') {
+ if (VAR_CHARINC == 0xFF)
+ return;
+
+ Common::KeyState ks = lastKeyHit;
+
+ int volume = _imuseDigital->diMUSEGetSFXGroupVol();
+ do {
+ if (ks.ascii == '+') {
+ VAR(VAR_CHARINC) -= 1;
+ if (VAR(VAR_CHARINC) < 0)
+ VAR(VAR_CHARINC) = 0;
+ } else {
+ VAR(VAR_CHARINC) += 1;
+ if (VAR(VAR_CHARINC) > 9)
+ VAR(VAR_CHARINC) = 9;
+ }
+
+ strcpy(tempStr, d.getPlainEngineString(31));
+ char *ptrToChar = strchr(tempStr, '=');
+ memset(ptrToChar, '\v', 10);
+ ptrToChar[9 - VAR(VAR_CHARINC)] = '\f';
+
+ showBannerAndPause(0, 0, tempStr);
+ ks = Common::KEYCODE_INVALID;
+ bool leftBtnPressed = false, rightBtnPressed = false;
+ waitForBannerInput(60, ks, leftBtnPressed, rightBtnPressed);
+ } while (ks.ascii == '+' || ks.ascii == '-');
+ clearBanner();
+ _imuseDigital->diMUSESetSFXGroupVol(volume);
+ return;
+ }
+ }
+
+ // F1 (the trigger for the original save/load dialog) is mapped to F5
+ if (!(_game.features & GF_DEMO) && lastKeyHit.keycode == Common::KEYCODE_F1 && lastKeyHit.hasFlags(0)) {
+ lastKeyHit = Common::KeyState(Common::KEYCODE_F5, 319);
}
// Fall back to V7 behavior...
ScummEngine_v7::processKeyboard(lastKeyHit);
+
}
void ScummEngine_v7::processKeyboard(Common::KeyState lastKeyHit) {
Commit: 7fea664d20329eb01e3255f0eb79119fad52365b
https://github.com/scummvm/scummvm/commit/7fea664d20329eb01e3255f0eb79119fad52365b
Author: AndywinXp (andywinxp at gmail.com)
Date: 2022-08-06T13:33:56+02:00
Commit Message:
SCUMM: COMI: Fix screen restoring in some edge cases
Changed paths:
engines/scumm/gfx_gui.cpp
engines/scumm/scumm_v7.h
engines/scumm/string_v7.cpp
diff --git a/engines/scumm/gfx_gui.cpp b/engines/scumm/gfx_gui.cpp
index bcb823519a4..26c5904223f 100644
--- a/engines/scumm/gfx_gui.cpp
+++ b/engines/scumm/gfx_gui.cpp
@@ -147,7 +147,7 @@ Common::KeyState ScummEngine_v7::showBannerAndPause(int bannerId, int32 waitTime
// Draw it!
drawInternalGUIControl(0, 0);
- drawDirtyScreenParts();
+ ScummEngine::drawDirtyScreenParts();
// Wait until the engine receives a new Keyboard or Mouse input,
// unless we have specified a positive waitTime: in that case, the banner
@@ -190,7 +190,8 @@ void ScummEngine_v7::clearBanner() {
}
markRectAsDirty(_virtscr[kMainVirtScreen].number, 0, _screenWidth + 8, _screenTop, _screenHeight + _screenTop);
- drawDirtyScreenParts();
+ ScummEngine::drawDirtyScreenParts();
+ _system->updateScreen();
}
}
@@ -292,7 +293,7 @@ void ScummEngine_v7::drawInternalGUIControl(int id, bool useSecondaryColor) {
textYPos = relCentY + (boxSizeY - textHeight) / 2 + 1;
- // Finally, choose the color and enqueue the text message
+ // Finally, choose the color and draw the text message
if (useSecondaryColor)
lineColor = ctrl->secondaryLineColor;
else
@@ -303,7 +304,7 @@ void ScummEngine_v7::drawInternalGUIControl(int id, bool useSecondaryColor) {
else
strcpy(buttonString, "null button");
- enqueueText((const byte *)buttonString, textXPos, textYPos, lineColor, 1, (TextStyleFlags)centerFlag);
+ drawTextImmediately((const byte *)buttonString, textXPos, textYPos, lineColor, 1, (TextStyleFlags)centerFlag);
// Restore the previous charset
if (oldId)
@@ -364,7 +365,7 @@ void ScummEngine_v7::confirmExitDialog() {
int oldId = _charset->getCurID();
_charset->setCurID(1);
- boxWidth = ((_textV7->getStringHeight(msgLabelPtr) + 32) & 0xFFF0) + 8;
+ boxWidth = ((_textV7->getStringWidth(msgLabelPtr) + 32) & 0xFFF0) + 8;
if (boxWidth <= 400)
boxWidth = 400;
@@ -386,10 +387,23 @@ void ScummEngine_v7::confirmExitDialog() {
_emptyMsg,
true);
+ // Save the pixels which will be overwritten by the dialog,
+ // so that we can restore them later. Note that the interpreter
+ // doesn't do this, but we have to...
+ if (!_bannerMem) {
+ _bannerMemSize = _screenWidth * _screenHeight;
+ _bannerMem = (byte *)malloc(_bannerMemSize * sizeof(byte));
+ if (_bannerMem)
+ memcpy(
+ _bannerMem,
+ _virtscr[kMainVirtScreen].getPixels(0, _screenTop),
+ _bannerMemSize);
+ }
+
drawInternalGUIControl(0, 0);
// The text is drawn as a separate entity
- enqueueText((const byte *)msgLabelPtr, 320, 200, getBannerColor(32), 1, (TextStyleFlags) true);
+ drawTextImmediately((const byte *)msgLabelPtr, 320, 200, getBannerColor(32), 1, (TextStyleFlags) true);
// Now set up and draw the Yes and No buttons...
if (_textV7->getStringWidth(noLabelPtr) <= _textV7->getStringWidth(yesLabelPtr)) {
@@ -439,7 +453,7 @@ void ScummEngine_v7::confirmExitDialog() {
drawInternalGUIControl(0, 0);
// Done, draw everything to screen!
- drawDirtyScreenParts();
+ ScummEngine::drawDirtyScreenParts();
// Stay in the dialog while we keep pressing CTRL-C...
Common::KeyState ks;
@@ -467,8 +481,24 @@ void ScummEngine_v7::confirmExitDialog() {
// let's wait half that time...
waitForTimer(45 * 2);
- // Since we're not explicitly clearing the dialog graphics, set up a full redraw...
- _fullRedraw = true;
+ // Again, he interpreter does not explicitly restore the screen
+ // after finishing displaying this query dialog, but we have to...
+ if (_bannerMem) {
+ memcpy(
+ _virtscr[kMainVirtScreen].getPixels(0, _screenTop),
+ _bannerMem,
+ _bannerMemSize);
+ free(_bannerMem);
+ _bannerMem = nullptr;
+
+ if (isSmushActive()) {
+ return;
+ }
+
+ markRectAsDirty(_virtscr[kMainVirtScreen].number, 0, _screenWidth + 8, _screenTop, _screenHeight + _screenTop);
+ ScummEngine::drawDirtyScreenParts();
+ _system->updateScreen();
+ }
// Finally, resume the engine, clear the input state, and restore the charset.
pt.clear();
diff --git a/engines/scumm/scumm_v7.h b/engines/scumm/scumm_v7.h
index 86bc8cdbbab..ab659f935ca 100644
--- a/engines/scumm/scumm_v7.h
+++ b/engines/scumm/scumm_v7.h
@@ -154,6 +154,7 @@ protected:
void createTextRenderer(GlyphRenderer_v7 *gr) override;
void enqueueText(const byte *text, int x, int y, byte color, byte charset, TextStyleFlags flags);
+ void drawTextImmediately(const byte *text, int x, int y, byte color, byte charset, TextStyleFlags flags);
void drawBlastTexts() override;
void showMessageDialog(const byte *msg) override;
diff --git a/engines/scumm/string_v7.cpp b/engines/scumm/string_v7.cpp
index dbed0a8233d..5580ca7ed9b 100644
--- a/engines/scumm/string_v7.cpp
+++ b/engines/scumm/string_v7.cpp
@@ -428,6 +428,32 @@ void ScummEngine_v7::enqueueText(const byte *text, int x, int y, byte color, byt
bt.flags = flags;
}
+void ScummEngine_v7::drawTextImmediately(const byte *text, int x, int y, byte color, byte charset, TextStyleFlags flags) {
+ // This function allows for a string to be immediately
+ // drawn on the screen without having to enqueueing it.
+ byte msg[256];
+ Common::Rect rect = _defaultTextClipRect;
+ int effX = x;
+ TextStyleFlags effFlags = flags;
+ VirtScreen *vs = &_virtscr[kMainVirtScreen];
+
+ convertMessageToString(text, msg, sizeof(msg));
+
+ _charset->setCurID(charset);
+
+ // If a Hebrew String comes up that is still marked as kStyleAlignLeft we fix it here...
+ if (_language == Common::HE_ISR && !(flags & (kStyleAlignCenter | kStyleAlignRight))) {
+ effFlags = (TextStyleFlags)(flags | kStyleAlignRight);
+ effX = _screenWidth - 1 - effX;
+ }
+
+ _textV7->drawString((const char *)msg, (byte *)vs->getPixels(0, _screenTop), rect, effX, y, vs->pitch, color, effFlags);
+
+ rect.top += _screenTop;
+ rect.bottom += _screenTop;
+ markRectAsDirty(vs->number, rect);
+}
+
void ScummEngine_v7::drawBlastTexts() {
VirtScreen *vs = &_virtscr[kMainVirtScreen];
Commit: a121b5773fdc9bfc488415c42d1fb819dd41973c
https://github.com/scummvm/scummvm/commit/a121b5773fdc9bfc488415c42d1fb819dd41973c
Author: AndywinXp (andywinxp at gmail.com)
Date: 2022-08-06T13:33:56+02:00
Commit Message:
SCUMM: COMI: Fix regression after processKeyboard() refactoring
Changed paths:
engines/scumm/input.cpp
diff --git a/engines/scumm/input.cpp b/engines/scumm/input.cpp
index 6ab5674952b..1f2965a64af 100644
--- a/engines/scumm/input.cpp
+++ b/engines/scumm/input.cpp
@@ -412,8 +412,9 @@ void ScummEngine_v8::processKeyboard(Common::KeyState lastKeyHit) {
}
// Actually show the main menu screen...
- if (!(_game.features & GF_DEMO) && !isSmushActive() && _keyScriptNo && (_keyScriptKey == lastKeyHit.ascii)) {
- runScript(_keyScriptNo, 0, 0, 0);
+ if (!(_game.features & GF_DEMO) && _keyScriptNo && (_keyScriptKey == lastKeyHit.ascii)) {
+ if (!isSmushActive())
+ runScript(_keyScriptNo, 0, 0, 0);
return;
}
Commit: dfa6a898cf6a7e51489787d951b10aa8fc248428
https://github.com/scummvm/scummvm/commit/dfa6a898cf6a7e51489787d951b10aa8fc248428
Author: AndywinXp (andywinxp at gmail.com)
Date: 2022-08-06T13:33:56+02:00
Commit Message:
SCUMM: COMI: Remove leftover from refactoring
Changed paths:
engines/scumm/input.cpp
diff --git a/engines/scumm/input.cpp b/engines/scumm/input.cpp
index 1f2965a64af..a6e4bc0d818 100644
--- a/engines/scumm/input.cpp
+++ b/engines/scumm/input.cpp
@@ -493,8 +493,7 @@ void ScummEngine_v8::processKeyboard(Common::KeyState lastKeyHit) {
}
// "Music Volume Low ========= High"
- if (isUsingOriginalGUI() &&
- (lastKeyHit.keycode == Common::KEYCODE_o || lastKeyHit.keycode == Common::KEYCODE_p)) {
+ if (lastKeyHit.keycode == Common::KEYCODE_o || lastKeyHit.keycode == Common::KEYCODE_p) {
Common::KeyState ks = lastKeyHit;
int volume = _imuseDigital->diMUSEGetMusicGroupVol();
Commit: 22f00bc16ef3cf121ff86c4ead3d12404274433a
https://github.com/scummvm/scummvm/commit/22f00bc16ef3cf121ff86c4ead3d12404274433a
Author: AndywinXp (andywinxp at gmail.com)
Date: 2022-08-06T13:33:56+02:00
Commit Message:
SCUMM: Remove very old obsolete workaround
Changed paths:
engines/scumm/scumm.cpp
diff --git a/engines/scumm/scumm.cpp b/engines/scumm/scumm.cpp
index d58146abfa2..24324e2e83d 100644
--- a/engines/scumm/scumm.cpp
+++ b/engines/scumm/scumm.cpp
@@ -2391,8 +2391,6 @@ void ScummEngine::scummLoop(int delta) {
}
}
- if (VAR_GAME_LOADED != 0xFF)
- VAR(VAR_GAME_LOADED) = 0;
load_game:
scummLoop_handleSaveLoad();
Commit: 1fc726787d75945000083b908c576d3ee093b6ca
https://github.com/scummvm/scummvm/commit/1fc726787d75945000083b908c576d3ee093b6ca
Author: AndywinXp (andywinxp at gmail.com)
Date: 2022-08-06T13:33:56+02:00
Commit Message:
SCUMM: COMI: Limit demo keys to demo only
Changed paths:
engines/scumm/input.cpp
diff --git a/engines/scumm/input.cpp b/engines/scumm/input.cpp
index a6e4bc0d818..33e9e954ce4 100644
--- a/engines/scumm/input.cpp
+++ b/engines/scumm/input.cpp
@@ -492,131 +492,133 @@ void ScummEngine_v8::processKeyboard(Common::KeyState lastKeyHit) {
return;
}
- // "Music Volume Low ========= High"
- if (lastKeyHit.keycode == Common::KEYCODE_o || lastKeyHit.keycode == Common::KEYCODE_p) {
- Common::KeyState ks = lastKeyHit;
-
- int volume = _imuseDigital->diMUSEGetMusicGroupVol();
- do {
- if (ks.keycode == Common::KEYCODE_o) {
- volume -= 16;
- if (volume < 0)
- volume = 0;
- } else {
- volume += 16;
- if (volume > 127)
- volume = 127;
- }
-
- strcpy(tempStr, d.getPlainEngineString(32));
- char *ptrToChar = strchr(tempStr, '=');
- memset(ptrToChar, '\v', 9);
- ptrToChar[volume / 15] = '\f';
-
- showBannerAndPause(0, 0, tempStr);
- ks = Common::KEYCODE_INVALID;
- bool leftBtnPressed = false, rightBtnPressed = false;
- waitForBannerInput(60, ks, leftBtnPressed, rightBtnPressed);
- } while (ks.keycode == Common::KEYCODE_o || ks.keycode == Common::KEYCODE_p);
- clearBanner();
- _imuseDigital->diMUSESetMusicGroupVol(volume);
- return;
- }
-
- // "Voice Volume Low ========= High"
- if (lastKeyHit.keycode == Common::KEYCODE_k || lastKeyHit.keycode == Common::KEYCODE_l) {
- Common::KeyState ks = lastKeyHit;
-
- int volume = _imuseDigital->diMUSEGetVoiceGroupVol();
- do {
- if (ks.keycode == Common::KEYCODE_k) {
- volume -= 16;
- if (volume < 0)
- volume = 0;
- } else {
- volume += 16;
- if (volume > 127)
- volume = 127;
- }
-
- strcpy(tempStr, d.getPlainEngineString(33));
- char *ptrToChar = strchr(tempStr, '=');
- memset(ptrToChar, '\v', 9);
- ptrToChar[volume / 15] = '\f';
-
- showBannerAndPause(0, 0, tempStr);
- ks = Common::KEYCODE_INVALID;
- bool leftBtnPressed = false, rightBtnPressed = false;
- waitForBannerInput(60, ks, leftBtnPressed, rightBtnPressed);
- } while (ks.keycode == Common::KEYCODE_k || ks.keycode == Common::KEYCODE_l);
- clearBanner();
- _imuseDigital->diMUSESetVoiceGroupVol(volume);
- return;
- }
-
- // "Sfx Volume Low ========= High"
- if (lastKeyHit.keycode == Common::KEYCODE_n || lastKeyHit.keycode == Common::KEYCODE_m) {
- Common::KeyState ks = lastKeyHit;
-
- int volume = _imuseDigital->diMUSEGetSFXGroupVol();
- do {
- if (ks.keycode == Common::KEYCODE_n) {
- volume -= 16;
- if (volume < 0)
- volume = 0;
- } else {
- volume += 16;
- if (volume > 127)
- volume = 127;
- }
-
- strcpy(tempStr, d.getPlainEngineString(34));
- char *ptrToChar = strchr(tempStr, '=');
- memset(ptrToChar, '\v', 9);
- ptrToChar[volume / 15] = '\f';
-
- showBannerAndPause(0, 0, tempStr);
- ks = Common::KEYCODE_INVALID;
- bool leftBtnPressed = false, rightBtnPressed = false;
- waitForBannerInput(60, ks, leftBtnPressed, rightBtnPressed);
- } while (ks.keycode == Common::KEYCODE_n || ks.keycode == Common::KEYCODE_m);
- clearBanner();
- _imuseDigital->diMUSESetSFXGroupVol(volume);
- return;
- }
+ if (_game.features & GF_DEMO) {
+ // "Music Volume Low ========= High"
+ if (lastKeyHit.keycode == Common::KEYCODE_o || lastKeyHit.keycode == Common::KEYCODE_p) {
+ Common::KeyState ks = lastKeyHit;
+
+ int volume = _imuseDigital->diMUSEGetMusicGroupVol();
+ do {
+ if (ks.keycode == Common::KEYCODE_o) {
+ volume -= 16;
+ if (volume < 0)
+ volume = 0;
+ } else {
+ volume += 16;
+ if (volume > 127)
+ volume = 127;
+ }
+
+ strcpy(tempStr, d.getPlainEngineString(32));
+ char *ptrToChar = strchr(tempStr, '=');
+ memset(ptrToChar, '\v', 9);
+ ptrToChar[volume / 15] = '\f';
+
+ showBannerAndPause(0, 0, tempStr);
+ ks = Common::KEYCODE_INVALID;
+ bool leftBtnPressed = false, rightBtnPressed = false;
+ waitForBannerInput(60, ks, leftBtnPressed, rightBtnPressed);
+ } while (ks.keycode == Common::KEYCODE_o || ks.keycode == Common::KEYCODE_p);
+ clearBanner();
+ _imuseDigital->diMUSESetMusicGroupVol(volume);
+ return;
+ }
- // "Text Speed Slow ========== Fast"
- if (lastKeyHit.ascii == '+' || lastKeyHit.ascii == '-') {
- if (VAR_CHARINC == 0xFF)
+ // "Voice Volume Low ========= High"
+ if (lastKeyHit.keycode == Common::KEYCODE_k || lastKeyHit.keycode == Common::KEYCODE_l) {
+ Common::KeyState ks = lastKeyHit;
+
+ int volume = _imuseDigital->diMUSEGetVoiceGroupVol();
+ do {
+ if (ks.keycode == Common::KEYCODE_k) {
+ volume -= 16;
+ if (volume < 0)
+ volume = 0;
+ } else {
+ volume += 16;
+ if (volume > 127)
+ volume = 127;
+ }
+
+ strcpy(tempStr, d.getPlainEngineString(33));
+ char *ptrToChar = strchr(tempStr, '=');
+ memset(ptrToChar, '\v', 9);
+ ptrToChar[volume / 15] = '\f';
+
+ showBannerAndPause(0, 0, tempStr);
+ ks = Common::KEYCODE_INVALID;
+ bool leftBtnPressed = false, rightBtnPressed = false;
+ waitForBannerInput(60, ks, leftBtnPressed, rightBtnPressed);
+ } while (ks.keycode == Common::KEYCODE_k || ks.keycode == Common::KEYCODE_l);
+ clearBanner();
+ _imuseDigital->diMUSESetVoiceGroupVol(volume);
return;
+ }
- Common::KeyState ks = lastKeyHit;
-
- int volume = _imuseDigital->diMUSEGetSFXGroupVol();
- do {
- if (ks.ascii == '+') {
- VAR(VAR_CHARINC) -= 1;
- if (VAR(VAR_CHARINC) < 0)
- VAR(VAR_CHARINC) = 0;
- } else {
- VAR(VAR_CHARINC) += 1;
- if (VAR(VAR_CHARINC) > 9)
- VAR(VAR_CHARINC) = 9;
- }
+ // "Sfx Volume Low ========= High"
+ if (lastKeyHit.keycode == Common::KEYCODE_n || lastKeyHit.keycode == Common::KEYCODE_m) {
+ Common::KeyState ks = lastKeyHit;
+
+ int volume = _imuseDigital->diMUSEGetSFXGroupVol();
+ do {
+ if (ks.keycode == Common::KEYCODE_n) {
+ volume -= 16;
+ if (volume < 0)
+ volume = 0;
+ } else {
+ volume += 16;
+ if (volume > 127)
+ volume = 127;
+ }
+
+ strcpy(tempStr, d.getPlainEngineString(34));
+ char *ptrToChar = strchr(tempStr, '=');
+ memset(ptrToChar, '\v', 9);
+ ptrToChar[volume / 15] = '\f';
+
+ showBannerAndPause(0, 0, tempStr);
+ ks = Common::KEYCODE_INVALID;
+ bool leftBtnPressed = false, rightBtnPressed = false;
+ waitForBannerInput(60, ks, leftBtnPressed, rightBtnPressed);
+ } while (ks.keycode == Common::KEYCODE_n || ks.keycode == Common::KEYCODE_m);
+ clearBanner();
+ _imuseDigital->diMUSESetSFXGroupVol(volume);
+ return;
+ }
- strcpy(tempStr, d.getPlainEngineString(31));
- char *ptrToChar = strchr(tempStr, '=');
- memset(ptrToChar, '\v', 10);
- ptrToChar[9 - VAR(VAR_CHARINC)] = '\f';
-
- showBannerAndPause(0, 0, tempStr);
- ks = Common::KEYCODE_INVALID;
- bool leftBtnPressed = false, rightBtnPressed = false;
- waitForBannerInput(60, ks, leftBtnPressed, rightBtnPressed);
- } while (ks.ascii == '+' || ks.ascii == '-');
- clearBanner();
- _imuseDigital->diMUSESetSFXGroupVol(volume);
- return;
+ // "Text Speed Slow ========== Fast"
+ if (lastKeyHit.ascii == '+' || lastKeyHit.ascii == '-') {
+ if (VAR_CHARINC == 0xFF)
+ return;
+
+ Common::KeyState ks = lastKeyHit;
+
+ int volume = _imuseDigital->diMUSEGetSFXGroupVol();
+ do {
+ if (ks.ascii == '+') {
+ VAR(VAR_CHARINC) -= 1;
+ if (VAR(VAR_CHARINC) < 0)
+ VAR(VAR_CHARINC) = 0;
+ } else {
+ VAR(VAR_CHARINC) += 1;
+ if (VAR(VAR_CHARINC) > 9)
+ VAR(VAR_CHARINC) = 9;
+ }
+
+ strcpy(tempStr, d.getPlainEngineString(31));
+ char *ptrToChar = strchr(tempStr, '=');
+ memset(ptrToChar, '\v', 10);
+ ptrToChar[9 - VAR(VAR_CHARINC)] = '\f';
+
+ showBannerAndPause(0, 0, tempStr);
+ ks = Common::KEYCODE_INVALID;
+ bool leftBtnPressed = false, rightBtnPressed = false;
+ waitForBannerInput(60, ks, leftBtnPressed, rightBtnPressed);
+ } while (ks.ascii == '+' || ks.ascii == '-');
+ clearBanner();
+ _imuseDigital->diMUSESetSFXGroupVol(volume);
+ return;
+ }
}
}
Commit: f9010ca8240bf71e0b14b50f2352be19ccc920d9
https://github.com/scummvm/scummvm/commit/f9010ca8240bf71e0b14b50f2352be19ccc920d9
Author: AndywinXp (andywinxp at gmail.com)
Date: 2022-08-06T13:33:56+02:00
Commit Message:
SCUMM: COMI: Fix original GUI glitches with blastTexts and blastObjects
Changed paths:
engines/scumm/gfx.cpp
engines/scumm/scumm.cpp
engines/scumm/scumm_v6.h
diff --git a/engines/scumm/gfx.cpp b/engines/scumm/gfx.cpp
index a4705aec6d2..d5b012a0a9b 100644
--- a/engines/scumm/gfx.cpp
+++ b/engines/scumm/gfx.cpp
@@ -572,8 +572,10 @@ void ScummEngine_v6::drawDirtyScreenParts() {
ScummEngine::drawDirtyScreenParts();
// Remove all blasted objects/text again.
- removeBlastTexts();
- removeBlastObjects();
+ if (_game.version < 8) {
+ removeBlastTexts();
+ removeBlastObjects();
+ }
}
/**
diff --git a/engines/scumm/scumm.cpp b/engines/scumm/scumm.cpp
index 24324e2e83d..cd7e1c00662 100644
--- a/engines/scumm/scumm.cpp
+++ b/engines/scumm/scumm.cpp
@@ -2373,6 +2373,17 @@ void ScummEngine::scummLoop(int delta) {
processInput();
+ // Saving is performed here in v8; this is important when saving the thumbnail,
+ // which would otherwise miss blastObjects (and possibly more) on the bitmap.
+ // Speaking of the devil, blastObjects are removed right after this operation...
+ // We also remove blastTexts here, being that this isn't done explicitly in the
+ // original, but we still need to...
+ if (_game.version == 8) {
+ scummLoop_handleSaveLoad();
+ ((ScummEngine_v6 *)this)->removeBlastObjects();
+ ((ScummEngine_v7 *)this)->removeBlastTexts();
+ }
+
scummLoop_updateScummVars();
if (_game.features & GF_AUDIOTRACKS) {
@@ -2391,8 +2402,9 @@ void ScummEngine::scummLoop(int delta) {
}
}
+ if (_game.version < 8)
load_game:
- scummLoop_handleSaveLoad();
+ scummLoop_handleSaveLoad();
if (_completeScreenRedraw) {
clearCharsetMask();
diff --git a/engines/scumm/scumm_v6.h b/engines/scumm/scumm_v6.h
index fcb1c6f764c..c11d1b38897 100644
--- a/engines/scumm/scumm_v6.h
+++ b/engines/scumm/scumm_v6.h
@@ -130,6 +130,7 @@ protected:
int findFreeArrayId();
public: // FIXME. TODO
void nukeArray(int array);
+ void removeBlastObjects();
protected:
virtual int readArray(int array, int index, int base);
@@ -154,7 +155,7 @@ protected:
int objectHeight, int scaleX, int scaleY, int image, int mode);
void drawBlastObjects();
void drawBlastObject(BlastObject *eo);
- void removeBlastObjects();
+
void removeBlastObject(BlastObject *eo);
void clearDrawQueues() override;
Commit: cb0e7cee16eb8389d25b159da93dee89f5b4cf05
https://github.com/scummvm/scummvm/commit/cb0e7cee16eb8389d25b159da93dee89f5b4cf05
Author: AndywinXp (andywinxp at gmail.com)
Date: 2022-08-06T13:33:56+02:00
Commit Message:
SCUMM: Fix compilation without v7-8 enabled
Changed paths:
engines/scumm/scumm.cpp
diff --git a/engines/scumm/scumm.cpp b/engines/scumm/scumm.cpp
index cd7e1c00662..06ced45cccf 100644
--- a/engines/scumm/scumm.cpp
+++ b/engines/scumm/scumm.cpp
@@ -2381,7 +2381,9 @@ void ScummEngine::scummLoop(int delta) {
if (_game.version == 8) {
scummLoop_handleSaveLoad();
((ScummEngine_v6 *)this)->removeBlastObjects();
+#ifdef ENABLE_SCUMM_7_8
((ScummEngine_v7 *)this)->removeBlastTexts();
+#endif
}
scummLoop_updateScummVars();
Commit: 5b58afff6141dced9a5e3c2260fbb65d089fa8c3
https://github.com/scummvm/scummvm/commit/5b58afff6141dced9a5e3c2260fbb65d089fa8c3
Author: AndywinXp (andywinxp at gmail.com)
Date: 2022-08-06T13:33:56+02:00
Commit Message:
SCUMM: COMI: Fix texts/objects glitch when exiting through main menu
Changed paths:
engines/scumm/script_v8.cpp
diff --git a/engines/scumm/script_v8.cpp b/engines/scumm/script_v8.cpp
index 7742afcda10..8fc71a185af 100644
--- a/engines/scumm/script_v8.cpp
+++ b/engines/scumm/script_v8.cpp
@@ -1183,7 +1183,9 @@ void ScummEngine_v8::o8_kernelSetFunctions() {
break;
case 34: // queryQuit
if (isUsingOriginalGUI()) {
- confirmExitDialog();
+ // Create an artificial CTRL-C keyPress
+ _keyPressed = Common::KEYCODE_c;
+ _keyPressed.flags |= Common::KBD_CTRL;
} else {
if (ConfMan.getBool("confirm_exit"))
confirmExitDialog();
Commit: 6ee5f03ffa15cfd02fa5bd8174164626e4110db1
https://github.com/scummvm/scummvm/commit/6ee5f03ffa15cfd02fa5bd8174164626e4110db1
Author: AndywinXp (andywinxp at gmail.com)
Date: 2022-08-06T13:33:56+02:00
Commit Message:
SCUMM: v7-8: Fix correct moment to call checkExecVerbs()
Also, remove 20 years old workarounds because of this
Changed paths:
engines/scumm/saveload.cpp
engines/scumm/script_v6.cpp
engines/scumm/scumm.cpp
diff --git a/engines/scumm/saveload.cpp b/engines/scumm/saveload.cpp
index c53db76a98c..af65cee12e0 100644
--- a/engines/scumm/saveload.cpp
+++ b/engines/scumm/saveload.cpp
@@ -739,11 +739,6 @@ bool ScummEngine::loadState(int slot, bool compat, Common::String &filename) {
sh = _screenH;
#ifdef ENABLE_SCUMM_7_8
- // Remove any blast text leftovers
- if (_game.version >= 7) {
- ((ScummEngine_v7 *)this)->removeBlastTexts();
- }
-
if (_game.version == 8 && isUsingOriginalGUI()) {
// If we are loading a savegame from the ScummVM launcher these two
// variables are going to be unassigned, since the game does not save these
diff --git a/engines/scumm/script_v6.cpp b/engines/scumm/script_v6.cpp
index f923a678dd0..5359f83e70d 100644
--- a/engines/scumm/script_v6.cpp
+++ b/engines/scumm/script_v6.cpp
@@ -781,27 +781,6 @@ void ScummEngine_v6::o6_startScript() {
return;
}
- // WORKAROUND bug #3591: When turning pages in the recipe book
- // (found on Blood Island), there is a brief moment where it displays
- // text from two different pages at the same time.
- //
- // The content of the books is drawing (in an endless loop) by local
- // script 2007. Changing the page is handled by script 2006, which
- // first stops script 2007; then switches the page; then restarts
- // script 2007. But it fails to clear the blast texts beforehand.
- // Hence, the next time blast text is drawn, both the old one (from
- // the old instance of script 2007) and the new text (from the new
- // instance) are briefly drawn simultaneously.
- //
- // This looks like a script bug to me (a missing call to clearTextQueue).
- // But this could also hint at a subtle bug in ScummVM; we should check
- // whether this bug occurs with the original engine or not.
- if (_game.id == GID_CMI && script == 2007 &&
- _currentRoom == 62 && vm.slot[_currentScript].number == 2006) {
-
- removeBlastTexts();
- }
-
runScript(script, (flags & 1) != 0, (flags & 2) != 0, args);
}
diff --git a/engines/scumm/scumm.cpp b/engines/scumm/scumm.cpp
index 06ced45cccf..4f63340d6fd 100644
--- a/engines/scumm/scumm.cpp
+++ b/engines/scumm/scumm.cpp
@@ -2373,13 +2373,19 @@ void ScummEngine::scummLoop(int delta) {
processInput();
+ // In v7-8 this function is executed at the end of processInput().
+ // we emulate the same behavior by calling it here...
+ if (_game.version >= 7)
+ checkExecVerbs();
+
// Saving is performed here in v8; this is important when saving the thumbnail,
- // which would otherwise miss blastObjects (and possibly more) on the bitmap.
- // Speaking of the devil, blastObjects are removed right after this operation...
- // We also remove blastTexts here, being that this isn't done explicitly in the
- // original, but we still need to...
+ // which would otherwise miss blastObjects/Texts on the bitmap.
if (_game.version == 8) {
scummLoop_handleSaveLoad();
+ }
+
+ // BlastObjects/Texts are removed in this moment of the codepath, in v7-8...
+ if (_game.version >= 7) {
((ScummEngine_v6 *)this)->removeBlastObjects();
#ifdef ENABLE_SCUMM_7_8
((ScummEngine_v7 *)this)->removeBlastTexts();
@@ -2432,8 +2438,15 @@ load_game:
if (_game.heversion >= 80) {
((SoundHE *)_sound)->processSoundCode();
}
+
runAllScripts();
- checkExecVerbs();
+
+ // SCUMM v7-8 executes checkExecVerbs inside the function
+ // which processes keyboard inputs, so we handle it above
+ // in that case.
+ if (_game.version < 7)
+ checkExecVerbs();
+
checkAndRunSentenceScript();
if (shouldQuit())
Commit: 1561996dff586c5aeb08a0a95c394760c8952790
https://github.com/scummvm/scummvm/commit/1561996dff586c5aeb08a0a95c394760c8952790
Author: AndywinXp (andywinxp at gmail.com)
Date: 2022-08-06T13:33:56+02:00
Commit Message:
SCUMM: v7-8: Apply blast pipeline corrections also to v7
Changed paths:
engines/scumm/gfx.cpp
diff --git a/engines/scumm/gfx.cpp b/engines/scumm/gfx.cpp
index d5b012a0a9b..24f7d63a0f4 100644
--- a/engines/scumm/gfx.cpp
+++ b/engines/scumm/gfx.cpp
@@ -571,8 +571,9 @@ void ScummEngine_v6::drawDirtyScreenParts() {
// Call the original method.
ScummEngine::drawDirtyScreenParts();
- // Remove all blasted objects/text again.
- if (_game.version < 8) {
+ // Remove all blasted objects/text again, except
+ // for v7-8 which do that at a later time.
+ if (_game.version < 7) {
removeBlastTexts();
removeBlastObjects();
}
Commit: a0cbacf26144706c05d9d8af599552f0487ec5a4
https://github.com/scummvm/scummvm/commit/a0cbacf26144706c05d9d8af599552f0487ec5a4
Author: AndywinXp (andywinxp at gmail.com)
Date: 2022-08-06T13:33:56+02:00
Commit Message:
SCUMM: v7-8: Amend removing call to removeBlastTexts()
So... apparently we need this :-)
Changed paths:
engines/scumm/saveload.cpp
diff --git a/engines/scumm/saveload.cpp b/engines/scumm/saveload.cpp
index af65cee12e0..c53db76a98c 100644
--- a/engines/scumm/saveload.cpp
+++ b/engines/scumm/saveload.cpp
@@ -739,6 +739,11 @@ bool ScummEngine::loadState(int slot, bool compat, Common::String &filename) {
sh = _screenH;
#ifdef ENABLE_SCUMM_7_8
+ // Remove any blast text leftovers
+ if (_game.version >= 7) {
+ ((ScummEngine_v7 *)this)->removeBlastTexts();
+ }
+
if (_game.version == 8 && isUsingOriginalGUI()) {
// If we are loading a savegame from the ScummVM launcher these two
// variables are going to be unassigned, since the game does not save these
Commit: 73586c04a3d8c1c1470268f0f8d2d75d5240b136
https://github.com/scummvm/scummvm/commit/73586c04a3d8c1c1470268f0f8d2d75d5240b136
Author: AndywinXp (andywinxp at gmail.com)
Date: 2022-08-06T13:33:56+02:00
Commit Message:
SCUMM: COMI: Prevent saving from the GMM on the original main menu
Changed paths:
engines/scumm/saveload.cpp
diff --git a/engines/scumm/saveload.cpp b/engines/scumm/saveload.cpp
index c53db76a98c..173a8350351 100644
--- a/engines/scumm/saveload.cpp
+++ b/engines/scumm/saveload.cpp
@@ -133,13 +133,15 @@ bool ScummEngine::canSaveGameStateCurrently() {
#ifdef ENABLE_SCUMM_7_8
// COMI always disables saving/loading (to tell the truth:
// the main menu) via its scripts, thus we need to make an
- // exception here. This the same forced overwriting of the
- // script decisions as in ScummEngine::processKeyboard.
+ // exception here, and always enable it unless we're on the
+ // original save/load screen. This the same forced overwriting
+ // of the script decisions as in ScummEngine::processKeyboard.
// Also, disable saving when a SAN video is playing.
if (_game.version >= 7 && ((ScummEngine_v7 *)this)->isSmushActive())
return false;
+
if (_game.id == GID_CMI)
- return true;
+ return _currentRoom != 92;
#endif
// SCUMM v4+ doesn't allow saving in room 0 or if
Commit: 1ac282c1e848f9afa7ae3103dd7531eb14fe1764
https://github.com/scummvm/scummvm/commit/1ac282c1e848f9afa7ae3103dd7531eb14fe1764
Author: AndywinXp (andywinxp at gmail.com)
Date: 2022-08-06T13:33:56+02:00
Commit Message:
SCUMM: COMI: Add fallback thumbnail for original menu
Changed paths:
engines/scumm/saveload.cpp
diff --git a/engines/scumm/saveload.cpp b/engines/scumm/saveload.cpp
index 173a8350351..2ef17ad9226 100644
--- a/engines/scumm/saveload.cpp
+++ b/engines/scumm/saveload.cpp
@@ -271,7 +271,17 @@ void ScummEngine_v8::stampScreenShot(int slot, int boxX, int boxY, int boxWidth,
}
heightSlice += 120;
}
-
+ } else {
+ // Fallback: this is an old savegame which does not have a SCUMM v8 thumbnail,
+ // so let's just show a brownish box which looks nice enough superimposed on
+ // the Captain's log yellowish background...
+ rgb = 0x001627;
+ color = remapPaletteColor(
+ brightness * ((rgb & 0xFF) >> 0) / 0xFF,
+ brightness * ((rgb & 0xFF00) >> 8) / 0xFF,
+ brightness * ((rgb & 0xFF0000) >> 16) / 0xFF,
+ -1);
+ drawBox(boxX, boxY, boxWidth, boxHeight - 1, color);
}
}
Commit: cb7e4592642f2e0de6cbfd31f879f06482055f3f
https://github.com/scummvm/scummvm/commit/cb7e4592642f2e0de6cbfd31f879f06482055f3f
Author: AndywinXp (andywinxp at gmail.com)
Date: 2022-08-06T13:33:56+02:00
Commit Message:
SCUMM: Fix subtitles parameters not being saved
Changed paths:
engines/scumm/saveload.cpp
diff --git a/engines/scumm/saveload.cpp b/engines/scumm/saveload.cpp
index 2ef17ad9226..e65f2a71e51 100644
--- a/engines/scumm/saveload.cpp
+++ b/engines/scumm/saveload.cpp
@@ -1851,6 +1851,8 @@ void syncWithSerializer(Common::Serializer &s, ScummEngine_v7::SubtitleText &st)
s.syncAsSint16LE(st.xpos, VER(61));
s.syncAsSint16LE(st.ypos, VER(61));
s.syncAsByte(st.actorSpeechMsg, VER(61));
+ s.syncAsByte(st.center, VER(106));
+ s.syncAsByte(st.wrap, VER(106));
}
void ScummEngine_v8::saveLoadWithSerializer(Common::Serializer &s) {
Commit: e1f0b5a25d806692fc6d7a81185e5c0cd39190f7
https://github.com/scummvm/scummvm/commit/e1f0b5a25d806692fc6d7a81185e5c0cd39190f7
Author: AndywinXp (andywinxp at gmail.com)
Date: 2022-08-06T13:33:56+02:00
Commit Message:
SCUMM: COMI (non-demo): Disable + and - keys for original GUI
Changed paths:
engines/scumm/input.cpp
diff --git a/engines/scumm/input.cpp b/engines/scumm/input.cpp
index 33e9e954ce4..bf17762f8fa 100644
--- a/engines/scumm/input.cpp
+++ b/engines/scumm/input.cpp
@@ -585,41 +585,45 @@ void ScummEngine_v8::processKeyboard(Common::KeyState lastKeyHit) {
_imuseDigital->diMUSESetSFXGroupVol(volume);
return;
}
+ }
- // "Text Speed Slow ========== Fast"
- if (lastKeyHit.ascii == '+' || lastKeyHit.ascii == '-') {
- if (VAR_CHARINC == 0xFF)
- return;
-
- Common::KeyState ks = lastKeyHit;
+ // "Text Speed Slow ========== Fast"
+ if (lastKeyHit.ascii == '+' || lastKeyHit.ascii == '-') {
+ if (!(_game.features & GF_DEMO)) {
+ // Catch the input and bail out
+ return;
+ }
- int volume = _imuseDigital->diMUSEGetSFXGroupVol();
- do {
- if (ks.ascii == '+') {
- VAR(VAR_CHARINC) -= 1;
- if (VAR(VAR_CHARINC) < 0)
- VAR(VAR_CHARINC) = 0;
- } else {
- VAR(VAR_CHARINC) += 1;
- if (VAR(VAR_CHARINC) > 9)
- VAR(VAR_CHARINC) = 9;
- }
+ if (VAR_CHARINC == 0xFF)
+ return;
- strcpy(tempStr, d.getPlainEngineString(31));
- char *ptrToChar = strchr(tempStr, '=');
- memset(ptrToChar, '\v', 10);
- ptrToChar[9 - VAR(VAR_CHARINC)] = '\f';
+ Common::KeyState ks = lastKeyHit;
+
+ do {
+ if (ks.ascii == '+') {
+ VAR(VAR_CHARINC) -= 1;
+ if (VAR(VAR_CHARINC) < 0)
+ VAR(VAR_CHARINC) = 0;
+ } else {
+ VAR(VAR_CHARINC) += 1;
+ if (VAR(VAR_CHARINC) > 9)
+ VAR(VAR_CHARINC) = 9;
+ }
- showBannerAndPause(0, 0, tempStr);
- ks = Common::KEYCODE_INVALID;
- bool leftBtnPressed = false, rightBtnPressed = false;
- waitForBannerInput(60, ks, leftBtnPressed, rightBtnPressed);
- } while (ks.ascii == '+' || ks.ascii == '-');
- clearBanner();
- _imuseDigital->diMUSESetSFXGroupVol(volume);
- return;
- }
+ strcpy(tempStr, d.getPlainEngineString(31));
+ char *ptrToChar = strchr(tempStr, '=');
+ memset(ptrToChar, '\v', 10);
+ ptrToChar[9 - VAR(VAR_CHARINC)] = '\f';
+
+ showBannerAndPause(0, 0, tempStr);
+ ks = Common::KEYCODE_INVALID;
+ bool leftBtnPressed = false, rightBtnPressed = false;
+ waitForBannerInput(60, ks, leftBtnPressed, rightBtnPressed);
+ } while (ks.ascii == '+' || ks.ascii == '-');
+ clearBanner();
+ return;
}
+
}
// F1 (the trigger for the original save/load dialog) is mapped to F5
Commit: ced78b19d5fba232a25844e16f3e86a77dab2e80
https://github.com/scummvm/scummvm/commit/ced78b19d5fba232a25844e16f3e86a77dab2e80
Author: AndywinXp (andywinxp at gmail.com)
Date: 2022-08-06T13:33:56+02:00
Commit Message:
SCUMM: COMI: Fix some more text/GUI rendering glitches
Changed paths:
engines/scumm/object.cpp
engines/scumm/scumm.cpp
engines/scumm/scumm_v7.h
engines/scumm/string_v7.cpp
diff --git a/engines/scumm/object.cpp b/engines/scumm/object.cpp
index a0dbb2be65c..62b8bfeb659 100644
--- a/engines/scumm/object.cpp
+++ b/engines/scumm/object.cpp
@@ -1825,12 +1825,12 @@ void ScummEngine_v6::drawBlastObject(BlastObject *eo) {
void ScummEngine_v6::removeBlastObjects() {
BlastObject *eo;
- int i;
eo = _blastObjectQueue;
- for (i = 0; i < _blastObjectQueuePos; i++, eo++) {
+ for (int i = 0; i < _blastObjectQueuePos; i++, eo++) {
removeBlastObject(eo);
}
+
_blastObjectQueuePos = 0;
}
diff --git a/engines/scumm/scumm.cpp b/engines/scumm/scumm.cpp
index 4f63340d6fd..0a379fa658b 100644
--- a/engines/scumm/scumm.cpp
+++ b/engines/scumm/scumm.cpp
@@ -2384,7 +2384,15 @@ void ScummEngine::scummLoop(int delta) {
scummLoop_handleSaveLoad();
}
- // BlastObjects/Texts are removed in this moment of the codepath, in v7-8...
+ // BlastObjects/Texts are removed in this moment of the codepath, in v7-8.
+ // V8 should just reset the queue and the rects should be restored somewhere else.
+ //
+ // We do that for the texts just after calling runAllScripts(), but this method
+ // doesn't quite work as well for the blastObjects as it does for the texts, so
+ // for now we'll have to live with one known glitch: if a system dialog is shown
+ // on the main menu (i.e. "Do you want to replace this saved game? (Y/N)"), it
+ // will wipe out all the blastObjects (the empty thumbnail rectangles) for the duration
+ // of said dialog.
if (_game.version >= 7) {
((ScummEngine_v6 *)this)->removeBlastObjects();
#ifdef ENABLE_SCUMM_7_8
@@ -2410,6 +2418,17 @@ void ScummEngine::scummLoop(int delta) {
}
}
+ // Another v8 quirk: runAllScripts() is called here, after that we can
+ // finally restore the blastTexts' rects, otherwise if a system dialog
+ // is shown we will lose all currently displayed blastTexts (see the
+ // comment above on the removal of blastTexts and blastObjects)
+ if (_game.version == 8) {
+ runAllScripts();
+#ifdef ENABLE_SCUMM_7_8
+ ((ScummEngine_v7 *)this)->restoreBlastTextsRects();
+#endif
+ }
+
if (_game.version < 8)
load_game:
scummLoop_handleSaveLoad();
@@ -2439,7 +2458,9 @@ load_game:
((SoundHE *)_sound)->processSoundCode();
}
- runAllScripts();
+ if (_game.version < 8) {
+ runAllScripts();
+ }
// SCUMM v7-8 executes checkExecVerbs inside the function
// which processes keyboard inputs, so we handle it above
diff --git a/engines/scumm/scumm_v7.h b/engines/scumm/scumm_v7.h
index ab659f935ca..b3e1231dbab 100644
--- a/engines/scumm/scumm_v7.h
+++ b/engines/scumm/scumm_v7.h
@@ -87,6 +87,7 @@ protected:
Common::Rect _defaultTextClipRect;
Common::Rect _wrappedTextClipRect;
bool _newTextRenderStyle;
+ int _blastTextRectsQueue = 0;
int _verbLineSpacing;
bool _existLanguageFile;
@@ -123,6 +124,7 @@ public:
void CHARSET_1() override;
bool isSmushActive() { return _smushActive; }
void removeBlastTexts() override;
+ void restoreBlastTextsRects();
protected:
diff --git a/engines/scumm/string_v7.cpp b/engines/scumm/string_v7.cpp
index 5580ca7ed9b..a05a78e9cab 100644
--- a/engines/scumm/string_v7.cpp
+++ b/engines/scumm/string_v7.cpp
@@ -497,14 +497,27 @@ void ScummEngine_v7::drawBlastTexts() {
}
void ScummEngine_v7::removeBlastTexts() {
- int i;
+ if (_game.version == 8) {
+ if (_blastTextQueuePos != 0)
+ _blastTextRectsQueue = _blastTextQueuePos;
+ _blastTextQueuePos = 0;
+ return;
+ }
- for (i = 0; i < _blastTextQueuePos; i++) {
+ for (int i = 0; i < _blastTextQueuePos; i++) {
restoreBackground(_blastTextQueue[i].rect);
}
_blastTextQueuePos = 0;
}
+void ScummEngine_v7::restoreBlastTextsRects() {
+ for (int i = 0; i < _blastTextRectsQueue; i++) {
+ restoreBackground(_blastTextQueue[i].rect);
+ }
+
+ _blastTextRectsQueue = 0;
+}
+
void ScummEngine_v8::printString(int m, const byte *msg) {
if (m == 4) {
const StringTab &st = _string[m];
Commit: b35bd37b0a301c215e65367b8a4d57ef8d70d79c
https://github.com/scummvm/scummvm/commit/b35bd37b0a301c215e65367b8a4d57ef8d70d79c
Author: AndywinXp (andywinxp at gmail.com)
Date: 2022-08-06T13:33:56+02:00
Commit Message:
SCUMM: Disable any GMM option key if the original GUI is in use
Changed paths:
engines/scumm/input.cpp
diff --git a/engines/scumm/input.cpp b/engines/scumm/input.cpp
index bf17762f8fa..c61edc73189 100644
--- a/engines/scumm/input.cpp
+++ b/engines/scumm/input.cpp
@@ -585,45 +585,39 @@ void ScummEngine_v8::processKeyboard(Common::KeyState lastKeyHit) {
_imuseDigital->diMUSESetSFXGroupVol(volume);
return;
}
- }
- // "Text Speed Slow ========== Fast"
- if (lastKeyHit.ascii == '+' || lastKeyHit.ascii == '-') {
- if (!(_game.features & GF_DEMO)) {
- // Catch the input and bail out
- return;
- }
+ // "Text Speed Slow ========== Fast"
+ if (lastKeyHit.ascii == '+' || lastKeyHit.ascii == '-') {
+ if (VAR_CHARINC == 0xFF)
+ return;
- if (VAR_CHARINC == 0xFF)
- return;
+ Common::KeyState ks = lastKeyHit;
- Common::KeyState ks = lastKeyHit;
-
- do {
- if (ks.ascii == '+') {
- VAR(VAR_CHARINC) -= 1;
- if (VAR(VAR_CHARINC) < 0)
- VAR(VAR_CHARINC) = 0;
- } else {
- VAR(VAR_CHARINC) += 1;
- if (VAR(VAR_CHARINC) > 9)
- VAR(VAR_CHARINC) = 9;
- }
+ do {
+ if (ks.ascii == '+') {
+ VAR(VAR_CHARINC) -= 1;
+ if (VAR(VAR_CHARINC) < 0)
+ VAR(VAR_CHARINC) = 0;
+ } else {
+ VAR(VAR_CHARINC) += 1;
+ if (VAR(VAR_CHARINC) > 9)
+ VAR(VAR_CHARINC) = 9;
+ }
- strcpy(tempStr, d.getPlainEngineString(31));
- char *ptrToChar = strchr(tempStr, '=');
- memset(ptrToChar, '\v', 10);
- ptrToChar[9 - VAR(VAR_CHARINC)] = '\f';
-
- showBannerAndPause(0, 0, tempStr);
- ks = Common::KEYCODE_INVALID;
- bool leftBtnPressed = false, rightBtnPressed = false;
- waitForBannerInput(60, ks, leftBtnPressed, rightBtnPressed);
- } while (ks.ascii == '+' || ks.ascii == '-');
- clearBanner();
- return;
- }
+ strcpy(tempStr, d.getPlainEngineString(31));
+ char *ptrToChar = strchr(tempStr, '=');
+ memset(ptrToChar, '\v', 10);
+ ptrToChar[9 - VAR(VAR_CHARINC)] = '\f';
+ showBannerAndPause(0, 0, tempStr);
+ ks = Common::KEYCODE_INVALID;
+ bool leftBtnPressed = false, rightBtnPressed = false;
+ waitForBannerInput(60, ks, leftBtnPressed, rightBtnPressed);
+ } while (ks.ascii == '+' || ks.ascii == '-');
+ clearBanner();
+ return;
+ }
+ }
}
// F1 (the trigger for the original save/load dialog) is mapped to F5
@@ -815,13 +809,14 @@ void ScummEngine_v3::processKeyboard(Common::KeyState lastKeyHit) {
}
void ScummEngine::processKeyboard(Common::KeyState lastKeyHit) {
- // Enable the following five special keys conditionally:
+ // Enable the following special keys conditionally:
bool restartKeyEnabled = (VAR_RESTART_KEY == 0xFF || VAR(VAR_RESTART_KEY) != 0);
bool pauseKeyEnabled = (VAR_PAUSE_KEY == 0xFF || VAR(VAR_PAUSE_KEY) != 0);
bool talkstopKeyEnabled = (VAR_TALKSTOP_KEY == 0xFF || VAR(VAR_TALKSTOP_KEY) != 0);
bool cutsceneExitKeyEnabled = (VAR_CUTSCENEEXIT_KEY == 0xFF || VAR(VAR_CUTSCENEEXIT_KEY) != 0);
bool mainmenuKeyEnabled = (VAR_MAINMENU_KEY == 0xFF || VAR(VAR_MAINMENU_KEY) != 0);
bool snapScrollKeyEnabled = (_game.version >= 2 && _game.version <= 4);
+ bool optionKeysEnabled = !isUsingOriginalGUI();
// In FM-TOWNS games F8 / restart is always enabled
if (_game.platform == Common::kPlatformFMTowns)
@@ -873,7 +868,7 @@ void ScummEngine::processKeyboard(Common::KeyState lastKeyHit) {
if (VAR_CAMERA_FAST_X != 0xFF)
VAR(VAR_CAMERA_FAST_X) = _snapScroll;
- } else if (lastKeyHit.ascii == '[' || lastKeyHit.ascii == ']') { // Change music volume
+ } else if (optionKeysEnabled && (lastKeyHit.ascii == '[' || lastKeyHit.ascii == ']')) { // Change music volume
int vol = ConfMan.getInt("music_volume") / 16;
if (lastKeyHit.ascii == ']' && vol < 16)
vol++;
@@ -891,7 +886,7 @@ void ScummEngine::processKeyboard(Common::KeyState lastKeyHit) {
ConfMan.setInt("music_volume", vol);
syncSoundSettings();
- } else if (lastKeyHit.ascii == '-' || lastKeyHit.ascii == '+') { // Change text speed
+ } else if (optionKeysEnabled && (lastKeyHit.ascii == '-' || lastKeyHit.ascii == '+')) { // Change text speed
if (lastKeyHit.ascii == '+' && _defaultTalkDelay > 0)
_defaultTalkDelay--;
else if (lastKeyHit.ascii == '-' && _defaultTalkDelay < 9)
Commit: 276e7620c71458268db73bcbe4c4b4c827c3678f
https://github.com/scummvm/scummvm/commit/276e7620c71458268db73bcbe4c4b4c827c3678f
Author: AndywinXp (andywinxp at gmail.com)
Date: 2022-08-06T13:33:56+02:00
Commit Message:
SCUMM: Use PaletteLookup for internal GUI
Changed paths:
engines/scumm/palette.cpp
engines/scumm/scumm.h
diff --git a/engines/scumm/palette.cpp b/engines/scumm/palette.cpp
index 75cfcd49c30..8dc27f30f5a 100644
--- a/engines/scumm/palette.cpp
+++ b/engines/scumm/palette.cpp
@@ -1546,26 +1546,9 @@ void ScummEngine::fetchBlackAndWhite(uint32 &black, uint32 &white, byte *palette
}
}
-uint32 ScummEngine::findClosestPaletteColor(byte *palette, int numOfSlots, byte r, byte g, byte b) {
- uint32 color = 0;
- uint32 redSquareDiff, blueSquareDiff, greenSquareDiff, weightedColorError;
- uint32 minErr = 10000000;
-
- // Iterate through the palette slots to find a color with the minimum
- // weighted error with respect to our queried RGB values.
- for (int i = 0; numOfSlots > i; ++i) {
- redSquareDiff = (r - palette[0]) * (r - palette[0]);
- greenSquareDiff = (g - palette[1]) * (g - palette[1]);
- blueSquareDiff = (b - palette[2]) * (b - palette[2]);
-
- weightedColorError = 3 * redSquareDiff + 5 * greenSquareDiff + 2 * blueSquareDiff;
- if (weightedColorError < minErr) {
- color = i;
- minErr = weightedColorError;
- }
- palette += 3;
- }
- return color;
+uint32 ScummEngine::findClosestPaletteColor(byte *palette, int paletteLength, byte r, byte g, byte b) {
+ _pl.setPalette(palette, paletteLength);
+ return (uint32)_pl.findBestColor(r, g, b, true);
}
void ScummEngine::updatePalette() {
diff --git a/engines/scumm/scumm.h b/engines/scumm/scumm.h
index b1815c928bd..7863f34a3db 100644
--- a/engines/scumm/scumm.h
+++ b/engines/scumm/scumm.h
@@ -38,6 +38,7 @@
#include "common/textconsole.h"
#include "graphics/surface.h"
#include "graphics/sjis.h"
+#include "graphics/palette.h"
#include "scumm/gfx.h"
#include "scumm/detection.h"
@@ -969,6 +970,7 @@ public:
protected:
ColorCycle _colorCycle[16]; // Palette cycles
uint8 _colorUsedByCycle[256];
+ Graphics::PaletteLookup _pl; // Used by the internal GUI
uint32 _ENCD_offs = 0, _EXCD_offs = 0;
uint32 _CLUT_offs = 0, _EPAL_offs = 0;
@@ -1050,7 +1052,7 @@ protected:
void stopCycle(int i);
virtual void palManipulateInit(int resID, int start, int end, int time);
void palManipulate();
- uint32 findClosestPaletteColor(byte *palette, int numOfSlots, byte r, byte g, byte b);
+ uint32 findClosestPaletteColor(byte *palette, int paletteLength, byte r, byte g, byte b);
public:
uint8 *getHEPaletteSlot(uint16 palSlot);
Commit: a4fd38b894cb89db10dc64e95707386ac2130548
https://github.com/scummvm/scummvm/commit/a4fd38b894cb89db10dc64e95707386ac2130548
Author: AndywinXp (andywinxp at gmail.com)
Date: 2022-08-06T13:33:56+02:00
Commit Message:
SCUMM: v7: Amend checkExecVerbs() being called earlier
While that was the correct place to call the function as per the disasm, it currently
breaks the screenShake effect, so unless a good reason to do a proper refactor
comes along, let's just bring things the way they were before for v7.
Changed paths:
engines/scumm/scumm.cpp
diff --git a/engines/scumm/scumm.cpp b/engines/scumm/scumm.cpp
index 0a379fa658b..d61878a05f6 100644
--- a/engines/scumm/scumm.cpp
+++ b/engines/scumm/scumm.cpp
@@ -2373,14 +2373,16 @@ void ScummEngine::scummLoop(int delta) {
processInput();
- // In v7-8 this function is executed at the end of processInput().
- // we emulate the same behavior by calling it here...
- if (_game.version >= 7)
+ if (_game.version == 8) {
+ // In v7-8 this function is executed at the end of processInput().
+ // Currently there are no known cases for v7 in which not calling this here,
+ // causes issues. Because of the way things are positioned in our implementation
+ // of the SCUMM loop, as of now enabling this for v7 breaks the screen shake
+ // effect. For v8 we really need to call this here, so let's do that...
checkExecVerbs();
- // Saving is performed here in v8; this is important when saving the thumbnail,
- // which would otherwise miss blastObjects/Texts on the bitmap.
- if (_game.version == 8) {
+ // Saving is performed here in v8; this is important when saving the thumbnail,
+ // which would otherwise miss blastObjects/Texts on the bitmap.
scummLoop_handleSaveLoad();
}
@@ -2464,8 +2466,8 @@ load_game:
// SCUMM v7-8 executes checkExecVerbs inside the function
// which processes keyboard inputs, so we handle it above
- // in that case.
- if (_game.version < 7)
+ // in that case. Again, we make an exception for v7, for now.
+ if (_game.version < 8)
checkExecVerbs();
checkAndRunSentenceScript();
Commit: b30e2ab98a2a5e7eea0066023241f55045c6be58
https://github.com/scummvm/scummvm/commit/b30e2ab98a2a5e7eea0066023241f55045c6be58
Author: AndywinXp (andywinxp at gmail.com)
Date: 2022-08-06T13:33:56+02:00
Commit Message:
SCUMM: v7-8: Add missing removeBlastTexts() call in startScene()
This change, verified in the disasm, fixes minor graphical glitches
in which the texts stay on for a frame longer than they need to be.
Changed paths:
engines/scumm/room.cpp
diff --git a/engines/scumm/room.cpp b/engines/scumm/room.cpp
index 67402681850..b20a3a0a99c 100644
--- a/engines/scumm/room.cpp
+++ b/engines/scumm/room.cpp
@@ -29,6 +29,7 @@
#include "scumm/object.h"
#include "scumm/resource.h"
#include "scumm/scumm_v3.h"
+#include "scumm/scumm_v7.h"
#include "scumm/sound.h"
#include "scumm/util.h"
@@ -43,6 +44,12 @@ void ScummEngine::startScene(int room, Actor *a, int objectNr) {
debugC(DEBUG_GENERAL, "Loading room %d", room);
+#ifdef ENABLE_SCUMM_7_8
+ if (_game.version >= 7) {
+ ((ScummEngine_v7 *)this)->removeBlastTexts();
+ }
+#endif
+
stopTalk();
fadeOut(_switchRoomEffect2);
Commit: c9c4f8026bafc04e28a53b0be6ebb37ac7d94e03
https://github.com/scummvm/scummvm/commit/c9c4f8026bafc04e28a53b0be6ebb37ac7d94e03
Author: AndywinXp (andywinxp at gmail.com)
Date: 2022-08-06T13:33:56+02:00
Commit Message:
SCUMM: COMI: Improve handling of GUI during SMUSH videos
Also, remove prehistoric hack which is now apparently unneeded and
messed with the ability to pause audio during SMUSH cutscenes for the
demo.
Changed paths:
engines/scumm/gfx_gui.cpp
engines/scumm/input.cpp
engines/scumm/sound.cpp
diff --git a/engines/scumm/gfx_gui.cpp b/engines/scumm/gfx_gui.cpp
index 26c5904223f..d6e4c686c03 100644
--- a/engines/scumm/gfx_gui.cpp
+++ b/engines/scumm/gfx_gui.cpp
@@ -492,6 +492,8 @@ void ScummEngine_v7::confirmExitDialog() {
_bannerMem = nullptr;
if (isSmushActive()) {
+ pt.clear();
+ clearClickedStatus();
return;
}
diff --git a/engines/scumm/input.cpp b/engines/scumm/input.cpp
index c61edc73189..0318d34f707 100644
--- a/engines/scumm/input.cpp
+++ b/engines/scumm/input.cpp
@@ -402,6 +402,9 @@ void ScummEngine_v8::processKeyboard(Common::KeyState lastKeyHit) {
InfoDialog d(this, 0);
char tempStr[64];
+ if (lastKeyHit.keycode == Common::KEYCODE_INVALID)
+ return;
+
// Main menu (allow both F1 and F5) mapping; unlike in
// the past we choose not to enable it without the
// original GUI selected as an option
@@ -418,7 +421,8 @@ void ScummEngine_v8::processKeyboard(Common::KeyState lastKeyHit) {
return;
}
- if (lastKeyHit.keycode == VAR(VAR_PAUSE_KEY)) {
+ if (lastKeyHit.keycode == VAR(VAR_PAUSE_KEY) ||
+ (lastKeyHit.keycode == Common::KEYCODE_SPACE && _game.features & GF_DEMO)) {
// Force the cursor OFF...
int8 oldCursorState = _cursor.state;
_cursor.state = 0;
@@ -497,6 +501,9 @@ void ScummEngine_v8::processKeyboard(Common::KeyState lastKeyHit) {
if (lastKeyHit.keycode == Common::KEYCODE_o || lastKeyHit.keycode == Common::KEYCODE_p) {
Common::KeyState ks = lastKeyHit;
+ if (isSmushActive())
+ _mixer->pauseAll(true);
+
int volume = _imuseDigital->diMUSEGetMusicGroupVol();
do {
if (ks.keycode == Common::KEYCODE_o) {
@@ -521,6 +528,10 @@ void ScummEngine_v8::processKeyboard(Common::KeyState lastKeyHit) {
} while (ks.keycode == Common::KEYCODE_o || ks.keycode == Common::KEYCODE_p);
clearBanner();
_imuseDigital->diMUSESetMusicGroupVol(volume);
+
+ if (isSmushActive())
+ _mixer->pauseAll(false);
+
return;
}
@@ -528,6 +539,9 @@ void ScummEngine_v8::processKeyboard(Common::KeyState lastKeyHit) {
if (lastKeyHit.keycode == Common::KEYCODE_k || lastKeyHit.keycode == Common::KEYCODE_l) {
Common::KeyState ks = lastKeyHit;
+ if (isSmushActive())
+ _mixer->pauseAll(true);
+
int volume = _imuseDigital->diMUSEGetVoiceGroupVol();
do {
if (ks.keycode == Common::KEYCODE_k) {
@@ -552,6 +566,10 @@ void ScummEngine_v8::processKeyboard(Common::KeyState lastKeyHit) {
} while (ks.keycode == Common::KEYCODE_k || ks.keycode == Common::KEYCODE_l);
clearBanner();
_imuseDigital->diMUSESetVoiceGroupVol(volume);
+
+ if (isSmushActive())
+ _mixer->pauseAll(false);
+
return;
}
@@ -559,6 +577,9 @@ void ScummEngine_v8::processKeyboard(Common::KeyState lastKeyHit) {
if (lastKeyHit.keycode == Common::KEYCODE_n || lastKeyHit.keycode == Common::KEYCODE_m) {
Common::KeyState ks = lastKeyHit;
+ if (isSmushActive())
+ _mixer->pauseAll(true);
+
int volume = _imuseDigital->diMUSEGetSFXGroupVol();
do {
if (ks.keycode == Common::KEYCODE_n) {
@@ -583,6 +604,10 @@ void ScummEngine_v8::processKeyboard(Common::KeyState lastKeyHit) {
} while (ks.keycode == Common::KEYCODE_n || ks.keycode == Common::KEYCODE_m);
clearBanner();
_imuseDigital->diMUSESetSFXGroupVol(volume);
+
+ if (isSmushActive())
+ _mixer->pauseAll(false);
+
return;
}
@@ -593,6 +618,9 @@ void ScummEngine_v8::processKeyboard(Common::KeyState lastKeyHit) {
Common::KeyState ks = lastKeyHit;
+ if (isSmushActive())
+ _mixer->pauseAll(true);
+
do {
if (ks.ascii == '+') {
VAR(VAR_CHARINC) -= 1;
@@ -615,6 +643,10 @@ void ScummEngine_v8::processKeyboard(Common::KeyState lastKeyHit) {
waitForBannerInput(60, ks, leftBtnPressed, rightBtnPressed);
} while (ks.ascii == '+' || ks.ascii == '-');
clearBanner();
+
+ if (isSmushActive())
+ _mixer->pauseAll(false);
+
return;
}
}
diff --git a/engines/scumm/sound.cpp b/engines/scumm/sound.cpp
index 3a129ab10f6..104224fa094 100644
--- a/engines/scumm/sound.cpp
+++ b/engines/scumm/sound.cpp
@@ -1193,12 +1193,6 @@ void Sound::pauseSounds(bool pause) {
if (_vm->_imuse)
_vm->_imuse->pause(pause);
- // Don't pause sounds if the game isn't active
- // FIXME - this is quite a nasty hack, replace with something cleaner, and w/o
- // having to access member vars directly!
- if (!_vm->_roomResource)
- return;
-
_soundsPaused = pause;
#ifdef ENABLE_SCUMM_7_8
Commit: f8defefe1e2ae6680ef99680f8d77a8602c13d47
https://github.com/scummvm/scummvm/commit/f8defefe1e2ae6680ef99680f8d77a8602c13d47
Author: AndywinXp (andywinxp at gmail.com)
Date: 2022-08-06T13:33:56+02:00
Commit Message:
SCUMM: Don't restore mouse position when using the original GUI
Changed paths:
engines/scumm/saveload.cpp
diff --git a/engines/scumm/saveload.cpp b/engines/scumm/saveload.cpp
index e65f2a71e51..1fa80730d27 100644
--- a/engines/scumm/saveload.cpp
+++ b/engines/scumm/saveload.cpp
@@ -1283,8 +1283,16 @@ void ScummEngine::saveLoadWithSerializer(Common::Serializer &s) {
s.syncAsSint16LE(_cursor.hotspotY, VER(20));
s.syncAsByte(_cursor.animate, VER(20));
s.syncAsByte(_cursor.animateIndex, VER(20));
- s.syncAsSint16LE(_mouse.x, VER(20));
- s.syncAsSint16LE(_mouse.y, VER(20));
+
+ // Don't restore the mouse position when using
+ // the original GUI, since the originals didn't
+ if (isUsingOriginalGUI()) {
+ s.skip(2, VER(106));
+ s.skip(2, VER(106));
+ } else {
+ s.syncAsSint16LE(_mouse.x, VER(20));
+ s.syncAsSint16LE(_mouse.y, VER(20));
+ }
s.syncBytes(_colorUsedByCycle, 256, VER(60));
s.syncAsByte(_doEffect, VER(8));
Commit: 660fb3dbefc5f1a6d4947837937f9fd2fa3bb243
https://github.com/scummvm/scummvm/commit/660fb3dbefc5f1a6d4947837937f9fd2fa3bb243
Author: AndywinXp (andywinxp at gmail.com)
Date: 2022-08-06T13:33:56+02:00
Commit Message:
SCUMM: COMI: Remove unnecessary sum in thumbnail handling
Changed paths:
engines/scumm/saveload.cpp
diff --git a/engines/scumm/saveload.cpp b/engines/scumm/saveload.cpp
index 1fa80730d27..2c1a1b9d41e 100644
--- a/engines/scumm/saveload.cpp
+++ b/engines/scumm/saveload.cpp
@@ -264,7 +264,7 @@ void ScummEngine_v8::stampScreenShot(int slot, int boxX, int boxY, int boxWidth,
for (int j = 0; j < boxWidth; j++) {
color = _savegameThumbnail[160 * (heightSlice / boxHeight) + (widthSlice / boxWidth)];
pixelX = j + boxX;
- pixelColor = tmpPalette[color + 0];
+ pixelColor = tmpPalette[color];
drawPixel(vs, pixelX, pixelY, pixelColor, false); // In the frontbuffer
drawPixel(vs, pixelX, pixelY, pixelColor, true); // In the backbuffer
widthSlice += 160;
Commit: 559f055d373358350e6d80cc738e817b09f0c483
https://github.com/scummvm/scummvm/commit/559f055d373358350e6d80cc738e817b09f0c483
Author: AndywinXp (andywinxp at gmail.com)
Date: 2022-08-06T13:33:56+02:00
Commit Message:
SCUMM: Skip mousePosition resume on load for original GUI regardless of savegame version
Changed paths:
engines/scumm/saveload.cpp
diff --git a/engines/scumm/saveload.cpp b/engines/scumm/saveload.cpp
index 2c1a1b9d41e..7d1993373c5 100644
--- a/engines/scumm/saveload.cpp
+++ b/engines/scumm/saveload.cpp
@@ -1287,8 +1287,8 @@ void ScummEngine::saveLoadWithSerializer(Common::Serializer &s) {
// Don't restore the mouse position when using
// the original GUI, since the originals didn't
if (isUsingOriginalGUI()) {
- s.skip(2, VER(106));
- s.skip(2, VER(106));
+ s.skip(2);
+ s.skip(2);
} else {
s.syncAsSint16LE(_mouse.x, VER(20));
s.syncAsSint16LE(_mouse.y, VER(20));
Commit: 3b2ccffbaae6ae19d89b26d2edd77ba6ea165090
https://github.com/scummvm/scummvm/commit/3b2ccffbaae6ae19d89b26d2edd77ba6ea165090
Author: AndywinXp (andywinxp at gmail.com)
Date: 2022-08-06T13:33:56+02:00
Commit Message:
SCUMM: COMI: Add support for the ScummVM standard thumbnail in the savescreen
Changed paths:
engines/scumm/saveload.cpp
engines/scumm/scumm_v8.h
diff --git a/engines/scumm/saveload.cpp b/engines/scumm/saveload.cpp
index 7d1993373c5..38bfa90364f 100644
--- a/engines/scumm/saveload.cpp
+++ b/engines/scumm/saveload.cpp
@@ -163,42 +163,85 @@ void ScummEngine::requestLoad(int slot) {
_saveLoadFlag = 2; // 2 for load
}
+static bool saveSaveGameHeader(Common::WriteStream *out, SaveGameHeader &hdr) {
+ hdr.type = MKTAG('S','C','V','M');
+ hdr.size = 0;
+ hdr.ver = CURRENT_VER;
+
+ out->writeUint32BE(hdr.type);
+ out->writeUint32LE(hdr.size);
+ out->writeUint32LE(hdr.ver);
+ out->write(hdr.name, sizeof(hdr.name));
+ return true;
+}
+
+static bool loadSaveGameHeader(Common::SeekableReadStream *in, SaveGameHeader &hdr) {
+ hdr.type = in->readUint32BE();
+ hdr.size = in->readUint32LE();
+ hdr.ver = in->readUint32LE();
+ in->read(hdr.name, sizeof(hdr.name));
+ return !in->err() && hdr.type == MKTAG('S','C','V','M');
+}
+
+namespace {
+bool loadAndCheckSaveGameHeader(Common::InSaveFile *in, int heversion, SaveGameHeader &hdr, Common::String *error = nullptr) {
+ if (!loadSaveGameHeader(in, hdr)) {
+ if (error) {
+ *error = "Invalid savegame";
+ }
+ return false;
+ }
+
+ if (hdr.ver > CURRENT_VER) {
+ hdr.ver = TO_LE_32(hdr.ver);
+ }
+
+ if (hdr.ver < VER(7) || hdr.ver > CURRENT_VER) {
+ if (error) {
+ *error = "Invalid version";
+ }
+ return false;
+ }
+
+ // We (deliberately) broke HE savegame compatibility at some point.
+ if (hdr.ver < VER(57) && heversion >= 60) {
+ if (error) {
+ *error = "Unsupported version";
+ }
+ return false;
+ }
+
+ hdr.name[sizeof(hdr.name) - 1] = 0;
+ return true;
+}
+} // End of anonymous namespace
+
void ScummEngine::copyHeapSaveGameToFile(int slot, const char *saveName) {
Common::String fileName;
SaveGameHeader hdr;
bool saveFailed = false;
Common::SeekableReadStream *heapSaveFile = openSaveFileForReading(1, true, fileName);
- hdr.type = heapSaveFile->readUint32BE();
- hdr.size = heapSaveFile->readUint32LE();
- hdr.ver = heapSaveFile->readUint32LE();
- heapSaveFile->read(hdr.name, sizeof(hdr.name));
- Common::strlcpy(hdr.name, saveName, sizeof(hdr.name));
+ saveFailed = !loadAndCheckSaveGameHeader(heapSaveFile, _game.heversion, hdr);
- if (heapSaveFile->err() || hdr.type != MKTAG('S','C','V','M')) {
+ Common::WriteStream *saveFile = openSaveFileForWriting(slot, false, fileName);
+ if (!saveFile) {
saveFailed = true;
} else {
- Common::WriteStream *saveFile = openSaveFileForWriting(slot, false, fileName);
- if (!saveFile) {
- saveFailed = true;
- } else {
- saveFile->writeUint32BE(hdr.type);
- saveFile->writeUint32LE(hdr.size);
- saveFile->writeUint32LE(hdr.ver);
- saveFile->write(hdr.name, sizeof(hdr.name));
-
- heapSaveFile->seek(sizeof(hdr), SEEK_SET);
- while (!heapSaveFile->eos()) {
- byte b = heapSaveFile->readByte();
- saveFile->writeByte(b);
- }
+ Common::strlcpy(hdr.name, saveName, sizeof(hdr.name));
+ saveSaveGameHeader(saveFile, hdr);
- saveFile->finalize();
- if (saveFile->err())
- saveFailed = true;
-
- delete saveFile;
+ heapSaveFile->seek(sizeof(hdr), SEEK_SET);
+ while (!heapSaveFile->eos()) {
+ byte b = heapSaveFile->readByte();
+ saveFile->writeByte(b);
}
+
+ saveFile->finalize();
+ if (saveFile->err())
+ saveFailed = true;
+
+ delete saveFile;
}
if (saveFailed)
@@ -240,14 +283,15 @@ void ScummEngine_v8::stampScreenShot(int slot, int boxX, int boxY, int boxWidth,
int color, pixelColor, rgb;
int heightSlice, widthSlice;
- bool success = false;
+ bool foundInternalThumbnail = false;
byte tmpPalette[256];
+ uint32 *thumbSurface = nullptr;
VirtScreen *vs = &_virtscr[kMainVirtScreen];
- success = fetchInternalSaveStateThumbnail(slot == 0 ? 1 : slot, slot == 0);
+ foundInternalThumbnail = fetchInternalSaveStateThumbnail(slot == 0 ? 1 : slot, slot == 0);
- if (success) {
+ if (foundInternalThumbnail) {
for (int i = 0; i < 256; i++) {
rgb = _savegameThumbnailPalette[i];
tmpPalette[i] = remapPaletteColor(
@@ -256,33 +300,62 @@ void ScummEngine_v8::stampScreenShot(int slot, int boxX, int boxY, int boxWidth,
brightness * ((rgb & 0xFF0000) >> 16) / 0xFF,
-1);
}
+ } else {
+ // The savegame does not contain an internal SCUMM v8 thumbnail: fetch the default ScummVM one,
+ // and process it with the brightness parameter beforehand...
+ thumbSurface = fetchScummVMSaveStateThumbnail(slot == 0 ? 1 : slot, slot == 0, brightness);
+
+ // Fallback: this is a savegame which does not have any of the two possible,
+ // thumbnails so let's just show a brownish box which looks nice enough
+ // superimposed on the Captain's log yellowish background...
+ // This is some kind of last resort fallback. We shouldn't arrive here,
+ // but still, better safe than sorry... :-)
+ if (!thumbSurface) {
+ rgb = 0x001627;
+ color = remapPaletteColor(
+ brightness * ((rgb & 0xFF) >> 0) / 0xFF,
+ brightness * ((rgb & 0xFF00) >> 8) / 0xFF,
+ brightness * ((rgb & 0xFF0000) >> 16) / 0xFF,
+ -1);
+
+ // The -1 after boxHeight is done to compensate for the fact that
+ // we can't directly control the back and front buffers (see below)
+ drawBox(boxX, boxY, boxWidth, boxHeight - 1, color);
+ return;
+ }
+ }
- heightSlice = 0;
- for (int i = 0; i < boxHeight; i++) {
- pixelY = boxY + i;
- widthSlice = 0;
- for (int j = 0; j < boxWidth; j++) {
+ // If we got here, it means we managed to fetch one of the
+ // thumbnails, so let's actually draw it to screen!
+ heightSlice = 0;
+ for (int i = 0; i < boxHeight; i++) {
+ pixelY = boxY + i;
+ widthSlice = 0;
+ for (int j = 0; j < boxWidth; j++) {
+ pixelX = j + boxX;
+
+ // Remember, the internal one is paletted, while the ScummVM one
+ // is blitted without going through a palette index...
+ if (foundInternalThumbnail) {
color = _savegameThumbnail[160 * (heightSlice / boxHeight) + (widthSlice / boxWidth)];
- pixelX = j + boxX;
pixelColor = tmpPalette[color];
- drawPixel(vs, pixelX, pixelY, pixelColor, false); // In the frontbuffer
- drawPixel(vs, pixelX, pixelY, pixelColor, true); // In the backbuffer
- widthSlice += 160;
+ } else {
+ pixelColor = thumbSurface[160 * (heightSlice / boxHeight) + (widthSlice / boxWidth)];
}
- heightSlice += 120;
+
+ // Draw twice; once in the frontbuffer, once in the backbuffer:
+ // this ensures that the lowest row of the image doesn't get overwritten
+ // by the blastText rect just below, containing the savegame name...
+ drawPixel(vs, pixelX, pixelY, pixelColor, false);
+ drawPixel(vs, pixelX, pixelY, pixelColor, true);
+
+ widthSlice += 160;
}
- } else {
- // Fallback: this is an old savegame which does not have a SCUMM v8 thumbnail,
- // so let's just show a brownish box which looks nice enough superimposed on
- // the Captain's log yellowish background...
- rgb = 0x001627;
- color = remapPaletteColor(
- brightness * ((rgb & 0xFF) >> 0) / 0xFF,
- brightness * ((rgb & 0xFF00) >> 8) / 0xFF,
- brightness * ((rgb & 0xFF0000) >> 16) / 0xFF,
- -1);
- drawBox(boxX, boxY, boxWidth, boxHeight - 1, color);
+ heightSlice += 120;
}
+
+ if (thumbSurface)
+ delete[] thumbSurface;
}
void ScummEngine_v8::createInternalSaveStateThumbnail() {
@@ -321,13 +394,7 @@ bool ScummEngine_v8::fetchInternalSaveStateThumbnail(int slotId, bool isHeapSave
// In order to fetch the internal COMI thumbnail, we perform the same routine
// used during normal loading, stripped down to support only version 106 onwards...
- hdr.type = in->readUint32BE();
- hdr.size = in->readUint32LE();
- hdr.ver = in->readUint32LE();
- in->read(hdr.name, sizeof(hdr.name));
-
- if (in->err() || hdr.type != MKTAG('S', 'C', 'V', 'M')) {
- warning("Invalid savegame header for savegame '%s'", filename.c_str());
+ if (!loadAndCheckSaveGameHeader(in, _game.heversion, hdr)) {
delete in;
return false;
}
@@ -337,6 +404,7 @@ bool ScummEngine_v8::fetchInternalSaveStateThumbnail(int slotId, bool isHeapSave
// Reject save games which do not contain the internal thumbnail...
if (hdr.ver < VER(106)) {
+ delete in;
return false;
}
@@ -362,6 +430,52 @@ bool ScummEngine_v8::fetchInternalSaveStateThumbnail(int slotId, bool isHeapSave
delete in;
return true;
}
+
+uint32 *ScummEngine_v8::fetchScummVMSaveStateThumbnail(int slotId, bool isHeapSave, int brightness) {
+ Common::String filename;
+ Graphics::Surface *thumbnailSurface;
+
+ // Perform the necessary steps to arrive at the thumbnail section of the save file...
+ Common::SeekableReadStream *in = openSaveFileForReading(slotId, isHeapSave, filename);
+ if (in) {
+ // We don't perform checks on the header: if we're here it means that the
+ // savestate follows the correct format and it is loadable.
+ in->skip(sizeof(uint32) * 3 + sizeof(SaveGameHeader::name));
+
+ // Load the thumbnail.
+ // We're under the assumption that its resolution will always be 160x120,
+ // which is a fourth of the original 640x480 internal resolution, so there's
+ // no need to scale the surface.
+ bool thumbSuccess = Graphics::loadThumbnail(*in, thumbnailSurface);
+ delete in;
+
+ if (thumbSuccess) {
+ // Now take the pixels from the surface, extract the RGB components, process them
+ // with the brightness parameter, and store them in an appropriate structure
+ // which the SCUMM graphics pipeline can use...
+ byte r, g, b;
+ uint32 *processedThumbnail = new uint32[thumbnailSurface->w * thumbnailSurface->h];
+ for (int i = 0; i < thumbnailSurface->h; i++) {
+ for (int j = 0; j < thumbnailSurface->w; j++) {
+ uint32 *ptr = (uint32 *)thumbnailSurface->getBasePtr(j, i);
+ thumbnailSurface->format.colorToRGB(*ptr, r, g, b);
+
+ processedThumbnail[i * thumbnailSurface->w + j] = getPaletteColorFromRGB(
+ _currentPalette,
+ brightness * r / 0xFF,
+ brightness * g / 0xFF,
+ brightness * b / 0xFF);
+ }
+ }
+
+ thumbnailSurface->free();
+ delete thumbnailSurface;
+ return processedThumbnail;
+ }
+ }
+
+ return nullptr;
+}
#endif
Common::SeekableReadStream *ScummEngine::openSaveFileForReading(int slot, bool compat, Common::String &fileName) {
@@ -374,18 +488,6 @@ Common::WriteStream *ScummEngine::openSaveFileForWriting(int slot, bool compat,
return _saveFileMan->openForSaving(fileName);
}
-static bool saveSaveGameHeader(Common::WriteStream *out, SaveGameHeader &hdr) {
- hdr.type = MKTAG('S','C','V','M');
- hdr.size = 0;
- hdr.ver = CURRENT_VER;
-
- out->writeUint32BE(hdr.type);
- out->writeUint32LE(hdr.size);
- out->writeUint32LE(hdr.ver);
- out->write(hdr.name, sizeof(hdr.name));
- return true;
-}
-
bool ScummEngine::saveState(Common::WriteStream *out, bool writeHeader) {
SaveGameHeader hdr;
@@ -515,14 +617,6 @@ bool ScummEngine_v4::savePreparedSavegame(int slot, char *desc) {
}
}
-static bool loadSaveGameHeader(Common::SeekableReadStream *in, SaveGameHeader &hdr) {
- hdr.type = in->readUint32BE();
- hdr.size = in->readUint32LE();
- hdr.ver = in->readUint32LE();
- in->read(hdr.name, sizeof(hdr.name));
- return !in->err() && hdr.type == MKTAG('S','C','V','M');
-}
-
bool ScummEngine::loadState(int slot, bool compat) {
// Wrapper around the other variant
Common::String filename;
@@ -852,39 +946,6 @@ bool ScummEngine::getSavegameName(int slot, Common::String &desc) {
return result;
}
-namespace {
-bool loadAndCheckSaveGameHeader(Common::InSaveFile *in, int heversion, SaveGameHeader &hdr, Common::String *error = nullptr) {
- if (!loadSaveGameHeader(in, hdr)) {
- if (error) {
- *error = "Invalid savegame";
- }
- return false;
- }
-
- if (hdr.ver > CURRENT_VER) {
- hdr.ver = TO_LE_32(hdr.ver);
- }
-
- if (hdr.ver < VER(7) || hdr.ver > CURRENT_VER) {
- if (error) {
- *error = "Invalid version";
- }
- return false;
- }
-
- // We (deliberately) broke HE savegame compatibility at some point.
- if (hdr.ver < VER(57) && heversion >= 60) {
- if (error) {
- *error = "Unsupported version";
- }
- return false;
- }
-
- hdr.name[sizeof(hdr.name) - 1] = 0;
- return true;
-}
-} // End of anonymous namespace
-
bool getSavegameName(Common::InSaveFile *in, Common::String &desc, int heversion) {
SaveGameHeader hdr;
diff --git a/engines/scumm/scumm_v8.h b/engines/scumm/scumm_v8.h
index f6975cfd6a9..5e90bfdd9e6 100644
--- a/engines/scumm/scumm_v8.h
+++ b/engines/scumm/scumm_v8.h
@@ -93,6 +93,7 @@ protected:
void saveLoadWithSerializer(Common::Serializer &s) override;
void createInternalSaveStateThumbnail();
bool fetchInternalSaveStateThumbnail(int slotId, bool isHeapSave);
+ uint32 *fetchScummVMSaveStateThumbnail(int slotId, bool isHeapSave, int brightness);
/* Version 8 script opcodes */
void o8_mod();
Commit: 2c9d7fd2ee99c0574eabe0f6455d733cbc0d7ca5
https://github.com/scummvm/scummvm/commit/2c9d7fd2ee99c0574eabe0f6455d733cbc0d7ca5
Author: AndywinXp (andywinxp at gmail.com)
Date: 2022-08-06T13:33:56+02:00
Commit Message:
SCUMM: COMI: Change how blastObject rects are restored for v8
This fixes the last remaining graphical glitches pertaining the original GUI
Changed paths:
engines/scumm/object.cpp
engines/scumm/saveload.cpp
engines/scumm/scumm.cpp
engines/scumm/scumm.h
engines/scumm/scumm_v6.h
engines/scumm/string_v7.cpp
diff --git a/engines/scumm/object.cpp b/engines/scumm/object.cpp
index 62b8bfeb659..b44febf8a1f 100644
--- a/engines/scumm/object.cpp
+++ b/engines/scumm/object.cpp
@@ -1824,25 +1824,51 @@ void ScummEngine_v6::drawBlastObject(BlastObject *eo) {
}
void ScummEngine_v6::removeBlastObjects() {
- BlastObject *eo;
+ // While v6-7 games restore the rect immediately, we only reset
+ // the blastObject queue in here for v8, since their graphics
+ // has to remain on screen until after runAllScripts().
+ if (_game.version == 8) {
+ if (_blastObjectQueuePos != 0) {
+ for (int i = 0; i < _blastObjectQueuePos; i++) {
+ _blastObjectsRectsToBeRestored[i] = _blastObjectQueue[i].rect;
+ _blastObjectRectsQueue = _blastObjectQueuePos;
+ }
+ }
- eo = _blastObjectQueue;
- for (int i = 0; i < _blastObjectQueuePos; i++, eo++) {
- removeBlastObject(eo);
+ _blastObjectQueuePos = 0;
+ return;
+ }
+
+ for (int i = 0; i < _blastObjectQueuePos; i++) {
+ restoreBlastObjectRect(_blastObjectQueue[i].rect);
}
_blastObjectQueuePos = 0;
}
-void ScummEngine_v6::removeBlastObject(BlastObject *eo) {
+void ScummEngine_v6::restoreBlastObjectsRects() {
+ // While v6-7 games restore the rect immediately in
+ // ScummEngine_v6::removeBlastObjects(), we do that here
+ // for v8, which has to restore the rects after runAllScripts().
+ if (_game.version < 8)
+ return;
+
+ for (int i = 0; i < _blastObjectRectsQueue; i++) {
+ restoreBlastObjectRect(_blastObjectsRectsToBeRestored[i]);
+
+ // Invalidate the rect after restoring it...
+ _blastObjectsRectsToBeRestored[i].setHeight(0);
+ }
+
+ _blastObjectRectsQueue = 0;
+}
+
+void ScummEngine_v6::restoreBlastObjectRect(Common::Rect r) {
VirtScreen *vs = &_virtscr[kMainVirtScreen];
- Common::Rect r;
int left_strip, right_strip;
int i;
- r = eo->rect;
-
r.clip(Common::Rect(vs->w, vs->h));
if (r.width() <= 0 || r.height() <= 0)
diff --git a/engines/scumm/saveload.cpp b/engines/scumm/saveload.cpp
index 38bfa90364f..f5ffabaa345 100644
--- a/engines/scumm/saveload.cpp
+++ b/engines/scumm/saveload.cpp
@@ -845,8 +845,9 @@ bool ScummEngine::loadState(int slot, bool compat, Common::String &filename) {
sh = _screenH;
#ifdef ENABLE_SCUMM_7_8
- // Remove any blast text leftovers
+ // Remove any blastText/blastObject leftovers
if (_game.version >= 7) {
+ ((ScummEngine_v6 *)this)->removeBlastObjects();
((ScummEngine_v7 *)this)->removeBlastTexts();
}
diff --git a/engines/scumm/scumm.cpp b/engines/scumm/scumm.cpp
index d61878a05f6..6b49187576b 100644
--- a/engines/scumm/scumm.cpp
+++ b/engines/scumm/scumm.cpp
@@ -2386,15 +2386,8 @@ void ScummEngine::scummLoop(int delta) {
scummLoop_handleSaveLoad();
}
- // BlastObjects/Texts are removed in this moment of the codepath, in v7-8.
- // V8 should just reset the queue and the rects should be restored somewhere else.
- //
- // We do that for the texts just after calling runAllScripts(), but this method
- // doesn't quite work as well for the blastObjects as it does for the texts, so
- // for now we'll have to live with one known glitch: if a system dialog is shown
- // on the main menu (i.e. "Do you want to replace this saved game? (Y/N)"), it
- // will wipe out all the blastObjects (the empty thumbnail rectangles) for the duration
- // of said dialog.
+ // BlastObjects/Texts are completely removed in this moment of the codepath, in v7.
+ // In v8 we just reset the queue: the rects will be restored after runAllScripts().
if (_game.version >= 7) {
((ScummEngine_v6 *)this)->removeBlastObjects();
#ifdef ENABLE_SCUMM_7_8
@@ -2420,12 +2413,11 @@ void ScummEngine::scummLoop(int delta) {
}
}
- // Another v8 quirk: runAllScripts() is called here, after that we can
- // finally restore the blastTexts' rects, otherwise if a system dialog
- // is shown we will lose all currently displayed blastTexts (see the
- // comment above on the removal of blastTexts and blastObjects)
+ // Another v8 quirk: runAllScripts() is called here; after that we can
+ // finally restore the blastTexts/blastObject rects...
if (_game.version == 8) {
runAllScripts();
+ ((ScummEngine_v6 *)this)->restoreBlastObjectsRects();
#ifdef ENABLE_SCUMM_7_8
((ScummEngine_v7 *)this)->restoreBlastTextsRects();
#endif
@@ -2648,6 +2640,7 @@ void ScummEngine::scummLoop_handleSaveLoad() {
GUI::TimedMessageDialog dialog(buf, 1500);
runDialog(dialog);
}
+
if (success && _saveLoadFlag != 1)
clearClickedStatus();
@@ -2854,8 +2847,6 @@ void ScummEngine_v8::scummLoop_handleSaveLoad() {
}
ScummEngine::scummLoop_handleSaveLoad();
-
- removeBlastObjects();
}
#endif
diff --git a/engines/scumm/scumm.h b/engines/scumm/scumm.h
index 7863f34a3db..0d0e6934cf0 100644
--- a/engines/scumm/scumm.h
+++ b/engines/scumm/scumm.h
@@ -1134,7 +1134,7 @@ protected:
* If the leftmost bit is set, the strip (background) is dirty
* needs to be redrawn.
*
- * The second leftmost bit is set by removeBlastObject() and
+ * The second leftmost bit is set by restoreBlastObjectsRect() and
* restoreBackground(), but I'm not yet sure why.
*/
uint32 gfxUsageBits[410 * 3];
diff --git a/engines/scumm/scumm_v6.h b/engines/scumm/scumm_v6.h
index c11d1b38897..512c3850b7c 100644
--- a/engines/scumm/scumm_v6.h
+++ b/engines/scumm/scumm_v6.h
@@ -82,7 +82,9 @@ protected:
};
int _blastObjectQueuePos;
+ int _blastObjectRectsQueue = 0;
BlastObject _blastObjectQueue[200];
+ Common::Rect _blastObjectsRectsToBeRestored[200];
// Akos Class
struct {
@@ -131,6 +133,7 @@ protected:
public: // FIXME. TODO
void nukeArray(int array);
void removeBlastObjects();
+ void restoreBlastObjectsRects();
protected:
virtual int readArray(int array, int index, int base);
@@ -156,7 +159,7 @@ protected:
void drawBlastObjects();
void drawBlastObject(BlastObject *eo);
- void removeBlastObject(BlastObject *eo);
+ void restoreBlastObjectRect(Common::Rect r);
void clearDrawQueues() override;
diff --git a/engines/scumm/string_v7.cpp b/engines/scumm/string_v7.cpp
index a05a78e9cab..18bff5a08f5 100644
--- a/engines/scumm/string_v7.cpp
+++ b/engines/scumm/string_v7.cpp
@@ -511,6 +511,9 @@ void ScummEngine_v7::removeBlastTexts() {
}
void ScummEngine_v7::restoreBlastTextsRects() {
+ if (_game.version < 8)
+ return;
+
for (int i = 0; i < _blastTextRectsQueue; i++) {
restoreBackground(_blastTextQueue[i].rect);
}
Commit: 1d6cfd62b81b87dddfa7a66a8e9ab12a2aa0a0b8
https://github.com/scummvm/scummvm/commit/1d6cfd62b81b87dddfa7a66a8e9ab12a2aa0a0b8
Author: AndywinXp (andywinxp at gmail.com)
Date: 2022-08-06T13:33:56+02:00
Commit Message:
SCUMM: COMI: Deactivate frame limiter on the menu
The original appears to do this in its own way; we do it in a simpler fashion.
As a bonus, the original menu controls do not feel like molasses.
Changed paths:
engines/scumm/scumm.cpp
diff --git a/engines/scumm/scumm.cpp b/engines/scumm/scumm.cpp
index 6b49187576b..0cd5cb57afc 100644
--- a/engines/scumm/scumm.cpp
+++ b/engines/scumm/scumm.cpp
@@ -2197,6 +2197,11 @@ Common::Error ScummEngine::go() {
delta = ceil(delta / 3.0) * 3;
}
+ // In COMI we put no speed limit while on the main menu.
+ if (_game.version == 8 && _currentRoom == 92) {
+ delta = 0;
+ }
+
// Wait, start and stop the stop watch at the time the wait is assumed
// to end. There is no guarantee that the wait is that exact,
// but this way if it overshoots that time will count as part
Commit: 917655b50a5f4a5fcb373c2d2d46e9f667c9d648
https://github.com/scummvm/scummvm/commit/917655b50a5f4a5fcb373c2d2d46e9f667c9d648
Author: AndywinXp (andywinxp at gmail.com)
Date: 2022-08-06T13:33:56+02:00
Commit Message:
SCUMM: Don't clear the GUI banners while SMUSH is active
Changed paths:
engines/scumm/gfx_gui.cpp
diff --git a/engines/scumm/gfx_gui.cpp b/engines/scumm/gfx_gui.cpp
index d6e4c686c03..ebae532cd59 100644
--- a/engines/scumm/gfx_gui.cpp
+++ b/engines/scumm/gfx_gui.cpp
@@ -156,7 +156,13 @@ Common::KeyState ScummEngine_v7::showBannerAndPause(int bannerId, int32 waitTime
bool leftBtnPressed = false, rightBtnPressed = false;
if (waitTime) {
waitForBannerInput(waitTime, ks, leftBtnPressed, rightBtnPressed);
- clearBanner();
+
+ // Don't manually clear the banner if a SMUSH movie is playing,
+ // as that will cause some rare small glitches. The SMUSH player
+ // will take care of that for us automatically when updating the
+ // screen for next frame.
+ if (!isSmushActive())
+ clearBanner();
}
// Finally, resume the engine, clear the input state, and restore the charset.
@@ -390,7 +396,7 @@ void ScummEngine_v7::confirmExitDialog() {
// Save the pixels which will be overwritten by the dialog,
// so that we can restore them later. Note that the interpreter
// doesn't do this, but we have to...
- if (!_bannerMem) {
+ if (!_bannerMem && !isSmushActive()) {
_bannerMemSize = _screenWidth * _screenHeight;
_bannerMem = (byte *)malloc(_bannerMemSize * sizeof(byte));
if (_bannerMem)
@@ -483,7 +489,7 @@ void ScummEngine_v7::confirmExitDialog() {
// Again, he interpreter does not explicitly restore the screen
// after finishing displaying this query dialog, but we have to...
- if (_bannerMem) {
+ if (_bannerMem && !isSmushActive()) {
memcpy(
_virtscr[kMainVirtScreen].getPixels(0, _screenTop),
_bannerMem,
@@ -491,12 +497,6 @@ void ScummEngine_v7::confirmExitDialog() {
free(_bannerMem);
_bannerMem = nullptr;
- if (isSmushActive()) {
- pt.clear();
- clearClickedStatus();
- return;
- }
-
markRectAsDirty(_virtscr[kMainVirtScreen].number, 0, _screenWidth + 8, _screenTop, _screenHeight + _screenTop);
ScummEngine::drawDirtyScreenParts();
_system->updateScreen();
Commit: 09a43c7134c06079464c6d3c0f8d0b59e2fb591c
https://github.com/scummvm/scummvm/commit/09a43c7134c06079464c6d3c0f8d0b59e2fb591c
Author: AndywinXp (andywinxp at gmail.com)
Date: 2022-08-06T13:33:56+02:00
Commit Message:
SCUMM: COMI: Always show the cursor during confirmExitDialog()
Changed paths:
engines/scumm/gfx_gui.cpp
diff --git a/engines/scumm/gfx_gui.cpp b/engines/scumm/gfx_gui.cpp
index ebae532cd59..3db542a8a8a 100644
--- a/engines/scumm/gfx_gui.cpp
+++ b/engines/scumm/gfx_gui.cpp
@@ -365,6 +365,7 @@ void ScummEngine_v7::confirmExitDialog() {
curCursorHotspotX = _cursor.hotspotX;
curCursorHotspotY = _cursor.hotspotY;
setDefaultCursor();
+ CursorMan.showMouse(true);
// Backup the current charsetId, since we're going to switch
// to charsetId == 1 and start taking measurements for the box...
Commit: 555a51978348510bee650760d7d93d1aa050a202
https://github.com/scummvm/scummvm/commit/555a51978348510bee650760d7d93d1aa050a202
Author: AndywinXp (andywinxp at gmail.com)
Date: 2022-08-06T13:33:56+02:00
Commit Message:
SCUMM: COMI: Improve accuracy for banner input handling
Changed paths:
engines/scumm/input.cpp
diff --git a/engines/scumm/input.cpp b/engines/scumm/input.cpp
index 0318d34f707..cee754963a4 100644
--- a/engines/scumm/input.cpp
+++ b/engines/scumm/input.cpp
@@ -706,6 +706,8 @@ void ScummEngine_v7::processKeyboard(Common::KeyState lastKeyHit) {
}
void ScummEngine_v7::waitForBannerInput(int32 waitTime, Common::KeyState &ks, bool &leftBtnClicked, bool &rightBtnClicked) {
+ bool validKey = false;
+
if (waitTime && waitTime != -1) {
uint32 millis = _system->getMillis();
while (((_system->getMillis() - millis) * (_timerFrequency / 4) / 1000) < waitTime) {
@@ -720,7 +722,7 @@ void ScummEngine_v7::waitForBannerInput(int32 waitTime, Common::KeyState &ks, bo
return;
}
} else {
- while (ks == Common::KEYCODE_INVALID && !leftBtnClicked && !rightBtnClicked) {
+ while (!validKey && !leftBtnClicked && !rightBtnClicked) {
waitForTimer(1); // Allow the engine to update the screen and fetch new inputs...
ks = _keyPressed;
leftBtnClicked = (_leftBtnPressed & msClicked) != 0;
@@ -728,6 +730,16 @@ void ScummEngine_v7::waitForBannerInput(int32 waitTime, Common::KeyState &ks, bo
if (shouldQuit())
return;
+
+ validKey = ks.keycode != Common::KEYCODE_INVALID &&
+ ks.keycode != Common::KEYCODE_LCTRL &&
+ ks.keycode != Common::KEYCODE_RCTRL &&
+ ks.keycode != Common::KEYCODE_LSHIFT &&
+ ks.keycode != Common::KEYCODE_RSHIFT &&
+ ks.keycode != Common::KEYCODE_UP &&
+ ks.keycode != Common::KEYCODE_DOWN &&
+ ks.keycode != Common::KEYCODE_LEFT &&
+ ks.keycode != Common::KEYCODE_RIGHT;
}
}
}
Commit: 7ac1b327e12c85813a001f5e062adee5b8b7a0b8
https://github.com/scummvm/scummvm/commit/7ac1b327e12c85813a001f5e062adee5b8b7a0b8
Author: AndywinXp (andywinxp at gmail.com)
Date: 2022-08-06T13:33:56+02:00
Commit Message:
SCUMM: COMI: Fix clearBanner() regression causing glitches on calls after SMUSH movies
Changed paths:
engines/scumm/gfx_gui.cpp
diff --git a/engines/scumm/gfx_gui.cpp b/engines/scumm/gfx_gui.cpp
index 3db542a8a8a..2ecb837d7ee 100644
--- a/engines/scumm/gfx_gui.cpp
+++ b/engines/scumm/gfx_gui.cpp
@@ -156,13 +156,7 @@ Common::KeyState ScummEngine_v7::showBannerAndPause(int bannerId, int32 waitTime
bool leftBtnPressed = false, rightBtnPressed = false;
if (waitTime) {
waitForBannerInput(waitTime, ks, leftBtnPressed, rightBtnPressed);
-
- // Don't manually clear the banner if a SMUSH movie is playing,
- // as that will cause some rare small glitches. The SMUSH player
- // will take care of that for us automatically when updating the
- // screen for next frame.
- if (!isSmushActive())
- clearBanner();
+ clearBanner();
}
// Finally, resume the engine, clear the input state, and restore the charset.
@@ -184,20 +178,23 @@ void ScummEngine_v7::clearBanner() {
// Restore the GFX content which was under the banner,
// and then mark that part of the screen as dirty.
if (_bannerMem) {
- memcpy(
- &_virtscr[kMainVirtScreen].getPixels(0, _screenTop)[(_screenWidth + 8) * (_screenHeight / 2 - 10)],
- _bannerMem,
- _bannerMemSize);
- free(_bannerMem);
- _bannerMem = nullptr;
+ // Don't manually clear the banner if a SMUSH movie is playing,
+ // as that will cause some rare small glitches. The SMUSH player
+ // will take care of that for us automatically when updating the
+ // screen for next frame.
+ if (!isSmushActive()) {
+ memcpy(
+ &_virtscr[kMainVirtScreen].getPixels(0, _screenTop)[(_screenWidth + 8) * (_screenHeight / 2 - 10)],
+ _bannerMem,
+ _bannerMemSize);
- if (isSmushActive()) {
- return;
+ markRectAsDirty(_virtscr[kMainVirtScreen].number, 0, _screenWidth + 8, _screenTop, _screenHeight + _screenTop);
+ ScummEngine::drawDirtyScreenParts();
+ _system->updateScreen();
}
- markRectAsDirty(_virtscr[kMainVirtScreen].number, 0, _screenWidth + 8, _screenTop, _screenHeight + _screenTop);
- ScummEngine::drawDirtyScreenParts();
- _system->updateScreen();
+ free(_bannerMem);
+ _bannerMem = nullptr;
}
}
Commit: a952852d8c431cfbd5b03d20736c0ec22e7a6643
https://github.com/scummvm/scummvm/commit/a952852d8c431cfbd5b03d20736c0ec22e7a6643
Author: AndywinXp (andywinxp at gmail.com)
Date: 2022-08-06T13:33:56+02:00
Commit Message:
SCUMM: Properly sync options between original and ScummVM GUIs
This also changes the talk delay to be the inverse value (which means the text speed),
like for the original games. This particular change has been tested to be working on all
SCUMM games in my possession, so we should not have any regressions and it accounts
for work already done for future original GUIs.
Changed paths:
engines/scumm/input.cpp
engines/scumm/script_v8.cpp
engines/scumm/scumm.cpp
diff --git a/engines/scumm/input.cpp b/engines/scumm/input.cpp
index cee754963a4..8f1caa9f4af 100644
--- a/engines/scumm/input.cpp
+++ b/engines/scumm/input.cpp
@@ -484,6 +484,23 @@ void ScummEngine_v8::processKeyboard(Common::KeyState lastKeyHit) {
}
ConfMan.setInt("original_gui_text_status", voiceMode);
+ switch (voiceMode) {
+ case 0:
+ ConfMan.setBool("speech_mute", false);
+ ConfMan.setBool("subtitles", false);
+ break;
+ case 1:
+ ConfMan.setBool("speech_mute", false);
+ ConfMan.setBool("subtitles", true);
+ break;
+ case 2:
+ ConfMan.setBool("speech_mute", true);
+ ConfMan.setBool("subtitles", true);
+ break;
+ default:
+ break;
+ }
+
ConfMan.flushToDisk();
syncSoundSettings();
return;
diff --git a/engines/scumm/script_v8.cpp b/engines/scumm/script_v8.cpp
index 8fc71a185af..fbb9ee7e196 100644
--- a/engines/scumm/script_v8.cpp
+++ b/engines/scumm/script_v8.cpp
@@ -1157,20 +1157,25 @@ void ScummEngine_v8::o8_kernelSetFunctions() {
int value = args[2];
const char *str = (const char *)getStringAddress(idx);
if (isUsingOriginalGUI()) {
- if (!strcmp(str, "SFX Volume"))
+ if (!strcmp(str, "SFX Volume")) {
ConfMan.setInt("sfx_volume", value * 2);
- else if (!strcmp(str, "Voice Volume"))
+ } else if (!strcmp(str, "Voice Volume")) {
ConfMan.setInt("speech_volume", value * 2);
- else if (!strcmp(str, "Music Volume"))
+ } else if (!strcmp(str, "Music Volume")) {
ConfMan.setInt("music_volume", value * 2);
- else if (!strcmp(str, "Text Status"))
+ } else if (!strcmp(str, "Text Status")) {
ConfMan.setInt("original_gui_text_status", value);
- else if (!strcmp(str, "Text Speed"))
+ ConfMan.setBool("speech_mute", value == 2);
+ ConfMan.setBool("subtitles", value > 0);
+ } else if (!strcmp(str, "Text Speed")) {
ConfMan.setInt("original_gui_text_speed", value);
- else if (!strcmp(str, "Object Names"))
+ setTalkSpeed(value);
+ } else if (!strcmp(str, "Object Names")) {
ConfMan.setInt("original_gui_object_labels", value);
- else if (!strcmp(str, "Saveload Page"))
+ ConfMan.setBool("object_labels", value > 0);
+ } else if (!strcmp(str, "Saveload Page")) {
ConfMan.setInt("original_gui_saveload_page", value);
+ }
ConfMan.flushToDisk();
}
@@ -1278,22 +1283,43 @@ void ScummEngine_v8::o8_kernelGetFunctions() {
{
int idx = args[1];
const char *str = (const char *)getStringAddress(idx);
- if (!strcmp(str, "SFX Volume"))
+ if (!strcmp(str, "SFX Volume")) {
push(ConfMan.getInt("sfx_volume") / 2);
- else if (!strcmp(str, "Voice Volume"))
+ } else if (!strcmp(str, "Voice Volume")) {
push(ConfMan.getInt("speech_volume") / 2);
- else if (!strcmp(str, "Music Volume"))
+ } else if (!strcmp(str, "Music Volume")) {
push(ConfMan.getInt("music_volume") / 2);
- else if (!strcmp(str, "Text Status"))
- push(isUsingOriginalGUI() ? ConfMan.getInt("original_gui_text_status") : ConfMan.getBool("subtitles"));
- else if (!strcmp(str, "Text Speed"))
- push(ConfMan.getInt("original_gui_text_speed"));
- else if (!strcmp(str, "Object Names"))
- push(isUsingOriginalGUI() ? ConfMan.getInt("original_gui_object_labels") : ConfMan.getBool("object_labels"));
- else if (!strcmp(str, "Saveload Page"))
- push(ConfMan.getInt("original_gui_saveload_page"));
- else // Use defaults
+ } else if (!strcmp(str, "Text Status")) {
+ if (ConfMan.hasKey("original_gui_text_status", _targetName) && isUsingOriginalGUI()) {
+ push(ConfMan.getInt("original_gui_text_status"));
+ } else if (ConfMan.hasKey("subtitles", _targetName)) {
+ push(ConfMan.getBool("subtitles"));
+ } else {
+ push(-1); // Default value
+ }
+ } else if (!strcmp(str, "Text Speed")) {
+ if (ConfMan.hasKey("original_gui_text_speed", _targetName) && isUsingOriginalGUI()) {
+ push(ConfMan.getInt("original_gui_text_speed"));
+ } else {
+ push(-1); // Default value
+ }
+ } else if (!strcmp(str, "Object Names")) {
+ if (ConfMan.hasKey("original_gui_object_labels", _targetName) && isUsingOriginalGUI()) {
+ push(ConfMan.getInt("original_gui_object_labels"));
+ } else if (ConfMan.hasKey("object_labels", _targetName)) {
+ push(ConfMan.getBool("object_labels"));
+ } else {
+ push(-1); // Default value
+ }
+ } else if (!strcmp(str, "Saveload Page")) {
+ if (ConfMan.hasKey("original_gui_saveload_page", _targetName) && isUsingOriginalGUI()) {
+ push(ConfMan.getInt("original_gui_saveload_page"));
+ } else {
+ push(-1); // Default value
+ }
+ } else { // Use defaults
push(-1);
+ }
debugC(DEBUG_GENERAL,"o8_kernelGetFunctions: readRegistryValue(%s)", str);
}
diff --git a/engines/scumm/scumm.cpp b/engines/scumm/scumm.cpp
index 0cd5cb57afc..ab4611740da 100644
--- a/engines/scumm/scumm.cpp
+++ b/engines/scumm/scumm.cpp
@@ -1377,9 +1377,19 @@ void ScummEngine::setupScumm(const Common::String &macResourceFile) {
#ifdef ENABLE_SCUMM_7_8
void ScummEngine_v7::setupScumm(const Common::String &macResourceFile) {
- if (ConfMan.hasKey("original_gui"))
+ if (ConfMan.hasKey("original_gui", _targetName))
_useOriginalGUI = ConfMan.getBool("original_gui");
+ // The object line toggle is always synchronized from the main game to
+ // our internal Game Options; at startup we do the opposite, since an user
+ // might change the toggle just before starting up the game...
+ if (_game.version == 8) {
+ if (ConfMan.hasKey("original_gui_object_labels", _targetName) &&
+ ConfMan.hasKey("object_labels", _targetName)) {
+ ConfMan.setInt("original_gui_object_labels", ConfMan.getBool("object_labels") ? 1 : 0);
+ }
+ }
+
if (_game.id == GID_DIG && (_game.features & GF_DEMO))
_smushFrameRate = 15;
else
@@ -2065,15 +2075,33 @@ void ScummEngine::setupMusic(int midi, const Common::String &macInstrumentFile)
void ScummEngine::syncSoundSettings() {
if (isUsingOriginalGUI() && _game.version == 8) {
- _voiceMode = ConfMan.getInt("original_gui_text_status");
+ if (ConfMan.hasKey("original_gui_text_status", _targetName)) {
+ _voiceMode = ConfMan.getInt("original_gui_text_status");
+ } else if (ConfMan.hasKey("subtitles", _targetName) && ConfMan.hasKey("speech_mute", _targetName)){
+ int guiTextStatus = 0;
+ if (ConfMan.getBool("speech_mute")) {
+ guiTextStatus = 2;
+ } else if (ConfMan.getBool("subtitles")) {
+ guiTextStatus = 1;
+ }
+
+ // Let's set it now so we don't have to do the conversion the next time...
+ ConfMan.setInt("original_gui_text_status", guiTextStatus);
+ _voiceMode = guiTextStatus;
+ }
if (VAR_VOICE_MODE != 0xFF)
VAR(VAR_VOICE_MODE) = _voiceMode;
if (ConfMan.hasKey("original_gui_text_speed", _targetName)) {
+ // If the value has been changed from the GMM, sync it...
+ if (getTalkSpeed() != ConfMan.getInt("original_gui_text_speed")) {
+ ConfMan.setInt("original_gui_text_speed", getTalkSpeed());
+ }
+
_defaultTalkDelay = ConfMan.getInt("original_gui_text_speed");
- // In the original GUI the talk delay is represented as text speed,
+ // In the original games the talk delay is represented as text speed,
// so we have to invert the value:
// - 9 is the highest text speed possible;
// - 0 is the lowest text speed possible.
@@ -2116,8 +2144,13 @@ void ScummEngine::syncSoundSettings() {
if (ConfMan.hasKey("talkspeed", _targetName)) {
_defaultTalkDelay = getTalkSpeed();
+
+ // In the original games the talk delay is represented as text speed,
+ // so we have to invert the value:
+ // - 9 is the highest text speed possible;
+ // - 0 is the lowest text speed possible.
if (VAR_CHARINC != 0xFF)
- VAR(VAR_CHARINC) = _defaultTalkDelay;
+ VAR(VAR_CHARINC) = 9 - _defaultTalkDelay;
}
// Backyard Baseball 2003 uses a unique subtitle variable,
@@ -2803,7 +2836,7 @@ void ScummEngine_v5::scummLoop_handleSaveLoad() {
// completely process, save and load both the VGA and EGA palettes all the time (regardless
// of the current render mode).
setCurrentPalette(_curPalIndex);
- }
+ }
}
// update IQ points after loading
More information about the Scummvm-git-logs
mailing list