[Scummvm-git-logs] scummvm master -> 5dec7446398c342c5322856dfbcbda5b1b9cbf4a
sluicebox
noreply at scummvm.org
Sat Dec 14 20:05:43 UTC 2024
This automated email contains information about 1 new commit which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
5dec744639 AGI: PREAGI: Improve event handling during sounds
Commit: 5dec7446398c342c5322856dfbcbda5b1b9cbf4a
https://github.com/scummvm/scummvm/commit/5dec7446398c342c5322856dfbcbda5b1b9cbf4a
Author: sluicebox (22204938+sluicebox at users.noreply.github.com)
Date: 2024-12-14T11:56:02-08:00
Commit Message:
AGI: PREAGI: Improve event handling during sounds
Games can now control event processing and interrupt behavior
during sounds and waits.
Fixes Mickey unresponsiveness during sounds and introduction.
Changed paths:
engines/agi/preagi/mickey.cpp
engines/agi/preagi/mickey.h
engines/agi/preagi/preagi.cpp
engines/agi/preagi/preagi.h
engines/agi/preagi/troll.cpp
diff --git a/engines/agi/preagi/mickey.cpp b/engines/agi/preagi/mickey.cpp
index 6cbf34ad543..118a6847e91 100644
--- a/engines/agi/preagi/mickey.cpp
+++ b/engines/agi/preagi/mickey.cpp
@@ -635,18 +635,19 @@ void MickeyEngine::printDatMessage(int iStr) {
// Sound
-void MickeyEngine::playNote(MSA_SND_NOTE note) {
- if (!note.counter) {
- // Pause
- _system->delayMillis((uint)(note.length / IDI_SND_TIMER_RESOLUTION));
- } else {
- playSpeakerNote(IDI_SND_OSCILLATOR_FREQUENCY / note.counter, (int32)(note.length / IDI_SND_TIMER_RESOLUTION));
+bool MickeyEngine::playNote(MSA_SND_NOTE note, WaitOptions options) {
+ int16 frequency = 0;
+ if (note.counter != 0) {
+ frequency = IDI_SND_OSCILLATOR_FREQUENCY / note.counter;
}
+ int32 lengthMs = (int32)(note.length / IDI_SND_TIMER_RESOLUTION);
+ return playSpeakerNote(frequency, lengthMs, options);
}
-void MickeyEngine::playSound(ENUM_MSA_SOUND iSound) {
+bool MickeyEngine::playSound(ENUM_MSA_SOUND iSound, WaitOptions options) {
+ bool completed = true;
if (!getFlag(VM_FLAG_SOUND_ON))
- return;
+ return completed;
Common::Event event;
MSA_SND_NOTE note;
@@ -658,7 +659,10 @@ void MickeyEngine::playSound(ENUM_MSA_SOUND iSound) {
for (int iNote = 0; iNote < 6; iNote++) {
note.counter = rnd(59600) + 59;
note.length = 4;
- playNote(note);
+ if (!playNote(note, options)) {
+ completed = false;
+ break;
+ }
}
break;
default:
@@ -669,36 +673,19 @@ void MickeyEngine::playSound(ENUM_MSA_SOUND iSound) {
if (!note.counter && !note.length)
break;
- playNote(note);
+ if (!playNote(note, options)) {
+ completed = false;
+ break;
+ }
pBuf += 3;
-
- if (iSound == IDI_MSA_SND_THEME) {
- while (_system->getEventManager()->pollEvent(event)) {
- switch (event.type) {
- case Common::EVENT_KEYDOWN:
- // don't interrupt if a modifier is pressed
- if (event.kbd.flags & Common::KBD_NON_STICKY) {
- continue;
- }
- // fall through
- case Common::EVENT_RETURN_TO_LAUNCHER:
- case Common::EVENT_QUIT:
- case Common::EVENT_LBUTTONUP:
- case Common::EVENT_RBUTTONUP:
- delete[] buffer;
- return;
- default:
- break;
- }
- }
- }
}
break;
}
delete[] buffer;
+ return completed;
}
// Graphics
@@ -801,7 +788,11 @@ void MickeyEngine::drawRoomAnimation() {
if (_gameStateMickey.nFrame < 0)
_gameStateMickey.nFrame = 15;
- playSound(IDI_MSA_SND_PRESS_BLUE);
+ // play the spaceship beep but don't process events during playback.
+ // this sound plays during menu usage, so events must not be consumed
+ // while waiting or else inputs will be dropped. playing this sound
+ // does create an input lag, but that is what happened in the original.
+ playSound(IDI_MSA_SND_PRESS_BLUE, kWaitBlock);
}
break;
@@ -1374,14 +1365,15 @@ void MickeyEngine::intro() {
_gameStateMickey.iRoom = IDI_MSA_PIC_TITLE;
drawRoom();
- // show copyright and play theme
+ // show copyright
printExeMsg(IDO_MSA_COPYRIGHT);
// Quit if necessary
if (shouldQuit())
return;
- playSound(IDI_MSA_SND_THEME);
+ // play theme
+ playSound(IDI_MSA_SND_THEME, kWaitAllowInterrupt);
// load game
_gameStateMickey.fIntro = true;
diff --git a/engines/agi/preagi/mickey.h b/engines/agi/preagi/mickey.h
index 906a42c6b11..13ac1c9ef1a 100644
--- a/engines/agi/preagi/mickey.h
+++ b/engines/agi/preagi/mickey.h
@@ -717,8 +717,8 @@ protected:
void patchMenu(MSA_MENU *);
void printDatString(int);
void printDatMessage(int);
- void playNote(MSA_SND_NOTE);
- void playSound(ENUM_MSA_SOUND);
+ bool playNote(MSA_SND_NOTE note, WaitOptions options);
+ bool playSound(ENUM_MSA_SOUND iSound, WaitOptions options = kWaitProcessEvents);
void drawRoomAnimation();
void drawRoom();
bool drawLogo();
diff --git a/engines/agi/preagi/preagi.cpp b/engines/agi/preagi/preagi.cpp
index 49778448320..19cd455e204 100644
--- a/engines/agi/preagi/preagi.cpp
+++ b/engines/agi/preagi/preagi.cpp
@@ -287,32 +287,72 @@ int PreAgiEngine::getSelection(SelectionTypes type) {
return 0;
}
-void PreAgiEngine::playSpeakerNote(int16 frequency, int32 length) {
- _speakerStream->play(Audio::PCSpeaker::kWaveFormSquare, frequency, length);
+bool PreAgiEngine::playSpeakerNote(int16 frequency, int32 length, WaitOptions options) {
+ // play note, unless this is a pause
+ if (frequency != 0) {
+ _speakerStream->play(Audio::PCSpeaker::kWaveFormSquare, frequency, length);
+ }
- uint32 startTime = _system->getMillis();
- while (_system->getMillis() - startTime < (uint32)length) {
- _system->updateScreen();
- _system->delayMillis(10);
+ // wait for note length
+ bool completed = wait(length, options);
+
+ // stop note if the wait was interrupted
+ if (!completed) {
+ if (frequency != 0) {
+ _speakerStream->stop();
+ }
}
+
+ return completed;
}
-void PreAgiEngine::wait(uint32 delay) {
+// A wait function that updates the screen, optionally allows events to be
+// processed, and optionally allows keyboard and mouse events to interrupt
+// the wait. Processing events keeps the program window responsive, but for
+// very short delays it may be better to not process events so that they
+// are buffered and not lost.
+bool PreAgiEngine::wait(uint32 delay, WaitOptions options) {
Common::Event event;
uint32 startTime = _system->getMillis();
+ bool processEvents = (options & kWaitProcessEvents) != 0;
+ bool allowInterrupt = (options == kWaitAllowInterrupt);
+
while (!shouldQuit()) {
// process events
- while (_eventMan->pollEvent(event)) {
+ if (processEvents) {
+ while (_eventMan->pollEvent(event)) {
+ switch (event.type) {
+ case Common::EVENT_KEYDOWN:
+ // don't interrupt if a modifier is pressed
+ if (event.kbd.flags & Common::KBD_NON_STICKY) {
+ continue;
+ }
+ // fall through
+ case Common::EVENT_LBUTTONUP:
+ case Common::EVENT_RBUTTONUP:
+ if (!allowInterrupt) {
+ continue;
+ }
+ // fall through
+ case Common::EVENT_RETURN_TO_LAUNCHER:
+ case Common::EVENT_QUIT:
+ return false; // interrupted by quit or input
+ default:
+ break;
+ }
+ }
}
if (_system->getMillis() - startTime >= delay) {
- return;
+ return true; // delay completed
}
_system->updateScreen();
_system->delayMillis(10);
}
+
+ return false; // interrupted by quit
}
} // End of namespace Agi
diff --git a/engines/agi/preagi/preagi.h b/engines/agi/preagi/preagi.h
index bf2653bf6d9..e30ed3ee1d6 100644
--- a/engines/agi/preagi/preagi.h
+++ b/engines/agi/preagi/preagi.h
@@ -50,6 +50,13 @@ enum SelectionTypes {
kSelBackspace
};
+// Options for controlling behavior during waits and sound playback
+enum WaitOptions {
+ kWaitBlock = 0x00, // no event processing, cannot be interrupted
+ kWaitProcessEvents = 0x01, // process events, stops on quit
+ kWaitAllowInterrupt = 0x03 // process events, stops on input or quit
+};
+
class PreAgiEngine : public AgiBase {
int _gameId;
@@ -101,8 +108,8 @@ protected:
// Saved Games
Common::SaveFileManager *getSaveFileMan() { return _saveFileMan; }
- void playSpeakerNote(int16 frequency, int32 length);
- void wait(uint32 delay);
+ bool playSpeakerNote(int16 frequency, int32 length, WaitOptions options);
+ bool wait(uint32 delay, WaitOptions options = kWaitProcessEvents);
private:
int _defaultColor;
diff --git a/engines/agi/preagi/troll.cpp b/engines/agi/preagi/troll.cpp
index 35d760e8bcc..3741fc21053 100644
--- a/engines/agi/preagi/troll.cpp
+++ b/engines/agi/preagi/troll.cpp
@@ -472,7 +472,10 @@ void TrollEngine::playTune(int tune, int len) {
int duration = READ_LE_UINT16(_gameData + ptr);
ptr += 2;
- playSpeakerNote(freq, duration);
+ // Play note without processing events.
+ // The sounds are so short in this game that we don't
+ // need to process events while playing notes.
+ playSpeakerNote(freq, duration, kWaitBlock);
}
}
More information about the Scummvm-git-logs
mailing list