[Scummvm-git-logs] scummvm master -> 3fd9958f2f4389b39655e8464c6be78098c2f5a9
dreammaster
noreply at scummvm.org
Wed Aug 26 01:52:16 UTC 2026
This automated email contains information about 9 new commits which have been
pushed to the 'scummvm' repo located at https://api.github.com/repos/scummvm/scummvm .
Summary:
1f079a0ad6 MADS: DRAGONSPHERE: Fix AdLib octave transposition
bf4902433e MADS: DRAGONSPHERE: Fix General MIDI driver validation
c4745f2ccd MADS: DRAGONSPHERE: Fix RSOUND sequence decoding
d238f08995 MADS: PHANTOM: Fix RSOUND sequence decoding
34545166e4 MADS: Use per-sample speech rates
c42b0dcd01 MADS: DRAGONSPHERE: Fix GSOUND sequence decoding
309df043ac MADS: FOREST: Fix digital sound volume control
61d9c9e6ed MADS: DRAGONSPHERE: Accept GSOUND termination stream
3fd9958f2f MADS: Fix repeated preloaded speech playback
Commit: 1f079a0ad6fa2863e1eea0b7f4c6375206a91643
https://github.com/scummvm/scummvm/commit/1f079a0ad6fa2863e1eea0b7f4c6375206a91643
Author: fusefib (fibofuse at gmail.com)
Date: 2026-08-26T11:52:07+10:00
Commit Message:
MADS: DRAGONSPHERE: Fix AdLib octave transposition
Perform ASOUND note transposition in the driver's native byte
width before deriving the OPL block and semitone. Negative section
9 transpositions otherwise bypass byte wrapping and produce wrong
pitches in the main menu and intro music.
Assisted-by: Codex:GPT-5.4
Changed paths:
engines/mads/dragonsphere/sound/asound.cpp
diff --git a/engines/mads/dragonsphere/sound/asound.cpp b/engines/mads/dragonsphere/sound/asound.cpp
index e92ac00affb..4ee55a0350b 100644
--- a/engines/mads/dragonsphere/sound/asound.cpp
+++ b/engines/mads/dragonsphere/sound/asound.cpp
@@ -681,13 +681,10 @@ void ASound::writeFrequency() {
uint16 aReg = (uint16)chanNum + 0xA0;
uint16 bReg = (uint16)chanNum + 0xB0;
- /* Note is 1-based; _octaveTranspose shifts by whole octaves. */
- int note = (int)ch->_note + (int)ch->_octaveTranspose - 1;
+ /* The native driver performs this addition in an 8-bit register. */
+ byte note = (byte)(ch->_note + ch->_octaveTranspose - 1);
int octave = note / 12;
int semi = note % 12;
- if (semi < 0) {
- semi += 12; --octave;
- }
/* F-number from table, with optional signed transpose offset. */
int16 fnum = (int16)SEMITONE_FREQ_TABLE[semi] + (int16)(int8)ch->_transpose;
@@ -726,14 +723,11 @@ void ASound::writeArpeggio() {
uint16 aReg = (uint16)chanNum + 0xA0;
uint16 bReg = (uint16)chanNum + 0xB0;
- /* dl = _note + _octaveTranspose + _writeVolumePending - 1 */
- int note = (int)ch->_note + (int)ch->_octaveTranspose
- + (int)ch->_writeVolumePending - 1;
+ /* The native driver performs these additions in an 8-bit register. */
+ byte note = (byte)(ch->_note + ch->_octaveTranspose
+ + ch->_writeVolumePending - 1);
int octave = note / 12;
int semi = note % 12;
- if (semi < 0) {
- semi += 12; --octave;
- }
uint16 freqEntry = SEMITONE_FREQ_TABLE[semi];
uint8 fnHigh = (uint8)((freqEntry >> 8) & 0x03);
Commit: bf4902433e9f1a072aa68b6708036c35831923e7
https://github.com/scummvm/scummvm/commit/bf4902433e9f1a072aa68b6708036c35831923e7
Author: fusefib (fibofuse at gmail.com)
Date: 2026-08-26T11:52:07+10:00
Commit Message:
MADS: DRAGONSPHERE: Fix General MIDI driver validation
Validate each GSOUND overlay's section-specific identity before
normalizing the section digit.
This accepts the verified retail drivers instead of rejecting them all
and silently falling back to AdLib.
Assisted-by: Codex:GPT-5.4
Changed paths:
engines/mads/dragonsphere/sound/gsound.cpp
diff --git a/engines/mads/dragonsphere/sound/gsound.cpp b/engines/mads/dragonsphere/sound/gsound.cpp
index 033cf01f997..7c462eedf0d 100644
--- a/engines/mads/dragonsphere/sound/gsound.cpp
+++ b/engines/mads/dragonsphere/sound/gsound.cpp
@@ -168,6 +168,9 @@ bool GSound::validateOverlay(const GSoundDriverData &driverData) {
if (file.read(identity, 21) != 21)
return false;
identity[21] = 0;
+ if (identity[11] != '0' + driverData.section)
+ return false;
+ identity[11] = 'N';
if (Common::String(identity) != "Dragon GM N12-21-93")
return false;
Commit: c4745f2ccd716bfb319bb14b92c00db504f13288
https://github.com/scummvm/scummvm/commit/c4745f2ccd716bfb319bb14b92c00db504f13288
Author: fusefib (fibofuse at gmail.com)
Date: 2026-08-26T11:52:07+10:00
Commit Message:
MADS: DRAGONSPHERE: Fix RSOUND sequence decoding
Continue decoding control opcodes until a timed note or chord event,
matching the native interpreter loop.
Correct the F1 through F4 opcode mapping so volume, pitch bend,
volume fades, and velocity update the proper channel fields. This
prevents MT-32 notes from being emitted with zero velocity.
Assisted-by: Codex:GPT-5.4
Changed paths:
engines/mads/dragonsphere/sound/rsound.cpp
diff --git a/engines/mads/dragonsphere/sound/rsound.cpp b/engines/mads/dragonsphere/sound/rsound.cpp
index b0e2df322d0..519782d9ded 100644
--- a/engines/mads/dragonsphere/sound/rsound.cpp
+++ b/engines/mads/dragonsphere/sound/rsound.cpp
@@ -981,7 +981,7 @@ dispatch:
ch->_pSrc = ch->_outerLoopPtr;
}
ch->_innerLoopPtr = ch->_pSrc;
- goto post_keyon;
+ goto dispatch;
}
case 0xFF: {
// End an inner loop. The restart pointer is the beginning of
@@ -1001,7 +1001,7 @@ dispatch:
} else {
ch->_pSrc = ch->_innerLoopPtr;
}
- goto post_keyon;
+ goto dispatch;
}
// ---- Loop / restart-pointer opcodes ----
@@ -1014,7 +1014,7 @@ dispatch:
ch->_innerLoopPtr = ch->_soundData;
ch->_outerLoopPtr = ch->_soundData;
}
- goto post_keyon;
+ goto dispatch;
}
case 0xFC: {
byte *ptr = loadData(readScriptWord(pSrc));
@@ -1023,17 +1023,17 @@ dispatch:
ch->_innerLoopPtr = ptr;
ch->_outerLoopPtr = ptr;
ch->_soundData = ptr;
- goto post_keyon;
+ goto dispatch;
}
case 0xFB: { // unconditional jump, no bookkeeping
ch->_pSrc = loadData(readScriptWord(pSrc));
- goto post_keyon;
+ goto dispatch;
}
case 0xFA: { // "call": jump, saving a resume point
byte *target = loadData(readScriptWord(pSrc));
ch->_branchTarget = ch->_pSrc + 3;
ch->_pSrc = target;
- goto post_keyon;
+ goto dispatch;
}
case 0xF9: { // "return"
if (ch->_branchTarget) {
@@ -1042,25 +1042,25 @@ dispatch:
} else {
ch->_pSrc++;
}
- goto post_keyon;
+ goto dispatch;
}
case 0xF8: {
ch->_program = readScriptByte(pSrc);
ch->_pSrc += 2;
sendProgramChange(midiChannel, ch->_program);
- goto post_keyon;
+ goto dispatch;
}
case 0xF7: {
ch->_noteOffset = readScriptByte(pSrc);
ch->_keyOnDelayOverride = 0;
ch->_pSrc += 2;
- goto post_keyon;
+ goto dispatch;
}
case 0xF6: {
ch->_keyOnDelayOverride = readScriptByte(pSrc);
ch->_noteOffset = 0;
ch->_pSrc += 2;
- goto post_keyon;
+ goto dispatch;
}
case 0xF5: {
ch->_pitchBendFadeReload = readScriptByte(pSrc);
@@ -1068,51 +1068,50 @@ dispatch:
ch->_pitchBendFadeCount = readScriptByte(pSrc);
ch->_pitchBendFadeCounter = 1;
ch->_pSrc += 4;
- goto post_keyon;
+ goto dispatch;
}
case 0xF4: {
- ch->_volume = readScriptByte(pSrc);
- ch->_pSrc += 2;
- sendVolume(ch);
- goto post_keyon;
- }
- case 0xF3: {
ch->_velocity = readScriptByte(pSrc);
ch->_pSrc += 2;
- goto post_keyon;
+ goto dispatch;
}
- case 0xF2: {
+ case 0xF3: {
ch->_volumeFadeReload = readScriptByte(pSrc);
ch->_volumeFadeStep = readScriptByte(pSrc);
ch->_volumeFadeCounter = 1;
ch->_pSrc += 3;
- goto post_keyon;
+ goto dispatch;
}
- case 0xF1: {
- int pitchBend = readScriptByte(pSrc);
- if (_usesDemoOpcodeSemantics || !ch->_pendingStop)
- ch->_pitchBend = pitchBend;
+ case 0xF2: {
+ ch->_pitchBend = readScriptByte(pSrc);
ch->_pSrc += 2;
sendPitchBend(midiChannel, ch->_pitchBend);
- goto post_keyon;
+ goto dispatch;
+ }
+ case 0xF1: {
+ if (!ch->_pendingStop)
+ ch->_volume = readScriptByte(pSrc);
+ ch->_pSrc += 2;
+ sendVolume(ch);
+ goto dispatch;
}
case 0xF0: {
ch->_pan = readScriptByte(pSrc);
sendPan(midiChannel, ch->_pan);
ch->_pSrc += 2;
- goto post_keyon;
+ goto dispatch;
}
case 0xEF: {
ch->_panFadeReload = readScriptByte(pSrc);
ch->_panFadeStep = readScriptByte(pSrc);
ch->_panFadeCounter = 1;
ch->_pSrc += 3;
- goto post_keyon;
+ goto dispatch;
}
case 0xEE: {
ch->_transpose = readScriptByte(pSrc);
ch->_pSrc += 2;
- goto post_keyon;
+ goto dispatch;
}
case 0xED: {
// ---- Chord event: [count][note1..noteN][duration] ----
Commit: d238f08995fc6bbbaaa1e190e1bf465994153b60
https://github.com/scummvm/scummvm/commit/d238f08995fc6bbbaaa1e190e1bf465994153b60
Author: fusefib (fibofuse at gmail.com)
Date: 2026-08-26T11:52:07+10:00
Commit Message:
MADS: PHANTOM: Fix RSOUND sequence decoding
Continue decoding control opcodes until a timed note or chord event,
matching the native interpreter loop.
Correct the F1 through F4 opcode mapping so volume, pitch bend,
volume fades, and velocity update the proper channel fields.
Assisted-by: Codex:GPT-5.4
Changed paths:
engines/mads/phantom/sound/rsound.cpp
diff --git a/engines/mads/phantom/sound/rsound.cpp b/engines/mads/phantom/sound/rsound.cpp
index 0333b784e79..9a8d069db5e 100644
--- a/engines/mads/phantom/sound/rsound.cpp
+++ b/engines/mads/phantom/sound/rsound.cpp
@@ -985,7 +985,7 @@ dispatch:
ch->_pSrc = ch->_outerLoopPtr;
}
ch->_innerLoopPtr = ch->_pSrc;
- goto post_keyon;
+ goto dispatch;
}
case 0xFF: {
// End an inner loop. The restart pointer is the beginning of
@@ -1005,7 +1005,7 @@ dispatch:
} else {
ch->_pSrc = ch->_innerLoopPtr;
}
- goto post_keyon;
+ goto dispatch;
}
// ---- Loop / restart-pointer opcodes ----
@@ -1018,7 +1018,7 @@ dispatch:
ch->_innerLoopPtr = ch->_soundData;
ch->_outerLoopPtr = ch->_soundData;
}
- goto post_keyon; // tail used by this cluster
+ goto dispatch;
}
case 0xFC: {
byte *ptr = loadData(readScriptWord(pSrc));
@@ -1027,17 +1027,17 @@ dispatch:
ch->_innerLoopPtr = ptr;
ch->_outerLoopPtr = ptr;
ch->_soundData = ptr;
- goto post_keyon;
+ goto dispatch;
}
case 0xFB: { // unconditional jump, no bookkeeping
ch->_pSrc = loadData(readScriptWord(pSrc));
- goto post_keyon;
+ goto dispatch;
}
case 0xFA: { // "call": jump, saving a resume point
byte *target = loadData(readScriptWord(pSrc));
ch->_branchTarget = ch->_pSrc + 3;
ch->_pSrc = target;
- goto post_keyon;
+ goto dispatch;
}
case 0xF9: { // "return"
if (ch->_branchTarget) {
@@ -1046,25 +1046,25 @@ dispatch:
} else {
ch->_pSrc++;
}
- goto post_keyon;
+ goto dispatch;
}
case 0xF8: {
ch->_program = readScriptByte(pSrc);
ch->_pSrc += 2;
sendProgramChange(midiChannel, ch->_program);
- goto post_keyon;
+ goto dispatch;
}
case 0xF7: {
ch->_noteOffset = readScriptByte(pSrc);
ch->_keyOnDelayOverride = 0;
ch->_pSrc += 2;
- goto post_keyon;
+ goto dispatch;
}
case 0xF6: {
ch->_keyOnDelayOverride = readScriptByte(pSrc);
ch->_noteOffset = 0;
ch->_pSrc += 2;
- goto post_keyon;
+ goto dispatch;
}
case 0xF5: {
ch->_pitchBendFadeReload = readScriptByte(pSrc);
@@ -1072,49 +1072,49 @@ dispatch:
ch->_pitchBendFadeCount = readScriptByte(pSrc);
ch->_pitchBendFadeCounter = 1;
ch->_pSrc += 4;
- goto post_keyon;
+ goto dispatch;
}
case 0xF4: {
- ch->_volume = readScriptByte(pSrc);
- ch->_pSrc += 2;
- sendVolume(midiChannel, ch->_volume);
- goto post_keyon;
- }
- case 0xF3: {
ch->_velocity = readScriptByte(pSrc);
ch->_pSrc += 2;
- goto post_keyon;
+ goto dispatch;
}
- case 0xF2: {
+ case 0xF3: {
ch->_volumeFadeReload = readScriptByte(pSrc);
ch->_volumeFadeStep = readScriptByte(pSrc);
ch->_volumeFadeCounter = 1;
ch->_pSrc += 3;
- goto post_keyon;
+ goto dispatch;
}
- case 0xF1: {
+ case 0xF2: {
ch->_pitchBend = readScriptByte(pSrc);
ch->_pSrc += 2;
sendPitchBend(midiChannel, ch->_pitchBend);
- goto post_keyon;
+ goto dispatch;
+ }
+ case 0xF1: {
+ ch->_volume = readScriptByte(pSrc);
+ ch->_pSrc += 2;
+ sendVolume(midiChannel, ch->_volume);
+ goto dispatch;
}
case 0xF0: {
ch->_pan = readScriptByte(pSrc);
sendPan(midiChannel, ch->_pan);
ch->_pSrc += 2;
- goto post_keyon;
+ goto dispatch;
}
case 0xEF: {
ch->_panFadeReload = readScriptByte(pSrc);
ch->_panFadeStep = readScriptByte(pSrc);
ch->_panFadeCounter = 1;
ch->_pSrc += 3;
- goto post_keyon;
+ goto dispatch;
}
case 0xEE: {
ch->_transpose = readScriptByte(pSrc);
ch->_pSrc += 2;
- goto post_keyon;
+ goto dispatch;
}
case 0xED: {
// ---- Chord event: [count][note1..noteN][duration] ----
Commit: 34545166e4e2cd14fb9f4b49fcead0b98d39fdc9
https://github.com/scummvm/scummvm/commit/34545166e4e2cd14fb9f4b49fcead0b98d39fdc9
Author: fusefib (fibofuse at gmail.com)
Date: 2026-08-26T11:52:07+10:00
Commit Message:
MADS: Use per-sample speech rates
Read the playback rate stored in each DSR directory entry instead of
selecting one rate for an entire game.
Phantom mixes 8000 and 11025 Hz samples in the same resource, and
the main-menu cackle is explicitly stored at 8000 Hz.
Assisted-by: Codex:GPT-5.4
Changed paths:
engines/mads/core/speech.cpp
diff --git a/engines/mads/core/speech.cpp b/engines/mads/core/speech.cpp
index a0452802cfb..e61fd0e52c9 100644
--- a/engines/mads/core/speech.cpp
+++ b/engines/mads/core/speech.cpp
@@ -38,7 +38,7 @@ Audio::AudioStream *speech_stream;
struct SpeechDir {
- int16 field0 = 0;
+ int16 sampleRate = 0;
int16 compression = 0;
int16 field4 = 0, field6 = 0, field8 = 0;
int32 size = 0;
@@ -50,7 +50,8 @@ struct SpeechDir {
void SpeechDir::load(Common::SeekableReadStream *src) {
- src->readMultipleLE(field0, compression, field4, field6, field8, size, offset);
+ src->readMultipleLE(sampleRate, compression, field4, field6, field8, size,
+ offset);
}
void speech_init() {
@@ -108,7 +109,7 @@ Audio::AudioStream *speech_load(const char *resName, int id, bool) {
// At this point we have valid data
memStream = new Common::MemoryReadStream(load_buf, speechDir.size, DisposeAfterUse::YES);
- audioStream = Audio::makeRawStream(memStream, g_engine->getGameID() == GType_RexNebular ? 8192 : 11025,
+ audioStream = Audio::makeRawStream(memStream, speechDir.sampleRate,
Audio::FLAG_UNSIGNED, DisposeAfterUse::YES);
done:
Commit: c42b0dcd01dcd2f67571c9808380f95718c1bd3f
https://github.com/scummvm/scummvm/commit/c42b0dcd01dcd2f67571c9808380f95718c1bd3f
Author: fusefib (fibofuse at gmail.com)
Date: 2026-08-26T11:52:07+10:00
Commit Message:
MADS: DRAGONSPHERE: Fix GSOUND sequence decoding
Decode the GSOUND volume, pitch-bend, volume-fade, and velocity
opcodes according to the native channel layout.
Apply the signed half-range conversion used by the original driver
for volume and velocity. This prevents GSOUND notes from being sent
with zero velocity.
Assisted-by: Codex:GPT-5.4
Changed paths:
engines/mads/dragonsphere/sound/gsound.cpp
engines/mads/dragonsphere/sound/gsound.h
diff --git a/engines/mads/dragonsphere/sound/gsound.cpp b/engines/mads/dragonsphere/sound/gsound.cpp
index 7c462eedf0d..906200d33a0 100644
--- a/engines/mads/dragonsphere/sound/gsound.cpp
+++ b/engines/mads/dragonsphere/sound/gsound.cpp
@@ -217,6 +217,11 @@ int8 GSound::readSignedByte(byte *&pSrc) {
return (int8)readByte(pSrc);
}
+int GSound::readCenteredValue(byte *&pSrc) {
+ const int value = readSignedByte(pSrc);
+ return 64 + (value >= 0 ? value / 2 : (value - 1) / 2);
+}
+
byte GSound::readByte(byte *&pSrc) {
if (!contains(pSrc + 1))
error("GSOUND bytecode read outside %s", _driverData.filename);
@@ -875,24 +880,24 @@ dispatch:
sendPan(channel);
goto dispatch;
case 0xF1:
+ channel._volume = readCenteredValue(pSrc);
+ channel._pSrc += 2;
+ sendVolume(channel);
+ goto dispatch;
+ case 0xF2:
channel._pitchBend = readByte(pSrc);
channel._pSrc += 2;
sendPitchBend(midiChannel, channel._pitchBend);
goto dispatch;
- case 0xF2:
+ case 0xF3:
channel._volumeFadeReload = readByte(pSrc);
channel._volumeFadeStep = readSignedByte(pSrc);
channel._volumeFadeCounter = 1;
channel._pSrc += 3;
goto dispatch;
- case 0xF3:
- channel._velocity = readByte(pSrc);
- channel._pSrc += 2;
- goto dispatch;
case 0xF4:
- channel._volume = readByte(pSrc);
+ channel._velocity = readCenteredValue(pSrc);
channel._pSrc += 2;
- sendVolume(channel);
goto dispatch;
case 0xF5:
channel._pitchBendFadeReload = readByte(pSrc);
diff --git a/engines/mads/dragonsphere/sound/gsound.h b/engines/mads/dragonsphere/sound/gsound.h
index 64de22c26cc..e766ff0e399 100644
--- a/engines/mads/dragonsphere/sound/gsound.h
+++ b/engines/mads/dragonsphere/sound/gsound.h
@@ -190,6 +190,7 @@ private:
void applyFades(GSoundChannel &channel);
int8 readSignedByte(byte *&pSrc);
+ int readCenteredValue(byte *&pSrc);
byte readByte(byte *&pSrc);
uint16 readWord(byte *&pSrc);
byte *readRoot(byte *&pSrc);
Commit: 309df043acfc7592319f5a2270516a9fc90e37cc
https://github.com/scummvm/scummvm/commit/309df043acfc7592319f5a2270516a9fc90e37cc
Author: fusefib (fibofuse at gmail.com)
Date: 2026-08-26T11:52:07+10:00
Commit Message:
MADS: FOREST: Fix digital sound volume control
Keep the digital volume API's volume-first argument order and
translate Forest's one-based channel numbers before indexing the
channel array.
Scale the room scripts' percentage values to the mixer range. This
restores room 306's ambient fade without reading outside the three
digital channels.
Assisted-by: Codex:GPT-5.4
Changed paths:
engines/mads/forest/sound/digi.cpp
diff --git a/engines/mads/forest/sound/digi.cpp b/engines/mads/forest/sound/digi.cpp
index 9488a97b60e..ced2a6a59b0 100644
--- a/engines/mads/forest/sound/digi.cpp
+++ b/engines/mads/forest/sound/digi.cpp
@@ -106,8 +106,11 @@ void DigiPlayer::setInitialVolume(int vol) {
_initialVolume = (vol < 0 || vol > 100) ? MAX_DIGI_VOLUME : vol * 327;
}
-void DigiPlayer::setVolume(int slot, int vol) {
- _mixer->setChannelVolume(_channels[slot]._soundHandle, (vol == MAX_DIGI_VOLUME) ? 255 : vol * 255 / 327);
+void DigiPlayer::setVolume(int vol, int slot) {
+ assert(slot >= 1 && slot <= MAX_DIGI_CHANNELS);
+ const byte volume = (vol < 0 || vol > 100) ? Audio::Mixer::kMaxChannelVolume :
+ vol * Audio::Mixer::kMaxChannelVolume / 100;
+ _mixer->setChannelVolume(_channels[slot - 1]._soundHandle, volume);
}
void digi_play_build_ii(char thing, int num, int slot) {
Commit: 61d9c9e6edd55722b4fa408b9c842cac55c94abb
https://github.com/scummvm/scummvm/commit/61d9c9e6edd55722b4fa408b9c842cac55c94abb
Author: fusefib (fibofuse at gmail.com)
Date: 2026-08-26T11:52:07+10:00
Commit Message:
MADS: DRAGONSPHERE: Accept GSOUND termination stream
Allow the GSOUND poller to consume the two-byte termination stream used
after a channel fade completes. The stream makes the channel inactive on
its next poll and is intentionally stored outside the mutable overlay
data. ScummVM rejected it as an escaped pointer.
Fixes: "ERROR: GSOUND channel stream escaped GSOUND.DR9!"
Assisted-by: Codex:GPT-5.6-sol
Changed paths:
engines/mads/dragonsphere/sound/gsound.cpp
diff --git a/engines/mads/dragonsphere/sound/gsound.cpp b/engines/mads/dragonsphere/sound/gsound.cpp
index 906200d33a0..08e35a1f253 100644
--- a/engines/mads/dragonsphere/sound/gsound.cpp
+++ b/engines/mads/dragonsphere/sound/gsound.cpp
@@ -199,6 +199,13 @@ bool GSound::validateOverlay(const GSoundDriverData &driverData) {
}
bool GSound::contains(const byte *ptr, uint32 count) const {
+ // Fade completion redirects the channel to this native { 0, 0 }
+ // termination stream before the poller makes the channel inactive.
+ if (ptr == _silenceStream)
+ return count <= sizeof(_silenceStream);
+ if (ptr == _silenceStream + 1)
+ return count <= sizeof(_silenceStream) - 1;
+
if (_soundData.empty())
return false;
const byte *start = &_soundData[0];
Commit: 3fd9958f2f4389b39655e8464c6be78098c2f5a9
https://github.com/scummvm/scummvm/commit/3fd9958f2f4389b39655e8464c6be78098c2f5a9
Author: fusefib (fibofuse at gmail.com)
Date: 2026-08-26T11:52:07+10:00
Commit Message:
MADS: Fix repeated preloaded speech playback
Clear the cached speech identifier after transferring its stream to the
mixer. ScummVM audio streams are consumed by playback and cannot be
reused like the original speech buffer.
Subsequent requests for the same sample now reload it instead of
attempting to play a null stream. This restores the second Phantom
cackle when the main menu appears.
Assisted-by: Codex:GPT-5.6-sol
Changed paths:
engines/mads/core/speech.cpp
diff --git a/engines/mads/core/speech.cpp b/engines/mads/core/speech.cpp
index e61fd0e52c9..2ec86d5f9b1 100644
--- a/engines/mads/core/speech.cpp
+++ b/engines/mads/core/speech.cpp
@@ -65,6 +65,7 @@ void speech_shutdown() {
speech_stream = nullptr;
}
+ global_speech_ready = -1;
speech_system_active = false;
}
@@ -128,6 +129,7 @@ void speech_play(const char *resName, int id) {
g_engine->playSpeech(speech);
speech_stream = nullptr;
+ global_speech_ready = -1;
}
void speech_all_off() {
@@ -143,6 +145,7 @@ void speech_go() {
g_engine->playSpeech(speech_stream);
speech_stream = nullptr;
}
+ global_speech_ready = -1;
}
void global_speech(int id) {
More information about the Scummvm-git-logs
mailing list